diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index c01016d0c2bce085fc61f1ae5bc8015f5a3487f0..280b3c4018e1264c9ddee5aeb3d33d79b7096cae 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -1358,22 +1358,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 dee7344e6b12635ba4f90dc1faa9c00be4682d72..15d7e73a0aa248625180fecca3cf5ae6876adab4 100644
--- a/Source/JavaScriptCore/DerivedSources.make
+++ b/Source/JavaScriptCore/DerivedSources.make
@@ -290,22 +290,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<JSON::Value> 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 8b290faebc1865519b0e7c514f497585dfc0bbda..53c68bca057c85c94201ef8e9870f0cb9e4cef6f 100644
--- a/Source/JavaScriptCore/inspector/InjectedScript.cpp
+++ b/Source/JavaScriptCore/inspector/InjectedScript.cpp
@@ -91,7 +91,7 @@ void InjectedScript::awaitPromise(const String& promiseObjectId, bool returnByVa
     makeAsyncCall(function, WTFMove(callback));
 }
 
-void InjectedScript::callFunctionOn(Protocol::ErrorString& errorString, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown)
+void InjectedScript::callFunctionOn(const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, bool awaitPromise, AsyncCallCallback&& callback)
 {
     Deprecated::ScriptFunctionCall function(injectedScriptObject(), "callFunctionOn"_s, inspectorEnvironment()->functionCallHandler());
     function.appendArgument(objectId);
@@ -99,10 +99,8 @@ void InjectedScript::callFunctionOn(Protocol::ErrorString& errorString, const St
     function.appendArgument(arguments);
     function.appendArgument(returnByValue);
     function.appendArgument(generatePreview);
-
-    std::optional<int> savedResultIndex;
-    makeEvalCall(errorString, function, result, wasThrown, savedResultIndex);
-    ASSERT(!savedResultIndex);
+    function.appendArgument(awaitPromise);
+    makeAsyncCall(function, WTFMove(callback));
 }
 
 void InjectedScript::evaluateOnCallFrame(Protocol::ErrorString& errorString, JSC::JSValue callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex)
@@ -289,6 +287,10 @@ RefPtr<Protocol::Runtime::RemoteObject> 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/InjectedScript.h b/Source/JavaScriptCore/inspector/InjectedScript.h
index e6b24967273095ae424ac9b3fe5e081ee8999ab7..9f7b72259ab79504b8bfcc24d35abe70d7372065 100644
--- a/Source/JavaScriptCore/inspector/InjectedScript.h
+++ b/Source/JavaScriptCore/inspector/InjectedScript.h
@@ -64,7 +64,7 @@ public:
     void evaluate(Protocol::ErrorString&, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex);
     void awaitPromise(const String& promiseObjectId, bool returnByValue, bool generatePreview, bool saveResult, AsyncCallCallback&&);
     void evaluateOnCallFrame(Protocol::ErrorString&, JSC::JSValue callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex);
-    void callFunctionOn(Protocol::ErrorString&, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown);
+    void callFunctionOn(const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, bool awaitPromise, AsyncCallCallback&&);
     void getFunctionDetails(Protocol::ErrorString&, const String& functionId, RefPtr<Protocol::Debugger::FunctionDetails>& result);
     void functionDetails(Protocol::ErrorString&, JSC::JSValue, RefPtr<Protocol::Debugger::FunctionDetails>& result);
     void getPreview(Protocol::ErrorString&, const String& objectId, RefPtr<Protocol::Runtime::ObjectPreview>& result);
diff --git a/Source/JavaScriptCore/inspector/InjectedScriptSource.js b/Source/JavaScriptCore/inspector/InjectedScriptSource.js
index 48baed6a1b7ffad453379a2f1eb71b8c4925f6c4..40d36f784f46e44dbad908402a71e6b02f499629 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;
         }
@@ -171,14 +171,16 @@ let InjectedScript = class InjectedScript
         return this._evaluateAndWrap(callFrame.evaluateWithScopeExtension, callFrame, expression, objectGroup, isEvalOnCallFrame, includeCommandLineAPI, returnByValue, generatePreview, saveResult);
     }
 
-    callFunctionOn(objectId, expression, args, returnByValue, generatePreview)
+    callFunctionOn(objectId, expression, args, returnByValue, generatePreview, awaitPromise, callback)
     {
         let parsedObjectId = this._parseObjectId(objectId);
         let object = this._objectForId(parsedObjectId);
         let objectGroupName = this._idToObjectGroupName[parsedObjectId.id];
 
-        if (!isDefined(object))
-            return "Could not find object with given id";
+        if (!isDefined(object)) {
+            callback(this._createThrownValue("Could not find object with given id", objectGroupName));
+            return ;
+        }
 
         let resolvedArgs = [];
         if (args) {
@@ -187,22 +189,37 @@ let InjectedScript = class InjectedScript
                 try {
                     resolvedArgs[i] = this._resolveCallArgument(callArgs[i]);
                 } catch (e) {
-                    return String(e);
+                    callback(this._createThrownValue(e, objectGroupName));
+                    return;
                 }
             }
         }
 
         try {
             let func = InjectedScriptHost.evaluate("(" + expression + ")");
-            if (typeof func !== "function")
-                return "Given expression does not evaluate to a function";
-
-            return {
-                wasThrown: false,
-                result: RemoteObject.create(func.apply(object, resolvedArgs), objectGroupName, returnByValue, generatePreview)
-            };
+            if (typeof func !== "function") {
+                callback(this._createThrownValue("Given expression does not evaluate to a function", objectGroupName));
+                return;
+            }
+            let result = func.apply(object, resolvedArgs);
+            if (awaitPromise && isDefined(result) && (InjectedScriptHost.internalConstructorName(result) === 'Promise')) {
+                result.then(value => {
+                    callback({
+                        wasThrown: false,
+                        result: RemoteObject.create(value, objectGroupName, returnByValue, generatePreview),
+                    });
+                }, reason => {
+                    callback(this._createThrownValue(reason, objectGroupName));
+                });
+            } else {
+                callback({
+                    wasThrown: false,
+                    result: RemoteObject.create(result, objectGroupName, returnByValue, generatePreview)
+                });
+            }
         } catch (e) {
-            return this._createThrownValue(e, objectGroupName);
+            callback(this._createThrownValue(e, objectGroupName));
+            return;
         }
     }
 
diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
index 82129b2f5439fbf59f6e8ab3c20a27f3b287a9fc..db1ce92dfdb35b9765ef743989959e0e396545a1 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<BackendDispatcher> 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<std::optional<long>> scopedRequestId(m_currentRequestId, requestId);
diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
index 37c4f9833d4981b47bcd8debd4a79109254641a2..1c82cc9783618234bef7024d91821ce509912526 100644
--- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
+++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
@@ -83,7 +83,10 @@ public:
     };
 
     void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*);
-    void dispatch(const String& message);
+
+    enum class InterceptionResult { Intercepted, Continue };
+    using Interceptor = WTF::Function<InterceptionResult(const RefPtr<JSON::Object>&)>;
+    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 <http://webkit.org/b/179847> 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<void()>&& 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<void()> m_resumeCallback;
     bool m_isPaused { false };
 };
diff --git a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp
index 76d72c7273f1bb2170485015d931b1fba92d3b5a..c0cf9588c04bfba0d6176c4d6af691bd56ca6cec 100644
--- a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp
+++ b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp
@@ -168,16 +168,15 @@ void InspectorRuntimeAgent::awaitPromise(const Protocol::Runtime::RemoteObjectId
     });
 }
 
-Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, std::optional<bool> /* wasThrown */>> InspectorRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& functionDeclaration, RefPtr<JSON::Array>&& arguments, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& /* emulateUserGesture */)
+void InspectorRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& functionDeclaration, RefPtr<JSON::Array>&& arguments, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& /* emulateUserGesture */, std::optional<bool>&& awaitPromise, Ref<CallFunctionOnCallback>&& callback)
 {
     Protocol::ErrorString errorString;
 
     InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
-    if (injectedScript.hasNoValue())
-        return makeUnexpected("Missing injected script for given objectId"_s);
-
-    RefPtr<Protocol::Runtime::RemoteObject> result;
-    std::optional<bool> wasThrown;
+    if (injectedScript.hasNoValue()) {
+        callback->sendFailure("Missing injected script for given objectId"_s);
+        return;
+    }
 
     JSC::Debugger::TemporarilyDisableExceptionBreakpoints temporarilyDisableExceptionBreakpoints(m_debugger);
 
@@ -187,15 +186,15 @@ Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, std::op
         muteConsole();
     }
 
-    injectedScript.callFunctionOn(errorString, objectId, functionDeclaration, arguments ? arguments->toJSONString() : nullString(), returnByValue.value_or(false), generatePreview.value_or(false), result, wasThrown);
+    injectedScript.callFunctionOn(objectId, functionDeclaration, arguments ? arguments->toJSONString() : nullString(), returnByValue.value_or(false), generatePreview.value_or(false), awaitPromise.value_or(false), [callback=WTFMove(callback)] (Protocol::ErrorString& errorString, RefPtr<Protocol::Runtime::RemoteObject>&& result, std::optional<bool>&& wasThrown, std::optional<int>&&) {
+        if (!result)
+            callback->sendFailure(errorString);
+        else
+            callback->sendSuccess(result.releaseNonNull(), WTFMove(wasThrown));
+    });
 
     if (pauseAndMute)
         unmuteConsole();
-
-    if (!result)
-        return makeUnexpected(errorString);
-
-    return { { result.releaseNonNull(), WTFMove(wasThrown) } };
 }
 
 Protocol::ErrorStringOr<Ref<Protocol::Runtime::ObjectPreview>> InspectorRuntimeAgent::getPreview(const Protocol::Runtime::RemoteObjectId& objectId)
diff --git a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h
index c4f6fa5b9de54317da07c2371a7126aae1c967aa..0d549faeb1f0f80c7a6e7c208c72c6ef9cf4dbd5 100644
--- a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h
+++ b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h
@@ -62,7 +62,7 @@ public:
     Protocol::ErrorStringOr<std::tuple<Protocol::Runtime::SyntaxErrorType, String /* message */, RefPtr<Protocol::Runtime::ErrorRange>>> parse(const String& expression) final;
     Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, std::optional<bool> /* wasThrown */, std::optional<int> /* savedResultIndex */>> evaluate(const String& expression, const String& objectGroup, std::optional<bool>&& includeCommandLineAPI, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<Protocol::Runtime::ExecutionContextId>&&, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& saveResult, std::optional<bool>&& emulateUserGesture) override;
     void awaitPromise(const Protocol::Runtime::RemoteObjectId&, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& saveResult, Ref<AwaitPromiseCallback>&&) final;
-    Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, std::optional<bool> /* wasThrown */>> callFunctionOn(const Protocol::Runtime::RemoteObjectId&, const String& functionDeclaration, RefPtr<JSON::Array>&& arguments, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& emulateUserGesture) override;
+    void callFunctionOn(const Protocol::Runtime::RemoteObjectId&, const String& functionDeclaration, RefPtr<JSON::Array>&& arguments, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& emulateUserGesture, std::optional<bool>&& awaitPromise, Ref<CallFunctionOnCallback>&&) override;
     Protocol::ErrorStringOr<void> releaseObject(const Protocol::Runtime::RemoteObjectId&) final;
     Protocol::ErrorStringOr<Ref<Protocol::Runtime::ObjectPreview>> getPreview(const Protocol::Runtime::RemoteObjectId&) final;
     Protocol::ErrorStringOr<std::tuple<Ref<JSON::ArrayOf<Protocol::Runtime::PropertyDescriptor>>, RefPtr<JSON::ArrayOf<Protocol::Runtime::InternalPropertyDescriptor>>>> getProperties(const Protocol::Runtime::RemoteObjectId&, std::optional<bool>&& ownProperties, std::optional<int>&& fetchStart, std::optional<int>&& fetchCount, std::optional<bool>&& generatePreview) final;
diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
index 508eb02ec95c52408384a1e2b77648afd426dd9d..c0099a56794ae411fe9cdce1a65a95f1a7e37924 100644
--- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
+++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
@@ -87,6 +87,34 @@ Protocol::ErrorStringOr<void> InspectorTargetAgent::sendMessageToTarget(const St
     return { };
 }
 
+Protocol::ErrorStringOr<void> 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<void> InspectorTargetAgent::close(const String& targetId,  std::optional<bool>&& 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..4169e227b5fb5a3a7fb51396c4679100f495719c 100644
--- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h
+++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h
@@ -50,15 +50,21 @@ public:
     Protocol::ErrorStringOr<void> setPauseOnStart(bool) final;
     Protocol::ErrorStringOr<void> resume(const String& targetId) final;
     Protocol::ErrorStringOr<void> sendMessageToTarget(const String& targetId, const String& message) final;
+    Protocol::ErrorStringOr<void> activate(const String& targetId) override;
+    Protocol::ErrorStringOr<void> close(const String& targetId, std::optional<bool>&& 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 3a91ac6b57fad7f472daa2e2107b3b483de70165..ff51e75762818b0bb5070ddf8de10e66018d63b0 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 <input type=file>",
+            "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..347a01b3fdd1a8277cb4104558e8bbfa63539374
--- /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": "fixedLayout", "type": "boolean" },
+                { "name": "deviceScaleFactor", "type": "number", "optional": true }
+            ]
+        },
+        {
+            "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..b9ab57a2b5739ed997231399b4bd4042a0cb0935
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Input.json
@@ -0,0 +1,223 @@
+{
+    "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": "dispatchWheelEvent",
+            "description": "Dispatches a wheel 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"
+                },
+                {
+                    "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 882a2d56befef0aba460cc8ff041969e0d2c1ed3..9aecd6067741af596e5ec7fdf9c832ea1267715a 100644
--- a/Source/JavaScriptCore/inspector/protocol/Network.json
+++ b/Source/JavaScriptCore/inspector/protocol/Network.json
@@ -324,6 +324,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..cf8c009d5591c4eac1a65e2c0de15533cb40b236 100644
--- a/Source/JavaScriptCore/inspector/protocol/Page.json
+++ b/Source/JavaScriptCore/inspector/protocol/Page.json
@@ -21,13 +21,20 @@
                 "ShowDebugBorders",
                 "ShowRepaintCounter",
                 "WebRTCEncryptionEnabled",
-                "WebSecurityEnabled"
+                "WebSecurityEnabled",
+                "DeviceOrientationEventEnabled",
+                "SpeechRecognitionEnabled",
+                "PointerLockEnabled",
+                "NotificationsEnabled",
+                "FullScreenEnabled",
+                "InputTypeMonthEnabled",
+                "InputTypeWeekEnabled"
             ]
         },
         {
             "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."
         },
         {
@@ -49,6 +56,12 @@
             "enum": ["Light", "Dark"],
             "description": "Page appearance name."
         },
+        {
+            "id": "ReducedMotion",
+            "type": "string",
+            "enum": ["Reduce", "NoPreference"],
+            "description": "Page reduced-motion media query override."
+        },
         {
             "id": "Frame",
             "type": "object",
@@ -112,6 +125,51 @@
                 { "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."}
+            ]
+        },
+        {
+            "id": "Insets",
+            "type": "object",
+            "properties": [
+                { "name": "top", "type": "number" },
+                { "name": "right", "type": "number" },
+                { "name": "bottom", "type": "number" },
+                { "name": "left", "type": "number" }
+            ]
         }
     ],
     "commands": [
@@ -131,6 +189,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.",
@@ -147,6 +213,14 @@
                 { "name": "value", "type": "string", "optional": true, "description": "Value to override the user agent with. If this value is not provided, the override is removed. Overrides are removed when Web Inspector closes/disconnects." }
             ]
         },
+        {
+            "name": "overridePlatform",
+            "description": "Override's the navigator.platform of the inspected page",
+            "targetTypes": ["page"],
+            "parameters": [
+                { "name": "value", "type": "string", "optional": true, "description": "Value to override the platform with. If this value is not provided, the override is removed. Overrides are removed when Web Inspector closes/disconnects." }
+            ]
+        },
         {
             "name": "overrideSetting",
             "description": "Allows the frontend to override the inspected page's settings.",
@@ -204,7 +278,8 @@
             "name": "setBootstrapScript",
             "targetTypes": ["page"],
             "parameters": [
-                { "name": "source", "type": "string", "optional": true, "description": "If `source` is provided (and not empty), it will be injected into all future global objects as soon as they're created. Omitting `source` will stop this from happening." }
+                { "name": "source", "type": "string", "optional": true, "description": "If `source` is provided (and not empty), it will be injected into all future global objects as soon as they're created. Omitting `source` will stop this from happening." },
+                { "name": "worldName", "type": "string", "optional": true, "description": "Isolated world name to evaluate the script in. If not specified main world will be used." }
             ]
         },
         {
@@ -270,6 +345,28 @@
                 { "name": "appearance", "$ref": "Appearance", "optional": true }
             ]
         },
+        {
+            "name": "setForcedReducedMotion",
+            "description": "Forces the reduced-motion media query for the page.",
+            "targetTypes": ["page"],
+            "parameters": [
+                { "name": "reducedMotion", "$ref": "ReducedMotion", "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.",
@@ -290,7 +387,8 @@
                 { "name": "y", "type": "integer", "description": "Y coordinate" },
                 { "name": "width", "type": "integer", "description": "Rectangle width" },
                 { "name": "height", "type": "integer", "description": "Rectangle height" },
-                { "name": "coordinateSystem", "$ref": "CoordinateSystem", "description": "Indicates the coordinate system of the supplied rectangle." }
+                { "name": "coordinateSystem", "$ref": "CoordinateSystem", "description": "Indicates the coordinate system of the supplied rectangle." },
+                { "name": "omitDeviceScaleFactor", "type": "boolean", "optional": true, "description": "By default, screenshot is inflated by device scale factor to avoid blurry image. This flag disables it." }
             ],
             "returns": [
                 { "name": "dataURL", "type": "string", "description": "Base64-encoded image data (PNG)." }
@@ -308,12 +406,92 @@
         {
             "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": "setComposition",
+            "description": "Set the current IME composition.",
+            "parameters": [
+                { "name": "text", "type": "string" },
+                { "name": "selectionStart", "type": "integer" },
+                { "name": "selectionLength", "type": "integer" },
+                { "name": "replacementStart", "type": "integer", "optional": true },
+                { "name": "replacementLength", "type": "integer", "optional": true }
+            ]
+        },
+        {
+            "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 }
+            ]
+        },
+        {
+            "name": "setVisibleContentRects",
+            "targetTypes": ["page"],
+            "parameters": [
+                { "name": "unobscuredContentRect", "$ref": "DOM.Rect", "optional": true },
+                { "name": "contentInsets", "$ref": "Insets", "optional": true },
+                { "name": "obscuredInsets", "$ref": "Insets", "optional": true },
+                { "name": "unobscuredInsets", "$ref": "Insets", "optional": true }
+            ]
+        },
+        {
+            "name": "updateScrollingState",
+            "description": "Ensures that the scroll regions are up to date."
         }
     ],
     "events": [
@@ -321,14 +499,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 +518,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 +565,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 +589,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 <input type=file>.",
+            "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..3aebbe625682094d0e8ac2f14ac33321dd475142
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Playwright.json
@@ -0,0 +1,289 @@
+{
+    "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": "NameValue",
+            "type": "object",
+            "description": "Name-value pair",
+            "properties": [
+                { "name": "name", "type": "string" },
+                { "name": "value", "type": "string" }
+            ]
+        },
+        {
+            "id": "OriginStorage",
+            "type": "object",
+            "description": "Origin object",
+            "properties": [
+                { "name": "origin", "type": "string", "description": "Origin." },
+                { "name": "items", "type": "array", "items": { "$ref": "NameValue" }, "description": "Storage entries." }
+            ]
+        },
+        {
+            "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": "getLocalStorageData",
+            "description": "Returns all local storage data in the given browser context.",
+            "async": true,
+            "parameters": [
+                { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
+            ],
+            "returns": [
+                { "name": "origins", "type": "array", "items": { "$ref": "OriginStorage" }, "description": "Local storage data." }
+            ]
+        },
+        {
+            "name": "setLocalStorageData",
+            "description": "Populates local storage data in the given browser context.",
+            "async": true,
+            "parameters": [
+                { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." },
+                { "name": "origins", "type": "array", "items": { "$ref": "OriginStorage" }, "description": "Local storage data." }
+            ]
+        },
+        {
+            "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." }
+            ]
+        },
+        {
+            "name": "cancelDownload",
+            "parameters": [
+                { "name": "uuid", "type": "string" }
+            ],
+            "description": "Cancels a current running download."
+        }
+    ],
+    "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/Runtime.json b/Source/JavaScriptCore/inspector/protocol/Runtime.json
index 274b01596d490fb81b48cf89bf668e0634e8b423..d08a9ddd745c748767ba8055907daa7beeffc219 100644
--- a/Source/JavaScriptCore/inspector/protocol/Runtime.json
+++ b/Source/JavaScriptCore/inspector/protocol/Runtime.json
@@ -261,12 +261,14 @@
                 { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether function call should stop on exceptions and mute console. Overrides setPauseOnException state." },
                 { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object which should be sent by value." },
                 { "name": "generatePreview", "type": "boolean", "optional": true, "description": "Whether preview should be generated for the result." },
-                { "name": "emulateUserGesture", "type": "boolean", "optional": true, "description": "Whether the expression should be considered to be in a user gesture or not." }
+                { "name": "emulateUserGesture", "type": "boolean", "optional": true, "description": "Whether the expression should be considered to be in a user gesture or not." },
+                { "name": "awaitPromise", "type": "boolean", "optional": true, "description": "Whether to automatically await returned promise." }
             ],
             "returns": [
                 { "name": "result", "$ref": "RemoteObject", "description": "Call result." },
                 { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." }
-            ]
+            ],
+            "async": true
         },
         {
             "name": "getPreview",
diff --git a/Source/JavaScriptCore/inspector/protocol/Screencast.json b/Source/JavaScriptCore/inspector/protocol/Screencast.json
new file mode 100644
index 0000000000000000000000000000000000000000..73a4e53ced3acc41316bb8d4c787306d3f28a27e
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Screencast.json
@@ -0,0 +1,64 @@
+{
+    "domain": "Screencast",
+    "availability": ["web"],
+    "types": [
+        {
+            "id": "ScreencastId",
+            "type": "string",
+            "description": "Unique identifier of the screencast."
+        }
+    ],
+    "commands": [
+        {
+            "name": "startVideo",
+            "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": "toolbarHeight", "type": "integer" }
+            ],
+            "returns": [
+                { "name": "screencastId", "$ref": "ScreencastId", "description": "Unique identifier of the screencast." }
+            ]
+        },
+        {
+            "name": "stopVideo",
+            "async": true,
+            "description": "Stops recoding video. Returns after the file has been closed."
+        },
+        {
+            "name": "startScreencast",
+            "description": "Starts screencast.",
+            "parameters": [
+                { "name": "width", "type": "integer" },
+                { "name": "height", "type": "integer" },
+                { "name": "toolbarHeight", "type": "integer" },
+                { "name": "quality", "type": "integer" }
+            ],
+            "returns": [
+                { "name": "generation", "type": "integer", "description": "Screencast session generation." }
+            ]
+        },
+        {
+            "name": "stopScreencast",
+            "description": "Stops screencast."
+        },
+        {
+            "name": "screencastFrameAck",
+            "parameters": [
+                { "name": "generation", "type": "integer", "description": "Screencast session generation" }
+            ]
+        }
+    ],
+    "events": [
+        {
+            "name": "screencastFrame",
+            "parameters": [
+                { "name": "data", "type": "string", "description": "Base64 data" },
+                { "name": "deviceWidth", "type": "integer" },
+                { "name": "deviceHeight", "type": "integer" }
+            ]
+        }
+    ]
+}
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 2decf8a83c80e80ca8677f4c787bf79c6c2995fa..9010384a32f7c2ab69a8fb20eb19cd566fd9f434 100644
--- a/Source/JavaScriptCore/runtime/DateConversion.cpp
+++ b/Source/JavaScriptCore/runtime/DateConversion.cpp
@@ -97,6 +97,9 @@ String formatDateTime(const GregorianDateTime& t, DateTimeFormat format, bool as
             appendNumber<2>(builder, offset / 60);
             appendNumber<2>(builder, offset % 60);
 
+            if (!WTF::timeZoneDisplayNameForAutomation().isEmpty()) {
+                builder.append(" (", WTF::timeZoneDisplayNameForAutomation(), ')');
+            } else {
 #if OS(WINDOWS)
             TIME_ZONE_INFORMATION timeZoneInformation;
             GetTimeZoneInformation(&timeZoneInformation);
@@ -109,6 +112,7 @@ String formatDateTime(const GregorianDateTime& t, DateTimeFormat format, bool as
 #endif
             if (timeZoneName[0])
                 builder.append(" (", timeZoneName, ')');
+            }
         }
     }
 
diff --git a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
index c2d49da98a660bc62b04afe19c578f2592fd4bb9..f27c12db93e099a2dea9ffeb57be72a0eedf656a 100644
--- a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
+++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
@@ -36,6 +36,7 @@
 #include <unicode/ucal.h>
 #include <unicode/uenum.h>
 #include <wtf/Range.h>
+#include <wtf/DateMath.h>
 #include <wtf/text/StringBuilder.h>
 #include <wtf/unicode/icu/ICUHelpers.h>
 
diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp
index 5219f8f7242b86f940e82823584e61fe2ba49e61..51bd401528326fc8fea07ed052d0f561411a254f 100644
--- a/Source/JavaScriptCore/runtime/JSDateMath.cpp
+++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp
@@ -76,6 +76,7 @@
 #include "VM.h"
 #include <limits>
 #include <wtf/unicode/icu/ICUHelpers.h>
+#include <wtf/DateMath.h>
 
 #if U_ICU_VERSION_MAJOR_NUM >= 69 || (U_ICU_VERSION_MAJOR_NUM == 68 && USE(APPLE_INTERNAL_SDK))
 #define HAVE_ICU_C_TIMEZONE_API 1
@@ -329,6 +330,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;
+
 #if HAVE(ICU_C_TIMEZONE_API)
     return timeZoneCache()->m_canonicalTimeZoneID;
 #else
@@ -363,12 +368,20 @@ Ref<DateInstanceData> DateCache::cachedDateInstanceData(double millisecondsFromE
 void DateCache::timeZoneCacheSlow()
 {
     ASSERT(!m_timeZoneCache);
+
+    String override = WTF::timeZoneForAutomation();
 #if HAVE(ICU_C_TIMEZONE_API)
     auto* cache = new OpaqueICUTimeZone;
 
     String canonical;
+    UErrorCode status = U_ZERO_ERROR;
     Vector<UChar, 32> timeZoneID;
-    auto status = callBufferProducingFunction(ucal_getHostTimeZone, timeZoneID);
+    if (override.isEmpty()) {
+        status = callBufferProducingFunction(ucal_getHostTimeZone, timeZoneID);
+        ASSERT_UNUSED(status, U_SUCCESS(status));
+    } else {
+        timeZoneID = override.charactersWithoutNullTermination();
+    }
     if (U_SUCCESS(status)) {
         Vector<UChar, 32> canonicalBuffer;
         auto status = callBufferProducingFunction(ucal_getCanonicalTimeZoneID, timeZoneID.data(), timeZoneID.size(), canonicalBuffer, nullptr);
@@ -385,6 +398,11 @@ void DateCache::timeZoneCacheSlow()
     ucal_setGregorianChange(cache->m_calendar.get(), minECMAScriptTime, &status); // Ignore "unsupported" error.
     m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(cache);
 #else
+    if (!override.isEmpty()) {
+        auto* timezone = icu::TimeZone::createTimeZone(override.utf8().data());
+        m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(bitwise_cast<OpaqueICUTimeZone*>(timezone));
+        return;
+    }
     // Do not use icu::TimeZone::createDefault. ICU internally has a cache for timezone and createDefault returns this cached value.
     m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(bitwise_cast<OpaqueICUTimeZone*>(icu::TimeZone::detectHostTimeZone()));
 #endif
diff --git a/Source/PlatformWPE.cmake b/Source/PlatformWPE.cmake
index fabd776e617d07a6c30b9f2df30f884491259359..d9c39df7db565545108c765407ce1cda544856f7 100644
--- a/Source/PlatformWPE.cmake
+++ b/Source/PlatformWPE.cmake
@@ -8,32 +8,3 @@ list(APPEND DocumentationDependencies
     "${CMAKE_SOURCE_DIR}/Source/WebKit/UIProcess/API/wpe/docs/wpe-${WPE_API_DOC_VERSION}-sections.txt"
     "${CMAKE_SOURCE_DIR}/Source/WebKit/WebProcess/InjectedBundle/API/wpe/docs/wpe-webextensions-${WPE_API_DOC_VERSION}-sections.txt"
 )
-
-if (ENABLE_GTKDOC)
-    install(DIRECTORY ${CMAKE_BINARY_DIR}/Documentation/wpe-${WPE_API_VERSION}/html/wpe-${WPE_API_VERSION}
-            DESTINATION "${CMAKE_INSTALL_DATADIR}/gtk-doc/html"
-    )
-    install(DIRECTORY ${CMAKE_BINARY_DIR}/Documentation/wpe-webextensions-${WPE_API_VERSION}/html/wpe-webextensions-${WPE_API_VERSION}
-        DESTINATION "${CMAKE_INSTALL_DATADIR}/gtk-doc/html"
-    )
-endif ()
-
-ADD_GTKDOC_GENERATOR("docs-build.stamp" "--wpe")
-if (ENABLE_GTKDOC)
-    add_custom_target(gtkdoc ALL DEPENDS "${CMAKE_BINARY_DIR}/docs-build.stamp")
-elseif (NOT ENABLED_COMPILER_SANITIZERS AND NOT CMAKE_CROSSCOMPILING AND NOT APPLE)
-    add_custom_target(gtkdoc DEPENDS "${CMAKE_BINARY_DIR}/docs-build.stamp")
-
-    # Add a default build step which check that documentation does not have any warnings
-    # or errors. This is useful to prevent breaking documentation inadvertently during
-    # the course of development.
-    if (DEVELOPER_MODE)
-        ADD_GTKDOC_GENERATOR("docs-build-no-html.stamp" "--wpe;--skip-html")
-        add_custom_target(gtkdoc-no-html ALL DEPENDS "${CMAKE_BINARY_DIR}/docs-build-no-html.stamp")
-    endif ()
-endif ()
-
-if (DEVELOPER_MODE)
-    add_custom_target(Documentation DEPENDS gtkdoc)
-    WEBKIT_DECLARE_DIST_TARGETS(WPE wpewebkit ${TOOLS_DIR}/wpe/manifest.txt.in)
-endif ()
diff --git a/Source/ThirdParty/libwebrtc/CMakeLists.txt b/Source/ThirdParty/libwebrtc/CMakeLists.txt
index be86666961906832f585adb43edeb381ad199222..23b1fd28ee684537fcbcc9c671e2bff827f11c53 100644
--- a/Source/ThirdParty/libwebrtc/CMakeLists.txt
+++ b/Source/ThirdParty/libwebrtc/CMakeLists.txt
@@ -292,6 +292,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_common.cc
     Source/third_party/libyuv/source/compare_gcc.cc
     Source/third_party/libyuv/source/convert.cc
@@ -1754,6 +1759,10 @@ set(webrtc_INCLUDE_DIRECTORIES PRIVATE
     Source/third_party/libsrtp/config
     Source/third_party/libsrtp/crypto/include
     Source/third_party/libsrtp/include
+# Playwright begin
+    Source/third_party/libwebm
+    Source/third_party/libvpx/source/libvpx
+# 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 dfe8ba87c6bed689f7f044d388b7c21b19936518..3de753ce55f0626e98d19a71c31f81f2c7b65c4c 100644
--- a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp
+++ b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp
@@ -330,4 +330,23 @@ __ZN3rtc6Thread12socketserverEv
 __ZN6webrtc32webrtc_sequence_checker_internal19SequenceCheckerImplC2Ev
 __ZNK3rtc14RTCCertificate17GetSSLCertificateEv
 __ZTVN6webrtc30WrappingAsyncDnsResolverResultE
-
+__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 dd884b22250114627213c4827ca176c283ec2525..9927a937145f23d05e907083a01748dd8015eb98 100644
--- a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.xcconfig
+++ b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.xcconfig
@@ -43,7 +43,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 a4eef414ab4e495956517320ae72235750e1c5d6..e8942e7e3b9cd57ae8b25e4854df37fee8bd760e 100644
--- a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj
+++ b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj
@@ -3871,6 +3871,9 @@
 		CDFD2FCC24C4DAF70048DAC3 /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = CDEBB40524C0191A00ADBD44 /* reader.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		CDFD2FCD24C4DAF70048DAC3 /* status.h in Headers */ = {isa = PBXBuildFile; fileRef = CDEBB40624C0191A00ADBD44 /* status.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		CDFD2FCE24C4DAF70048DAC3 /* webm_parser.h in Headers */ = {isa = PBXBuildFile; fileRef = CDEBB40824C0191A00ADBD44 /* webm_parser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		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 */
@@ -8309,6 +8312,9 @@
 		CDEBB49D24C0191A00ADBD44 /* master_parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = master_parser.h; sourceTree = "<group>"; };
 		CDFD2F9624C4B2F90048DAC3 /* vp9_header_parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vp9_header_parser.h; sourceTree = "<group>"; };
 		CDFD2F9A24C4B2F90048DAC3 /* vp9_header_parser.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = vp9_header_parser.cc; sourceTree = "<group>"; };
+		F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvmuxerutil.cc; path = mkvmuxer/mkvmuxerutil.cc; sourceTree = "<group>"; };
+		F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvmuxer.cc; path = mkvmuxer/mkvmuxer.cc; sourceTree = "<group>"; };
+		F3B7819824C7CC5200FCB122 /* mkvwriter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvwriter.cc; path = mkvmuxer/mkvwriter.cc; sourceTree = "<group>"; };
 		FB39D0D11200F0E300088E69 /* libwebrtc.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libwebrtc.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
@@ -15289,6 +15295,7 @@
 			isa = PBXGroup;
 			children = (
 				CDFD2F9224C4B2F90048DAC3 /* common */,
+				F3B7819524C7CC1300FCB122 /* mkvmuxer */,
 				CDEBB19224C0191800ADBD44 /* webm_parser */,
 			);
 			path = libwebm;
@@ -15423,6 +15430,16 @@
 			path = common;
 			sourceTree = "<group>";
 		};
+		F3B7819524C7CC1300FCB122 /* mkvmuxer */ = {
+			isa = PBXGroup;
+			children = (
+				F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */,
+				F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */,
+				F3B7819824C7CC5200FCB122 /* mkvwriter.cc */,
+			);
+			name = mkvmuxer;
+			sourceTree = "<group>";
+		};
 		FB39D06E1200ED9200088E69 = {
 			isa = PBXGroup;
 			children = (
@@ -17494,7 +17511,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;
@@ -18638,6 +18655,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 */,
@@ -19084,6 +19102,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 */,
@@ -19314,6 +19333,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 */,
 				41323A1D2665288B00B38623 /* packet_sequencer.cc in Sources */,
 				4131BF2D234B88200028A615 /* rtc_stats_collector.cc in Sources */,
diff --git a/Source/WTF/Scripts/Preferences/WebPreferences.yaml b/Source/WTF/Scripts/Preferences/WebPreferences.yaml
index 6475aa03dd643fbb8c57c933750e2e53469444d1..ab2f792bc27bc377031539c4ffc3df8f263f0edd 100644
--- a/Source/WTF/Scripts/Preferences/WebPreferences.yaml
+++ b/Source/WTF/Scripts/Preferences/WebPreferences.yaml
@@ -1042,7 +1042,7 @@ InspectorStartsAttached:
   exposed: [ WebKit ]
   defaultValue:
     WebKit:
-      default: true
+      default: false
 
 InspectorWindowFrame:
   type: String
@@ -1782,6 +1782,17 @@ PluginsEnabled:
     WebCore:
       default: false
 
+PointerLockEnabled:
+  type: bool
+  condition: ENABLE(POINTER_LOCK)
+  defaultValue:
+    WebKitLegacy:
+      default: true
+    WebKit:
+      default: true
+    WebCore:
+      default: true
+
 PrivateClickMeasurementEnabled:
   type: bool
   humanReadableName: "Private Click Measurement"
diff --git a/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml b/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml
index be9acb429aa256d906c4a419c6f1c7fa451cf2e3..27cd55e2dfa1cc95ceb11f951f6a8b120470ca4b 100644
--- a/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml
+++ b/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml
@@ -433,7 +433,7 @@ CrossOriginOpenerPolicyEnabled:
     WebKitLegacy:
       default: false
     WebKit:
-      default: true
+      default: false
     WebCore:
       default: false
 
@@ -812,9 +812,9 @@ MaskWebGLStringsEnabled:
     WebKitLegacy:
       default: true
     WebKit:
-      default: true
+      default: false
     WebCore:
-      default: true
+      default: false
 
 # FIXME: This is on by default in WebKit2. Perhaps we should consider turning it on for WebKitLegacy as well.
 MediaCapabilitiesExtensionsEnabled:
@@ -1292,7 +1292,7 @@ SpeechRecognitionEnabled:
     WebKitLegacy:
       default: false
     WebKit:
-      "HAVE(SPEECHRECOGNIZER) && ENABLE(MEDIA_STREAM)": true
+      "ENABLE(MEDIA_STREAM)": true
       default: false
     WebCore:
       default: false
diff --git a/Source/WTF/wtf/DateMath.cpp b/Source/WTF/wtf/DateMath.cpp
index ebd69a4c76cd7acb0a233be552071158ca2171ca..2ee388e94a56d3de9c9fb2506d2ddead2db1ef87 100644
--- a/Source/WTF/wtf/DateMath.cpp
+++ b/Source/WTF/wtf/DateMath.cpp
@@ -76,9 +76,14 @@
 #include <limits>
 #include <stdint.h>
 #include <time.h>
+#include <unicode/ucal.h>
 #include <wtf/Assertions.h>
 #include <wtf/ASCIICType.h>
+#include <wtf/Language.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/ThreadSpecific.h>
 #include <wtf/text/StringBuilder.h>
+#include <wtf/unicode/UTF8Conversion.h>
 
 #if OS(WINDOWS)
 #include <windows.h>
@@ -92,6 +97,18 @@ template<unsigned length> inline bool startsWithLettersIgnoringASCIICase(const c
     return equalLettersIgnoringASCIICase(string, lowercaseLetters, length - 1);
 }
 
+struct TimeZoneForAutomation {
+    UCalendar* cal;
+    String id;
+    String displayName;
+};
+
+static TimeZoneForAutomation& innerTimeZoneForAutomation()
+{
+    static NeverDestroyed<WTF::ThreadSpecific<TimeZoneForAutomation>> 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<UChar> 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<UChar, 32> 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<UChar, 32> 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 7bb27e9976fb14e06fa4ee48553617fca06d8d7b..79ac2c9e778c1efca4f588edd4271bf8d25b1aa6 100644
--- a/Source/WTF/wtf/DateMath.h
+++ b/Source/WTF/wtf/DateMath.h
@@ -393,6 +393,10 @@ inline double timeToMS(double hour, double min, double sec, double ms)
     return (((hour * WTF::minutesPerHour + min) * WTF::secondsPerMinute + sec) * WTF::msPerSecond + ms);
 }
 
+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 b263ee464856665ce90f783d6ce7e0ded9aee067..1d29a03a2a5bf81b2b308bc3923b55002afc409c 100644
--- a/Source/WTF/wtf/PlatformEnable.h
+++ b/Source/WTF/wtf/PlatformEnable.h
@@ -412,7 +412,7 @@
 #endif
 
 #if !defined(ENABLE_ORIENTATION_EVENTS)
-#define ENABLE_ORIENTATION_EVENTS 0
+#define ENABLE_ORIENTATION_EVENTS 1
 #endif
 
 #if OS(WINDOWS)
@@ -473,7 +473,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/PlatformEnableCocoa.h b/Source/WTF/wtf/PlatformEnableCocoa.h
index 3f1cd334a7ac0894aaddd90a0a4ab0322b013317..f9042b94a52ccd223a4ec3d1bdaf8b4f8b293352 100644
--- a/Source/WTF/wtf/PlatformEnableCocoa.h
+++ b/Source/WTF/wtf/PlatformEnableCocoa.h
@@ -224,7 +224,7 @@
 #define ENABLE_DATA_DETECTION 1
 #endif
 
-#if !defined(ENABLE_DEVICE_ORIENTATION) && !PLATFORM(MAC) && !PLATFORM(MACCATALYST)
+#if !defined(ENABLE_DEVICE_ORIENTATION) && !PLATFORM(MACCATALYST)
 #define ENABLE_DEVICE_ORIENTATION 1
 #endif
 
diff --git a/Source/WTF/wtf/PlatformGTK.cmake b/Source/WTF/wtf/PlatformGTK.cmake
index 3901bfb0f5479064f4e7b67c90621ff26d74b580..5b3615a871d0d7123822394c94d5ce1005e80394 100644
--- a/Source/WTF/wtf/PlatformGTK.cmake
+++ b/Source/WTF/wtf/PlatformGTK.cmake
@@ -77,6 +77,7 @@ list(APPEND WTF_LIBRARIES
     ${GLIB_LIBRARIES}
     Threads::Threads
     ZLIB::ZLIB
+    stdc++fs
 )
 
 if (Journald_FOUND)
diff --git a/Source/WTF/wtf/PlatformHave.h b/Source/WTF/wtf/PlatformHave.h
index 3c3106cbec7fb2e255cab3acb1d41cac76941c04..dbf3e055eca007cd80976048465b52e4e77c6ccc 100644
--- a/Source/WTF/wtf/PlatformHave.h
+++ b/Source/WTF/wtf/PlatformHave.h
@@ -384,7 +384,7 @@
 #define HAVE_FOUNDATION_WITH_SAME_SITE_COOKIE_SUPPORT 1
 #endif
 
-#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST) || PLATFORM(GTK) || PLATFORM(WPE)
+#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/WTF/wtf/PlatformWPE.cmake b/Source/WTF/wtf/PlatformWPE.cmake
index f8bedf1af5d20d9c93a96af565e416bfb0df6faa..a072e5e130822d3658cbab453aef8d160a0a73de 100644
--- a/Source/WTF/wtf/PlatformWPE.cmake
+++ b/Source/WTF/wtf/PlatformWPE.cmake
@@ -50,6 +50,7 @@ list(APPEND WTF_LIBRARIES
     ${GLIB_LIBRARIES}
     Threads::Threads
     ZLIB::ZLIB
+    stdc++fs
 )
 
 if (Journald_FOUND)
diff --git a/Source/WebCore/DerivedSources.make b/Source/WebCore/DerivedSources.make
index 6051405ada53f685bcd81120ba2697408f723868..70dcd353afc701e9468882c4558d38abe40fe942 100644
--- a/Source/WebCore/DerivedSources.make
+++ b/Source/WebCore/DerivedSources.make
@@ -953,6 +953,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 \
@@ -1497,9 +1501,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 e272ecdef2a7d066a121ec366a9906d4b8db14c7..f922d861134d44958c58e6332fb3d029da150921 100644
--- a/Source/WebCore/Modules/geolocation/Geolocation.cpp
+++ b/Source/WebCore/Modules/geolocation/Geolocation.cpp
@@ -371,8 +371,9 @@ bool Geolocation::shouldBlockGeolocationRequests()
     bool isSecure = SecurityOrigin::isSecure(document()->url()) || document()->isSecureContext();
     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 bc5c6219b5dadc3b1cdc590d65c897b7250b1e21..37d07ef4f59ad450077d90d451cf512005f360f4 100644
--- a/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm
+++ b/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm
@@ -56,7 +56,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 cfbfe4f66dbc339e68179f4ceb48a02c3c122926..66050a7c29254f73d04273510b5e0642f79e9173 100644
--- a/Source/WebCore/PlatformWPE.cmake
+++ b/Source/WebCore/PlatformWPE.cmake
@@ -42,6 +42,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS
 
     platform/graphics/wayland/PlatformDisplayWayland.h
     platform/graphics/wayland/WlUniquePtr.h
+    platform/wpe/SelectionData.h
 )
 
 set(CSS_VALUE_PLATFORM_DEFINES "HAVE_OS_DARK_MODE_SUPPORT=1")
diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt
index eafb0854821731b2d7c8ae572c44815598f41cca..d7681ec1662e9a45ff2fbb4fde458b01aa0f86f8 100644
--- a/Source/WebCore/SourcesCocoa.txt
+++ b/Source/WebCore/SourcesCocoa.txt
@@ -610,3 +610,9 @@ platform/graphics/angle/ANGLEUtilities.cpp @no-unify
 platform/graphics/angle/ExtensionsGLANGLE.cpp @no-unify
 platform/graphics/angle/GraphicsContextGLANGLE.cpp @no-unify
 platform/graphics/angle/TemporaryANGLESetting.cpp @no-unify
+
+// Playwright begin
+JSTouch.cpp
+JSTouchEvent.cpp
+JSTouchList.cpp
+// Playwright end
diff --git a/Source/WebCore/SourcesGTK.txt b/Source/WebCore/SourcesGTK.txt
index 491786b51d3ecaab0a061831ae06e745989cf30d..c3fcb832fed7dd015b838c588453da2bfa21cd79 100644
--- a/Source/WebCore/SourcesGTK.txt
+++ b/Source/WebCore/SourcesGTK.txt
@@ -103,7 +103,7 @@ platform/graphics/egl/GLContextEGLLibWPE.cpp @no-unify
 platform/graphics/egl/GLContextEGLWayland.cpp @no-unify
 platform/graphics/egl/GLContextEGLX11.cpp @no-unify
 
-platform/graphics/glx/GLContextGLX.cpp
+platform/graphics/glx/GLContextGLX.cpp @no-unify
 
 platform/graphics/gtk/ColorGtk.cpp
 platform/graphics/gtk/DisplayRefreshMonitorGtk.cpp
diff --git a/Source/WebCore/SourcesWPE.txt b/Source/WebCore/SourcesWPE.txt
index fd058e8f614edba70fd0d104285864e768eceb5d..375547aee2755513950c253666eeb5696505ab24 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
 
@@ -85,8 +87,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 9f85e4986c53a1cc8d63b3394d3f7295832af387..1228fda7c688c5b24cecaf07e21437d34f016042 100644
--- a/Source/WebCore/WebCore.order
+++ b/Source/WebCore/WebCore.order
@@ -3090,7 +3090,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 26f9e950e52cc4d7daf8eddbe289d7014fe1ced0..fa881b8bbb2a282b5f759908b5527901084b3850 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -5439,6 +5439,13 @@
 		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 */; };
+		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, ); }; };
@@ -17584,6 +17591,14 @@
 		EDEC98020AED7E170059137F /* WebCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCorePrefix.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
 		EFB7287B2124C73D005C2558 /* CanvasActivityRecord.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CanvasActivityRecord.cpp; sourceTree = "<group>"; };
 		EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanvasActivityRecord.h; sourceTree = "<group>"; };
+		F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchEvent.h; sourceTree = "<group>"; };
+		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 = "<group>"; };
+		F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchPoint.h; sourceTree = "<group>"; };
 		F12171F316A8BC63000053CA /* WebVTTElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebVTTElement.cpp; sourceTree = "<group>"; };
 		F12171F416A8BC63000053CA /* WebVTTElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebVTTElement.h; sourceTree = "<group>"; };
 		F32BDCD52363AAC90073B6AE /* UserGestureEmulationScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserGestureEmulationScope.cpp; sourceTree = "<group>"; };
@@ -23849,7 +23864,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 */,
@@ -29789,6 +29809,8 @@
 				29E4D8DF16B0940F00C84704 /* PlatformSpeechSynthesizer.h */,
 				1AD8F81A11CAB9E900E93E54 /* PlatformStrategies.cpp */,
 				1AD8F81911CAB9E900E93E54 /* PlatformStrategies.h */,
+				F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */,
+				F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */,
 				0FD7C21D23CE41E30096D102 /* PlatformWheelEvent.cpp */,
 				935C476A09AC4D4F00A6AAB4 /* PlatformWheelEvent.h */,
 				BCBB8AB513F1AFB000734DF0 /* PODInterval.h */,
@@ -32084,6 +32106,7 @@
 				BCCFBAE70B5152ED0001F1D7 /* DocumentParser.h */,
 				AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */,
 				AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */,
+				F050E17323AD6A800011CE47 /* DocumentTouch.cpp */,
 				6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */,
 				6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */,
 				7CE7FA5B1EF882300060C9D6 /* DocumentTouch.cpp */,
@@ -33101,6 +33124,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 */,
@@ -35216,6 +35240,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 */,
@@ -36311,6 +36336,7 @@
 				1AD8F81B11CAB9E900E93E54 /* PlatformStrategies.h in Headers */,
 				0F7D07331884C56C00B4AF86 /* PlatformTextTrack.h in Headers */,
 				074E82BB18A69F0E007EF54C /* PlatformTimeRanges.h in Headers */,
+				F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */,
 				CD1F9B022700323D00617EB6 /* PlatformVideoColorPrimaries.h in Headers */,
 				CD1F9B01270020B700617EB6 /* PlatformVideoColorSpace.h in Headers */,
 				CD1F9B032700323D00617EB6 /* PlatformVideoMatrixCoefficients.h in Headers */,
@@ -38315,6 +38341,7 @@
 				1ABA76CA11D20E50004C201C /* CSSPropertyNames.cpp in Sources */,
 				2D22830323A8470700364B7E /* CursorMac.mm in Sources */,
 				5CBD59592280E926002B22AA /* CustomHeaderFields.cpp in Sources */,
+				F050E17423AD6A800011CE47 /* DocumentTouch.cpp in Sources */,
 				6E72F54C229DCD0C00B3E151 /* ExtensionsGLANGLE.cpp in Sources */,
 				7CE6CBFD187F394900D46BF5 /* FormatConverter.cpp in Sources */,
 				5130F2F624AEA60A00E1D0A0 /* GameControllerSoftLink.mm in Sources */,
@@ -38384,6 +38411,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 */,
@@ -38432,6 +38460,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 */,
@@ -38964,6 +38993,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 d649f1cd2cec7a8da6f04debe5524a770d09b9f5..707d7c1fedc1434b09f6fd66b7d5ebed43913bed 100644
--- a/Source/WebCore/accessibility/AccessibilityObject.cpp
+++ b/Source/WebCore/accessibility/AccessibilityObject.cpp
@@ -61,6 +61,7 @@
 #include "HTMLParserIdioms.h"
 #include "HTMLTextAreaElement.h"
 #include "HitTestResult.h"
+#include "InspectorInstrumentation.h"
 #include "LocalizedStrings.h"
 #include "MathMLNames.h"
 #include "NodeList.h"
@@ -3542,10 +3543,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/bindings/js/WebCoreBuiltinNames.h b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h
index fa35e1bd8c44c86cc260eadf66e29f205c1efcd7..ec9947a51374ec042333dcde3e7d8df4c92b8cee 100644
--- a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h
+++ b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h
@@ -110,6 +110,8 @@ namespace WebCore {
     macro(Database) \
     macro(DataTransferItem) \
     macro(DataTransferItemList) \
+    macro(DeviceMotionEvent) \
+    macro(DeviceOrientationEvent) \
     macro(DocumentTimeline) \
     macro(EnterPictureInPictureEvent) \
     macro(ExtendableEvent) \
diff --git a/Source/WebCore/css/MediaQueryEvaluator.cpp b/Source/WebCore/css/MediaQueryEvaluator.cpp
index 9c00886958d5ae32edd5f76f76843d0bdfaffe70..63e99946a89893f39465e7858be329498e68cb0f 100644
--- a/Source/WebCore/css/MediaQueryEvaluator.cpp
+++ b/Source/WebCore/css/MediaQueryEvaluator.cpp
@@ -847,7 +847,11 @@ static bool prefersContrastEvaluate(CSSValue* value, const CSSToLengthConversion
 static bool prefersReducedMotionEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix)
 {
     bool userPrefersReducedMotion = false;
-
+    
+    std::optional<bool> reducedMotionOverride = frame.page()->useReducedMotionOverride();
+    if (reducedMotionOverride)
+        userPrefersReducedMotion = reducedMotionOverride.value();
+    else {
     switch (frame.settings().forcedPrefersReducedMotionAccessibilityValue()) {
     case ForcedAccessibilityValue::On:
         userPrefersReducedMotion = true;
@@ -860,6 +864,7 @@ static bool prefersReducedMotionEvaluate(CSSValue* value, const CSSToLengthConve
 #endif
         break;
     }
+    }
 
     if (!value)
         return userPrefersReducedMotion;
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> DataTransfer::createForDrag(const Document& document)
     return adoptRef(*new DataTransfer(StoreMode::ReadWrite, Pasteboard::createForDragAndDrop(PagePasteboardContext::create(document.pageID())), Type::DragAndDropData));
 }
 
+#if PLATFORM(MAC)
+Ref<DataTransfer> DataTransfer::createForDrag(const Document& document, const String& pasteboardName)
+{
+    return adoptRef(*new DataTransfer(StoreMode::ReadWrite, makeUnique<Pasteboard>(PagePasteboardContext::create(document.pageID()), pasteboardName), Type::DragAndDropData));
+}
+#endif
+
+
 Ref<DataTransfer> DataTransfer::createForDragStartEvent(const Document& document)
 {
     auto dataTransfer = adoptRef(*new DataTransfer(StoreMode::ReadWrite, makeUnique<StaticPasteboard>(), 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<DataTransfer> createForDrag(const Document&);
+#if PLATFORM(MAC)
+    static Ref<DataTransfer> createForDrag(const Document&, const String& pasteboardName);
+#endif
     static Ref<DataTransfer> createForDragStartEvent(const Document&);
     static Ref<DataTransfer> createForDrop(const Document&, std::unique_ptr<Pasteboard>&&, OptionSet<DragOperation>, bool draggingFiles);
     static Ref<DataTransfer> createForUpdatingDropTarget(const Document&, std::unique_ptr<Pasteboard>&&, OptionSet<DragOperation>, bool draggingFiles);
diff --git a/Source/WebCore/dom/DeviceMotionEvent.idl b/Source/WebCore/dom/DeviceMotionEvent.idl
index fca03d4c02903b5992884c108c317a65160e924f..f42d3f0d7024677e296fba281076c521166ba36e 100644
--- a/Source/WebCore/dom/DeviceMotionEvent.idl
+++ b/Source/WebCore/dom/DeviceMotionEvent.idl
@@ -25,6 +25,7 @@
 
 [
     Conditional=DEVICE_ORIENTATION,
+    EnabledBySetting=DeviceOrientationEventEnabled,
     Exposed=Window
 ] interface DeviceMotionEvent : Event {
     readonly attribute Acceleration? acceleration;
diff --git a/Source/WebCore/dom/DeviceOrientationEvent.idl b/Source/WebCore/dom/DeviceOrientationEvent.idl
index 905bb471d59c7d86a86aa3da193f98506971d3f5..9fd2bba81e821cba25da66a1c1838f1d26fdd109 100644
--- a/Source/WebCore/dom/DeviceOrientationEvent.idl
+++ b/Source/WebCore/dom/DeviceOrientationEvent.idl
@@ -25,6 +25,7 @@
 
 [
     Conditional=DEVICE_ORIENTATION,
+    EnabledBySetting=DeviceOrientationEventEnabled,
     Exposed=Window
 ] interface DeviceOrientationEvent : Event {
     readonly attribute unrestricted double? alpha;
diff --git a/Source/WebCore/dom/Document+PointerLock.idl b/Source/WebCore/dom/Document+PointerLock.idl
index 898027004b8553cac8130541026af70ffb5ee073..883d6a7df7a164625037cd8cee95c8fe4312b9e8 100644
--- a/Source/WebCore/dom/Document+PointerLock.idl
+++ b/Source/WebCore/dom/Document+PointerLock.idl
@@ -25,6 +25,7 @@
 
 // https://w3c.github.io/pointerlock/#extensions-to-the-document-interface
 [
+    EnabledBySetting=PointerLockEnabled,
     Conditional=POINTER_LOCK
 ] partial interface Document {
     [NotEnumerable] attribute EventHandler onpointerlockchange; // FIXME: Should be enumerable.
diff --git a/Source/WebCore/dom/DocumentOrShadowRoot+PointerLock.idl b/Source/WebCore/dom/DocumentOrShadowRoot+PointerLock.idl
index 9b8dbfc15ce078702321abcd6c0e636df7a60510..2956f7098e87af10ab8f5584b456ce9a6d432a20 100644
--- a/Source/WebCore/dom/DocumentOrShadowRoot+PointerLock.idl
+++ b/Source/WebCore/dom/DocumentOrShadowRoot+PointerLock.idl
@@ -25,6 +25,7 @@
 
 // https://w3c.github.io/pointerlock/#extensions-to-the-documentorshadowroot-mixin
 [
+    EnabledBySetting=PointerLockEnabled,
     Conditional=POINTER_LOCK
 ] partial interface mixin DocumentOrShadowRoot {
     readonly attribute Element? pointerLockElement;
diff --git a/Source/WebCore/dom/Element+PointerLock.idl b/Source/WebCore/dom/Element+PointerLock.idl
index f27718c1e2b8cd0a8075e556d4cdba7d9ae8fc54..2b61721594e5435845f3151e0de345e90eafc9ea 100644
--- a/Source/WebCore/dom/Element+PointerLock.idl
+++ b/Source/WebCore/dom/Element+PointerLock.idl
@@ -24,6 +24,7 @@
  */
 
 [
+    EnabledBySetting=PointerLockEnabled,
     Conditional=POINTER_LOCK
 ] partial interface Element {
     undefined requestPointerLock();
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> PointerEvent::create(const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref<WindowProxy>&& view)
+{
+    const auto& type = pointerEventType(event.touchPoints().at(index).state());
+    return adoptRef(*new PointerEvent(type, event, typeIsCancelable(type), index, isPrimary, WTFMove(view)));
+}
+
+Ref<PointerEvent> PointerEvent::create(const String& type, const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref<WindowProxy>&& 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<WindowProxy>&& 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<PointerEvent> create(const String& type, short button, const MouseEvent&, PointerID, const String& pointerType);
     static Ref<PointerEvent> create(const String& type, PointerID, const String& pointerType, IsPrimary = IsPrimary::No);
 
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
+#if ENABLE(TOUCH_EVENTS)
     static Ref<PointerEvent> create(const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref<WindowProxy>&&);
     static Ref<PointerEvent> create(const String& type, const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref<WindowProxy>&&);
 #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<WindowProxy>&&);
 #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<PasteOption>
         pasteAsFragment(*fragment, canSmartReplaceWithPasteboard(*pasteboard), chosePlainText, options.contains(PasteOption::IgnoreMailBlockquote) ? MailBlockquoteHandling::IgnoreBlockquote : MailBlockquoteHandling::RespectBlockquote);
 }
 
+RefPtr<DocumentFragment> 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 a2377bc1f2b46aa4f48816fc37061e09a49c9762..2a93fc1b820e6ac2e0d071b4b7197fca85e4d1a9 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"
@@ -201,6 +202,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 833c0ba844f87bced9b2430138ec7676c883bffc..ea8adf5a94705ff9e7c1ec8301a980a4d48e83d0 100644
--- a/Source/WebCore/inspector/InspectorController.cpp
+++ b/Source/WebCore/inspector/InspectorController.cpp
@@ -382,8 +382,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);
 }
@@ -524,4 +524,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 f6fec7cfbcbd2d7fba30bdd3138e0edfb3f69054..519786c307944a5ca4ba468513ba257b8c28def2 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; }
@@ -153,6 +157,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 a7ca7162d791ed7fba8cc91c21a2cf3af6e69a7e..f43705d3dcb96c2f6fa7a359b5a3fd10a6c18e30 100644
--- a/Source/WebCore/inspector/InspectorInstrumentation.cpp
+++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp
@@ -569,6 +569,13 @@ void InspectorInstrumentation::applyUserAgentOverrideImpl(InstrumentingAgents& i
         pageAgent->applyUserAgentOverride(userAgent);
 }
 
+void InspectorInstrumentation::applyPlatformOverrideImpl(InstrumentingAgents& instrumentingAgents, String& platform)
+{
+    if (auto* pageAgent = instrumentingAgents.enabledPageAgent())
+        pageAgent->applyPlatformOverride(platform);
+}
+
+
 void InspectorInstrumentation::applyEmulatedMediaImpl(InstrumentingAgents& instrumentingAgents, String& media)
 {
     if (auto* pageAgent = instrumentingAgents.enabledPageAgent())
@@ -636,6 +643,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())
@@ -668,20 +681,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)
@@ -762,12 +772,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()) {
@@ -804,6 +808,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)
 {
@@ -1286,6 +1296,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;
@@ -1297,6 +1337,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<Document>(context))
diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h
index 8e65c4eb10233521f48c7f4b120ad2c8909a07ba..089f6520bfec96d96d54f7916d7db41887e1b591 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 "CanvasBase.h"
 #include "CanvasRenderingContext.h"
@@ -45,6 +46,7 @@
 #include "HitTestResult.h"
 #include "InspectorInstrumentationPublic.h"
 #include "Page.h"
+#include "ResourceError.h"
 #include "ResourceLoader.h"
 #include "ResourceLoaderIdentifier.h"
 #include "StorageArea.h"
@@ -77,6 +79,7 @@ class DOMWrapperWorld;
 class Document;
 class DocumentLoader;
 class EventListener;
+class HTMLInputElement;
 class HTTPHeaderMap;
 class InspectorTimelineAgent;
 class InstrumentingAgents;
@@ -187,6 +190,7 @@ public:
     static void didRecalculateStyle(Document&);
     static void didScheduleStyleRecalculation(Document&);
     static void applyUserAgentOverride(Frame&, String&);
+    static void applyPlatformOverride(Frame&, String&);
     static void applyEmulatedMedia(Frame&, String&);
 
     static void willSendRequest(Frame*, ResourceLoaderIdentifier, DocumentLoader*, ResourceRequest&, const ResourceResponse& redirectResponse, const CachedResource*);
@@ -196,6 +200,7 @@ public:
     static void didReceiveData(Frame*, ResourceLoaderIdentifier, const uint8_t* data, int dataLength, int encodedDataLength);
     static void didFinishLoading(Frame*, DocumentLoader*, ResourceLoaderIdentifier, const NetworkLoadMetrics&, ResourceLoader*);
     static void didFailLoading(Frame*, DocumentLoader*, ResourceLoaderIdentifier, const ResourceError&);
+    static void didReceiveMainResourceError(Frame&, const ResourceError&);
 
     static void willSendRequest(WorkerOrWorkletGlobalScope&, ResourceLoaderIdentifier, ResourceRequest&);
     static void didReceiveResourceResponse(WorkerOrWorkletGlobalScope&, ResourceLoaderIdentifier, const ResourceResponse&);
@@ -222,11 +227,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
@@ -313,6 +318,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(); }
@@ -329,6 +340,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&);
@@ -406,6 +419,7 @@ private:
     static void didRecalculateStyleImpl(InstrumentingAgents&);
     static void didScheduleStyleRecalculationImpl(InstrumentingAgents&, Document&);
     static void applyUserAgentOverrideImpl(InstrumentingAgents&, String&);
+    static void applyPlatformOverrideImpl(InstrumentingAgents&, String&);
     static void applyEmulatedMediaImpl(InstrumentingAgents&, String&);
 
     static void willSendRequestImpl(InstrumentingAgents&, ResourceLoaderIdentifier, DocumentLoader*, ResourceRequest&, const ResourceResponse& redirectResponse, const CachedResource*);
@@ -417,6 +431,7 @@ private:
     static void didReceiveDataImpl(InstrumentingAgents&, ResourceLoaderIdentifier, const uint8_t* data, int dataLength, int encodedDataLength);
     static void didFinishLoadingImpl(InstrumentingAgents&, ResourceLoaderIdentifier, DocumentLoader*, const NetworkLoadMetrics&, ResourceLoader*);
     static void didFailLoadingImpl(InstrumentingAgents&, ResourceLoaderIdentifier, DocumentLoader*, const ResourceError&);
+    static void didReceiveMainResourceErrorImpl(InstrumentingAgents&, Frame&, const ResourceError&);
     static void willLoadXHRSynchronouslyImpl(InstrumentingAgents&);
     static void didLoadXHRSynchronouslyImpl(InstrumentingAgents&);
     static void scriptImportedImpl(InstrumentingAgents&, ResourceLoaderIdentifier, const String& sourceString);
@@ -427,11 +442,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
@@ -513,6 +528,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&);
 
@@ -1031,6 +1052,13 @@ inline void InspectorInstrumentation::applyUserAgentOverride(Frame& frame, Strin
         applyUserAgentOverrideImpl(*agents, userAgent);
 }
 
+inline void InspectorInstrumentation::applyPlatformOverride(Frame& frame, String& platform)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (auto* agents = instrumentingAgents(frame))
+        applyPlatformOverrideImpl(*agents, platform);
+}
+
 inline void InspectorInstrumentation::applyEmulatedMedia(Frame& frame, String& media)
 {
     FAST_RETURN_IF_NO_FRONTENDS(void());
@@ -1081,7 +1109,7 @@ inline void InspectorInstrumentation::didReceiveThreadableLoaderResponse(Documen
     if (auto* agents = instrumentingAgents(documentThreadableLoader.document()))
         didReceiveThreadableLoaderResponseImpl(*agents, documentThreadableLoader, identifier);
 }
-    
+
 inline void InspectorInstrumentation::didReceiveData(Frame* frame, ResourceLoaderIdentifier identifier, const uint8_t* data, int dataLength, int encodedDataLength)
 {
     FAST_RETURN_IF_NO_FRONTENDS(void());
@@ -1119,6 +1147,13 @@ inline void InspectorInstrumentation::didFailLoading(WorkerOrWorkletGlobalScope&
     didFailLoadingImpl(instrumentingAgents(globalScope), identifier, nullptr, 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::continueAfterXFrameOptionsDenied(Frame& frame, ResourceLoaderIdentifier identifier, DocumentLoader& loader, const ResourceResponse& response)
 {
     // Treat the same as didReceiveResponse.
@@ -1209,13 +1244,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());
@@ -1244,6 +1272,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)
 {
@@ -1674,6 +1709,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 3805f84245f6cb73c45844364d54f822b6beb26d..a6c62b3bcceaa054095cb9edb853de606cc53d0f 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 std::optional<Color> parseColor(RefPtr<JSON::Object>&& colorObject)
+// static
+std::optional<Color> InspectorDOMAgent::parseColor(RefPtr<JSON::Object>&& colorObject)
 {
     if (!colorObject)
         return std::nullopt;
@@ -150,7 +158,7 @@ static std::optional<Color> parseColor(RefPtr<JSON::Object>&& colorObject)
 
 static Color parseConfigColor(const String& fieldName, JSON::Object& configObject)
 {
-    return parseColor(configObject.getObject(fieldName)).value_or(Color::transparentBlack);
+    return InspectorDOMAgent::parseColor(configObject.getObject(fieldName)).value_or(Color::transparentBlack);
 }
 
 static bool parseQuad(Ref<JSON::Array>&& quadArray, FloatQuad* quad)
@@ -431,6 +439,20 @@ Node* InspectorDOMAgent::assertNode(Protocol::ErrorString& errorString, Protocol
     return node;
 }
 
+Node* InspectorDOMAgent::assertNode(Protocol::ErrorString& errorString, std::optional<Protocol::DOM::NodeId>&& 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);
@@ -1384,16 +1406,7 @@ Protocol::ErrorStringOr<void> InspectorDOMAgent::highlightSelector(Ref<JSON::Obj
 Protocol::ErrorStringOr<void> InspectorDOMAgent::highlightNode(Ref<JSON::Object>&& highlightInspectorObject, std::optional<Protocol::DOM::NodeId>&& 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);
 
@@ -1595,15 +1608,136 @@ Protocol::ErrorStringOr<void> InspectorDOMAgent::setInspectedNode(Protocol::DOM:
     return { };
 }
 
-Protocol::ErrorStringOr<Ref<Protocol::Runtime::RemoteObject>> 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<Inspector::Protocol::DOM::Quad> 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<JSON::ArrayOf<Inspector::Protocol::DOM::Quad>> buildArrayOfQuads(const Vector<FloatQuad>& quads)
+{
+    auto result = JSON::ArrayOf<Inspector::Protocol::DOM::Quad>::create();
+    for (const auto& quad : quads)
+        result->addItem(buildObjectForQuad(quad));
+    return result;
+}
+
+Inspector::Protocol::ErrorStringOr<std::tuple<String /* contentFrameId */, String /* ownerFrameId */>> 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<HTMLFrameOwnerElement>(*node)) {
+        const auto& frameOwner = downcast<HTMLFrameOwnerElement>(*node);
+        String frameId = pageAgent->frameId(frameOwner.contentFrame());
+        if (!frameId.isEmpty())
+            contentFrameId = frameId;
+    }
+
+    return { { contentFrameId, ownerFrameId } };
+}
+
+Protocol::ErrorStringOr<void> InspectorDOMAgent::scrollIntoViewIfNeeded(const String& objectId, RefPtr<JSON::Object>&& 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) {
+        std::optional<double> x = rect->getDouble("x");
+        std::optional<double> y = rect->getDouble("y");
+        std::optional<double> width = rect->getDouble("width");
+        std::optional<double> 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<Ref<JSON::ArrayOf<Protocol::DOM::Quad>>> 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<FloatQuad> quads;
+    renderer->absoluteQuads(quads);
+    for (auto& quad : quads)
+        frameQuadToViewport(*containingView, quad, m_inspectedPage.pageScaleFactor());
+    return buildArrayOfQuads(quads);
+}
+
+Protocol::ErrorStringOr<Ref<Protocol::Runtime::RemoteObject>> InspectorDOMAgent::resolveNode(std::optional<Inspector::Protocol::DOM::NodeId>&& nodeId, const String& objectId, std::optional<int>&& 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);
 
@@ -2837,7 +2971,7 @@ Protocol::ErrorStringOr<Protocol::DOM::NodeId> InspectorDOMAgent::pushNodeByPath
     return makeUnexpected("Missing node for given path"_s);
 }
 
-RefPtr<Protocol::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
+RefPtr<Inspector::Protocol::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup, std::optional<int>&& contextId)
 {
     Document* document = &node->document();
     if (auto* templateHost = document->templateDocumentHost())
@@ -2846,12 +2980,16 @@ RefPtr<Protocol::Runtime::RemoteObject> 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)
@@ -2874,4 +3012,42 @@ Protocol::ErrorStringOr<void> InspectorDOMAgent::setAllowEditingUserAgentShadowT
     return { };
 }
 
+Protocol::ErrorStringOr<void> InspectorDOMAgent::setInputFiles(const String& objectId, Ref<JSON::Array>&& 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<HTMLInputElement*>(node);
+    Vector<Ref<File>> fileObjects;
+    for (unsigned i = 0; i < files->length(); ++i) {
+        RefPtr<JSON::Value> item = files->get(i);
+        RefPtr<JSON::Object> 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);
+
+        std::optional<Vector<uint8_t>> buffer = base64Decode(data);
+        if (!buffer)
+            return makeUnexpected("Unable to decode given content"_s);
+
+        ScriptExecutionContext* context = element->scriptExecutionContext();
+        fileObjects.append(File::create(context, Blob::create(context, WTFMove(*buffer), type), name));
+    }
+    RefPtr<FileList> 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 4eb63b7985721ac6ea6003c884989179c78eda00..b0e628854f24c15a25fbad6aebab1c55a6568545 100644
--- a/Source/WebCore/inspector/agents/InspectorDOMAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.h
@@ -57,6 +57,7 @@ namespace WebCore {
 
 class AXCoreObject;
 class CharacterData;
+class Color;
 class DOMEditor;
 class Document;
 class Element;
@@ -86,6 +87,7 @@ public:
     static String toErrorString(Exception&&);
 
     static String documentURLString(Document*);
+    static std::optional<Color> parseColor(RefPtr<JSON::Object>&&);
 
     // 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.
@@ -129,7 +131,7 @@ public:
     Inspector::Protocol::ErrorStringOr<std::tuple<String /* searchId */, int /* resultCount */>> performSearch(const String& query, RefPtr<JSON::Array>&& nodeIds, std::optional<bool>&& caseSensitive);
     Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Inspector::Protocol::DOM::NodeId>>> getSearchResults(const String& searchId, int fromIndex, int toIndex);
     Inspector::Protocol::ErrorStringOr<void> discardSearchResults(const String& searchId);
-    Inspector::Protocol::ErrorStringOr<Ref<Inspector::Protocol::Runtime::RemoteObject>> resolveNode(Inspector::Protocol::DOM::NodeId, const String& objectGroup);
+    Inspector::Protocol::ErrorStringOr<Ref<Inspector::Protocol::Runtime::RemoteObject>> resolveNode(std::optional<Inspector::Protocol::DOM::NodeId>&& nodeId, const String& objectId, std::optional<int>&& contextId, const String& objectGroup);
     Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<String>>> getAttributes(Inspector::Protocol::DOM::NodeId);
 #if PLATFORM(IOS_FAMILY)
     Inspector::Protocol::ErrorStringOr<void> setInspectModeEnabled(bool, RefPtr<JSON::Object>&& highlightConfig);
@@ -154,6 +156,10 @@ public:
     Inspector::Protocol::ErrorStringOr<void> focus(Inspector::Protocol::DOM::NodeId);
     Inspector::Protocol::ErrorStringOr<void> setInspectedNode(Inspector::Protocol::DOM::NodeId);
     Inspector::Protocol::ErrorStringOr<void> setAllowEditingUserAgentShadowTrees(bool);
+    Inspector::Protocol::ErrorStringOr<std::tuple<String /* contentFrameId */, String /* ownerFrameId */>> describeNode(const String& objectId);
+    Inspector::Protocol::ErrorStringOr<void> scrollIntoViewIfNeeded(const String& objectId, RefPtr<JSON::Object>&& rect);
+    Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Inspector::Protocol::DOM::Quad>>> getContentQuads(const String& objectId);
+    Inspector::Protocol::ErrorStringOr<void> setInputFiles(const String& objectId, Ref<JSON::Array>&& files);
 
     // InspectorInstrumentation
     Inspector::Protocol::DOM::NodeId identifierForNode(Node&);
@@ -191,7 +197,7 @@ public:
     Node* nodeForId(Inspector::Protocol::DOM::NodeId);
     Inspector::Protocol::DOM::NodeId boundNodeId(const Node*);
 
-    RefPtr<Inspector::Protocol::Runtime::RemoteObject> resolveNode(Node*, const String& objectGroup);
+    RefPtr<Inspector::Protocol::Runtime::RemoteObject> resolveNode(Node*, const String& objectGroup, std::optional<int>&& contextId);
     bool handleMousePress();
     void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags);
     void inspect(Node*);
@@ -202,12 +208,15 @@ public:
     void reset();
 
     Node* assertNode(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId);
+    Node* assertNode(Inspector::Protocol::ErrorString&, std::optional<Inspector::Protocol::DOM::NodeId>&& nodeId, const String& objectId);
     Element* assertElement(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId);
     Document* assertDocument(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId);
 
     RefPtr<JSC::Breakpoint> 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<Inspector::Protocol::DOM::NodeId>&);
     
     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 4e3daf1ade47318795babaf852c2362b39949bdd..e84dc843dcd71b21cf27b50272c0051deb777d1f 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"
@@ -307,8 +309,8 @@ static Ref<Protocol::Network::Request> 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<uint8_t> bytes = request.httpBody()->flatten();
+        requestObject->setPostData(base64EncodeToString(bytes));
     }
     return requestObject;
 }
@@ -353,6 +355,8 @@ RefPtr<Protocol::Network::Response> InspectorNetworkAgent::buildObjectForResourc
         .setSource(responseSource(response.source()))
         .release();
 
+    responseObject->setRequestHeaders(buildObjectForHeaders(response.m_httpRequestHeaderFields));
+
     if (resourceLoader) {
         auto* metrics = response.deprecatedNetworkLoadMetricsOrNull();
         responseObject->setTiming(buildObjectForTiming(metrics ? *metrics : NetworkLoadMetrics::emptyMetrics(), *resourceLoader));
@@ -490,9 +494,15 @@ static InspectorPageAgent::ResourceType resourceTypeForLoadType(InspectorInstrum
 
 void InspectorNetworkAgent::willSendRequest(ResourceLoaderIdentifier identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse, const CachedResource* cachedResource)
 {
-    if (!cachedResource && loader)
-        cachedResource = InspectorPageAgent::cachedResource(loader->frame(), request.url());
-    willSendRequest(identifier, loader, request, redirectResponse, resourceTypeForCachedResource(cachedResource));
+    InspectorPageAgent::ResourceType resourceType;
+    if (request.initiatorIdentifier() == initiatorIdentifierForEventSource()) {
+        resourceType = InspectorPageAgent::EventSource;
+    } else {
+        if (!cachedResource && loader)
+            cachedResource = InspectorPageAgent::cachedResource(loader->frame(), request.url());
+        resourceType = resourceTypeForCachedResource(cachedResource);
+    }
+    willSendRequest(identifier, loader, request, redirectResponse, resourceType);
 }
 
 void InspectorNetworkAgent::willSendRequestOfType(ResourceLoaderIdentifier identifier, DocumentLoader* loader, ResourceRequest& request, InspectorInstrumentation::LoadType loadType)
@@ -1190,6 +1200,9 @@ Protocol::ErrorStringOr<void> 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));
@@ -1289,14 +1302,25 @@ Protocol::ErrorStringOr<void> InspectorNetworkAgent::interceptRequestWithRespons
     response.setHTTPStatusCode(status);
     response.setHTTPStatusText(statusText);
     HTTPHeaderMap explicitHeaders;
+    String setCookieValue;
     for (auto& header : headers.get()) {
         auto headerValue = header.value->asString();
-        if (!!headerValue)
+        if (equalIgnoringASCIICase(header.key, "Set-Cookie"))
+            setCookieValue = headerValue;
+        else if (!!headerValue)
             explicitHeaders.add(header.key, 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());
@@ -1337,6 +1361,12 @@ Protocol::ErrorStringOr<void> InspectorNetworkAgent::interceptRequestWithError(c
     return { };
 }
 
+Inspector::Protocol::ErrorStringOr<void> InspectorNetworkAgent::setEmulateOfflineState(bool offline)
+{
+    platformStrategies()->loaderStrategy()->setEmulateOfflineState(offline);
+    return { };
+}
+
 bool InspectorNetworkAgent::shouldTreatAsText(const String& mimeType)
 {
     return startsWithLettersIgnoringASCIICase(mimeType, "text/")
@@ -1378,6 +1408,12 @@ std::optional<String> InspectorNetworkAgent::textContentForCachedResource(Cached
     return std::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 8f6fbcc293aebf8b9d5c945d2829a1527b74bc7f..22a97f735adb973b0aef74e54a897d15eb0591b3 100644
--- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
@@ -34,6 +34,8 @@
 #include "InspectorInstrumentation.h"
 #include "InspectorPageAgent.h"
 #include "InspectorWebAgentBase.h"
+#include "ResourceError.h"
+#include "SharedBuffer.h"
 #include "WebSocket.h"
 #include <JavaScriptCore/InspectorBackendDispatchers.h>
 #include <JavaScriptCore/InspectorFrontendDispatchers.h>
@@ -72,6 +74,7 @@ public:
     static Ref<TextResourceDecoder> createTextDecoder(const String& mimeType, const String& textEncodingName);
     static std::optional<String> textContentForCachedResource(CachedResource&);
     static bool cachedResourceContent(CachedResource&, String* result, bool* base64Encoded);
+    static String initiatorIdentifierForEventSource();
 
     // InspectorAgentBase
     void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) final;
@@ -94,6 +97,7 @@ public:
     Inspector::Protocol::ErrorStringOr<void> interceptWithResponse(const Inspector::Protocol::Network::RequestId&, const String& content, bool base64Encoded, const String& mimeType, std::optional<int>&& status, const String& statusText, RefPtr<JSON::Object>&& headers) final;
     Inspector::Protocol::ErrorStringOr<void> interceptRequestWithResponse(const Inspector::Protocol::Network::RequestId&, const String& content, bool base64Encoded, const String& mimeType, int status, const String& statusText, Ref<JSON::Object>&& headers) final;
     Inspector::Protocol::ErrorStringOr<void> interceptRequestWithError(const Inspector::Protocol::Network::RequestId&, Inspector::Protocol::Network::ResourceErrorType) final;
+    Inspector::Protocol::ErrorStringOr<void> setEmulateOfflineState(bool offline) final;
 
     // InspectorInstrumentation
     void willRecalculateStyle();
diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
index 9b5cad959a8e6f2c2bf70e1aee14287459d06612..340468e16678ffd65256f29a0126692c616c25de 100644
--- a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
@@ -32,20 +32,28 @@
 #include "config.h"
 #include "InspectorPageAgent.h"
 
+#include "AXObjectCache.h"
+#include "BackForwardController.h"
 #include "CachedResource.h"
 #include "CachedResourceLoader.h"
+#include "CompositionHighlight.h"
 #include "Cookie.h"
 #include "CookieJar.h"
+#include "CustomHeaderFields.h"
 #include "DOMWrapperWorld.h"
 #include "DocumentInlines.h"
 #include "DocumentLoader.h"
+#include "Editor.h"
 #include "ElementInlines.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"
@@ -56,19 +64,30 @@
 #include "MIMETypeRegistry.h"
 #include "MemoryCache.h"
 #include "Page.h"
+#include "PageRuntimeAgent.h"
 #include "RenderObject.h"
 #include "RenderTheme.h"
+#include "RuntimeEnabledFeatures.h"
+#include "SimpleRange.h"
 #include "ScriptController.h"
 #include "ScriptSourceCode.h"
+#include "ScriptState.h"
 #include "SecurityOrigin.h"
 #include "Settings.h"
 #include "StyleScope.h"
 #include <pal/text/TextEncoding.h>
+#include "TextIterator.h"
+#include "TypingCommand.h"
 #include "UserGestureIndicator.h"
 #include <JavaScriptCore/ContentSearchUtilities.h>
 #include <JavaScriptCore/IdentifiersFactory.h>
+#include <JavaScriptCore/InjectedScriptManager.h>
 #include <JavaScriptCore/RegularExpression.h>
+#include <wtf/DateMath.h>
 #include <wtf/ListHashSet.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/Ref.h>
+#include <wtf/RefPtr.h>
 #include <wtf/Stopwatch.h>
 #include <wtf/text/Base64.h>
 #include <wtf/text/StringBuilder.h>
@@ -81,11 +100,15 @@
 #include "LegacyWebArchive.h"
 #endif
 
-
 namespace WebCore {
 
 using namespace Inspector;
 
+static HashMap<String, Ref<DOMWrapperWorld>>& createdUserWorlds() {
+    static NeverDestroyed<HashMap<String, Ref<DOMWrapperWorld>>> nameToWorld;
+    return nameToWorld;
+}
+
 static bool decodeBuffer(const uint8_t* buffer, unsigned size, const String& textEncodingName, String* result)
 {
     if (buffer) {
@@ -235,6 +258,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)
@@ -322,6 +347,7 @@ InspectorPageAgent::InspectorPageAgent(PageAgentContext& context, InspectorClien
     , m_frontendDispatcher(makeUnique<Inspector::PageFrontendDispatcher>(context.frontendRouter))
     , m_backendDispatcher(Inspector::PageBackendDispatcher::create(context.backendDispatcher, this))
     , m_inspectedPage(context.inspectedPage)
+    , m_injectedScriptManager(context.injectedScriptManager)
     , m_client(client)
     , m_overlay(overlay)
 {
@@ -353,12 +379,20 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::enable()
     defaultAppearanceDidChange(m_inspectedPage.defaultUseDarkAppearance());
 #endif
 
+    if (!createdUserWorlds().isEmpty()) {
+        Vector<DOMWrapperWorld*> worlds;
+        for (const auto& world : createdUserWorlds().values())
+            worlds.append(world.ptr());
+        ensureUserWorldsExistInAllFrames(worlds);
+    }
     return { };
 }
 
 Protocol::ErrorStringOr<void> InspectorPageAgent::disable()
 {
     m_instrumentingAgents.setEnabledPageAgent(nullptr);
+    m_interceptFileChooserDialog = false;
+    m_bypassCSP = false;
 
     setShowPaintRects(false);
 #if !PLATFORM(IOS_FAMILY)
@@ -407,6 +441,22 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::reload(std::optional<bool>&& i
     return { };
 }
 
+Protocol::ErrorStringOr<void> InspectorPageAgent::goBack()
+{
+    if (!m_inspectedPage.backForward().goBack())
+        return makeUnexpected("Failed to go back"_s);
+
+    return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::goForward()
+{
+    if (!m_inspectedPage.backForward().goForward())
+        return makeUnexpected("Failed to go forward"_s);
+
+    return { };
+}
+
 Protocol::ErrorStringOr<void> InspectorPageAgent::navigate(const String& url)
 {
     UserGestureIndicator indicator { ProcessingUserGesture };
@@ -427,6 +477,13 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::overrideUserAgent(const String
     return { };
 }
 
+Protocol::ErrorStringOr<void> InspectorPageAgent::overridePlatform(const String& value)
+{
+    m_platformOverride = value;
+
+    return { };
+}
+
 Protocol::ErrorStringOr<void> InspectorPageAgent::overrideSetting(Protocol::Page::Setting setting, std::optional<bool>&& value)
 {
     auto& inspectedPageSettings = m_inspectedPage.settings();
@@ -440,6 +497,12 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::overrideSetting(Protocol::Page
         inspectedPageSettings.setAuthorAndUserStylesEnabledInspectorOverride(value);
         return { };
 
+#if ENABLE(DEVICE_ORIENTATION)
+    case Protocol::Page::Setting::DeviceOrientationEventEnabled:
+        inspectedPageSettings.setDeviceOrientationEventEnabled(value.value_or(false));
+        return { };
+#endif
+
     case Protocol::Page::Setting::ICECandidateFilteringEnabled:
         inspectedPageSettings.setICECandidateFilteringEnabledInspectorOverride(value);
         return { };
@@ -465,6 +528,36 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::overrideSetting(Protocol::Page
         inspectedPageSettings.setNeedsSiteSpecificQuirksInspectorOverride(value);
         return { };
 
+#if ENABLE(NOTIFICATIONS)
+    case Protocol::Page::Setting::NotificationsEnabled:
+        inspectedPageSettings.setNotificationsEnabled(value.value_or(false));
+        return { };
+#endif
+
+#if ENABLE(FULLSCREEN_API)
+    case Protocol::Page::Setting::FullScreenEnabled:
+        inspectedPageSettings.setFullScreenEnabled(value.value_or(false));
+        return { };
+#endif
+
+#if ENABLE(INPUT_TYPE_MONTH)
+    case Protocol::Page::Setting::InputTypeMonthEnabled:
+        inspectedPageSettings.setInputTypeMonthEnabled(value.value_or(false));
+        return { };
+#endif
+
+#if ENABLE(INPUT_TYPE_WEEK)
+    case Protocol::Page::Setting::InputTypeWeekEnabled:
+        inspectedPageSettings.setInputTypeWeekEnabled(value.value_or(false));
+        return { };
+#endif
+
+#if ENABLE(POINTER_LOCK)
+    case Protocol::Page::Setting::PointerLockEnabled:
+        inspectedPageSettings.setPointerLockEnabled(value.value_or(false));
+        return { };
+#endif
+
     case Protocol::Page::Setting::ScriptEnabled:
         inspectedPageSettings.setScriptEnabledInspectorOverride(value);
         return { };
@@ -477,6 +570,12 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::overrideSetting(Protocol::Page
         inspectedPageSettings.setShowRepaintCounterInspectorOverride(value);
         return { };
 
+#if ENABLE(MEDIA_STREAM)
+    case Protocol::Page::Setting::SpeechRecognitionEnabled:
+        inspectedPageSettings.setSpeechRecognitionEnabled(value.value_or(false));
+        return { };
+#endif
+
     case Protocol::Page::Setting::WebRTCEncryptionEnabled:
         inspectedPageSettings.setWebRTCEncryptionEnabledInspectorOverride(value);
         return { };
@@ -697,9 +796,13 @@ Protocol::ErrorStringOr<std::tuple<String, bool /* base64Encoded */>> InspectorP
     return { { content, base64Encoded } };
 }
 
-Protocol::ErrorStringOr<void> InspectorPageAgent::setBootstrapScript(const String& source)
+Protocol::ErrorStringOr<void> InspectorPageAgent::setBootstrapScript(const String& source, const String& worldName)
 {
-    m_bootstrapScript = source;
+    String key = worldName.isNull() ? emptyString() : worldName;
+    if (source.isEmpty())
+        m_worldNameToBootstrapScript.remove(key);
+    else
+        m_worldNameToBootstrapScript.set(key, source);
 
     return { };
 }
@@ -802,15 +905,16 @@ Protocol::ErrorStringOr<void> 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)
@@ -818,13 +922,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)
@@ -836,20 +950,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, frame);
-        return identifier;
-    }).iterator->value;
+
+    String identifier = globalIDForFrame(*frame);
+    m_identifierToFrame.set(identifier, 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)
@@ -860,11 +972,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));
@@ -885,6 +992,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)
 {
@@ -894,13 +1007,22 @@ void InspectorPageAgent::defaultAppearanceDidChange(bool useDarkAppearance)
 
 void InspectorPageAgent::didClearWindowObjectInWorld(Frame& frame, DOMWrapperWorld& world)
 {
-    if (&world != &mainThreadNormalWorld())
+    if (m_worldNameToBootstrapScript.isEmpty())
         return;
 
-    if (m_bootstrapScript.isEmpty())
+    if (world.name().isEmpty() && &world != &mainThreadNormalWorld())
+       return;
+
+    String worldName = world.name();
+    // Null string cannot be used as a key.
+    if (worldName.isNull())
+        worldName = emptyString();
+
+    if (!m_worldNameToBootstrapScript.contains(worldName))
         return;
 
-    frame.script().evaluateIgnoringException(ScriptSourceCode(m_bootstrapScript, URL { URL(), "web-inspector://bootstrap.js"_s }));
+    String bootstrapScript = m_worldNameToBootstrapScript.get(worldName);
+    frame.script().evaluateInWorldIgnoringException(ScriptSourceCode(bootstrapScript, URL { URL(), "web-inspector://bootstrap.js"_s }), world);
 }
 
 void InspectorPageAgent::didPaint(RenderObject& renderer, const LayoutRect& rect)
@@ -944,6 +1066,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<Protocol::Page::Frame> InspectorPageAgent::buildObjectForFrame(Frame* frame)
 {
     ASSERT_ARG(frame, frame);
@@ -1057,6 +1225,12 @@ void InspectorPageAgent::applyUserAgentOverride(String& userAgent)
         userAgent = m_userAgentOverride;
 }
 
+void InspectorPageAgent::applyPlatformOverride(String& platform)
+{
+    if (!m_platformOverride.isEmpty())
+        platform = m_platformOverride;
+}
+
 void InspectorPageAgent::applyEmulatedMedia(String& media)
 {
     if (!m_emulatedMedia.isEmpty())
@@ -1080,11 +1254,13 @@ Protocol::ErrorStringOr<String> InspectorPageAgent::snapshotNode(Protocol::DOM::
     return snapshot->toDataURL("image/png"_s, std::nullopt, PreserveResolution::Yes);
 }
 
-Protocol::ErrorStringOr<String> InspectorPageAgent::snapshotRect(int x, int y, int width, int height, Protocol::Page::CoordinateSystem coordinateSystem)
+Protocol::ErrorStringOr<String> InspectorPageAgent::snapshotRect(int x, int y, int width, int height, Protocol::Page::CoordinateSystem coordinateSystem, std::optional<bool>&& omitDeviceScaleFactor)
 {
     SnapshotOptions options { { }, PixelFormat::BGRA8, DestinationColorSpace::SRGB() };
     if (coordinateSystem == Protocol::Page::CoordinateSystem::Viewport)
         options.flags.add(SnapshotFlags::InViewCoordinates);
+    if (omitDeviceScaleFactor.has_value() && *omitDeviceScaleFactor)
+        options.flags.add(SnapshotFlags::OmitDeviceScaleFactor);
 
     IntRect rectangle(x, y, width, height);
     auto snapshot = snapshotFrameRect(m_inspectedPage.mainFrame(), rectangle, WTFMove(options));
@@ -1095,6 +1271,47 @@ Protocol::ErrorStringOr<String> InspectorPageAgent::snapshotRect(int x, int y, i
     return snapshot->toDataURL("image/png"_s, std::nullopt, PreserveResolution::Yes);
 }
 
+Protocol::ErrorStringOr<void> InspectorPageAgent::setForcedReducedMotion(std::optional<Protocol::Page::ReducedMotion>&& reducedMotion)
+{
+    if (!reducedMotion) {
+        m_inspectedPage.setUseReducedMotionOverride(std::nullopt);
+        return { };
+    }
+
+    switch (*reducedMotion) {
+        case Protocol::Page::ReducedMotion::Reduce:
+            m_inspectedPage.setUseReducedMotionOverride(true);
+            return { };
+        case Protocol::Page::ReducedMotion::NoPreference:
+            m_inspectedPage.setUseReducedMotionOverride(false);
+            return { };
+    }
+
+    ASSERT_NOT_REACHED();
+    return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setTimeZone(const String& timeZone)
+{
+    bool success = WTF::setTimeZoneForAutomation(timeZone);
+    if (!success)
+        return makeUnexpected("Invalid time zone " + timeZone);
+
+    return { };
+}
+
+Protocol::ErrorStringOr<void> 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<String> InspectorPageAgent::archive()
 {
@@ -1107,7 +1324,6 @@ Protocol::ErrorStringOr<String> InspectorPageAgent::archive()
 }
 #endif
 
-#if !PLATFORM(COCOA)
 Protocol::ErrorStringOr<void> InspectorPageAgent::setScreenSizeOverride(std::optional<int>&& width, std::optional<int>&& height)
 {
     if (width.has_value() != height.has_value())
@@ -1122,6 +1338,630 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::setScreenSizeOverride(std::opt
     m_inspectedPage.mainFrame().setOverrideScreenSize(FloatSize(width.value_or(0), height.value_or(0)));
     return { };
 }
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::insertText(const String& text)
+{
+    UserGestureIndicator indicator { ProcessingUserGesture };
+    Frame& frame = m_inspectedPage.focusController().focusedOrMainFrame();
+
+    if (frame.editor().hasComposition()) {
+        frame.editor().confirmComposition(text);
+    } else {
+        Document* focusedDocument = frame.document();
+        TypingCommand::insertText(*focusedDocument, text, 0);
+    }
+    return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setComposition(const String& text, int selectionStart, int selectionLength, std::optional<int>&& replacementStart, std::optional<int>&& replacementLength)
+{
+    Frame& frame = m_inspectedPage.focusController().focusedOrMainFrame();
+
+    UserGestureIndicator indicator { ProcessingUserGesture };
+
+    if (!frame.selection().selection().isContentEditable())
+        return { };
+    if (replacementStart) {
+        WebCore::CharacterRange range { static_cast<uint64_t>(*replacementStart), replacementLength ? static_cast<uint64_t>(*replacementLength) : 0 };
+        auto* element = frame.selection().rootEditableElementOrDocumentElement();
+        if (element)
+            frame.selection().setSelection(VisibleSelection(resolveCharacterRange(makeRangeSelectingNodeContents(*element), range)));
+    }
+    frame.editor().setComposition(text, { }, { }, static_cast<uint64_t>(selectionStart), selectionStart + selectionLength);
+    return { };
+}
+
+static String roleFromObject(RefPtr<AXCoreObject> 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::Model:
+            return "Model";
+        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<Inspector::Protocol::Page::AXNode> snapshotForAXObject(RefPtr<AXCoreObject> 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->children().isEmpty()) {
+        Ref<JSON::ArrayOf<Inspector::Protocol::Page::AXNode>> children = JSON::ArrayOf<Inspector::Protocol::Page::AXNode>::create();
+        for (auto& childObject : axObject->children())
+            children->addItem(snapshotForAXObject(childObject, nodeToFind));
+        axNode->setChildren(WTFMove(children));
+    }
+    return axNode;
+}
+
+
+Protocol::ErrorStringOr<Ref<Protocol::Page::AXNode>> InspectorPageAgent::accessibilitySnapshot(const String& objectId)
+{
+    if (!WebCore::AXObjectCache::accessibilityEnabled())
+        WebCore::AXObjectCache::enableAccessibility();
+    RefPtr document = 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<Inspector::Protocol::Page::AXNode> axNode = snapshotForAXObject(RefPtr { axObject }, node);
+    m_doingAccessibilitySnapshot = false;
+    return axNode;
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setInterceptFileChooserDialog(bool enabled)
+{
+    m_interceptFileChooserDialog = enabled;
+    return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setDefaultBackgroundColorOverride(RefPtr<JSON::Object>&& 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(std::optional<Color>());
+        return { };
+    }
+
+    view->updateBackgroundRecursively(InspectorDOMAgent::parseColor(WTFMove(color)));
+    return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::createUserWorld(const String& name)
+{
+    if (createdUserWorlds().contains(name))
+        return makeUnexpected("World with the given name already exists"_s);
+
+    Ref<DOMWrapperWorld> world = ScriptController::createWorld(name, ScriptController::WorldType::User);
+    ensureUserWorldsExistInAllFrames({world.ptr()});
+    createdUserWorlds().set(name, WTFMove(world));
+    return { };
+}
+
+void InspectorPageAgent::ensureUserWorldsExistInAllFrames(const Vector<DOMWrapperWorld*>& worlds)
+{
+    for (Frame* frame = &m_inspectedPage.mainFrame(); frame; frame = frame->tree().traverseNext()) {
+        for (auto* world : worlds)
+            frame->windowProxy().jsWindowProxy(*world)->window();
+    }
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setBypassCSP(bool enabled)
+{
+    m_bypassCSP = enabled;
+    return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::crash()
+{
+    CRASH();
+    return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setOrientationOverride(std::optional<int>&& 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
+}
+
+static std::optional<FloatBoxExtent> parseInsets(RefPtr<JSON::Object>&& insets)
+{
+    std::optional<double> top = insets->getDouble("top");
+    std::optional<double> right = insets->getDouble("right");
+    std::optional<double> bottom = insets->getDouble("bottom");
+    std::optional<double> left = insets->getDouble("left");
+    if (top && right && bottom && left)
+        return FloatBoxExtent(static_cast<float>(*top), static_cast<float>(*right), static_cast<float>(*bottom), static_cast<float>(*left));
+    return std::optional<FloatBoxExtent>();
+}
+
+static std::optional<FloatRect> parseRect(RefPtr<JSON::Object>&& insets)
+{
+    std::optional<double> x = insets->getDouble("x");
+    std::optional<double> y = insets->getDouble("y");
+    std::optional<double> width = insets->getDouble("width");
+    std::optional<double> height = insets->getDouble("height");
+    if (x && y && width && height)
+        return FloatRect(static_cast<float>(*x), static_cast<float>(*y), static_cast<float>(*width), static_cast<float>(*height));
+    return std::optional<FloatRect>();
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setVisibleContentRects(RefPtr<JSON::Object>&& unobscuredContentRect, RefPtr<JSON::Object>&& contentInsets, RefPtr<JSON::Object>&& obscuredInsets, RefPtr<JSON::Object>&& unobscuredInsets)
+{
+    FrameView* view = m_inspectedPage.mainFrame().view();
+    if (!view)
+        return makeUnexpected("Internal error: No frame view to set content rects for"_s);
+
+    if (unobscuredContentRect) {
+        std::optional<FloatRect> ucr = parseRect(WTFMove(unobscuredContentRect));
+        if (!ucr)
+            return makeUnexpected("Invalid unobscured content rect");
+
+        view->setUnobscuredContentSize(FloatSize(ucr->width(), ucr->height()));
+    }
+
+    if (contentInsets) {
+        std::optional<FloatBoxExtent> ci = parseInsets(WTFMove(contentInsets));
+        if (!ci)
+            return makeUnexpected("Invalid content insets");
+
+        m_inspectedPage.setContentInsets(*ci);
+    }
+
+    if (obscuredInsets) {
+        std::optional<FloatBoxExtent> oi = parseInsets(WTFMove(obscuredInsets));
+        if (!oi)
+            return makeUnexpected("Invalid obscured insets");
+
+        m_inspectedPage.setObscuredInsets(*oi);
+    }
+
+    if (unobscuredInsets) {
+        std::optional<FloatBoxExtent> ui = parseInsets(WTFMove(unobscuredInsets));
+        if (!ui)
+            return makeUnexpected("Invalid unobscured insets");
+
+        m_inspectedPage.setUnobscuredSafeAreaInsets(*ui);
+    }
+    return {};
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::updateScrollingState()
+{
+    auto* scrollingCoordinator = m_inspectedPage.scrollingCoordinator();
+    if (!scrollingCoordinator)
+        return {};
+    scrollingCoordinator->commitTreeStateIfNeeded();
+    return {};
+}
 
 } // namespace WebCore
diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.h b/Source/WebCore/inspector/agents/InspectorPageAgent.h
index b51addb1bd8f2cce69560799cd1d952d2de42838..ab460cc0c30020ab6ae53d15e8f231913cb59703 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 <JavaScriptCore/InspectorBackendDispatchers.h>
 #include <JavaScriptCore/InspectorFrontendDispatchers.h>
 #include <wtf/HashMap.h>
 #include <wtf/Seconds.h>
 #include <wtf/text/WTFString.h>
 
+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<SharedBuffer>&&, const String& textEncodingName, bool withBase64Encode, String* result);
     static Vector<CachedResource*> cachedResourcesForFrame(Frame*);
     static void resourceContent(Inspector::Protocol::ErrorString&, Frame*, const URL&, String* result, bool* base64Encoded);
@@ -95,15 +103,18 @@ public:
     Inspector::Protocol::ErrorStringOr<void> enable();
     Inspector::Protocol::ErrorStringOr<void> disable();
     Inspector::Protocol::ErrorStringOr<void> reload(std::optional<bool>&& ignoreCache, std::optional<bool>&& revalidateAllResources);
+    Inspector::Protocol::ErrorStringOr<void> goBack();
+    Inspector::Protocol::ErrorStringOr<void> goForward();
     Inspector::Protocol::ErrorStringOr<void> navigate(const String& url);
     Inspector::Protocol::ErrorStringOr<void> overrideUserAgent(const String&);
+    Inspector::Protocol::ErrorStringOr<void> overridePlatform(const String&);
     Inspector::Protocol::ErrorStringOr<void> overrideSetting(Inspector::Protocol::Page::Setting, std::optional<bool>&& value);
     Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Inspector::Protocol::Page::Cookie>>> getCookies();
     Inspector::Protocol::ErrorStringOr<void> setCookie(Ref<JSON::Object>&&);
     Inspector::Protocol::ErrorStringOr<void> deleteCookie(const String& cookieName, const String& url);
     Inspector::Protocol::ErrorStringOr<Ref<Inspector::Protocol::Page::FrameResourceTree>> getResourceTree();
     Inspector::Protocol::ErrorStringOr<std::tuple<String, bool /* base64Encoded */>> getResourceContent(const Inspector::Protocol::Network::FrameId&, const String& url);
-    Inspector::Protocol::ErrorStringOr<void> setBootstrapScript(const String& source);
+    Inspector::Protocol::ErrorStringOr<void> setBootstrapScript(const String& source, const String& worldName);
     Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Inspector::Protocol::GenericTypes::SearchMatch>>> searchInResource(const Inspector::Protocol::Network::FrameId&, const String& url, const String& query, std::optional<bool>&& caseSensitive, std::optional<bool>&& isRegex, const Inspector::Protocol::Network::RequestId&);
     Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Inspector::Protocol::Page::SearchResult>>> searchInResources(const String&, std::optional<bool>&& caseSensitive, std::optional<bool>&& isRegex);
 #if !PLATFORM(IOS_FAMILY)
@@ -114,35 +125,55 @@ public:
 #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
     Inspector::Protocol::ErrorStringOr<void> setForcedAppearance(std::optional<Inspector::Protocol::Page::Appearance>&&);
 #endif
+    Inspector::Protocol::ErrorStringOr<void> setForcedReducedMotion(std::optional<Inspector::Protocol::Page::ReducedMotion>&&);
+    Inspector::Protocol::ErrorStringOr<void> setTimeZone(const String&);
+    Inspector::Protocol::ErrorStringOr<void> setTouchEmulationEnabled(bool);
     Inspector::Protocol::ErrorStringOr<String> snapshotNode(Inspector::Protocol::DOM::NodeId);
-    Inspector::Protocol::ErrorStringOr<String> snapshotRect(int x, int y, int width, int height, Inspector::Protocol::Page::CoordinateSystem);
+    Inspector::Protocol::ErrorStringOr<String> snapshotRect(int x, int y, int width, int height, Inspector::Protocol::Page::CoordinateSystem, std::optional<bool>&& omitDeviceScaleFactor);
 #if ENABLE(WEB_ARCHIVE) && USE(CF)
     Inspector::Protocol::ErrorStringOr<String> archive();
 #endif
-#if !PLATFORM(COCOA)
     Inspector::Protocol::ErrorStringOr<void> setScreenSizeOverride(std::optional<int>&& width, std::optional<int>&& height);
-#endif
+
+    Inspector::Protocol::ErrorStringOr<void> insertText(const String& text);
+    Inspector::Protocol::ErrorStringOr<void> setComposition(const String& text, int selectionStart, int selectionLength, std::optional<int>&& replacementStart, std::optional<int>&& replacementLength);
+    Inspector::Protocol::ErrorStringOr<Ref<Inspector::Protocol::Page::AXNode>> accessibilitySnapshot(const String& objectId);
+    Inspector::Protocol::ErrorStringOr<void> setInterceptFileChooserDialog(bool enabled);
+    Inspector::Protocol::ErrorStringOr<void> setDefaultBackgroundColorOverride(RefPtr<JSON::Object>&&);
+    Inspector::Protocol::ErrorStringOr<void> createUserWorld(const String&);
+    Inspector::Protocol::ErrorStringOr<void> setBypassCSP(bool);
+    Inspector::Protocol::ErrorStringOr<void> crash();
+    Inspector::Protocol::ErrorStringOr<void> setOrientationOverride(std::optional<int>&& angle);
+    Inspector::Protocol::ErrorStringOr<void> setVisibleContentRects(RefPtr<JSON::Object>&& unobscuredContentRect, RefPtr<JSON::Object>&& contentInsets, RefPtr<JSON::Object>&& obscuredInsets, RefPtr<JSON::Object>&& unobscuredInsets);
+    Inspector::Protocol::ErrorStringOr<void> updateScrollingState();
 
     // 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
     void applyUserAgentOverride(String&);
+    void applyPlatformOverride(String&);
     void applyEmulatedMedia(String&);
     void didClearWindowObjectInWorld(Frame&, DOMWrapperWorld&);
     void didPaint(RenderObject&, const LayoutRect&);
     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 +182,7 @@ public:
 
 private:
     double timestamp();
+    void ensureUserWorldsExistInAllFrames(const Vector<DOMWrapperWorld*>&);
 
     static bool mainResourceContent(Frame*, bool withBase64Encode, String* result);
     static bool dataContent(const uint8_t* data, unsigned size, const String& textEncodingName, bool withBase64Encode, String* result);
@@ -162,18 +194,20 @@ private:
     RefPtr<Inspector::PageBackendDispatcher> 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<Frame*, String> m_frameToIdentifier;
     HashMap<String, WeakPtr<Frame>> m_identifierToFrame;
-    HashMap<DocumentLoader*, String> m_loaderToIdentifier;
+    HashMap<String, String> m_worldNameToBootstrapScript;
     String m_userAgentOverride;
+    String m_platformOverride;
     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 c13374b161eebbf67860a0009bec14a35c53299f..aed9a5566b52b56cf93d660872b54e20eb9c44f1 100644
--- a/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp
@@ -168,7 +168,11 @@ void InspectorWorkerAgent::connectToWorkerInspectorProxy(WorkerInspectorProxy& p
 
     m_connectedProxies.set(proxy.identifier(), proxy);
 
-    m_frontendDispatcher->workerCreated(proxy.identifier(), proxy.url().string(), proxy.name());
+    ASSERT(is<Document>(proxy.scriptExecutionContext()));
+    Document& document = downcast<Document>(*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 55d9518494195b96df165a94c1c2963adceb8395..98035b606587337e5fdacd31459a196fa7c28702 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"
@@ -69,7 +70,11 @@ bool PageDebuggerAgent::enabled() const
 
 Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, std::optional<bool> /* wasThrown */, std::optional<int> /* savedResultIndex */>> PageDebuggerAgent::evaluateOnCallFrame(const Protocol::Debugger::CallFrameId& callFrameId, const String& expression, const String& objectGroup, std::optional<bool>&& includeCommandLineAPI, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& saveResult, std::optional<bool>&& 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));
 }
@@ -121,8 +126,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<UserGestureEmulationScope>(m_inspectedPage, true));
+        m_breakpointActionUserGestureEmulationScopeStack.append(makeUniqueRef<UserGestureEmulationScope>(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 b32f3f699c2d2a377289760b245ac81784102458..48f0fab7f07bfc2b2408764e9adec252cc380705 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, std::optional<Protocol::Runtime::ExecutionContextId>&& executionContextId)
 {
     if (!executionContextId) {
@@ -191,14 +202,24 @@ void PageRuntimeAgent::notifyContextCreated(const Protocol::Network::FrameId& fr
 
 Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, std::optional<bool> /* wasThrown */, std::optional<int> /* savedResultIndex */>> PageRuntimeAgent::evaluate(const String& expression, const String& objectGroup, std::optional<bool>&& includeCommandLineAPI, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<Protocol::Runtime::ExecutionContextId>&& executionContextId, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& saveResult, std::optional<bool>&& emulateUserGesture)
 {
-    UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture);
+    String errorString;
+    InjectedScript injectedScript = injectedScriptForEval(errorString, std::optional<Protocol::Runtime::ExecutionContextId>(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<std::tuple<Ref<Protocol::Runtime::RemoteObject>, std::optional<bool> /* wasThrown */>> PageRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& expression, RefPtr<JSON::Array>&& optionalArguments, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& emulateUserGesture)
+void PageRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& expression, RefPtr<JSON::Array>&& optionalArguments, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& emulateUserGesture, std::optional<bool>&& awaitPromise, Ref<CallFunctionOnCallback>&& callback)
 {
-    UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture);
-    return InspectorRuntimeAgent::callFunctionOn(objectId, expression, WTFMove(optionalArguments), WTFMove(doNotPauseOnExceptionsAndMuteConsole), WTFMove(returnByValue), WTFMove(generatePreview), WTFMove(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), WTFMove(awaitPromise), WTFMove(callback));
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
index 6aba3a2c6e8bbb7a0bca4f07824cf4de8ce36f8e..537e3b34d6405e412bf0e2350909c9afda06bed8 100644
--- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
+++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
@@ -54,25 +54,25 @@ public:
     ~PageRuntimeAgent();
 
     // RuntimeBackendDispatcherHandler
-    Inspector::Protocol::ErrorStringOr<void> enable();
-    Inspector::Protocol::ErrorStringOr<void> disable();
-    Inspector::Protocol::ErrorStringOr<std::tuple<Ref<Inspector::Protocol::Runtime::RemoteObject>, std::optional<bool> /* wasThrown */, std::optional<int> /* savedResultIndex */>> evaluate(const String& expression, const String& objectGroup, std::optional<bool>&& includeCommandLineAPI, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<Inspector::Protocol::Runtime::ExecutionContextId>&&, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& saveResult, std::optional<bool>&& emulateUserGesture);
-    Inspector::Protocol::ErrorStringOr<std::tuple<Ref<Inspector::Protocol::Runtime::RemoteObject>, std::optional<bool> /* wasThrown */>> callFunctionOn(const Inspector::Protocol::Runtime::RemoteObjectId&, const String& expression, RefPtr<JSON::Array>&& arguments, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& emulateUserGesture);
+    Inspector::Protocol::ErrorStringOr<void> enable() override;
+    Inspector::Protocol::ErrorStringOr<void> disable() override;
+    Inspector::Protocol::ErrorStringOr<std::tuple<Ref<Inspector::Protocol::Runtime::RemoteObject>, std::optional<bool> /* wasThrown */, std::optional<int> /* savedResultIndex */>> evaluate(const String& expression, const String& objectGroup, std::optional<bool>&& includeCommandLineAPI, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<Inspector::Protocol::Runtime::ExecutionContextId>&&, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& saveResult, std::optional<bool>&& emulateUserGesture) override;
+    void callFunctionOn(const Inspector::Protocol::Runtime::RemoteObjectId&, const String& functionDeclaration, RefPtr<JSON::Array>&& arguments, std::optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, std::optional<bool>&& returnByValue, std::optional<bool>&& generatePreview, std::optional<bool>&& emulateUserGesture, std::optional<bool>&& awaitPromise, Ref<CallFunctionOnCallback>&&) override;
 
     // InspectorInstrumentation
     void frameNavigated(Frame&);
     void didClearWindowObjectInWorld(Frame&, DOMWrapperWorld&);
+    void didReceiveMainResourceError(Frame&);
 
 private:
-    Inspector::InjectedScript injectedScriptForEval(Inspector::Protocol::ErrorString&, std::optional<Inspector::Protocol::Runtime::ExecutionContextId>&&);
-    void muteConsole();
-    void unmuteConsole();
+    Inspector::InjectedScript injectedScriptForEval(Inspector::Protocol::ErrorString&, std::optional<Inspector::Protocol::Runtime::ExecutionContextId>&&) override;
+    void muteConsole() override;
+    void unmuteConsole() override;
     void reportExecutionContextCreation();
     void notifyContextCreated(const Inspector::Protocol::Network::FrameId&, JSC::JSGlobalObject*, const DOMWrapperWorld&, SecurityOrigin* = nullptr);
 
     std::unique_ptr<Inspector::RuntimeFrontendDispatcher> m_frontendDispatcher;
     RefPtr<Inspector::RuntimeBackendDispatcher> 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 8699436e3f962b465b47aebebd601ee90152ef83..35fbd46627f68d9ebac52500bc560d4fd9866166 100644
--- a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp
+++ b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp
@@ -38,9 +38,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 ? std::optional<ProcessingUserGestureState>(ProcessingUserGesture) : std::nullopt)
+    , m_gestureIndicator(emulateUserGesture ? std::optional<ProcessingUserGestureState>(ProcessingUserGesture) : std::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/layout/integration/LayoutIntegrationLineLayout.cpp b/Source/WebCore/layout/integration/LayoutIntegrationLineLayout.cpp
index 74c38ea363a9d0090e1dbda9740ef680d0052d49..432d939c41f3d6fbf673e79b95df5d225174101d 100644
--- a/Source/WebCore/layout/integration/LayoutIntegrationLineLayout.cpp
+++ b/Source/WebCore/layout/integration/LayoutIntegrationLineLayout.cpp
@@ -277,7 +277,7 @@ void LineLayout::updateFormattingRootGeometryAndInvalidate()
 
     auto updateGeometry = [&](auto& root) {
         root.setContentBoxWidth(flow.contentLogicalWidth());
-        root.setPadding(Layout::Edges { { flow.paddingStart(), flow.paddingEnd() }, { flow.paddingBefore(), flow.paddingAfter() } });
+	root.setPadding(Layout::Edges { { flow.paddingStart(), flow.paddingEnd() }, { flow.paddingBefore(), flow.paddingAfter() } });
         root.setBorder(Layout::Edges { { flow.borderStart(), flow.borderEnd() }, { flow.borderBefore(), flow.borderAfter() } });
         root.setHorizontalMargin({ });
         root.setVerticalMargin({ });
diff --git a/Source/WebCore/loader/CookieJar.h b/Source/WebCore/loader/CookieJar.h
index 982691dd2dfe2f65201370a12302b5086703c126..4af72beb3b1405ffac78e89e7fbb2b14d6647903 100644
--- a/Source/WebCore/loader/CookieJar.h
+++ b/Source/WebCore/loader/CookieJar.h
@@ -43,6 +43,7 @@ struct CookieRequestHeaderFieldProxy;
 class NetworkStorageSession;
 class StorageSessionProvider;
 struct SameSiteInfo;
+class ResourceLoader;
 
 class WEBCORE_EXPORT CookieJar : public RefCounted<CookieJar> {
 public:
@@ -66,6 +67,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&, IsForDOMCookieAccess = IsForDOMCookieAccess::No);
diff --git a/Source/WebCore/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp
index cf6ccf2bd089250c603fd04b74c3ec8c0e49c4f1..36cee6b7de987d793c763dce71ec141116a4ded0 100644
--- a/Source/WebCore/loader/DocumentLoader.cpp
+++ b/Source/WebCore/loader/DocumentLoader.cpp
@@ -1468,8 +1468,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 f7f3f3844f18447be8dd7b82d3a4435002216762..b445c8c291b1ffb7b05d0a1e348d42cdff54734c 100644
--- a/Source/WebCore/loader/DocumentLoader.h
+++ b/Source/WebCore/loader/DocumentLoader.h
@@ -169,9 +169,13 @@ public:
 
     WEBCORE_EXPORT virtual void detachFromFrame();
 
+    virtual void replacedByFragmentNavigation(Frame&) { }
+
     WEBCORE_EXPORT FrameLoader* frameLoader() const;
     WEBCORE_EXPORT SubresourceLoader* mainResourceLoader() const;
     WEBCORE_EXPORT RefPtr<SharedBuffer> 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 6c5ee3a9b31ae8b84db920b66ebf214f26ec9ad6..a9b3e56a72d68ebe3a5dc73a2082c8b0b0f9bb06 100644
--- a/Source/WebCore/loader/FrameLoader.cpp
+++ b/Source/WebCore/loader/FrameLoader.cpp
@@ -1154,6 +1154,7 @@ void FrameLoader::loadInSameDocument(const URL& url, SerializedScriptValue* stat
     }
 
     m_client->dispatchDidNavigateWithinPage();
+    InspectorInstrumentation::didNavigateWithinPage(m_frame);
 
     m_frame.document()->statePopped(stateObject ? Ref<SerializedScriptValue> { *stateObject } : SerializedScriptValue::nullValue());
     m_client->dispatchDidPopStateWithinPage();
@@ -1481,6 +1482,7 @@ void FrameLoader::load(FrameLoadRequest&& request)
 
 void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, NavigationAction&& action, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler<void()>&& completionHandler)
 {
+    InspectorInstrumentation::frameScheduledNavigation(m_frame, Seconds(0));
     FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadWithNavigationAction: frame load started");
 
     if (request.url().protocolIsJavaScript()) {
@@ -1590,6 +1592,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<DocumentLoader> oldDocumentLoader = m_documentLoader;
         NavigationAction action { *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission };
 
@@ -2792,12 +2796,17 @@ String FrameLoader::userAgent(const URL& url) const
 
 String FrameLoader::navigatorPlatform() const
 {
+    String platform;
+
     if (auto* documentLoader = m_frame.mainFrame().loader().activeDocumentLoader()) {
         auto& customNavigatorPlatform = documentLoader->customNavigatorPlatform();
         if (!customNavigatorPlatform.isEmpty())
-            return customNavigatorPlatform;
+            platform = customNavigatorPlatform;
     }
-    return String();
+
+    InspectorInstrumentation::applyPlatformOverride(m_frame, platform);
+
+    return platform;
 }
 
 void FrameLoader::dispatchOnloadEvents()
@@ -3200,6 +3209,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)
@@ -3967,9 +3978,6 @@ String FrameLoader::referrer() const
 
 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
 {
-    if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
-        return;
-
     Vector<Ref<DOMWrapperWorld>> worlds;
     ScriptController::getAllWorlds(worlds);
     for (auto& world : worlds)
@@ -3978,13 +3986,13 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
 
 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
 {
-    if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.windowProxy().existingJSWindowProxy(world))
-        return;
+    if (m_frame.windowProxy().existingJSWindowProxy(world)) {
+        if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
+            m_client->dispatchDidClearWindowObjectInWorld(world);
 
-    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 aef668bd63ed5fcd45e61e9d1f107cfb6aef264b..16bf309b93be78f4a0e8ee89e5a6afcfa755530a 100644
--- a/Source/WebCore/loader/LoaderStrategy.h
+++ b/Source/WebCore/loader/LoaderStrategy.h
@@ -86,6 +86,7 @@ public:
 
     virtual bool isOnLine() const = 0;
     virtual void addOnlineStateChangeListener(Function<void(bool)>&&) = 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 d0805795af21d39fc6858d4ac0168745f011fec4..34db61fe02ea27453f2e4646415a97bf0fcb647a 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 "ThreadableBlobRegistry.h"
 #include <wtf/CompletionHandler.h>
@@ -252,26 +253,32 @@ void FrameLoader::PolicyChecker::checkNewWindowPolicy(NavigationAction&& navigat
 
     auto blobURLLifetimeExtension = extendBlobURLLifetimeIfNecessary(request);
 
+    InspectorInstrumentation::willCheckNewWindowPolicy(m_frame, request.url());
     auto requestIdentifier = PolicyCheckIdentifier::create();
     m_frame.loader().client().dispatchDecidePolicyForNewWindowAction(navigationAction, request, formState.get(), frameName, requestIdentifier, [frame = Ref { 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, formState, frameName, navigationAction, ShouldContinuePolicyCheck::Yes);
             return;
         }
diff --git a/Source/WebCore/loader/ProgressTracker.cpp b/Source/WebCore/loader/ProgressTracker.cpp
index fa84c366c63175f9fb4730eb85c4677fc3d6368f..ecf5b8dc97e35910baf493424e673155cfa7d7a4 100644
--- a/Source/WebCore/loader/ProgressTracker.cpp
+++ b/Source/WebCore/loader/ProgressTracker.cpp
@@ -152,6 +152,8 @@ void ProgressTracker::progressCompleted(Frame& frame)
     if (!m_numProgressTrackedFrames || m_originatingProgressFrame == &frame)
         finalProgressComplete();
 
+    InspectorInstrumentation::frameStoppedLoading(frame);
+
     m_client->didChangeEstimatedProgress();
 }
 
@@ -177,8 +179,6 @@ void ProgressTracker::finalProgressComplete()
     frame->loader().client().setMainFrameDocumentReady(true);
     m_client->progressFinished(*frame);
     frame->loader().loadProgressingStatusChanged();
-
-    InspectorInstrumentation::frameStoppedLoading(*frame);
 }
 
 void ProgressTracker::incrementProgress(ResourceLoaderIdentifier identifier, const ResourceResponse& response)
diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h
index 7d6ce2a54539f9b23eca243f0922de41ade8c189..2badd22f830ab475b2a3ca69f8b170e143232f3e 100644
--- a/Source/WebCore/page/ChromeClient.h
+++ b/Source/WebCore/page/ChromeClient.h
@@ -314,7 +314,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 659e3d260b9d34525881e64fe22e83b8584ab8cf..47dbdcab030cb5be500db44ebd3ba6aef1a6c16d 100644
--- a/Source/WebCore/page/EventHandler.cpp
+++ b/Source/WebCore/page/EventHandler.cpp
@@ -140,6 +140,7 @@
 
 #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
 #include "PlatformTouchEvent.h"
+#include "PointerCaptureController.h"
 #endif
 
 #if ENABLE(MAC_GESTURE_EVENTS)
@@ -799,9 +800,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;
@@ -841,8 +840,6 @@ VisiblePosition EventHandler::selectionExtentRespectingEditingBoundary(const Vis
     return adjustedTarget->renderer()->positionForPoint(LayoutPoint(selectionEndPoint), nullptr);
 }
 
-#if ENABLE(DRAG_SUPPORT)
-
 #if !PLATFORM(IOS_FAMILY)
 
 bool EventHandler::supportsSelectionUpdatesOnMouseDrag() const
@@ -864,8 +861,10 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
 
     Ref<Frame> protectedFrame(m_frame);
 
+#if ENABLE(DRAG_SUPPORT)
     if (handleDrag(event, checkDragHysteresis))
         return true;
+#endif
 
     RefPtr targetNode = event.targetNode();
     if (event.event().button() != LeftButton || !targetNode)
@@ -886,7 +885,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);
@@ -903,6 +904,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
@@ -934,6 +937,8 @@ bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
     return targetElement && page->dragController().draggableElement(&m_frame, targetElement.get(), result.roundedPointInInnerNodeFrame(), state);
 }
 
+#endif // ENABLE(DRAG_SUPPORT)
+
 void EventHandler::updateSelectionForMouseDrag()
 {
     if (!supportsSelectionUpdatesOnMouseDrag())
@@ -1028,7 +1033,6 @@ void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResul
     if (oldSelection != newSelection && ImageOverlay::isOverlayText(newSelection.start().containerNode()) && ImageOverlay::isOverlayText(newSelection.end().containerNode()))
         invalidateClick();
 }
-#endif // ENABLE(DRAG_SUPPORT)
 
 void EventHandler::lostMouseCapture()
 {
@@ -1076,9 +1080,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;
@@ -2045,10 +2047,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;
 }
@@ -4111,7 +4111,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) {
@@ -4518,7 +4525,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());
 
@@ -4645,6 +4653,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 eac1d5f340086c3636bff6109651dec9f4eb30fe..6da03d6a69a9ac5d0eb50ddc90ac77f6fa85b659 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();
@@ -385,10 +383,8 @@ private:
     bool startKeyboardScrolling(KeyboardEvent&);
     void stopKeyboardScrolling();
 
-#if ENABLE(DRAG_SUPPORT)
     bool handleMouseDraggedEvent(const MouseEventWithHitTestResults&, CheckDragHysteresis = ShouldCheckDragHysteresis);
     bool shouldAllowMouseDownToStartDrag() const;
-#endif
 
     WEBCORE_EXPORT bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&);
 
@@ -488,10 +484,8 @@ private:
     void defaultTabEventHandler(KeyboardEvent&);
     void defaultArrowEventHandler(FocusDirection, KeyboardEvent&);
 
-#if ENABLE(DRAG_SUPPORT)
     OptionSet<DragSourceAction> 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.
@@ -499,9 +493,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);
     
@@ -593,8 +588,8 @@ private:
     Timer m_autoHideCursorTimer;
 #endif
 
-#if ENABLE(DRAG_SUPPORT)
     LayoutPoint m_dragStartPosition;
+#if ENABLE(DRAG_SUPPORT)
     RefPtr<Element> 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 602631bb7cd10860b1a3121043c97d8efe44761d..867320c576201d35124a186ac60c2927d9511afb 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"
@@ -94,6 +95,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 7788ee5755febf003f929b6df5de094fd7a9338f..227640e9a941afe56dc2d80512e48d195de9aef9 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 "DocumentTimelinesController.h"
@@ -73,6 +74,7 @@
 #include "NavigationScheduler.h"
 #include "Navigator.h"
 #include "NodeList.h"
+#include "NodeRenderStyle.h"
 #include "NodeTraversal.h"
 #include "Page.h"
 #include "ProcessWarming.h"
@@ -191,6 +193,7 @@ Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, UniqueRef<FrameLoa
 void Frame::init()
 {
     m_loader->init();
+    InspectorInstrumentation::frameAttached(this);
 }
 
 Ref<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, UniqueRef<FrameLoaderClient>&& client)
@@ -376,7 +379,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)
@@ -1169,6 +1172,362 @@ DataDetectionResultsStorage& Frame::dataDetectionResults()
 
 #endif
 
+#if !PLATFORM(IOS_FAMILY)
+
+void Frame::betterApproximateNode(const IntPoint& testPoint, const NodeQualifier& nodeQualifierFunction, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect)
+{
+    IntRect candidateRect;
+    constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent, HitTestRequest::Type::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<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent, HitTestRequest::Type::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<int>(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<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent, HitTestRequest::Type::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<Element>(node))
+        return false;
+
+    auto& element = downcast<Element>(node);
+    if (element.isMouseFocusable())
+        return true;
+
+    if (RefPtr shadowRoot = element.shadowRoot()) {
+        if (shadowRoot->delegatesFocus()) {
+            for (auto& node : composedTreeDescendants(element)) {
+                if (is<Element>(node) && downcast<Element>(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<HTMLAreaElement>(*node))
+                        *nodeBounds = snappedIntRect(downcast<HTMLAreaElement>(*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<HTMLAreaElement>(*node))
+                        *nodeBounds = snappedIntRect(downcast<HTMLAreaElement>(*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<RenderTextControl>(*renderer).canScroll()) {
+                scrollingAncestor = node;
+                continue;
+            }
+
+            auto& style = renderer->style();
+
+            if (renderer->hasNonVisibleOverflow()
+                && (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);
+}
+
+#endif // !PLATFORM(IOS_FAMILY)
+
 } // namespace WebCore
 
 #undef FRAME_RELEASE_LOG_ERROR
diff --git a/Source/WebCore/page/Frame.h b/Source/WebCore/page/Frame.h
index 124df1885f71dcd7d65e01d69fd79b104a07e672..51f87cd8710add1be6b6e3b99d9dc5bd5bbd264e 100644
--- a/Source/WebCore/page/Frame.h
+++ b/Source/WebCore/page/Frame.h
@@ -112,8 +112,8 @@ enum {
 };
 
 enum OverflowScrollAction { DoNotPerformOverflowScroll, PerformOverflowScroll };
-using NodeQualifier = Function<Node* (const HitTestResult&, Node* terminationNode, IntRect* nodeBounds)>;
 #endif
+using NodeQualifier = Function<Node* (const HitTestResult&, Node* terminationNode, IntRect* nodeBounds)>;
 
 // FIXME: Rename Frame to LocalFrame and AbstractFrame to Frame.
 class Frame final : public AbstractFrame {
@@ -218,10 +218,6 @@ public:
     WEBCORE_EXPORT DataDetectionResultsStorage& dataDetectionResults();
 #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);
@@ -229,6 +225,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;
 
@@ -299,6 +299,7 @@ public:
 
     WEBCORE_EXPORT FloatSize screenSize() const;
     void setOverrideScreenSize(FloatSize&&);
+    bool hasScreenSizeOverride() const { return !m_overrideScreenSize.isEmpty(); }
 
     void selfOnlyRef();
     void selfOnlyDeref();
@@ -337,7 +338,6 @@ private:
 #if ENABLE(DATA_DETECTION)
     std::unique_ptr<DataDetectionResultsStorage> 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);
     
@@ -345,6 +345,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 8273a64fcdfb7d34eaa76f98ba7a2117eafbfbe6..8a2f97ac8f935a71fce96913f8b10551a85de563 100644
--- a/Source/WebCore/page/FrameSnapshotting.cpp
+++ b/Source/WebCore/page/FrameSnapshotting.cpp
@@ -103,7 +103,7 @@ RefPtr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRect& image
     // Other paint behaviors are set by paintContentsForSnapshot.
     frame.view()->setPaintBehavior(paintBehavior);
 
-    float scaleFactor = frame.page()->deviceScaleFactor();
+    float scaleFactor = options.flags.contains(SnapshotFlags::OmitDeviceScaleFactor) ? 1 : frame.page()->deviceScaleFactor();
 
     if (frame.page()->delegatesScaling())
         scaleFactor *= frame.page()->pageScaleFactor();
@@ -114,7 +114,12 @@ RefPtr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRect& image
     auto buffer = ImageBuffer::create(imageRect.size(), RenderingMode::Unaccelerated, scaleFactor, options.colorSpace, options.pixelFormat);
     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<ImageBuffer> 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/FrameSnapshotting.h b/Source/WebCore/page/FrameSnapshotting.h
index 1b77026f51092001cda86e32480890395b145b2e..6026bc23508016454f331b06c9f071a88f55cccc 100644
--- a/Source/WebCore/page/FrameSnapshotting.h
+++ b/Source/WebCore/page/FrameSnapshotting.h
@@ -50,6 +50,7 @@ enum class SnapshotFlags : uint8_t {
     PaintSelectionAndBackgroundsOnly = 1 << 4,
     PaintEverythingExcludingSelection = 1 << 5,
     PaintWithIntegralScaleFactor = 1 << 6,
+    OmitDeviceScaleFactor = 1 << 7,
 };
 
 struct SnapshotOptions {
diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp
index 28d1fc3242174a680711027877d4153923790220..058b5309eed081fcc1e4158f66e806421dcc9d56 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<void> History::stateObjectAdded(RefPtr<SerializedScriptValue>&& 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 2cd19a110b2b86923f4631299da355063c8bb511..82c438e2772198c19584d56de64be61162453a31 100644
--- a/Source/WebCore/page/Page.cpp
+++ b/Source/WebCore/page/Page.cpp
@@ -472,6 +472,37 @@ void Page::setOverrideViewportArguments(const std::optional<ViewportArguments>&
         document->updateViewportArguments();
 }
 
+FloatSize Page::screenSize()
+{
+    return m_overrideScreenSize.value_or(screenRect(mainFrame().view()).size());
+}
+
+void Page::setOverrideScreenSize(std::optional<FloatSize> 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.value_or(chrome().client().deviceOrientation());
+}
+
+void Page::setOverrideOrientation(std::optional<int> orientation)
+{
+    if (orientation == m_overrideOrientation)
+        return;
+
+    m_overrideOrientation = orientation;
+    mainFrame().orientationChanged();
+}
+#endif
+
 ScrollingCoordinator* Page::scrollingCoordinator()
 {
     if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) {
@@ -1308,10 +1339,6 @@ void Page::didCommitLoad()
     m_isEditableRegionEnabled = false;
 #endif
 
-#if HAVE(OS_DARK_MODE_SUPPORT)
-    setUseDarkAppearanceOverride(std::nullopt);
-#endif
-
     resetSeenPlugins();
     resetSeenMediaEngines();
 
@@ -3315,6 +3342,16 @@ void Page::setUseDarkAppearanceOverride(std::optional<bool> valueOverride)
 #endif
 }
 
+void Page::setUseReducedMotionOverride(std::optional<bool> valueOverride)
+{
+    if (valueOverride == m_useReducedMotionOverride)
+        return;
+
+    m_useReducedMotionOverride = valueOverride;
+
+    appearanceDidChange();
+}
+
 void Page::setFullscreenInsets(const FloatBoxExtent& insets)
 {
     if (insets == m_fullscreenInsets)
diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h
index d09ae215184558929a31388a8ff0b2ba4fdbd4c8..6381b441ad76417f0df14cbb14dcca4f76191f8d 100644
--- a/Source/WebCore/page/Page.h
+++ b/Source/WebCore/page/Page.h
@@ -272,6 +272,9 @@ public:
     const std::optional<ViewportArguments>& overrideViewportArguments() const { return m_overrideViewportArguments; }
     WEBCORE_EXPORT void setOverrideViewportArguments(const std::optional<ViewportArguments>&);
 
+    WEBCORE_EXPORT FloatSize screenSize();
+    void setOverrideScreenSize(std::optional<FloatSize> size);
+
     static void refreshPlugins(bool reload);
     WEBCORE_EXPORT PluginData& pluginData();
     void clearPluginData();
@@ -326,6 +329,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)
@@ -486,6 +493,8 @@ public:
     WEBCORE_EXPORT void effectiveAppearanceDidChange(bool useDarkAppearance, bool useElevatedUserInterfaceLevel);
     bool defaultUseDarkAppearance() const { return m_useDarkAppearance; }
     void setUseDarkAppearanceOverride(std::optional<bool>);
+    std::optional<bool> useReducedMotionOverride() const { return m_useReducedMotionOverride; }
+    void setUseReducedMotionOverride(std::optional<bool>);
 
 #if ENABLE(TEXT_AUTOSIZING)
     float textAutosizingWidth() const { return m_textAutosizingWidth; }
@@ -881,6 +890,11 @@ public:
 
     WEBCORE_EXPORT Vector<Ref<Element>> editableElementsInRect(const FloatRect&) const;
 
+#if ENABLE(ORIENTATION_EVENTS)
+    int orientation() const;
+    void setOverrideOrientation(std::optional<int>);
+#endif
+
 #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY)
     DeviceOrientationUpdateProvider* deviceOrientationUpdateProvider() const { return m_deviceOrientationUpdateProvider.get(); }
 #endif
@@ -979,6 +993,9 @@ private:
 
 #if ENABLE(DRAG_SUPPORT)
     const std::unique_ptr<DragController> m_dragController;
+#if PLATFORM(MAC)
+    String m_overrideDragPasteboardName;
+#endif
 #endif
     const std::unique_ptr<FocusController> m_focusController;
 #if ENABLE(CONTEXT_MENUS)
@@ -1058,6 +1075,7 @@ private:
     bool m_useElevatedUserInterfaceLevel { false };
     bool m_useDarkAppearance { false };
     std::optional<bool> m_useDarkAppearanceOverride;
+    std::optional<bool> m_useReducedMotionOverride;
 
 #if ENABLE(TEXT_AUTOSIZING)
     float m_textAutosizingWidth { 0 };
@@ -1232,6 +1250,11 @@ private:
 #endif
 
     std::optional<ViewportArguments> m_overrideViewportArguments;
+    std::optional<FloatSize> m_overrideScreenSize;
+
+#if ENABLE(ORIENTATION_EVENTS)
+    std::optional<int> m_overrideOrientation;
+#endif
 
 #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY)
     RefPtr<DeviceOrientationUpdateProvider> m_deviceOrientationUpdateProvider;
diff --git a/Source/WebCore/page/PointerCaptureController.cpp b/Source/WebCore/page/PointerCaptureController.cpp
index 62904802dda2b68fcde3bd0f05b3ea1cf7e31284..ac37a8a0abd2fee236a743fd7a976484bbb46fe1 100644
--- a/Source/WebCore/page/PointerCaptureController.cpp
+++ b/Source/WebCore/page/PointerCaptureController.cpp
@@ -196,7 +196,7 @@ bool PointerCaptureController::preventsCompatibilityMouseEventsForIdentifier(Poi
     return capturingData && capturingData->preventsCompatibilityMouseEvents;
 }
 
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
+#if ENABLE(TOUCH_EVENTS)
 static bool hierarchyHasCapturingEventListeners(Element* target, const AtomString& eventName)
 {
     for (RefPtr<ContainerNode> currentNode = target; currentNode; currentNode = currentNode->parentInComposedTree()) {
@@ -477,7 +477,7 @@ void PointerCaptureController::cancelPointer(PointerID pointerId, const IntPoint
     capturingData->pendingTargetOverride = nullptr;
     capturingData->state = CapturingData::State::Cancelled;
 
-#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 45435f77e4bc790aa60bdebc27ea69b9ba889c30..65ae0b7b220d7736a42981ff18798a2ec83dbdbe 100644
--- a/Source/WebCore/page/PointerCaptureController.h
+++ b/Source/WebCore/page/PointerCaptureController.h
@@ -57,7 +57,7 @@ public:
 
     RefPtr<PointerEvent> 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
 
@@ -77,7 +77,7 @@ private:
 
         RefPtr<Element> pendingTargetOverride;
         RefPtr<Element> targetOverride;
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
+#if ENABLE(TOUCH_EVENTS)
         RefPtr<Element> previousTarget;
 #endif
         bool hasAnyElement() const {
diff --git a/Source/WebCore/page/RuntimeEnabledFeatures.cpp b/Source/WebCore/page/RuntimeEnabledFeatures.cpp
index 04fff21a26adbc73d8b74dbf55acc8e9824f35da..cd7346fe3b4701724431bc1617e13d2e6f775151 100644
--- a/Source/WebCore/page/RuntimeEnabledFeatures.cpp
+++ b/Source/WebCore/page/RuntimeEnabledFeatures.cpp
@@ -61,7 +61,11 @@ RuntimeEnabledFeatures& RuntimeEnabledFeatures::sharedFeatures()
 #if ENABLE(TOUCH_EVENTS)
 bool RuntimeEnabledFeatures::touchEventsEnabled() const
 {
-    return m_touchEventsEnabled.value_or(screenHasTouchDevice());
+    return m_touchEventsEnabled.value_or(platformScreenHasTouchDevice());
+}
+bool RuntimeEnabledFeatures::isTouchPrimaryInputDevice() const
+{
+    return m_touchEventsEnabled.value_or(platformScreenIsTouchPrimaryInputDevice());
 }
 #endif
 
diff --git a/Source/WebCore/page/RuntimeEnabledFeatures.h b/Source/WebCore/page/RuntimeEnabledFeatures.h
index 6258c0167d1f2c9f7811f7606787a2ef7f76a2f4..8a2b0d132553c30924f5747406d9040d63544dae 100644
--- a/Source/WebCore/page/RuntimeEnabledFeatures.h
+++ b/Source/WebCore/page/RuntimeEnabledFeatures.h
@@ -191,6 +191,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<int>(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<int>(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<unsigned>(frame->screenSize().height());
     return static_cast<unsigned>(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<unsigned>(frame->screenSize().width());
     return static_cast<unsigned>(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<SocketStreamHandle> 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<ThreadableWebSocketChannel> SocketProvider::createWebSocketChannel(Document&, WebSocketChannelClient&)
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
index bb780481e89cb19c16789fb14b422e70afcd5197..191cf3a48d951292ba582458d2f17a1c49edbb6d 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
+++ b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
@@ -293,6 +293,8 @@ bool ContentSecurityPolicy::protocolMatchesSelf(const URL& url) const
 template<typename Predicate, typename... Args>
 typename std::enable_if<!std::is_convertible<Predicate, ContentSecurityPolicy::ViolatedDirectiveCallback>::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)
@@ -306,6 +308,8 @@ typename std::enable_if<!std::is_convertible<Predicate, ContentSecurityPolicy::V
 template<typename Predicate, typename... Args>
 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) {
@@ -322,6 +326,8 @@ bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposit
 template<typename Predicate, typename... Args>
 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>(args)...)) {
diff --git a/Source/WebCore/page/wpe/DragControllerWPE.cpp b/Source/WebCore/page/wpe/DragControllerWPE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3dedfa855f990643e3e7bbe7754abca4e88a0f1c
--- /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);
+}
+
+std::optional<DragOperation> DragController::dragOperation(const DragData& dragData)
+{
+    // FIXME: This logic is incomplete
+    if (dragData.containsURL())
+        return DragOperation::Copy;
+
+    return std::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 1fb0e9d5cee3b3df4ee1e96eb8d75016ad687fc5..497bd34cc97e2d20c9d6982a8d92d852451743cd 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/RefPtrCairo.h
 )
 
diff --git a/Source/WebCore/platform/DragData.h b/Source/WebCore/platform/DragData.h
index 6600dfa7b189e15fab7fb796f66ef1a79dcd22f3..4c0bc485ca92614efca23a5a2da871b77d5285d3 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 6dfe0dd3ea4da3a1f5f0f6c79d6d1a3bf00c3159..683c1bdb2cb33538af14dcc5dab89d07dcd34eff 100644
--- a/Source/WebCore/platform/DragImage.cpp
+++ b/Source/WebCore/platform/DragImage.cpp
@@ -279,7 +279,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 7d247dcd1a16f342c1754c45c4a73529bf8f71b2..6903f0a0ab250526f533bcc69e1af11e578fb03d 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<String> clientTypes;
     Vector<RefPtr<SharedBuffer>> 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<PasteboardContext>&&, SelectionData&);
+    explicit Pasteboard(std::unique_ptr<PasteboardContext>&&, SelectionData&&);
+#endif
+
 #if PLATFORM(WIN)
     explicit Pasteboard(std::unique_ptr<PasteboardContext>&&, IDataObject*);
     explicit Pasteboard(std::unique_ptr<PasteboardContext>&&, WCDataObject*);
@@ -253,6 +254,12 @@ public:
     static std::unique_ptr<Pasteboard> createForGlobalSelection(std::unique_ptr<PasteboardContext>&&);
 #endif
 
+#if PLATFORM(WPE)
+    const SelectionData& selectionData() const {
+        return *m_selectionData;
+    }
+#endif
+
 #if PLATFORM(IOS_FAMILY)
     explicit Pasteboard(std::unique_ptr<PasteboardContext>&&, int64_t changeCount);
     explicit Pasteboard(std::unique_ptr<PasteboardContext>&&, const String& pasteboardName);
@@ -287,6 +294,7 @@ public:
     COMPtr<IDataObject> 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<WCDataObject> 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)
+    std::optional<SelectionData> m_selectionData;
+#endif
+
 #if PLATFORM(COCOA)
     String m_pasteboardName;
     int64_t m_changeCount;
@@ -353,6 +365,7 @@ private:
     COMPtr<IDataObject> m_dataObject;
     COMPtr<WCDataObject> 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 1d3edd9585338828c7074fd8389e437c16c42d92..0f4b5b074f6c95919a09567bd1338577c0930627 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 d47d193e8bee85c2d2a35e218decdd84b7212dc1..a1cd2f3b8f025436b596d1b1081357d9290763ea 100644
--- a/Source/WebCore/platform/PlatformScreen.h
+++ b/Source/WebCore/platform/PlatformScreen.h
@@ -155,12 +155,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 ab745c4bba9f23e18aba3cf136e3e915310b9051..b97ce7699e3bd705016cb1d209ba90f507ba394a 100644
--- a/Source/WebCore/platform/ScrollableArea.h
+++ b/Source/WebCore/platform/ScrollableArea.h
@@ -103,7 +103,7 @@ public:
     void stopKeyboardScrollAnimation();
 
 #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/SourcesGLib.txt b/Source/WebCore/platform/SourcesGLib.txt
index 53f48ba8ad99364680457daf4dcbae632360be12..8825859d561113f14ba6ef8d860c5202d2fbd253 100644
--- a/Source/WebCore/platform/SourcesGLib.txt
+++ b/Source/WebCore/platform/SourcesGLib.txt
@@ -33,6 +33,7 @@ platform/glib/LowPowerModeNotifierGLib.cpp
 platform/glib/RemoteCommandListenerGLib.cpp
 platform/glib/SharedBufferGlib.cpp
 platform/glib/UserAgentGLib.cpp
+platform/glib/PlatformSpeechSynthesizerGLib.cpp
 
 platform/network/glib/DNSResolveQueueGLib.cpp
 platform/network/glib/NetworkStateNotifierGLib.cpp
diff --git a/Source/WebCore/platform/glib/PlatformSpeechSynthesizerGLib.cpp b/Source/WebCore/platform/glib/PlatformSpeechSynthesizerGLib.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f0c3a183e5bc44bdfa4201e0db2067b41bf51580
--- /dev/null
+++ b/Source/WebCore/platform/glib/PlatformSpeechSynthesizerGLib.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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.
+ */
+
+#import "config.h"
+#import "PlatformSpeechSynthesizer.h"
+
+#if ENABLE(SPEECH_SYNTHESIS)
+
+namespace WebCore {
+
+PlatformSpeechSynthesizer::PlatformSpeechSynthesizer(PlatformSpeechSynthesizerClient* client)
+    : m_speechSynthesizerClient(client)
+{
+}
+
+PlatformSpeechSynthesizer::~PlatformSpeechSynthesizer()
+{
+}
+
+void PlatformSpeechSynthesizer::initializeVoiceList()
+{
+}
+
+void PlatformSpeechSynthesizer::pause()
+{
+}
+
+void PlatformSpeechSynthesizer::resume()
+{
+}
+
+void PlatformSpeechSynthesizer::speak(RefPtr<PlatformSpeechSynthesisUtterance>&& utterance)
+{
+}
+
+void PlatformSpeechSynthesizer::cancel()
+{
+}
+
+void PlatformSpeechSynthesizer::resetState()
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SPEECH_SYNTHESIS)
diff --git a/Source/WebCore/platform/graphics/FontCascade.h b/Source/WebCore/platform/graphics/FontCascade.h
index 6af5812d8a722b8fdbd39381bd64832769e4fa3a..02b9400c438c630f43c6a2e7301db4ac3311dcdc 100644
--- a/Source/WebCore/platform/graphics/FontCascade.h
+++ b/Source/WebCore/platform/graphics/FontCascade.h
@@ -291,7 +291,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 4db603a94f3af1b1bce94ab0f1ae36054c004fcc..c1820f48eb86348f8ca678fde636244e8c91267e 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp
@@ -48,6 +48,13 @@
 #include <wtf/glib/GUniquePtr.h>
 #endif
 
+#if PLATFORM(WPE) || PLATFORM(WIN)
+#include <stdio.h> // 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<u
     return cairo_surface_write_to_png_stream(image, writeFunction, output) == CAIRO_STATUS_SUCCESS;
 }
 
-Vector<uint8_t> data(cairo_surface_t* image, const String& mimeType, std::optional<double>)
+static Vector<uint8_t> 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<uint8_t> 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<uint8_t> data(cairo_surface_t* image, const String& mimeType, std::optional<double> quality)
 {
+    if (mimeType == "image/jpeg") {
+        int qualityPercent = 100;
+        if (quality)
+            qualityPercent = static_cast<int>(*quality * 100.0 + 0.5);
+        return encodeJpeg(image, qualityPercent);
+    }
+
     Vector<uint8_t> 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 8677d106bf2d0f53044b47fba0e6736efcd3aeb6..9b28f9d917536d2c2699f613adf296bbdd965969 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h
@@ -36,10 +36,10 @@ class PixelBuffer;
 
 WEBCORE_EXPORT uint8_t verifyImageBufferIsBigEnough(const void* buffer, size_t bufferSize);
 
-CFStringRef jpegUTI();
+WEBCORE_EXPORT CFStringRef jpegUTI();
 WEBCORE_EXPORT RetainPtr<CFStringRef> utiFromImageBufferMIMEType(const String&);
 
-Vector<uint8_t> data(CGImageRef, CFStringRef destinationUTI, std::optional<double> quality);
+WEBCORE_EXPORT Vector<uint8_t> data(CGImageRef, CFStringRef destinationUTI, std::optional<double> quality);
 Vector<uint8_t> data(const PixelBuffer&, const String& mimeType, std::optional<double> quality);
 
 WEBCORE_EXPORT String dataURL(CGImageRef, CFStringRef destinationUTI, const String& mimeType, std::optional<double> quality);
diff --git a/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h
index 70a084bd9eb6375bcec4ac89b95092aad8c146b4..6bc9698129073a49e474537905600743b6a5bd35 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h
@@ -23,6 +23,7 @@
 #pragma once
 
 #include "FilterEffectApplier.h"
+#include "PixelBuffer.h"
 
 namespace WebCore {
 
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp
index 68b6cd3f524bf6a09eaf7fd6848fbac1da733ab3..991d7f20c21290db6732f02f8455974167e34bcf 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 "IntRect.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<unsigned> stringIndicesFromClusters(const Vector<WORD>& clusters,
     return stringIndices;
 }
 
+static int compactScriptItemsIfNeeded(const UChar* cp, unsigned stringLength, Vector<SCRIPT_ITEM>& 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 44dfdecb31b071536225167675a5def53f721af8..5a20442e398b6970877f5c8702a7181509138a5c 100644
--- a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
+++ b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
@@ -37,8 +37,10 @@
 #include <gdk/gdk.h>
 #include <gdk/gdkkeysyms.h>
 #include <pal/text/TextEncoding.h>
+#include <wtf/HashMap.h>
 #include <wtf/HexNumber.h>
 #include <wtf/glib/GUniquePtr.h>
+#include <mutex>
 
 namespace WebCore {
 
@@ -1294,6 +1296,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode)
 
 }
 
+static const HashMap<int, unsigned>& gdkToWindowsKeyCodeMap()
+{
+    static HashMap<int, unsigned>* 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<int, unsigned>();
+            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 80958ba565a877224d0ed37e4e4057b4be0dde24..eca42bf5181bc4a95efca9c9c3f5ce0f987fea43 100644
--- a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp
+++ b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp
@@ -224,7 +224,7 @@ bool screenSupportsExtendedColor(Widget*)
 }
 
 #if ENABLE(TOUCH_EVENTS)
-bool screenHasTouchDevice()
+bool platformScreenHasTouchDevice()
 {
     auto* display = gdk_display_get_default();
     if (!display)
@@ -234,7 +234,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 f4c905dc15a2183629b0e9817dc24135e0ff7fe5..e9925e7a9fc3cbf5fefffaf38f409fbeec189cb0 100644
--- a/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp
+++ b/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp
@@ -32,6 +32,10 @@
 #include "PasteboardStrategy.h"
 #include "PlatformStrategies.h"
 
+#if ENABLE(DRAG_SUPPORT)
+#include "DragData.h"
+#endif
+
 namespace WebCore {
 
 std::unique_ptr<Pasteboard> Pasteboard::createForCopyAndPaste(std::unique_ptr<PasteboardContext>&& context)
@@ -73,6 +77,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());
 }
 
@@ -84,6 +98,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);
 }
 
@@ -111,7 +134,12 @@ void Pasteboard::read(PasteboardFileReader&, std::optional<size_t>)
 
 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&)
@@ -119,13 +147,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()
@@ -156,6 +199,35 @@ void Pasteboard::write(const Color&)
 {
 }
 
+#if ENABLE(DRAG_SUPPORT)
+
+Pasteboard::Pasteboard(std::unique_ptr<PasteboardContext>&& context, SelectionData&& selectionData)
+    : m_context(WTFMove(context))
+    , m_selectionData(WTFMove(selectionData))
+{
+}
+
+Pasteboard::Pasteboard(std::unique_ptr<PasteboardContext>&& context, SelectionData& selectionData)
+    : m_context(WTFMove(context))
+    , m_selectionData(selectionData)
+{
+}
+
+std::unique_ptr<Pasteboard> Pasteboard::createForDragAndDrop(std::unique_ptr<PasteboardContext>&& context)
+{
+    return makeUnique<Pasteboard>(WTFMove(context), SelectionData());
+}
+
+std::unique_ptr<Pasteboard> Pasteboard::create(const DragData& dragData)
+{
+    RELEASE_ASSERT(dragData.platformData());
+    return makeUnique<Pasteboard>(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 <wpe/wpe.h>
+#include <wtf/HashMap.h>
 #include <wtf/HexNumber.h>
 #include <wtf/text/StringBuilder.h>
+#include <mutex>
 
 namespace WebCore {
 
@@ -1291,6 +1293,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(unsigned keycode)
     return 0;
 }
 
+static const HashMap<int, unsigned>& WPEToWindowsKeyCodeMap()
+{
+    static HashMap<int, unsigned>* 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<int, unsigned>();
+            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/NetworkStorageSession.h b/Source/WebCore/platform/network/NetworkStorageSession.h
index 3cbe3f9473d4ef35b0577847bcb9f0c70355fc27..86dc55f9d09a2c9a92e1ed535a6f3888b078cae3 100644
--- a/Source/WebCore/platform/network/NetworkStorageSession.h
+++ b/Source/WebCore/platform/network/NetworkStorageSession.h
@@ -154,6 +154,8 @@ public:
     NetworkingContext* context() const;
 #endif
 
+    WEBCORE_EXPORT void setCookiesFromResponse(const URL& firstParty, const SameSiteInfo&, const URL&, const String& setCookieValue);
+
     WEBCORE_EXPORT HTTPCookieAcceptPolicy cookieAcceptPolicy() const;
     WEBCORE_EXPORT void setCookie(const Cookie&);
     WEBCORE_EXPORT void setCookies(const Vector<Cookie>&, const URL&, const URL& mainDocumentURL);
diff --git a/Source/WebCore/platform/network/ResourceResponseBase.h b/Source/WebCore/platform/network/ResourceResponseBase.h
index 262e53180d6dd7c4d133ddc1daf5652bd6f31c76..d09aed9c9c58afe3c2040e1d5d683374365e65f8 100644
--- a/Source/WebCore/platform/network/ResourceResponseBase.h
+++ b/Source/WebCore/platform/network/ResourceResponseBase.h
@@ -221,6 +221,8 @@ public:
 
     WEBCORE_EXPORT static ResourceResponse dataURLResponse(const URL&, const DataURLDecoder::Result&);
 
+    HTTPHeaderMap m_httpRequestHeaderFields;
+
 protected:
     enum InitLevel {
         Uninitialized,
@@ -300,6 +302,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.
@@ -372,6 +375,12 @@ bool ResourceResponseBase::decode(Decoder& decoder, ResourceResponseBase& respon
         return false;
     response.m_httpHeaderFields = WTFMove(*httpHeaderFields);
 
+    std::optional<HTTPHeaderMap> 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) {
         std::optional<Box<NetworkLoadMetrics>> networkLoadMetrics;
diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h
index 7330aa933924791f1292c0847921e3b367493d96..a5238a748d1fb4bfa5b3e0882fe62f4029f84e5f 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<SocketStreamHandleImpl> 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<SocketStreamHandleImpl> 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:
     std::optional<size_t> 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<const StorageSessionProvider> m_storageSessionProvider;
+    bool m_ignoreCertificateErrors { false };
 
     StreamBuffer<uint8_t, 1024 * 1024> 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 311aef2d80fe7336cd8e5113c39d950db8f4394c..995545c175a9b22145f82c7efa8ef539cec4279b 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);
 
@@ -357,7 +358,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/cocoa/NetworkStorageSessionCocoa.mm b/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm
index b28ebbddea4fba00a321d18d20bef45bd0392ac7..7291be7bb171ad99142147270389152b1bd34eb5 100644
--- a/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm
+++ b/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm
@@ -466,6 +466,22 @@ void NetworkStorageSession::setCookiesFromDOM(const URL& firstParty, const SameS
     END_BLOCK_OBJC_EXCEPTIONS
 }
 
+void NetworkStorageSession::setCookiesFromResponse(const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, const String& setCookieValue)
+{
+    Vector<String> cookieValues = setCookieValue.split('\n');
+    size_t count = cookieValues.size();
+    auto* cookies = [NSMutableArray arrayWithCapacity:count];
+    for (const auto& cookieValue : cookieValues) {
+        NSString* cookieString = (NSString *)cookieValue;
+        NSString* cookieKey = @"Set-Cookie";
+        NSDictionary* headers = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObject:cookieString] forKeys:[NSArray arrayWithObject:cookieKey]];
+        NSArray<NSHTTPCookie*>* parsedCookies = [NSHTTPCookie cookiesWithResponseHeaderFields:headers forURL:(NSURL *)url];
+        [cookies addObject:parsedCookies[0]];
+    }
+    NSURL *cookieURL = url;
+    setHTTPCookiesForURL(cookieStorage().get(), cookies, cookieURL, firstParty, sameSiteInfo);
+}
+
 static NSHTTPCookieAcceptPolicy httpCookieAcceptPolicy(CFHTTPCookieStorageRef cookieStorage)
 {
     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
diff --git a/Source/WebCore/platform/network/curl/CookieJarDB.h b/Source/WebCore/platform/network/curl/CookieJarDB.h
index c4eb67d6f7c334076b32b798dcea40b570681e6f..ce86ab28225aa466350671441294f2ace8851bbd 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 c0704f0cdd6442373f7b70bfe61539bf5b37d625..02fb139ccd854642242fef2c75d8fd15db8fe42d 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 4f59b20e8db27903994b33154ce64b0994f3a0ba..e18315445ee05d47b81f00b47ab84ec5d5ae032b 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<CurlStream> create(CurlStreamScheduler& scheduler, CurlStreamID streamID, URL&& url)
+    static std::unique_ptr<CurlStream> create(CurlStreamScheduler& scheduler, CurlStreamID streamID, bool ignoreCertificateErrors, URL&& url)
     {
-        return makeUnique<CurlStream>(scheduler, streamID, WTFMove(url));
+        return makeUnique<CurlStream>(scheduler, streamID, ignoreCertificateErrors, WTFMove(url));
     }
 
-    CurlStream(CurlStreamScheduler&, CurlStreamID, URL&&);
+    CurlStream(CurlStreamScheduler&, CurlStreamID, bool ignoreCertificateErrors, URL&&);
     virtual ~CurlStream();
 
     void send(UniqueArray<uint8_t>&&, size_t);
diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp
index d94ff4f9169a6c0b5adb9719f5506d0fb80e6f89..3f955607764d028807d150619bf7f49e08bc3e7e 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 0c39c90aac884fca48849388acc1b42bad16d620..dd8e50686c348b46d5ae92fd67a31eb0cbdb014f 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<uint8_t>&&, size_t);
 
diff --git a/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp b/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp
index 5249bfb4a5ba52981e1f4cbe43048e27507b033a..52b8d0703ebb2fb0737b73bc7ebcf3abe3d7ed9e 100644
--- a/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp
+++ b/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp
@@ -116,6 +116,12 @@ void NetworkStorageSession::setCookieAcceptPolicy(CookieAcceptPolicy policy) con
     cookieDatabase().setAcceptPolicy(policy);
 }
 
+void  NetworkStorageSession::setCookiesFromResponse(const URL& firstParty, const SameSiteInfo&, const URL& url, const String& setCookieValue)
+{
+    for (auto& cookieString : setCookieValue.split('\n'))
+        cookieDatabase().setCookie(firstParty, url, cookieString, CookieJarDB::Source::Network);
+}
+
 HTTPCookieAcceptPolicy NetworkStorageSession::cookieAcceptPolicy() const
 {
     switch (cookieDatabase().acceptPolicy()) {
diff --git a/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h
index b804fde0973bbfb28331cf7c3a1f20b043e74fe8..af3005261593b5fa91484c98c43d021227716231 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<SocketStreamHandleImpl> create(const URL& url, SocketStreamHandleClient& client, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, client, provider)); }
+    static Ref<SocketStreamHandleImpl> 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;
     std::optional<size_t> 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 4b9491c11543f2b60f12d36e9e6a0cbaae34a72e..e907fc00a2a426384ce1e471847911c9ba1739af 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/NetworkStorageSessionSoup.cpp b/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp
index 5b32534e2bcaf1701331e9541013b8a5c38c4d36..2e8c12c871ba10d5769c400ec31d4fca6641aaca 100644
--- a/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp
+++ b/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp
@@ -408,6 +408,30 @@ void NetworkStorageSession::setCookie(const Cookie& cookie)
     soup_cookie_jar_add_cookie(cookieStorage(), cookie.toSoupCookie());
 }
 
+void  NetworkStorageSession::setCookiesFromResponse(const URL& firstParty, const SameSiteInfo&, const URL& url, const String& setCookieValue)
+{
+    auto origin = urlToSoupURI(url);
+    if (!origin)
+        return;
+
+    auto firstPartyURI = urlToSoupURI(firstParty);
+    if (!firstPartyURI)
+        return;
+
+    for (auto& cookieString : setCookieValue.split('\n')) {
+        GUniquePtr<SoupCookie> cookie(soup_cookie_parse(cookieString.utf8().data(), origin.get()));
+
+        if (!cookie)
+            continue;
+
+#if SOUP_CHECK_VERSION(2, 67, 1)
+        soup_cookie_jar_add_cookie_full(cookieStorage(), cookie.release(), origin.get(), firstPartyURI.get());
+#else
+        soup_cookie_jar_add_cookie_with_first_party(cookieStorage(), firstPartyURI.get(), cookie.release());
+#endif
+    }
+}
+
 void NetworkStorageSession::deleteCookie(const Cookie& cookie)
 {
     GUniquePtr<SoupCookie> targetCookie(cookie.toSoupCookie());
diff --git a/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h
index 88df3748e980a22e71bd835864caf24b6b7ea50b..f83c7f2535fd1abae7b1cccca946254b9407f86f 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<SocketStreamHandleImpl> create(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider*)
+    static Ref<SocketStreamHandleImpl> 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 4093537da5579db54326cc88b54e4ab17a2e22e3..0beae7659ed600fc9900d758884c1d70c86bd53e 100644
--- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp
+++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp
@@ -38,6 +38,7 @@
 #include <wtf/text/CString.h>
 #include <wtf/text/StringBuilder.h>
 #include <wtf/text/win/WCharStringExtras.h>
+#include "Pasteboard.h"
 
 namespace WebCore {
 
@@ -691,7 +692,10 @@ template<typename T> void getStringData(IDataObject* data, FORMATETC* format, Ve
     STGMEDIUM store;
     if (FAILED(data->GetData(format, &store)))
         return;
-    dataStrings.append(String(static_cast<T*>(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<T*>(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<char>&);
diff --git a/Source/WebCore/platform/win/DragDataWin.cpp b/Source/WebCore/platform/win/DragDataWin.cpp
index 207572d157ba2173c045e01da8f9b83b034c047e..6590bd36b23bdcbc947b191d2c011414655dfd68 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 aae6c99dd052985a43718846b68536454050c234..7e2e5d0c1de90f1454f7fdb71a40ab71228dcbe9 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 2b31285870303d09b0245365d61ab891111daab5..36e2efa8b05c21c003607e9143a213eb089ebfbb 100644
--- a/Source/WebCore/platform/win/PasteboardWin.cpp
+++ b/Source/WebCore/platform/win/PasteboardWin.cpp
@@ -1126,7 +1126,21 @@ void Pasteboard::writeCustomData(const Vector<PasteboardCustomData>& 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) {
@@ -1165,4 +1179,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<IEnumFORMATETC> itr;
+
+    if (FAILED(dragObject->EnumFormatEtc(DATADIR_GET, &itr)) || !itr)
+        return dragDataMap;
+
+    FORMATETC dataFormat;
+    while (itr->Next(1, &dataFormat, 0) == S_OK) {
+        Vector<String> dataStrings;
+        getClipboardData(dragObject.get(), &dataFormat, dataStrings);
+        if (!dataStrings.isEmpty())
+            dragDataMap.set(dataFormat.cfFormat, dataStrings);
+    }
+    return dragDataMap;
+}
+
 } // namespace WebCore
diff --git a/Source/WebCore/platform/win/ScrollbarThemeWin.cpp b/Source/WebCore/platform/win/ScrollbarThemeWin.cpp
index e89ec9d83d8abc141938716f24eaba061a085af3..6005d02b9bf20ef2cbf9382fdf50c863952c8db5 100644
--- a/Source/WebCore/platform/win/ScrollbarThemeWin.cpp
+++ b/Source/WebCore/platform/win/ScrollbarThemeWin.cpp
@@ -114,8 +114,7 @@ static int scrollbarThicknessInPixels()
 
 int ScrollbarThemeWin::scrollbarThickness(ScrollbarControlSize, ScrollbarExpansionState)
 {
-    float inverseScaleFactor = 1.0f / deviceScaleFactorForWindow(0);
-    return clampTo<int>(inverseScaleFactor * scrollbarThicknessInPixels());
+    return 0;
 }
 
 void ScrollbarThemeWin::themeChanged()
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<String> 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..e77e6db7a93a9dfcaad3866eb445edf4ebfe33b5
--- /dev/null
+++ b/Source/WebCore/platform/wpe/DragImageWPE.cpp
@@ -0,0 +1,73 @@
+/*
+ *  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;
+}
+
+DragImageRef createDragImageForColor(const Color&, const FloatRect&, float, Path&)
+{
+    return nullptr;
+}
+
+}
diff --git a/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp b/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp
index bbdd1ce76241d933ada9c43fabae4912cbfa64e1..e6ae01a77350c519b203f6ed2910f63871b9b829 100644
--- a/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp
+++ b/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp
@@ -93,12 +93,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 <wtf/glib/GUniquePtr.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+
+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<GError> error;
+            GUniquePtr<gchar> 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("<a href=\"");
+    markup.append(url.string());
+    markup.append("\">");
+    GUniquePtr<gchar> escaped(g_markup_escape_text(actualLabel.utf8().data(), -1));
+    markup.append(String::fromUTF8(escaped.get()));
+    markup.append("</a>");
+    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 <wtf/HashMap.h>
+#include <wtf/URL.h>
+#include <wtf/text/StringHash.h>
+
+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<String>& 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<SharedBuffer>&& 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<String> m_filenames;
+    RefPtr<Image> m_image;
+    bool m_canSmartReplace { false };
+    RefPtr<SharedBuffer> m_customData;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index fbef46090d074e2fb6fa2c475c1e59f741cca2c2..caf0d9ebf5b7f4ef735a16213f0bd951df067fe3 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -2618,7 +2618,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 0f281a057cf65180e4be869906e82c6b17b8020c..3c2bed5a8f01a8b486db6336dde6b38139c2cefa 100644
--- a/Source/WebCore/rendering/RenderTextControl.cpp
+++ b/Source/WebCore/rendering/RenderTextControl.cpp
@@ -207,13 +207,13 @@ void RenderTextControl::layoutExcludedChildren(bool relayoutChildren)
     }
 }
 
-#if PLATFORM(IOS_FAMILY)
 bool RenderTextControl::canScroll() const
 {
     auto innerText = innerTextElement();
     return innerText && innerText->renderer() && innerText->renderer()->hasNonVisibleOverflow();
 }
 
+#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 2e90534ffd8da83b7dc54d46fa7def16319bbb43..2493c00d58957751c65c37eb409fa8d675efd5ca 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 291cc9892e81027d9caed1d9db7061d73e674170..82250607745fb5b7f7148b0b2381f626a746de7d 100644
--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp
+++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp
@@ -76,6 +76,11 @@
 #include <WebCore/SameSiteInfo.h>
 #include <WebCore/SecurityPolicy.h>
 
+#if PLATFORM(COCOA)
+#include "NetworkDataTaskCocoa.h"
+#include "NetworkSessionCocoa.h"
+#endif
+
 #if ENABLE(APPLE_PAY_REMOTE_UI)
 #include "WebPaymentCoordinatorProxyMessages.h"
 #endif
@@ -964,6 +969,14 @@ void NetworkConnectionToWebProcess::clearPageSpecificData(PageIdentifier pageID)
 #endif
 }
 
+void NetworkConnectionToWebProcess::setCookieFromResponse(const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, const String& setCookieValue)
+{
+    auto* networkStorageSession = storageSession();
+    if (!networkStorageSession)
+        return;
+    networkStorageSession->setCookiesFromResponse(firstParty, sameSiteInfo, url, setCookieValue);
+}
+
 #if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
 void NetworkConnectionToWebProcess::removeStorageAccessForFrame(FrameIdentifier frameID, PageIdentifier pageID)
 {
diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h
index e817b7b62d249787dc4ab19edebb0c4f68512f2e..b3b923d1a0508d1bc8d8238fc5526437a62fcca1 100644
--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h
+++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h
@@ -289,6 +289,8 @@ private:
 
     void clearPageSpecificData(WebCore::PageIdentifier);
 
+    void setCookieFromResponse(const URL& firstParty, const WebCore::SameSiteInfo&, const URL& url, const String& setCookieValue);
+
 #if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
     void removeStorageAccessForFrame(WebCore::FrameIdentifier, WebCore::PageIdentifier);
 
diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in
index 005f632ef577c9c16a7dd7c1e6c67c911b42676c..53d84bccb064cc99f998b10519a3993ee29b613e 100644
--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in
+++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in
@@ -66,6 +66,8 @@ messages -> NetworkConnectionToWebProcess LegacyReceiver {
 
     ClearPageSpecificData(WebCore::PageIdentifier pageID);
 
+    SetCookieFromResponse(URL firstParty, struct WebCore::SameSiteInfo sameSiteInfo, URL url, String setCookieValue);
+
 #if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
     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 43f5bbe7b1abe09dd774c92b5c0e4f42dce1ddb7..5e44be4f1bbee607b24d33ef12f18987e815162c 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"
@@ -580,6 +579,59 @@ void NetworkProcess::destroySession(PAL::SessionID sessionID)
     removeStorageManagerForSession(sessionID);
 }
 
+void NetworkProcess::getAllCookies(PAL::SessionID sessionID, CompletionHandler<void(Vector<WebCore::Cookie>&&)>&& completionHandler)
+{
+    if (auto* networkStorageSession = storageSession(sessionID)) {
+        completionHandler(networkStorageSession->getAllCookies());
+        return;
+    }
+    completionHandler({ });
+}
+
+void NetworkProcess::setCookies(PAL::SessionID sessionID, Vector<WebCore::Cookie> cookies, CompletionHandler<void(bool)>&& 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<void(bool)>&& completionHandler)
+{
+    if (auto* networkStorageSession = storageSession(sessionID)) {
+        networkStorageSession->deleteAllCookies();
+        completionHandler(true);
+        return;
+    }
+    completionHandler(false);
+}
+
+void NetworkProcess::getLocalStorageData(PAL::SessionID sessionID, CompletionHandler<void(Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>>&&)>&& completionHandler)
+{
+    if (m_storageManagerSet->contains(sessionID)) {
+        m_storageManagerSet->getLocalStorageData(sessionID, WTFMove(completionHandler));
+        return;
+    }
+    completionHandler(Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>>());
+}
+
+void NetworkProcess::setLocalStorageData(PAL::SessionID sessionID, WebKit::StorageNamespaceIdentifier storageNamespaceID, Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>>&& origins, CompletionHandler<void(String)>&& completionHandler)
+{
+    if (m_storageManagerSet->contains(sessionID)) {
+        m_storageManagerSet->setLocalStorageData(sessionID, storageNamespaceID, WTFMove(origins), WTFMove(completionHandler));
+        return;
+    }
+    completionHandler("Cannot find storage manager for given session id");
+}
+
+void NetworkProcess::setIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignore)
+{
+    if (auto* networkSession = this->networkSession(sessionID))
+        networkSession->setIgnoreCertificateErrors(ignore);
+}
+
 #if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
 void NetworkProcess::dumpResourceLoadStatistics(PAL::SessionID sessionID, CompletionHandler<void(String)>&& completionHandler)
 {
diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h
index 9bc57ee37eb609c397ed7e3d22f55e064d02e017..4d507c781525e582f869364b223cd50f4535e444 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.h
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.h
@@ -35,6 +35,7 @@
 #include "NetworkResourceLoadIdentifier.h"
 #include "RTCDataChannelRemoteManagerProxy.h"
 #include "SandboxExtension.h"
+#include "StorageNamespaceIdentifier.h"
 #include "WebIDBServer.h"
 #include "WebPageProxyIdentifier.h"
 #include "WebResourceLoadStatisticsStore.h"
@@ -80,6 +81,7 @@ class SessionID;
 
 namespace WebCore {
 class CertificateInfo;
+struct Cookie;
 class CurlProxySettings;
 class ProtectionSpace;
 class StorageQuotaManager;
@@ -211,6 +213,14 @@ public:
 
     void addWebsiteDataStore(WebsiteDataStoreParameters&&);
 
+    void getAllCookies(PAL::SessionID, CompletionHandler<void(Vector<WebCore::Cookie>&&)>&&);
+    void setCookies(PAL::SessionID, Vector<WebCore::Cookie>, CompletionHandler<void(bool)>&&);
+    void deleteAllCookies(PAL::SessionID, CompletionHandler<void(bool)>&&);
+    void setIgnoreCertificateErrors(PAL::SessionID, bool);
+
+    void getLocalStorageData(PAL::SessionID sessionID, CompletionHandler<void(Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>>&&)>&&);
+    void setLocalStorageData(PAL::SessionID sessionID, WebKit::StorageNamespaceIdentifier storageNamespaceID, Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>>&& origins, CompletionHandler<void(String)>&&);
+
 #if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
     void clearPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
     void clearUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
index 8d34e713966c7e90ab435b1bfdd3e3d3b6c2083c..4ebdca94755a7b9404f7d7885708cc1dbc83187b 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
@@ -78,6 +78,14 @@ 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 std::optional<WebKit::NavigatingToAppBoundDomain> isNavigatingToAppBoundDomain, enum:bool WebKit::LastNavigationWasAppInitiated lastNavigationWasAppInitiated);
 
+    GetAllCookies(PAL::SessionID sessionID) -> (Vector<WebCore::Cookie> cookies) Async
+    SetCookies(PAL::SessionID sessionID, Vector<WebCore::Cookie> cookies) -> (bool success) Async
+    DeleteAllCookies(PAL::SessionID sessionID) -> (bool success) Async
+    SetIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignoreTLSErrors)
+
+    GetLocalStorageData(PAL::SessionID sessionID) -> (Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>> origins) Async
+    SetLocalStorageData(PAL::SessionID sessionID, WebKit::StorageNamespaceIdentifier storageNamespaceID, Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>> origins) -> (String error) Async
+
 #if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
     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 f8511ff158bc55f97adbe205d781ab2c66400ef0..cdd9a336faea14b6c818ae3fa040e56815d363a0 100644
--- a/Source/WebKit/NetworkProcess/NetworkSession.h
+++ b/Source/WebKit/NetworkProcess/NetworkSession.h
@@ -175,6 +175,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<ServiceWorkerSoftUpdateLoader>&& loader) { m_softUpdateLoaders.add(WTFMove(loader)); }
     void removeSoftUpdateLoader(ServiceWorkerSoftUpdateLoader* loader) { m_softUpdateLoaders.remove(loader); }
@@ -235,6 +238,7 @@ protected:
     bool m_privateClickMeasurementDebugModeEnabled { false };
     std::optional<WebCore::PrivateClickMeasurement> m_ephemeralMeasurement;
     bool m_isRunningEphemeralMeasurementTest { false };
+    bool m_ignoreCertificateErrors { false };
 
     HashSet<Ref<NetworkResourceLoader>> m_keptAliveLoads;
 
diff --git a/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp b/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
index 8e30448e0d72c61f60506f758559b790d4a7bda6..77663f51040b4fe368994873d68c19df14073d2d 100644
--- a/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
+++ b/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
@@ -43,7 +43,7 @@ Ref<NetworkSocketStream> 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/WebStorage/LocalStorageNamespace.cpp b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageNamespace.cpp
index 04c49bb4c914ebd93c7bcc09154e8c1d76e844b3..ace4b6eaa8ff94bdbd9d6aa041233b46f02f4fa1 100644
--- a/Source/WebKit/NetworkProcess/WebStorage/LocalStorageNamespace.cpp
+++ b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageNamespace.cpp
@@ -29,6 +29,7 @@
 #include "StorageArea.h"
 #include "StorageManager.h"
 #include <WebCore/SecurityOriginData.h>
+#include <wtf/Forward.h>
 
 namespace WebKit {
 
@@ -103,4 +104,11 @@ Vector<StorageAreaIdentifier> LocalStorageNamespace::storageAreaIdentifiers() co
     return identifiers;
 }
 
+void LocalStorageNamespace::forEachStorageArea(Function<void(const StorageArea&)> callback) const
+{
+    ASSERT(!RunLoop::isMain());
+    for (auto& storageArea : m_storageAreaMap.values())
+        callback(*storageArea);
+}
+
 } // namespace WebKit
diff --git a/Source/WebKit/NetworkProcess/WebStorage/LocalStorageNamespace.h b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageNamespace.h
index 73c35fc615f88a8d313848a4384875ac7d42505e..eaecae4ba4eda91ed39ecf35d075bc6369eac72b 100644
--- a/Source/WebKit/NetworkProcess/WebStorage/LocalStorageNamespace.h
+++ b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageNamespace.h
@@ -28,7 +28,7 @@
 #include "StorageAreaIdentifier.h"
 #include "StorageNamespaceIdentifier.h"
 #include <WebCore/SecurityOriginData.h>
-#include <wtf/Forward.h>
+#include <wtf/Function.h>
 #include <wtf/HashMap.h>
 #include <wtf/WeakPtr.h>
 
@@ -58,6 +58,8 @@ public:
 
     Vector<StorageAreaIdentifier> storageAreaIdentifiers() const;
 
+    void forEachStorageArea(Function<void(const StorageArea&)>) const;
+
 private:
     StorageManager& m_storageManager;
     unsigned m_quotaInBytes { 0 };
diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageArea.cpp b/Source/WebKit/NetworkProcess/WebStorage/StorageArea.cpp
index c84ead430ab15d94fd8ef2533d6e492872b6e12b..06bffb27005e00041d22673ababe603885307e84 100644
--- a/Source/WebKit/NetworkProcess/WebStorage/StorageArea.cpp
+++ b/Source/WebKit/NetworkProcess/WebStorage/StorageArea.cpp
@@ -112,6 +112,18 @@ void StorageArea::setItem(IPC::Connection::UniqueID sourceConnection, StorageAre
     dispatchEvents(sourceConnection, storageAreaImplID, key, oldValue, value, urlString);
 }
 
+void StorageArea::setItems(const HashMap<String, String>& items, bool& quotaException) {
+    ASSERT(!RunLoop::isMain());
+
+    for (const auto& item : items) {
+        String oldValue;
+        if (isEphemeral())
+            m_sessionStorageMap->setItem(item.key, item.value, oldValue, quotaException);
+        else
+            ensureDatabase().setItem(item.key, item.value, oldValue, quotaException);
+    }
+}
+
 void StorageArea::removeItem(IPC::Connection::UniqueID sourceConnection, StorageAreaImplIdentifier storageAreaImplID, const String& key, const String& urlString)
 {
     ASSERT(!RunLoop::isMain());
diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageArea.h b/Source/WebKit/NetworkProcess/WebStorage/StorageArea.h
index f57a72b6bdc3382469d69adb1b1201c7a9f07a84..c501211b094312ca44f0bf92de5d6ebc6bb843f9 100644
--- a/Source/WebKit/NetworkProcess/WebStorage/StorageArea.h
+++ b/Source/WebKit/NetworkProcess/WebStorage/StorageArea.h
@@ -64,6 +64,7 @@ public:
     void removeItem(IPC::Connection::UniqueID sourceConnection, StorageAreaImplIdentifier, const String& key, const String& urlString);
     void clear(IPC::Connection::UniqueID sourceConnection, StorageAreaImplIdentifier, const String& urlString);
 
+    void setItems(const HashMap<String, String>& items, bool& quotaException);
     HashMap<String, String> items() const;
     void clear();
 
diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp
index cb901b6c58b1859ae8be2ad9da9002d822b80612..1759668c2bd0fe375cbe12728a964317f66edb69 100644
--- a/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp
+++ b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp
@@ -148,6 +148,19 @@ HashSet<SecurityOriginData> StorageManager::getLocalStorageOriginsCrossThreadCop
     return origins;
 }
 
+Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>> StorageManager::getLocalStorageDataCrossThreadCopy() const
+{
+    ASSERT(!RunLoop::isMain());
+
+    Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>> result;
+    for (const auto& localStorageNameSpace : m_localStorageNamespaces.values()) {
+        localStorageNameSpace->forEachStorageArea([&] (const StorageArea& area) {
+            result.append({ area.securityOrigin().isolatedCopy(), area.items() });
+        });
+    }
+    return result;
+}
+
 Vector<LocalStorageDatabaseTracker::OriginDetails> StorageManager::getLocalStorageOriginDetailsCrossThreadCopy() const
 {
     ASSERT(!RunLoop::isMain());
diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManager.h b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.h
index 47c84e483fa93672815651b3d2196a2b56cb02ab..bc5603f78e5a4d8499bd2795d2da6ed6c28d7210 100644
--- a/Source/WebKit/NetworkProcess/WebStorage/StorageManager.h
+++ b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.h
@@ -66,6 +66,7 @@ public:
     void deleteSessionStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&);
 
     HashSet<WebCore::SecurityOriginData> getLocalStorageOriginsCrossThreadCopy() const;
+    Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>> getLocalStorageDataCrossThreadCopy() const;
     void deleteLocalStorageOriginsModifiedSince(WallTime);
     void deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&);
     Vector<LocalStorageDatabaseTracker::OriginDetails> getLocalStorageOriginDetailsCrossThreadCopy() const;
diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.cpp b/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.cpp
index 3feedcd688f112417104518ab452259dd995ab12..05a530ccba65a5a6708e00e0e2c1826186474c61 100644
--- a/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.cpp
+++ b/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.cpp
@@ -245,6 +245,50 @@ void StorageManagerSet::getLocalStorageOrigins(PAL::SessionID sessionID, GetOrig
     });
 }
 
+void StorageManagerSet::getLocalStorageData(PAL::SessionID sessionID, GetLocalStorageDataCallback&& completionHandler)
+{
+    ASSERT(RunLoop::isMain());
+
+    m_queue->dispatch([this, protectedThis = Ref { *this }, sessionID, completionHandler = WTFMove(completionHandler)]() mutable {
+        auto* storageManager = m_storageManagers.get(sessionID);
+        ASSERT(storageManager);
+
+        auto origins = storageManager->getLocalStorageDataCrossThreadCopy();
+        RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), origins = WTFMove(origins)]() mutable {
+            completionHandler(WTFMove(origins));
+        });
+    });
+}
+
+void StorageManagerSet::setLocalStorageData(PAL::SessionID sessionID, WebKit::StorageNamespaceIdentifier storageNamespaceID, Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>>&& origins, CompletionHandler<void(String)>&& completionHandler)
+{
+    ASSERT(RunLoop::isMain());
+
+    m_queue->dispatch([this, protectedThis = Ref { *this }, sessionID, storageNamespaceID, origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable {
+        auto* storageManager = m_storageManagers.get(sessionID);
+        ASSERT(storageManager);
+
+        String error;
+        for (const auto& originData : origins) {
+            auto* storageArea = storageManager->createLocalStorageArea(storageNamespaceID, originData.first.isolatedCopy(), m_queue.copyRef());
+            if (!storageArea) {
+                error = "Cannot create storage area";
+                break;
+            }
+            bool quotaException = false;
+            storageArea->setItems(originData.second, quotaException);
+            if (quotaException) {
+                error = "Storage quota exceeded";
+                break;
+            }
+        }
+
+        RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), error = WTFMove(error)]() mutable {
+            completionHandler(error);
+        });
+    });
+}
+
 void StorageManagerSet::deleteLocalStorageModifiedSince(PAL::SessionID sessionID, WallTime time, DeleteCallback&& completionHandler)
 {
     ASSERT(RunLoop::isMain());
diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.h b/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.h
index d602a5f90999fc7f440e2468d40332625ed37083..577b76728f762e7f5aa509531a65eaabba205da6 100644
--- a/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.h
+++ b/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.h
@@ -46,6 +46,7 @@ using ConnectToStorageAreaCallback = CompletionHandler<void(const std::optional<
 using GetValuesCallback = CompletionHandler<void(const HashMap<String, String>&)>;
 using GetOriginsCallback = CompletionHandler<void(HashSet<WebCore::SecurityOriginData>&&)>;
 using GetOriginDetailsCallback = CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>;
+using GetLocalStorageDataCallback = CompletionHandler<void(Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>>&&)>;
 using DeleteCallback = CompletionHandler<void()>;
 
 class StorageManagerSet : public IPC::Connection::WorkQueueMessageReceiver {
@@ -73,6 +74,8 @@ public:
     void deleteLocalStorageModifiedSince(PAL::SessionID, WallTime, DeleteCallback&&);
     void deleteLocalStorageForOrigins(PAL::SessionID, const Vector<WebCore::SecurityOriginData>&, DeleteCallback&&);
     void getLocalStorageOriginDetails(PAL::SessionID, GetOriginDetailsCallback&&);
+    void getLocalStorageData(PAL::SessionID, GetLocalStorageDataCallback&&);
+    void setLocalStorageData(PAL::SessionID sessionID, WebKit::StorageNamespaceIdentifier storageNamespaceID, Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>>&& origins, CompletionHandler<void(String)>&&);
     void renameOrigin(PAL::SessionID, const URL&, const URL&, CompletionHandler<void()>&&);
 
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
index eae005b37aa2e6130dd0dd4b5780f171735268c4..37464a459932a4cd01d89bf749ae9742f51eb548 100644
--- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
+++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
@@ -735,7 +735,7 @@ void NetworkSessionCocoa::setClientAuditToken(const WebCore::AuthenticationChall
 
     if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
         sessionCocoa->setClientAuditToken(challenge);
-        if (NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(challenge))
+        if (sessionCocoa->ignoreCertificateErrors() || sessionCocoa->allowsSpecificHTTPSCertificateForHost(challenge))
             return completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
 
         NSURLSessionTaskTransactionMetrics *metrics = task._incompleteTaskMetrics.transactionMetrics.lastObject;
@@ -968,6 +968,13 @@ ALLOW_DEPRECATED_DECLARATIONS_END
 
         resourceResponse.setDeprecatedNetworkLoadMetrics(WebCore::copyTimingData(taskMetrics, networkDataTask->networkLoadMetrics()));
 
+        __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);
+
         networkDataTask->didReceiveResponse(WTFMove(resourceResponse), negotiatedLegacyTLS, [completionHandler = makeBlockPtr(completionHandler), taskIdentifier](WebCore::PolicyAction policyAction) {
 #if !LOG_DISABLED
             LOG(NetworkSession, "%llu didReceiveResponse completionHandler (%d)", taskIdentifier, policyAction);
diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp
index 677c61da1a1894c1f59656d92709eb71d591a553..87831278a49f08a141c3899f369907b4637e0706 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 <WebCore/AuthenticationChallenge.h>
 #include <WebCore/CookieJar.h>
 #include <WebCore/CurlRequest.h>
@@ -40,6 +44,7 @@
 #include <WebCore/ShouldRelaxThirdPartyCookieBlocking.h>
 #include <WebCore/SynchronousLoaderClient.h>
 #include <pal/text/TextEncoding.h>
+#include <wtf/FileSystem.h>
 
 namespace WebKit {
 
@@ -77,6 +82,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->start();
 }
 
@@ -106,6 +113,9 @@ void NetworkDataTaskCurl::cancel()
 
     if (m_curlRequest)
         m_curlRequest->cancel();
+
+    if (isDownload())
+        deleteDownloadFile();
 }
 
 void NetworkDataTaskCurl::invalidateAndCancel()
@@ -150,6 +160,7 @@ void NetworkDataTaskCurl::curlDidReceiveResponse(CurlRequest& request, CurlRespo
     m_response = ResourceResponse(receivedResponse);
     m_response.setCertificateInfo(WTFMove(receivedResponse.certificateInfo));
     m_response.setDeprecatedNetworkLoadMetrics(Box<NetworkLoadMetrics>::create(WTFMove(receivedResponse.networkLoadMetrics)));
+    m_response.m_httpRequestHeaderFields = request.resourceRequest().httpHeaderFields();
 
     handleCookieHeaders(request.resourceRequest(), receivedResponse);
 
@@ -177,7 +188,10 @@ void NetworkDataTaskCurl::curlDidReceiveBuffer(CurlRequest&, Ref<SharedBuffer>&&
     Ref protectedThis { *this };
     if (state() == State::Canceling || state() == State::Completed || (!m_client && !isDownload()))
         return;
-
+    if (isDownload()) {
+        FileSystem::writeToFile(m_downloadDestinationFile, buffer->data(), buffer->size());
+        return;
+    }
     m_client->didReceiveData(WTFMove(buffer));
 }
 
@@ -186,9 +200,26 @@ 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);
+        FileSystem::closeFile(m_downloadDestinationFile);
+        m_downloadDestinationFile = FileSystem::invalidPlatformFileHandle;
+        download->didFinish();
+        return;
+    }
     m_client->didCompleteWithError({ }, WTFMove(networkLoadMetrics));
 }
 
+void NetworkDataTaskCurl::deleteDownloadFile()
+{
+    if (m_downloadDestinationFile != FileSystem::invalidPlatformFileHandle) {
+        FileSystem::closeFile(m_downloadDestinationFile);
+        FileSystem::deleteFile(m_pendingDownloadLocation);
+        m_downloadDestinationFile = FileSystem::invalidPlatformFileHandle;
+    }
+}
+
 void NetworkDataTaskCurl::curlDidFailWithError(CurlRequest& request, ResourceError&& resourceError, CertificateInfo&& certificateInfo)
 {
     if (state() == State::Canceling || state() == State::Completed || (!m_client && !isDownload()))
@@ -199,6 +230,14 @@ void NetworkDataTaskCurl::curlDidFailWithError(CurlRequest& request, ResourceErr
         return;
     }
 
+    if (isDownload()) {
+        deleteDownloadFile();
+        auto* download = m_session->networkProcess().downloadManager().download(m_pendingDownloadID);
+        ASSERT(download);
+        download->didFail(resourceError, IPC::DataReference());
+        return;
+    }
+
     m_client->didCompleteWithError(resourceError);
 }
 
@@ -236,6 +275,19 @@ void NetworkDataTaskCurl::invokeDidReceiveResponse()
         case PolicyAction::Ignore:
             invalidateAndCancel();
             break;
+        case PolicyAction::Download: {
+            FileSystem::deleteFile(m_pendingDownloadLocation);
+            auto& downloadManager = m_session->networkProcess().downloadManager();
+            auto download = makeUnique<Download>(downloadManager, m_pendingDownloadID, *this, *m_session, suggestedFilename());
+            auto* downloadPtr = download.get();
+            downloadManager.dataTaskBecameDownloadTask(m_pendingDownloadID, WTFMove(download));
+            m_downloadDestinationFile = FileSystem::openFile(m_pendingDownloadLocation, FileSystem::FileOpenMode::Write);
+            downloadPtr->didCreateDestination(m_pendingDownloadLocation);
+
+            if (m_curlRequest)
+                m_curlRequest->completeDidReceiveResponse();
+            break;
+        }
         default:
             notImplemented();
             break;
@@ -315,6 +367,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->start();
 
         if (m_state != State::Suspended) {
diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h
index 1c427ddb78d6953fe8960c5692afde4f4f0eee85..cf33ff6076dd95ffe564f1dde89c177acd27b02c 100644
--- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h
+++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h
@@ -32,6 +32,7 @@
 #include <WebCore/ProtectionSpace.h>
 #include <WebCore/ResourceResponse.h>
 #include <WebCore/ShouldRelaxThirdPartyCookieBlocking.h>
+#include <wtf/FileSystem.h>
 #include <wtf/MonotonicTime.h>
 
 namespace WebCore {
@@ -85,13 +86,13 @@ 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&);
     void blockCookies();
     void unblockCookies();
-
-    String suggestedFilename() const override;
+    void deleteDownloadFile();
 
     State m_state { State::Suspended };
 
@@ -103,6 +104,8 @@ private:
     WebCore::FrameIdentifier m_frameID;
     WebCore::PageIdentifier m_pageID;
 
+    FileSystem::PlatformFileHandle m_downloadDestinationFile { FileSystem::invalidPlatformFileHandle };
+
     bool m_blockingCookies { false };
 
     WebCore::ShouldRelaxThirdPartyCookieBlocking m_shouldRelaxThirdPartyCookieBlocking { WebCore::ShouldRelaxThirdPartyCookieBlocking::No };
diff --git a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
index e67e05ba8478a581830e397068b32fb08d91b7ed..898f4f228753ef2cee226a9f486556b84fd7bf62 100644
--- a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
+++ b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
@@ -493,6 +493,8 @@ void NetworkDataTaskSoup::didSendRequest(GRefPtr<GInputStream>&& inputStream)
             m_networkLoadMetrics.failsTAOCheck = !passesTimingAllowOriginCheck(m_response, *origin);
     }
 
+    auto& additionalMetrics = additionalNetworkLoadMetricsForWebInspector();
+    m_response.m_httpRequestHeaderFields = additionalMetrics.requestHeaders;
     dispatchDidReceiveResponse();
 }
 
@@ -590,6 +592,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<NetworkSessionSoup&>(*m_session).soupNetworkSession().checkTLSErrors(url, certificate, tlsErrors);
     if (!error)
         return true;
@@ -1217,6 +1221,12 @@ WebCore::AdditionalNetworkLoadMetricsForWebInspector& NetworkDataTaskSoup::addit
     return *m_networkLoadMetrics.additionalNetworkLoadMetricsForWebInspector;
 }
 
+static void headers_size(const char *name, const char *value, gpointer pointer)
+{
+    int* size = static_cast<int*>(pointer);
+    *size += strlen(name) + strlen(value) + 4;
+}
+
 void NetworkDataTaskSoup::didGetHeaders()
 {
     // We are a bit more conservative with the persistent credential storage than the session store,
@@ -1262,6 +1272,20 @@ void NetworkDataTaskSoup::didGetHeaders()
         additionalMetrics.tlsProtocol = tlsProtocolVersionToString(soup_message_get_tls_protocol_version(m_soupMessage.get()));
         additionalMetrics.tlsCipher = String::fromUTF8(soup_message_get_tls_ciphersuite_name(m_soupMessage.get()));
         additionalMetrics.responseHeaderBytesReceived = soup_message_metrics_get_response_header_bytes_received(metrics);
+#else
+        {
+            auto* requestHeaders = soup_message_get_request_headers(m_soupMessage.get());
+            int requestHeadersSize = 0;
+            soup_message_headers_foreach(requestHeaders, headers_size, &requestHeadersSize);
+            additionalMetrics.requestHeaderBytesSent = requestHeadersSize;
+        }
+
+        {
+            auto* responseHeaders = soup_message_get_response_headers(m_soupMessage.get());
+            int responseHeadersSize = 0;
+            soup_message_headers_foreach(responseHeaders, headers_size, &responseHeadersSize);
+            additionalMetrics.responseHeaderBytesReceived = responseHeadersSize;
+        }
 #endif
     }
 
diff --git a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
index 9873026a091fdf2974be1a1e734e6f5b30a7d7c5..17f2905841f190ab2e18862c5df477c4994bde5f 100644
--- a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
+++ b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
@@ -109,6 +109,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)
@@ -119,6 +124,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<WebSocketTask> NetworkSessionSoup::createWebSocketTask(WebPageProxyIdentifier, NetworkSocketChannel& channel, const ResourceRequest& request, const String& protocol)
 {
     GRefPtr<SoupMessage> soupMessage = request.createSoupMessage(blobRegistry());
@@ -127,14 +141,21 @@ std::unique_ptr<WebSocketTask> NetworkSessionSoup::createWebSocketTask(WebPagePr
 
     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<WebSocketTask>(channel, request, soupSession(), soupMessage.get(), protocol);
diff --git a/Source/WebKit/PlatformGTK.cmake b/Source/WebKit/PlatformGTK.cmake
index 826e2db522c2a7b3b895e8735aeb47b2c38e299f..da3f72fb1ff59978fae76d8578677d58fd3246c8 100644
--- a/Source/WebKit/PlatformGTK.cmake
+++ b/Source/WebKit/PlatformGTK.cmake
@@ -465,6 +465,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)
@@ -518,6 +521,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 ()
 
@@ -532,6 +538,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 ${WebKit2Gtk_DERIVED_SOURCES_DIR}/webkit/WebKitEnumTypes.h)
diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake
index 529644655e0120d862ee8e886e67ac9f12692037..dc3cf7b3bafe259d44b04a16b6903b3b2b0c4b57 100644
--- a/Source/WebKit/PlatformWPE.cmake
+++ b/Source/WebKit/PlatformWPE.cmake
@@ -172,6 +172,7 @@ set(WPE_API_INSTALLED_HEADERS
     ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitOptionMenuItem.h
     ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitPermissionRequest.h
     ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitPlugin.h
+    ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitPointerLockPermissionRequest.h
     ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitPolicyDecision.h
     ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitRectangle.h
     ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitResponsePolicyDecision.h
@@ -298,6 +299,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"
@@ -320,8 +322,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 350fdd497eaaab711059c54b5075015b19379368..bf5cd7221e1a131dd880d11e968b132782359937 100644
--- a/Source/WebKit/PlatformWin.cmake
+++ b/Source/WebKit/PlatformWin.cmake
@@ -75,8 +75,12 @@ list(APPEND WebKit_SOURCES
 
     UIProcess/wc/DrawingAreaProxyWC.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
@@ -94,6 +98,7 @@ list(APPEND WebKit_SOURCES
     WebProcess/MediaCache/WebMediaKeyStorageManager.cpp
 
     WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp
+    WebProcess/WebCoreSupport/win/WebDragClientWin.cpp
 
     WebProcess/WebPage/AcceleratedSurface.cpp
 
@@ -149,6 +154,72 @@ list(APPEND WebKit_MESSAGES_IN_FILES
     WebProcess/GPU/graphics/wc/RemoteWCLayerTreeHostProxy
 )
 
+# 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_mmi.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_msa.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon64.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_win.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_argb.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from_argb.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from.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/rotate_any.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_argb.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate.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_mmi.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_msa.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon64.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon.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_mmi.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_msa.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon64.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_win.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.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_mmi.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_msa.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon64.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon.cc"
+    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_uv.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})
 
@@ -201,6 +272,7 @@ if (${WTF_PLATFORM_WIN_CAIRO})
         OpenSSL::SSL
         mfuuid.lib
         strmiids.lib
+        ${LIBVPX_CUSTOM_LIBRARY}
     )
 endif ()
 
diff --git a/Source/WebKit/Scripts/generate-unified-sources.sh b/Source/WebKit/Scripts/generate-unified-sources.sh
index b6d40ad9e9547bd40de85c9c85a35c1e25cdf191..4f1ac83cb3a226eccd07839837923cbc44bab923 100755
--- a/Source/WebKit/Scripts/generate-unified-sources.sh
+++ b/Source/WebKit/Scripts/generate-unified-sources.sh
@@ -14,7 +14,7 @@ if [ -z "${BUILD_SCRIPTS_DIR}" ]; then
     fi
 fi
 
-UnifiedSourceCppFileCount=111
+UnifiedSourceCppFileCount=112
 UnifiedSourceMmFileCount=80
 
 if [ $# -eq 0 ]; then
diff --git a/Source/WebKit/Shared/API/c/wpe/WebKit.h b/Source/WebKit/Shared/API/c/wpe/WebKit.h
index caf67e1dece5b727e43eba780e70814f8fdb0f63..740150d2589d6e16a516daa3bf6ef899ac538c99 100644
--- a/Source/WebKit/Shared/API/c/wpe/WebKit.h
+++ b/Source/WebKit/Shared/API/c/wpe/WebKit.h
@@ -77,6 +77,7 @@
 // From Source/WebKit/UIProcess/API/C
 #include <WebKit/WKBackForwardListItemRef.h>
 #include <WebKit/WKBackForwardListRef.h>
+#include <WebKit/WKBrowserInspector.h>
 #include <WebKit/WKContext.h>
 #include <WebKit/WKContextConfigurationRef.h>
 #include <WebKit/WKCredential.h>
diff --git a/Source/WebKit/Shared/NativeWebKeyboardEvent.h b/Source/WebKit/Shared/NativeWebKeyboardEvent.h
index ee8cac1c980039c4a36de5501ab7f135e710d06b..deae2be9e720ff76186ecea89920dfc39c4f186a 100644
--- a/Source/WebKit/Shared/NativeWebKeyboardEvent.h
+++ b/Source/WebKit/Shared/NativeWebKeyboardEvent.h
@@ -33,6 +33,7 @@
 #if USE(APPKIT)
 #include <wtf/RetainPtr.h>
 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<WebCore::KeypressCommand>&);
+    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<Modifier> modifiers, WallTime timestamp, Vector<WebCore::KeypressCommand>&& 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<String>&& commands);
     NativeWebKeyboardEvent(const String&, std::optional<Vector<WebCore::CompositionUnderline>>&&, std::optional<EditingRange>&&);
     NativeWebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, Vector<String>&& commands, bool isKeypad, OptionSet<Modifier>);
+    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<Modifier> modifiers, WallTime timestamp, Vector<String>&& 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, std::optional<Vector<WebCore::CompositionUnderline>>&&, std::optional<EditingRange>&&);
+    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<Modifier> 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<MSG>&& 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<Modifier> 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 001558dd58f4d85f360d5711caa03db33889011e..1e0898f985f1d13036d31e3e284258a3c64fa0a4 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<Modifier> 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/NativeWebWheelEvent.h b/Source/WebKit/Shared/NativeWebWheelEvent.h
index f2f3979fcac9dfd97d0e0ead600fe35eb8defd40..ac91412e1a96bdf521b1890a66e465dc54293d31 100644
--- a/Source/WebKit/Shared/NativeWebWheelEvent.h
+++ b/Source/WebKit/Shared/NativeWebWheelEvent.h
@@ -67,7 +67,8 @@ public:
 #elif PLATFORM(WIN)
     NativeWebWheelEvent(HWND, UINT message, WPARAM, LPARAM);
 #endif
-
+    NativeWebWheelEvent(const WebWheelEvent & webWheelEvent)
+        : WebWheelEvent(webWheelEvent) { }
 #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 64982bc48102a4adb20a7e60e21bd492d653374c..bae76818c6260b9bf93fc2e4a601b5b6581a2716 100644
--- a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
+++ b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
@@ -119,6 +119,10 @@
 #include <WebCore/TextRecognitionResult.h>
 #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 {
@@ -1379,6 +1383,9 @@ void ArgumentCoder<WindowFeatures>::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<WindowFeatures>::decode(Decoder& decoder, WindowFeatures& windowFeatures)
@@ -1407,6 +1414,12 @@ bool ArgumentCoder<WindowFeatures>::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;
 }
 
@@ -1420,6 +1433,11 @@ void ArgumentCoder<DragData>::encode(Encoder& encoder, const DragData& dragData)
 #if PLATFORM(COCOA)
     encoder << dragData.pasteboardName();
     encoder << dragData.fileNames();
+#endif
+#if PLATFORM(WIN)
+    DragData dragDataCopy = dragData;
+    HashMap<unsigned int, Vector<String>> hash = dragDataCopy.dragDataMap();
+    encoder << hash;
 #endif
     encoder << dragData.dragDestinationActionMask();
     encoder << dragData.pageID();
@@ -1443,9 +1461,16 @@ bool ArgumentCoder<DragData>::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<String> fileNames;
+#endif
+
 #if PLATFORM(COCOA)
+    Vector<String> fileNames;
     if (!decoder.decode(pasteboardName))
         return false;
 
@@ -1461,8 +1486,14 @@ bool ArgumentCoder<DragData>::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 <wtf/EnumTraits.h>
 #include <wtf/OptionSet.h>
+#include <wtf/RefCounted.h>
 #include <wtf/WallTime.h>
 #include <wtf/text/WTFString.h>
 
diff --git a/Source/WebKit/Shared/WebKeyboardEvent.cpp b/Source/WebKit/Shared/WebKeyboardEvent.cpp
index 3679736973ebc06771c7d94591909688f28a70b4..8df0a8e223551e2ee73e816adcb3b31153c54eb5 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<WebCore::KeypressCommand>& commands, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> 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<Modifier> modifiers, WallTime timestamp, Vector<WebCore::KeypressCommand>&& 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, std::optional<Vector<WebCore::CompositionUnderline>>&& preeditUnderlines, std::optional<EditingRange>&& preeditSelectionRange, Vector<String>&& commands, bool isKeypad, OptionSet<Modifier> 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<Modifier> modifiers, WallTime timestamp, Vector<String>&& 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<Modifier> modifiers, WallTime timestamp)
@@ -142,6 +179,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<Modifier> 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 1817691d3e12ddec8169248c791826cc13b057e3..cdc90eda23ed5ba20ee78a02c0dd632be4bc615a 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<WebCore::KeypressCommand>&, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, 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<Modifier>, WallTime timestamp, Vector<WebCore::KeypressCommand>&& commands);
 #elif PLATFORM(GTK)
     WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, std::optional<Vector<WebCore::CompositionUnderline>>&&, std::optional<EditingRange>&&, Vector<String>&& commands, bool isKeypad, OptionSet<Modifier>, 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<Modifier>, WallTime timestamp, Vector<String>&& 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<Modifier>, 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, std::optional<Vector<WebCore::CompositionUnderline>>&&, std::optional<EditingRange>&&, bool isKeypad, OptionSet<Modifier>, 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<Modifier>, 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<Modifier>, 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<Modifier>, WallTime timestamp);
 #endif
 
     const String& text() const { return m_text; }
diff --git a/Source/WebKit/Shared/WebMouseEvent.h b/Source/WebKit/Shared/WebMouseEvent.h
index 3dbe10d49b4de34636900efe31fb57e7e60e341c..1457cbaad0bf5c3b17902fd8c2f243a2c0688716 100644
--- a/Source/WebKit/Shared/WebMouseEvent.h
+++ b/Source/WebKit/Shared/WebMouseEvent.h
@@ -59,6 +59,7 @@ public:
 
     Button button() const { return static_cast<Button>(m_button); }
     unsigned short buttons() const { return m_buttons; }
+    void playwrightSetButtons(unsigned short buttons) { m_buttons = buttons; }
     const WebCore::IntPoint& position() const { return m_position; } // Relative to the view.
     const WebCore::IntPoint& globalPosition() const { return m_globalPosition; }
     float deltaX() const { return m_deltaX; }
diff --git a/Source/WebKit/Shared/WebPageCreationParameters.cpp b/Source/WebKit/Shared/WebPageCreationParameters.cpp
index 582c5e3be33511629ccc66f821ecf2e01bc536d9..2d1bb12439f1f720c8ff77130f56d1ced2915127 100644
--- a/Source/WebKit/Shared/WebPageCreationParameters.cpp
+++ b/Source/WebKit/Shared/WebPageCreationParameters.cpp
@@ -158,6 +158,8 @@ void WebPageCreationParameters::encode(IPC::Encoder& encoder) const
     encoder << crossOriginAccessControlCheckEnabled;
     encoder << processDisplayName;
 
+    encoder << shouldPauseInInspectorWhenShown;
+
     encoder << shouldCaptureAudioInUIProcess;
     encoder << shouldCaptureAudioInGPUProcess;
     encoder << shouldCaptureVideoInUIProcess;
@@ -549,7 +551,10 @@ std::optional<WebPageCreationParameters> WebPageCreationParameters::decode(IPC::
     if (!processDisplayName)
         return std::nullopt;
     parameters.processDisplayName = WTFMove(*processDisplayName);
-    
+
+    if (!decoder.decode(parameters.shouldPauseInInspectorWhenShown))
+        return std::nullopt;
+
     if (!decoder.decode(parameters.shouldCaptureAudioInUIProcess))
         return std::nullopt;
 
diff --git a/Source/WebKit/Shared/WebPageCreationParameters.h b/Source/WebKit/Shared/WebPageCreationParameters.h
index ebd51f5461fd35aa408fcde6927a16186374f6a9..fc2274d0f5b03f5ff3eb5b20060b24c473d9bdb1 100644
--- a/Source/WebKit/Shared/WebPageCreationParameters.h
+++ b/Source/WebKit/Shared/WebPageCreationParameters.h
@@ -254,6 +254,8 @@ struct WebPageCreationParameters {
 
     WebCore::ShouldRelaxThirdPartyCookieBlocking shouldRelaxThirdPartyCookieBlocking { WebCore::ShouldRelaxThirdPartyCookieBlocking::No };
 
+    bool shouldPauseInInspectorWhenShown { false };
+
 #if PLATFORM(GTK)
     GtkSettingsState gtkSettings;
 #endif
diff --git a/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp b/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp
index 2d1c6dc88b16b7be6b9b14e8806d758ca176a7a8..c226107217233063822cb4d0c356f6333edabd2a 100644
--- a/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp
+++ b/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp
@@ -162,7 +162,9 @@ bool defaultOfflineWebApplicationCacheEnabled()
 
 bool defaultUseGPUProcessForCanvasRenderingEnabled()
 {
-#if ENABLE(GPU_PROCESS_BY_DEFAULT) || PLATFORM(WIN)
+#if PLATFORM(WIN)
+    bool defaultValue = false; // Playwright: force-disable on Windows
+#elif ENABLE(GPU_PROCESS_BY_DEFAULT)
     bool defaultValue = true;
 #else
     bool defaultValue = false;
@@ -190,7 +192,7 @@ bool defaultUseGPUProcessForMediaEnabled()
 bool defaultUseGPUProcessForWebGLEnabled()
 {
 #if PLATFORM(WIN)
-    bool defaultValue = true;
+    bool defaultValue = false; // Playwright: force disable on Windows
 #else
     bool defaultValue = false;
 #endif
diff --git a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
index c204637774ee803eac42a34cde79aa556f143b82..345f5b08179e3dd239725bed06e48b46bc718336 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(), std::optional<Vector<WebCore::CompositionUnderline>>(event.preeditUnderlines()), std::optional<EditingRange>(event.preeditSelectionRange()), Vector<String>(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 7cc65739c320cb4312d9d705284220a383a0293a..da53885517d55d424423ee3d0dcead25825cc022 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<GdkEvent*>(event.nativeEvent())) : nullptr)
 {
 }
diff --git a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
index 03e118154f6bb5b704b4ecb83d3d9543f8c5a5fa..9725caaac6ee65a96ea324ddbb4e1a3785bbc028 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 @@ std::optional<WebPlatformTouchPoint> WebPlatformTouchPoint::decode(IPC::Decoder&
 
 } // 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..678010b33d70dae6369ace4337b4c0eb81152250
--- /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 <WebCore/GraphicsContext.h>
+#include <WebCore/Image.h>
+#include <WebCore/SelectionData.h>
+
+namespace IPC {
+using namespace WebCore;
+using namespace WebKit;
+
+static void encodeImage(Encoder& encoder, Image& image)
+{
+    RefPtr<ShareableBitmap> 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>& image)
+{
+    ShareableBitmap::Handle handle;
+    if (!decoder.decode(handle))
+        return false;
+
+    RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(handle);
+    if (!bitmap)
+        return false;
+    image = bitmap->createImage();
+    if (!image)
+        return false;
+    return true;
+}
+
+void ArgumentCoder<SelectionData>::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<SharedBuffer>(selection.customData());
+
+    bool canSmartReplace = selection.canSmartReplace();
+    encoder << canSmartReplace;
+}
+
+std::optional<SelectionData> ArgumentCoder<SelectionData>::decode(Decoder& decoder)
+{
+    SelectionData selection;
+
+    bool hasText;
+    if (!decoder.decode(hasText))
+        return std::nullopt;
+    if (hasText) {
+        String text;
+        if (!decoder.decode(text))
+            return std::nullopt;
+        selection.setText(text);
+    }
+
+    bool hasMarkup;
+    if (!decoder.decode(hasMarkup))
+        return std::nullopt;
+    if (hasMarkup) {
+        String markup;
+        if (!decoder.decode(markup))
+            return std::nullopt;
+        selection.setMarkup(markup);
+    }
+
+    bool hasURL;
+    if (!decoder.decode(hasURL))
+        return std::nullopt;
+    if (hasURL) {
+        String url;
+        if (!decoder.decode(url))
+            return std::nullopt;
+        selection.setURL(URL(URL(), url), String());
+    }
+
+    bool hasURIList;
+    if (!decoder.decode(hasURIList))
+        return std::nullopt;
+    if (hasURIList) {
+        String uriList;
+        if (!decoder.decode(uriList))
+            return std::nullopt;
+        selection.setURIList(uriList);
+    }
+
+    bool hasImage;
+    if (!decoder.decode(hasImage))
+        return std::nullopt;
+    if (hasImage) {
+        RefPtr<Image> image;
+        if (!decodeImage(decoder, image))
+            return std::nullopt;
+        selection.setImage(image.get());
+    }
+
+    bool hasCustomData;
+    if (!decoder.decode(hasCustomData))
+        return std::nullopt;
+    if (hasCustomData) {
+        RefPtr<SharedBuffer> buffer;
+        if (!decoder.decode(buffer))
+            return std::nullopt;
+        selection.setCustomData(Ref<SharedBuffer>(*buffer));
+    }
+
+    bool canSmartReplace;
+    if (!decoder.decode(canSmartReplace))
+        return std::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..789a0d7cf69704c8f665a9ed79348fbcbc1301c4
--- /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<WebCore::SelectionData> {
+    static void encode(Encoder&, const WebCore::SelectionData&);
+    static std::optional<WebCore::SelectionData> decode(Decoder&);
+};
+
+} // namespace IPC
diff --git a/Source/WebKit/Shared/win/WebEventFactory.cpp b/Source/WebKit/Shared/win/WebEventFactory.cpp
index 85d6f74114f4e7f82d9502d1b99d69098d6a49b6..6896c9756edb233dda46c7031e1af69923da8c23 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<WebPlatformTouchPoint>&& touchPoints)
+WebTouchEvent WebEventFactory::createWebTouchEvent()
 {
     return WebTouchEvent();
 }
diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt
index 05a85b0196042016ab685f20d4bef73c46265607..605962d551e56959656ffe39b031cd8731e61ac7 100644
--- a/Source/WebKit/Sources.txt
+++ b/Source/WebKit/Sources.txt
@@ -388,11 +388,14 @@ Shared/XR/XRDeviceProxy.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
@@ -401,6 +404,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
@@ -442,6 +446,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
@@ -563,7 +569,11 @@ UIProcess/Inspector/WebInspectorUtilities.cpp
 UIProcess/Inspector/WebPageDebuggable.cpp
 UIProcess/Inspector/WebPageInspectorController.cpp
 
+UIProcess/Inspector/Agents/CairoJpegEncoder.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 c8be55869276e50620bd335c00e666df2c454a94..cd3ba1872ae0406bd183de4b53854794de17a093 100644
--- a/Source/WebKit/SourcesCocoa.txt
+++ b/Source/WebKit/SourcesCocoa.txt
@@ -270,6 +270,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
@@ -442,6 +443,7 @@ UIProcess/Inspector/ios/WKInspectorHighlightView.mm
 UIProcess/Inspector/ios/WKInspectorNodeSearchGestureRecognizer.mm
 
 UIProcess/Inspector/mac/RemoteWebInspectorUIProxyMac.mm
+UIProcess/Inspector/mac/ScreencastEncoderMac.mm
 UIProcess/Inspector/mac/WebInspectorUIProxyMac.mm
 UIProcess/Inspector/mac/WKInspectorResourceURLSchemeHandler.mm
 UIProcess/Inspector/mac/WKInspectorViewController.mm
diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt
index f21246f00c18f2381fcee7317f9649f1b661e342..dc2fe29b9dcf0cf9726a38797806dd886e603e2a 100644
--- a/Source/WebKit/SourcesGTK.txt
+++ b/Source/WebKit/SourcesGTK.txt
@@ -127,6 +127,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
@@ -242,6 +243,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
@@ -259,6 +261,7 @@ UIProcess/gtk/ClipboardGtk4.cpp @no-unify
 UIProcess/gtk/WebDateTimePickerGtk.cpp
 UIProcess/gtk/GtkSettingsManager.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
@@ -271,6 +274,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 94419dd86f079c5c53e68ce8e79b915505a87ab0..076d3c33ccbdd2894239375a308df5bd61c59242 100644
--- a/Source/WebKit/SourcesWPE.txt
+++ b/Source/WebKit/SourcesWPE.txt
@@ -86,6 +86,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
@@ -120,6 +121,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
@@ -154,6 +156,7 @@ UIProcess/API/glib/WebKitOptionMenu.cpp @no-unify
 UIProcess/API/glib/WebKitOptionMenuItem.cpp @no-unify
 UIProcess/API/glib/WebKitPermissionRequest.cpp @no-unify
 UIProcess/API/glib/WebKitPlugin.cpp @no-unify
+UIProcess/API/glib/WebKitPointerLockPermissionRequest.cpp @no-unify
 UIProcess/API/glib/WebKitPolicyDecision.cpp @no-unify
 UIProcess/API/glib/WebKitPrivate.cpp @no-unify
 UIProcess/API/glib/WebKitProtocolHandler.cpp @no-unify
@@ -186,6 +189,7 @@ UIProcess/API/wpe/InputMethodFilterWPE.cpp @no-unify
 UIProcess/API/wpe/PageClientImpl.cpp @no-unify
 UIProcess/API/wpe/TouchGestureController.cpp @no-unify
 UIProcess/API/wpe/WebKitColor.cpp @no-unify
+UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.cpp @no-unify
 UIProcess/API/wpe/WebKitInputMethodContextWPE.cpp @no-unify
 UIProcess/API/wpe/WebKitPopupMenu.cpp @no-unify
 UIProcess/API/wpe/WebKitRectangle.cpp @no-unify
@@ -202,6 +206,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
@@ -224,6 +229,11 @@ UIProcess/linux/MemoryPressureMonitor.cpp
 UIProcess/soup/WebCookieManagerProxySoup.cpp
 UIProcess/soup/WebProcessPoolSoup.cpp
 
+UIProcess/wpe/InspectorTargetProxyWPE.cpp
+UIProcess/wpe/WebColorPickerWPE.cpp
+UIProcess/wpe/WebDateTimePickerWPE.cpp
+UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp
+UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
 UIProcess/wpe/WebPageProxyWPE.cpp
 
 WebProcess/GPU/media/gstreamer/VideoLayerRemoteGStreamer.cpp
@@ -252,6 +262,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 cfd9c3981337c7dd02c623ce8ba686ea36bbffb9..27148d775f97804de9d7a88d57ba1dd5f60c8e16 100644
--- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
+++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
@@ -54,6 +54,9 @@ Ref<ProcessPoolConfiguration> ProcessPoolConfiguration::copy()
     copy->m_attrStyleEnabled = this->m_attrStyleEnabled;
     copy->m_shouldThrowExceptionForGlobalConstantRedeclaration = this->m_shouldThrowExceptionForGlobalConstantRedeclaration;
     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 cc642c51ba663e843df54d14cfccb6d4ef81726c..229ae1a7df1e418f9b09bf9c3c3bb1edc3292a7c 100644
--- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
+++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
@@ -102,6 +102,11 @@ public:
     const Vector<WTF::String>& overrideLanguages() const { return m_overrideLanguages; }
     void setOverrideLanguages(Vector<WTF::String>&& 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; }
 
@@ -175,6 +180,9 @@ private:
     bool m_attrStyleEnabled { false };
     bool m_shouldThrowExceptionForGlobalConstantRedeclaration { true };
     Vector<WTF::String> 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 2016cb48dd38e195271578c86103f4cbcc651429..469878cbbcafe4c6033068ce385fc9f8fbe14d58 100644
--- a/Source/WebKit/UIProcess/API/APIUIClient.h
+++ b/Source/WebKit/UIProcess/API/APIUIClient.h
@@ -103,6 +103,7 @@ public:
     virtual void runJavaScriptAlert(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function<void()>&& completionHandler) { completionHandler(); }
     virtual void runJavaScriptConfirm(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function<void(bool)>&& completionHandler) { completionHandler(false); }
     virtual void runJavaScriptPrompt(WebKit::WebPageProxy&, const WTF::String&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function<void(const WTF::String&)>&& 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<WebKit::WebEvent::Modifier>, Object*) { }
diff --git a/Source/WebKit/UIProcess/API/C/WKInspector.cpp b/Source/WebKit/UIProcess/API/C/WKInspector.cpp
index e1465edd29caf3109c17d44bb3c88aaba98cfbb5..32d569d3240c583334b8b6512407430fd448ae75 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 "WebInspectorUIProxy.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<InspectorPlaywrightAgentClientWin>(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 92ffd2147089216b00fe371cdbc3adf787defce7..c588d60634701ad4c1cec974cfb680806ea7e096 100644
--- a/Source/WebKit/UIProcess/API/C/WKPage.cpp
+++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp
@@ -1775,6 +1775,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)
@@ -1804,6 +1811,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 ed980be17cdf9faec3f7af1bdc7cfd640bab8fc2..ca3c0ff1ec6d30173ae15e786f30ef1bad0e5bb6 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/WKUIDelegate.h b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h
index 82003ea11098fa60e7ac7e2cdd29ea86154c7ccb..b0ebb2874de88f8e11c515d973b4e2cea160304a 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h
@@ -135,6 +135,12 @@ typedef NS_ENUM(NSInteger, WKMediaCaptureType) {
  */
 - (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;
 
 /*! @abstract A delegate to request permission for microphone audio and camera video access.
  @param webView The web view invoking the delegate method.
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h
index afa925f36c29db9c23921298dead9cce737500d6..42d396342acdb6d39830f611df0ee40ea6ec879e 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h
@@ -24,7 +24,6 @@
  */
 
 #import <WebKit/WKFoundation.h>
-
 #import <WebKit/WKWebsiteDataRecord.h>
 
 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 7ef06950ab07d3e1a7616cbcb58bd25785359ec7..fa1320d8842b593c3ff2907a9daf2cc25ec1ef39 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
@@ -44,6 +44,7 @@
 #import "_WKResourceLoadStatisticsThirdPartyInternal.h"
 #import "_WKWebsiteDataStoreConfigurationInternal.h"
 #import "_WKWebsiteDataStoreDelegate.h"
+#import <pal/SessionID.h>
 #import <WebCore/Credential.h>
 #import <WebCore/RegistrationDatabase.h>
 #import <WebCore/VersionChecks.h>
@@ -205,6 +206,11 @@ static WallTime toSystemClockTime(NSDate *date)
     });
 }
 
+- (uint64_t) sessionID
+{
+    return _websiteDataStore->sessionID().toUInt64();
+}
+
 static Vector<WebKit::WebsiteDataRecord> toWebsiteDataRecords(NSArray *dataRecords)
 {
     Vector<WebKit::WebsiteDataRecord> 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 <WebKit/WKFoundation.h>
+#import <WebKit/WKProcessPool.h>
+#import <WebKit/WKWebsiteDataStore.h>
+#import <Foundation/Foundation.h>
+
+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 <NSObject>
+- (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<InspectorPlaywrightAgentClientMac>(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 1f4c571931265c75912f8d24c795d0c522ee74f6..71ca08f3b335d97124db9c216bc5a6ba327ad5f3 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 <wtf/cocoa/VectorCocoa.h>
 #import <wtf/WeakObjCPtr.h>
 
 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 <wtf/RetainPtr.h>
 
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKInspectorExtension.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKInspectorExtension.mm
index 580e718dd168a0195024852d40cc45c2c1826712..cf52b56614c98237fce83ce09e13095031163978 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 <wtf/BlockPtr.h>
+#import <wtf/URL.h>
 
 #if ENABLE(INSPECTOR_EXTENSIONS)
 
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
index 784983c103b29ca3c774c6204926594ebc8dfee4..08ad04cd82b4187eed05b3fa18f01bd38ecbe207 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
@@ -66,6 +66,7 @@ WK_CLASS_AVAILABLE(macos(10.10), ios(8.0))
 @property (nonatomic) pid_t presentingApplicationPID WK_API_AVAILABLE(macos(10.13), ios(11.0));
 @property (nonatomic) audit_token_t presentingApplicationProcessToken WK_API_AVAILABLE(macos(10.13), ios(11.3));
 @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 processSwapsOnNavigationWithinSameNonHTTPFamilyProtocol WK_API_AVAILABLE(macos(12.0), ios(15.0));
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
index 92b509ad482f4d3b5a69a00b0fd23c4d0aab16ae..33c77395b21577e8c6911a60fb1c674a75837c8f 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
@@ -257,6 +257,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 00b250e5d3ee4dbd4537e23fcb1f6e44a454607c..e1701062ef7df02ed7b83ff19c84df0fe43e4661 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 1e827013c603ae8bd43d798170deb98fc3153852..2075bc78069bde530ec237c0b761773c10013948 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm
@@ -35,6 +35,7 @@
 #import "WebPageProxy.h"
 #import "_WKUserContentWorldInternal.h"
 #import <WebCore/WebCoreObjCExtras.h>
+#import <WebKit/WKContentWorldInternal.h>
 #import <wtf/cocoa/VectorCocoa.h>
 
 @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 <wtf/glib/GRefPtr.h>
+#include <wtf/glib/WTFGType.h>
+
+/**
+ * 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<WebKitBrowserInspector> 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<WebKit::InspectorPlaywrightAgentClientGlib>(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 64c90f9f25fc44911e819ab94fa973bf0b82a0e4..8d8c739fb903b71f7881801cb41901f241709b2a 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
+++ b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
@@ -98,6 +98,10 @@ private:
         page.makeViewBlankIfUnpaintedSinceLastLoadCommit();
         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 1b128a4c6825de9f93550725c5195f4ab0443548..eb6114654dc8961140693f9bbbdcc87d33901a6e 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
+++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
@@ -121,8 +121,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_SYSTEM_APPEARANCE_FOR_SCROLLBARS,
 #endif
@@ -210,8 +210,8 @@ struct _WebKitWebContextPrivate {
 
     RefPtr<WebProcessPool> processPool;
     bool clientsDetached;
-#if PLATFORM(GTK)
     bool psonEnabled;
+#if PLATFORM(GTK)
 #if !USE(GTK4)
     bool useSystemAppearanceForScrollbars;
 #endif
@@ -312,11 +312,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
@@ -341,10 +339,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_SYSTEM_APPEARANCE_FOR_SCROLLBARS:
         g_value_set_boolean(value, webkit_web_context_get_use_system_appearance_for_scrollbars(context));
@@ -371,10 +369,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_SYSTEM_APPEARANCE_FOR_SCROLLBARS:
         webkit_web_context_set_use_system_appearance_for_scrollbars(context, g_value_get_boolean(value));
@@ -391,10 +389,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<char> bundleFilename(g_build_filename(injectedBundleDirectory(), INJECTED_BUNDLE_FILENAME, nullptr));
 
     WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(object);
@@ -403,8 +410,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
@@ -446,6 +453,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;
@@ -514,7 +523,6 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass
             WEBKIT_TYPE_WEBSITE_DATA_MANAGER,
             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
-#if PLATFORM(GTK)
     /**
      * WebKitWebContext:process-swap-on-cross-site-navigation-enabled:
      *
@@ -536,6 +544,7 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass
             FALSE,
             static_cast<GParamFlags>(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 4e5d73257144b51dd42a4efacc70eefcce853e95..eef10d6772ca98525717ad1834aa78cb6846a5eb 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
+++ b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
@@ -32,6 +32,7 @@
 #include "WebCertificateInfo.h"
 #include "WebContextMenuItem.h"
 #include "WebContextMenuItemData.h"
+#include "WebPageInspectorController.h"
 #include "WebKitAuthenticationRequestPrivate.h"
 #include "WebKitBackForwardListPrivate.h"
 #include "WebKitContextMenuClient.h"
@@ -51,6 +52,7 @@
 #include "WebKitJavascriptResultPrivate.h"
 #include "WebKitNavigationClient.h"
 #include "WebKitNotificationPrivate.h"
+#include "WebKitPointerLockPermissionRequest.h"
 #include "WebKitPrivate.h"
 #include "WebKitResponsePolicyDecision.h"
 #include "WebKitScriptDialogPrivate.h"
@@ -85,7 +87,6 @@
 
 #if PLATFORM(GTK)
 #include "WebKitInputMethodContextImplGtk.h"
-#include "WebKitPointerLockPermissionRequest.h"
 #include "WebKitPrintOperationPrivate.h"
 #include "WebKitWebInspectorPrivate.h"
 #include "WebKitWebViewBasePrivate.h"
@@ -133,6 +134,7 @@ enum {
     CLOSE,
 
     SCRIPT_DIALOG,
+    SCRIPT_DIALOG_HANDLED,
 
     DECIDE_POLICY,
     PERMISSION_REQUEST,
@@ -465,6 +467,9 @@ void WebKitWebViewClient::handleDownloadRequest(WKWPE::View&, DownloadProxy& dow
 
 void WebKitWebViewClient::frameDisplayed(WKWPE::View&)
 {
+    if (RefPtr<cairo_surface_t> surface = adoptRef(webkitWebViewBackendTakeScreenshot(m_webView->priv->backend.get())))
+        getPage(m_webView).inspectorController().didPaint(surface.get());
+
     {
         SetForScope<bool> inFrameDisplayedGuard(m_webView->priv->inFrameDisplayed, true);
         for (const auto& callback : m_webView->priv->frameDisplayedCallbacks) {
@@ -495,6 +500,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)
@@ -546,7 +552,7 @@ static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision*
 
 static gboolean webkitWebViewPermissionRequest(WebKitWebView*, WebKitPermissionRequest* request)
 {
-#if ENABLE(POINTER_LOCK)
+#if ENABLE(POINTER_LOCK) && PLATFORM(GTK)
     if (WEBKIT_IS_POINTER_LOCK_PERMISSION_REQUEST(request)) {
         webkit_permission_request_allow(request);
         return TRUE;
@@ -1722,6 +1728,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
@@ -2554,6 +2569,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 fbab1afe9ca09f5e6a6793f5065f08fc76bfedaf..23f66f4da6229d88271e4b732414088b7cc0397e 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<void(bool)>&& completionHandler);
 void webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText, Function<void(const String&)>&& completionHandler);
 void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView*, const CString& message, Function<void(bool)>&& 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 9204440b028fd175af6f0feb1c780ea7cb938dd8..8d6b56f2f7a92b12a7e7b13ba6bdbc6de0df31c2 100644
--- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
+++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
@@ -250,6 +250,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 <webkit2/webkit2.h> can be included directly."
+#endif
+
+#ifndef WebKitBrowserInspector_h
+#define WebKitBrowserInspector_h
+
+#include <glib-object.h>
+#include <webkit2/WebKitDefines.h>
+#include <webkit2/WebKitWebView.h>
+
+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 3a96753c9cf9e6d3a3d277ad82ec6f4a98635cbd..530927447170960bec796908174efff308fd5912 100644
--- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp
+++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp
@@ -2472,6 +2472,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 187df5e92217097766a94ad21ec631273a9764fa..64720ed966eba1578fa0a869561dd7bab2e15e0e 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 "InputMethodState.h"
 #include "SameDocumentNavigationType.h"
@@ -119,3 +120,5 @@ void webkitWebViewBaseSynthesizeWheelEvent(WebKitWebViewBase*, const GdkEvent*,
 void webkitWebViewBaseMakeBlank(WebKitWebViewBase*, bool);
 void webkitWebViewBasePageGrabbedTouch(WebKitWebViewBase*);
 void webkitWebViewBaseSetShouldNotifyFocusEvents(WebKitWebViewBase*, bool);
+
+WebKit::AcceleratedBackingStore* webkitWebViewBaseGetAcceleratedBackingStore(WebKitWebViewBase*);
diff --git a/Source/WebKit/UIProcess/API/gtk/webkit2.h b/Source/WebKit/UIProcess/API/gtk/webkit2.h
index 5cd9524252a97d4ea64dfeb22e5a47b55f36c887..45da62b4ffe54d5cfd680dd40cabd6f45bc993a6 100644
--- a/Source/WebKit/UIProcess/API/gtk/webkit2.h
+++ b/Source/WebKit/UIProcess/API/gtk/webkit2.h
@@ -32,6 +32,7 @@
 #include <webkit2/WebKitAutomationSession.h>
 #include <webkit2/WebKitBackForwardList.h>
 #include <webkit2/WebKitBackForwardListItem.h>
+#include <webkit2/WebKitBrowserInspector.h>
 #include <webkit2/WebKitColorChooserRequest.h>
 #include <webkit2/WebKitContextMenu.h>
 #include <webkit2/WebKitContextMenuActions.h>
diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp
index 6c3e1c955042055b3016e04e4bc9c400c5a5c905..4371a9da51f6b55be180c86c9e9518894fd8728f 100644
--- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp
+++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp
@@ -32,8 +32,11 @@
 #include "NativeWebWheelEvent.h"
 #include "TouchGestureController.h"
 #include "WPEView.h"
+#include "WebColorPickerWPE.h"
+#include "WebDateTimePickerWPE.h"
 #include "WebContextMenuProxy.h"
 #include "WebContextMenuProxyWPE.h"
+#include "WebKitDataListSuggestionsDropdown.h"
 #include "WebKitPopupMenu.h"
 #include <WebCore/ActivityState.h>
 #include <WebCore/DOMPasteAccess.h>
@@ -194,7 +197,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)
@@ -447,4 +450,23 @@ void PageClientImpl::selectionDidChange()
     m_view.selectionDidChange();
 }
 
+#if ENABLE(DATALIST_ELEMENT)
+RefPtr<WebKit::WebDataListSuggestionsDropdown> PageClientImpl::createDataListSuggestionsDropdown(WebKit::WebPageProxy& page)
+{
+    return WebKitDataListSuggestionsDropdown::create(page);
+}
+#endif
+
+RefPtr<WebColorPicker> PageClientImpl::createColorPicker(WebPageProxy* page, const WebCore::Color& color, const WebCore::IntRect& rect, Vector<WebCore::Color>&&)
+{
+    return WebColorPickerWPE::create(*page, color, rect);
+}
+
+#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
+RefPtr<WebDateTimePicker> PageClientImpl::createDateTimePicker(WebPageProxy& page)
+{
+    return WebDateTimePickerWPE::create(page);
+}
+#endif
+
 } // namespace WebKit
diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h
index ca30000e1a06b85886716c8d991ef485963fd635..e178dc92338312823553719495ea7b67f4b853d7 100644
--- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h
+++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h
@@ -166,6 +166,17 @@ private:
 
     void selectionDidChange() override;
 
+#if ENABLE(DATALIST_ELEMENT)
+    RefPtr<WebKit::WebDataListSuggestionsDropdown> createDataListSuggestionsDropdown(WebKit::WebPageProxy& page) override;
+#endif
+
+#if ENABLE(INPUT_TYPE_COLOR)
+    RefPtr<WebColorPicker> createColorPicker(WebPageProxy*, const WebCore::Color& initialColor, const WebCore::IntRect&, Vector<WebCore::Color>&&) override;
+#endif
+#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
+    RefPtr<WebDateTimePicker> createDateTimePicker(WebPageProxy&) override;
+#endif
+
     WKWPE::View& m_view;
 };
 
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 <wpe/webkit.h> can be included directly."
+#endif
+
+#ifndef WebKitBrowserInspector_h
+#define WebKitBrowserInspector_h
+
+#include <glib-object.h>
+#include <wpe/WebKitDefines.h>
+#include <wpe/WebKitWebView.h>
+
+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/WebKitDataListSuggestionsDropdown.cpp b/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..afafef2b7fb433e006b1763e653e200bc80edcbd
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 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 "WebKitDataListSuggestionsDropdown.h"
+
+#if ENABLE(DATALIST_ELEMENT)
+
+#include "WebPageProxy.h"
+
+namespace WebKit {
+
+WebKitDataListSuggestionsDropdown::WebKitDataListSuggestionsDropdown(WebPageProxy& page)
+    : WebDataListSuggestionsDropdown(page)
+{
+}
+
+WebKitDataListSuggestionsDropdown::~WebKitDataListSuggestionsDropdown()
+{
+}
+
+void WebKitDataListSuggestionsDropdown::show(WebCore::DataListSuggestionInformation&& information)
+{
+}
+
+void WebKitDataListSuggestionsDropdown::handleKeydownWithIdentifier(const String& key)
+{
+}
+
+void WebKitDataListSuggestionsDropdown::close()
+{
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(DATALIST_ELEMENT)
diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.h b/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a099832c3dd959f456fcae49a1d62a9477d2758
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 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
+
+#if ENABLE(DATALIST_ELEMENT)
+
+#include "WebDataListSuggestionsDropdown.h"
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class WebKitDataListSuggestionsDropdown final : public WebDataListSuggestionsDropdown {
+public:
+    static Ref<WebKitDataListSuggestionsDropdown> create(WebPageProxy& page)
+    {
+        return adoptRef(*new WebKitDataListSuggestionsDropdown(page));
+    }
+
+    ~WebKitDataListSuggestionsDropdown();
+
+private:
+    WebKitDataListSuggestionsDropdown(WebPageProxy&);
+
+    void show(WebCore::DataListSuggestionInformation&&) final;
+    void handleKeydownWithIdentifier(const String&) final;
+    void close() final;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(DATALIST_ELEMENT)
diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitPointerLockPermissionRequest.h b/Source/WebKit/UIProcess/API/wpe/WebKitPointerLockPermissionRequest.h
new file mode 100644
index 0000000000000000000000000000000000000000..a47e7eeb15094655c87d41ad0de7973306121184
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/wpe/WebKitPointerLockPermissionRequest.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION)
+#error "Only <webkit2/webkit2.h> can be included directly."
+#endif
+
+#ifndef WebKitPointerLockPermissionRequest_h
+#define WebKitPointerLockPermissionRequest_h
+
+#include <glib-object.h>
+#include <wpe/WebKitDefines.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_POINTER_LOCK_PERMISSION_REQUEST            (webkit_pointer_lock_permission_request_get_type())
+#define WEBKIT_POINTER_LOCK_PERMISSION_REQUEST(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_POINTER_LOCK_PERMISSION_REQUEST, WebKitPointerLockPermissionRequest))
+#define WEBKIT_POINTER_LOCK_PERMISSION_REQUEST_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  WEBKIT_TYPE_POINTER_LOCK_PERMISSION_REQUEST, WebKitPointerLockPermissionRequestClass))
+#define WEBKIT_IS_POINTER_LOCK_PERMISSION_REQUEST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_POINTER_LOCK_PERMISSION_REQUEST))
+#define WEBKIT_IS_POINTER_LOCK_PERMISSION_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  WEBKIT_TYPE_POINTER_LOCK_PERMISSION_REQUEST))
+#define WEBKIT_POINTER_LOCK_PERMISSION_REQUEST_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  WEBKIT_TYPE_POINTER_LOCK_PERMISSION_REQUEST, WebKitPointerLockPermissionRequestClass))
+
+typedef struct _WebKitPointerLockPermissionRequest        WebKitPointerLockPermissionRequest;
+typedef struct _WebKitPointerLockPermissionRequestClass   WebKitPointerLockPermissionRequestClass;
+typedef struct _WebKitPointerLockPermissionRequestPrivate WebKitPointerLockPermissionRequestPrivate;
+
+struct _WebKitPointerLockPermissionRequest {
+    GObject parent;
+
+    /*< private >*/
+    WebKitPointerLockPermissionRequestPrivate *priv;
+};
+
+struct _WebKitPointerLockPermissionRequestClass {
+    GObjectClass parent_class;
+
+    void (*_webkit_reserved0) (void);
+    void (*_webkit_reserved1) (void);
+    void (*_webkit_reserved2) (void);
+    void (*_webkit_reserved3) (void);
+};
+
+WEBKIT_API GType
+webkit_pointer_lock_permission_request_get_type (void);
+
+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 <glib-object.h>
 #include <wpe/WebKitDefines.h>
 #include <wpe/wpe.h>
+#include <cairo.h>
 
 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 c0e1359abff7d0f6bf08853baba831e64312e49a..c06c34d0c0056aad1c1c886343fe14bfb11c6325 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
@@ -327,6 +327,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
 
 <SUBSECTION Private>
 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 c2221efc00618c2ec4d20a88c59840767bd52ff5..71f1cd7e07c705a7c830ff5c4f7d7f981bb363f2 100644
--- a/Source/WebKit/UIProcess/API/wpe/webkit.h
+++ b/Source/WebKit/UIProcess/API/wpe/webkit.h
@@ -32,6 +32,7 @@
 #include <wpe/WebKitAutomationSession.h>
 #include <wpe/WebKitBackForwardList.h>
 #include <wpe/WebKitBackForwardListItem.h>
+#include <wpe/WebKitBrowserInspector.h>
 #include <wpe/WebKitContextMenu.h>
 #include <wpe/WebKitContextMenuActions.h>
 #include <wpe/WebKitContextMenuItem.h>
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..cfb57a48ce387b79613b757e2eb4de2c378aac30
--- /dev/null
+++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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 "InspectorPlaywrightAgentClient.h"
+#include "RemoteInspectorPipe.h"
+#include "WebKit2Initialize.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebKit {
+
+void initializeBrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client)
+{
+    // Initialize main loop before creating inspecor agent and pipe queues.
+    WebKit::InitializeWebKit2();
+
+    class BrowserInspectorPipe {
+    public:
+        BrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client)
+            : m_playwrightAgent(std::move(client))
+            , m_remoteInspectorPipe(m_playwrightAgent)
+        {
+        }
+
+        InspectorPlaywrightAgent m_playwrightAgent;
+        RemoteInspectorPipe m_remoteInspectorPipe;
+    };
+
+    static NeverDestroyed<BrowserInspectorPipe> 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<InspectorPlaywrightAgentClient> client);
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/Cocoa/AutomationClient.mm b/Source/WebKit/UIProcess/Cocoa/AutomationClient.mm
index 30860712f58b2a8d48cef5da4e6f03345f2921ba..e715496c24529689784ba4d481d23441ab68cf1e 100644
--- a/Source/WebKit/UIProcess/Cocoa/AutomationClient.mm
+++ b/Source/WebKit/UIProcess/Cocoa/AutomationClient.mm
@@ -35,6 +35,7 @@
 #import <wtf/RunLoop.h>
 #import <wtf/spi/cf/CFBundleSPI.h>
 #import <wtf/text/WTFString.h>
+#import <wtf/RunLoop.h>
 
 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 <wtf/Forward.h>
+#include <wtf/CompletionHandler.h>
 #include "SOAuthorizationSession.h"
 #include <wtf/CompletionHandler.h>
 
@@ -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/SubFrameSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.h
index 8a95a3f8036bb0c664954c23ba3ecf72058ae711..dd10e28e2499cd84be2d072dc7567050ca1e3001 100644
--- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.h
+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.h
@@ -32,6 +32,7 @@
 #include "NavigationSOAuthorizationSession.h"
 #include <WebCore/FrameIdentifier.h>
 #include <wtf/Deque.h>
+#include <variant>
 
 namespace WebKit {
 
diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h
index fdaaa1eb7130fd68da1fa8740343426b451cd288..74ce6bcd445822d69286a96f4d62aeadbf891805 100644
--- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h
+++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h
@@ -95,6 +95,7 @@ private:
         void runJavaScriptAlert(WebPageProxy&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function<void()>&& completionHandler) final;
         void runJavaScriptConfirm(WebPageProxy&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function<void(bool)>&& completionHandler) final;
         void runJavaScriptPrompt(WebPageProxy&, const WTF::String&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function<void(const WTF::String&)>&&) final;
+        void handleJavaScriptDialog(WebKit::WebPageProxy&, bool accept, const WTF::String&) final;
         void presentStorageAccessConfirmDialog(const WTF::String& requestingDomain, const WTF::String& currentDomain, CompletionHandler<void(bool)>&&);
         void requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler<void(bool)>&&) final;
         void decidePolicyForGeolocationPermissionRequest(WebPageProxy&, WebFrameProxy&, const FrameInfoData&, Function<void(bool)>&) final;
@@ -190,6 +191,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 6d59a8f6416a225a3981099fbf1e6cf6a93732be..c0a9dbe0c7afa3a526194ff6022bf4d000e6fc28 100644
--- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
+++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
@@ -109,6 +109,7 @@ void UIDelegate::setDelegate(id <WKUIDelegate> 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.webViewRequestGeolocationPermissionForOriginDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestGeolocationPermissionForOrigin:initiatedByFrame:decisionHandler:)];
@@ -381,6 +382,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<void(bool)>&& completionHandler)
 {
     if (!m_uiDelegate)
diff --git a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm
index 6a50a08103395865839ffa780e835b758335fabe..f2dd42fde3a21cc83f176613c671debe1f877e7a 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm
+++ b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm
@@ -36,6 +36,7 @@
 #import "InsertTextOptions.h"
 #import "LoadParameters.h"
 #import "PageClient.h"
+#import "PasteboardTypes.h"
 #import "QuarantineSPI.h"
 #import "QuickLookThumbnailLoader.h"
 #import "SafeBrowsingSPI.h"
@@ -236,9 +237,66 @@ 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) {
+            auto attachment = attachmentForIdentifier(info.attachmentIdentifier);
+            if (!attachment) {
+                dragCancelled();
+                return;
+            }
+            NSString *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 = std::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 159c7222e270a2f589158e1aab8c2aaa146ba292..0649e6611d6f1b3e1ec949d0fe974b0dfc8501bb 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
+++ b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
@@ -411,7 +411,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)
@@ -716,8 +716,8 @@ void WebProcessPool::registerNotificationObservers()
     }];
 
     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));
     }];
 
     m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationDidBecomeActiveNotification object:NSApp queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
diff --git a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
index 3f6dd1f242e7a115ecf798390f34b635c6e8d6f9..9eb27efc6b344b4937a3aa693d0a62c8ab143bee 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
+++ b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
@@ -511,6 +511,9 @@ public:
     void provideDataForPasteboard(NSPasteboard *, NSString *type);
     NSArray *namesOfPromisedFilesDroppedAtDestination(NSURL *dropDestination);
 
+// Paywright begin
+    RetainPtr<CGImageRef> takeSnapshotForAutomation();
+// Paywright end
     RefPtr<ViewSnapshot> takeViewSnapshot();
     void saveBackForwardSnapshotForCurrentItem();
     void saveBackForwardSnapshotForItem(WebBackForwardListItem&);
diff --git a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
index 3d9e877b0cb75654b6391639557f52b60392cac9..7cb2c03f05520eca9ba9d98351b5918db925a73b 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
+++ b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
@@ -2623,6 +2623,11 @@ WebCore::DestinationColorSpace WebViewImpl::colorSpace()
         if (!m_colorSpace)
             m_colorSpace = [NSColorSpace sRGBColorSpace];
     }
+    // Playwright begin
+    // window.colorSpace is sometimes null on popup windows in headless mode
+    if (!m_colorSpace)
+        return DestinationColorSpace::SRGB();
+    // Playwright end
 
     ASSERT(m_colorSpace);
     return WebCore::DestinationColorSpace { [m_colorSpace CGColorSpace] };
@@ -4633,6 +4638,18 @@ static RetainPtr<CGImageRef> takeWindowSnapshot(CGSWindowID windowID, bool captu
     return adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, windowID, imageOptions));
 }
 
+// Paywright begin
+RetainPtr<CGImageRef> 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<ViewSnapshot> WebViewImpl::takeViewSnapshot()
 {
     NSWindow *window = [m_view window];
diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
index 89d38d344b08cb3ed6cc7db62bc4c5162e0f28f0..3c2de7a336a028f6c8371ddeeca528a9989bd486 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 <WebCore/PlatformDisplay.h>
 #include <WebCore/Region.h>
+#include <wtf/Vector.h>
 
 #if PLATFORM(GTK)
+#include "WebKitWebViewBasePrivate.h"
 #include <gtk/gtk.h>
 #endif
 
@@ -51,6 +54,13 @@
 #include <d3d11_1.h>
 #endif
 
+#if PLATFORM(WIN)
+#include <cairo-win32.h>
+#include <windows.h>
+#include <WebCore/HWndDC.h>
+#include <WebCore/RefPtrCairo.h>
+#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<void ()>&& callback)
+{
+    m_callbacks.append(WTFMove(callback));
+}
+
 void DrawingAreaProxyCoordinatedGraphics::waitForBackingStoreUpdateOnNextPaint()
 {
     m_hasReceivedFirstUpdate = true;
@@ -250,6 +269,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<cairo_surface_t> 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 b23a45ff7d313317d8ba64fb430ebba3b6adef71..8419b69c5e278cf88a3ab6b98c335eddeea44e53 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 <wtf/Function.h>
 #include <wtf/RunLoop.h>
 
 namespace WebCore {
@@ -49,6 +50,10 @@ public:
 
     bool isInAcceleratedCompositingMode() const { return !m_layerTreeContext.isEmpty(); }
     const LayerTreeContext& layerTreeContext() const { return m_layerTreeContext; }
+    void waitForSizeUpdate(Function<void ()>&&);
+#if !PLATFORM(WPE)
+    void captureFrame();
+#endif
 
 private:
     // DrawingAreaProxy
@@ -68,6 +73,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&);
@@ -131,12 +139,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<Function<void ()>> m_callbacks;
+
 #if !PLATFORM(WPE)
     bool m_isBackingStoreDiscardable { true };
     std::unique_ptr<BackingStore> m_backingStore;
     RunLoop::Timer<DrawingAreaProxyCoordinatedGraphics> m_discardBackingStoreTimer;
 #endif
     std::unique_ptr<DrawingMonitor> 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 eb0cfc3757cee17105bc4373a0877d86c89859d3..21fda5454cf8218ffedac88aa1a7b4627d9d5fa0 100644
--- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp
+++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp
@@ -42,8 +42,10 @@
 #include <WebCore/MIMETypeRegistry.h>
 #include <WebCore/ResourceResponseBase.h>
 #include <wtf/FileSystem.h>
+#include <wtf/NeverDestroyed.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/WTFString.h>
+#include <wtf/UUID.h>
 
 namespace WebKit {
 using namespace WebCore;
@@ -56,7 +58,10 @@ DownloadProxy::DownloadProxy(DownloadProxyMap& downloadProxyMap, WebsiteDataStor
     , m_request(resourceRequest)
     , m_originatingPage(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, this);
 }
 
 DownloadProxy::~DownloadProxy()
@@ -75,9 +80,12 @@ static RefPtr<API::Data> createData(const IPC::DataReference& data)
 void DownloadProxy::cancel(CompletionHandler<void(API::Data*)>&& completionHandler)
 {
     if (m_dataStore) {
-        m_dataStore->networkProcess().sendWithAsyncReply(Messages::NetworkProcess::CancelDownload(m_downloadID), [this, protectedThis = Ref { *this }, completionHandler = WTFMove(completionHandler)] (const IPC::DataReference& resumeData) mutable {
+        auto* instrumentation = m_dataStore->downloadInstrumentation();
+        m_dataStore->networkProcess().sendWithAsyncReply(Messages::NetworkProcess::CancelDownload(m_downloadID), [this, protectedThis = Ref { *this }, completionHandler = WTFMove(completionHandler), instrumentation] (const IPC::DataReference& resumeData) mutable {
             m_legacyResumeData = createData(resumeData);
             completionHandler(m_legacyResumeData.get());
+            if (instrumentation)
+                instrumentation->downloadFinished(m_uuid, "canceled"_s);
             m_downloadProxyMap.downloadFinished(*this);
         });
     } else
@@ -164,6 +172,21 @@ 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);
+            if (auto handle = SandboxExtension::createHandle(destination, SandboxExtension::Type::ReadWrite))
+                sandboxExtensionHandle = WTFMove(*handle);
+        }
+        completionHandler(destination, WTFMove(sandboxExtensionHandle), AllowOverwrite::Yes);
+        return;
+    }
+
     m_client->decideDestinationWithSuggestedFilename(*this, response, ResourceResponseBase::sanitizeSuggestedFilename(suggestedFilename), [this, protectedThis = Ref { *this }, completionHandler = WTFMove(completionHandler)] (AllowOverwrite allowOverwrite, String destination) mutable {
         SandboxExtension::Handle sandboxExtensionHandle;
         if (!destination.isNull()) {
@@ -184,6 +207,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);
@@ -194,6 +219,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 e87f14a1772973db924624671dd40fe919904a5e..711335158c64e743a17e31c082a402eb0be9ac23 100644
--- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h
+++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h
@@ -147,6 +147,7 @@ private:
 #if PLATFORM(COCOA)
     RetainPtr<NSProgress> m_progress;
 #endif
+    String m_uuid;
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.h b/Source/WebKit/UIProcess/DrawingAreaProxy.h
index babc553d170fc71d582e26426e8cf903a9e80d33..3ec1d0258344dc5fef94c73bdd3c7d5cbc7652c9 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<void ()>&&);
 
 #if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER)
     // The timeout we use when waiting for a DidUpdateGeometry message.
@@ -161,6 +162,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/CairoJpegEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9426d9eed59f433eac62b8eb6a16139b84079949
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.cpp
@@ -0,0 +1,244 @@
+/* Copyright 2018 Bernhard R. Fischer, 4096R/8E24F29D <bf@abenteuerland.at>
+ *
+ * This file is part of Cairo_JPG.
+ *
+ * Cairo_JPG 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Cairo_JPG 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 General Public License
+ * along with Cairo_JPG.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/*! \file cairo_jpg.c
+ * This file contains two functions for reading and writing JPEG files from
+ * and to Cairo image surfaces. It uses the functions from the libjpeg.
+ * Most of the code is directly derived from the online example at
+ * http://libjpeg-turbo.virtualgl.org/Documentation/Documentation
+ *
+ * All prototypes are defined in cairo_jpg.h All functions and their parameters
+ * and return values are described below directly at the functions. You may
+ * also have a look at the preprocessor macros defined below.
+ *
+ * To compile this code you need to have installed the packages libcairo2-dev
+ * and libjpeg-dev. Compile with the following to create an object file to link
+ * with your code:
+ * gcc -std=c99 -Wall -c `pkg-config cairo libjpeg --cflags --libs` cairo_jpg.c
+ * Use the following command to include the main() function and create an
+ * executable for testing of this code:
+ * gcc -std=c99 -Wall -o cairo_jpg -DCAIRO_JPEG_MAIN `pkg-config cairo libjpeg --cflags --libs` cairo_jpg.c
+ *
+ * @author Bernhard R. Fischer, 4096R/8E24F29D bf@abenteuerland.at
+ * @version 2020/01/18
+ * @license LGPL3.
+ */
+
+#if USE(CAIRO)
+
+#include "CairoJpegEncoder.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <cairo.h>
+extern "C" {
+#include "jpeglib.h"
+}
+
+/*! Macro to activate main() function. This is only used for testing. Comment
+ * it out (#undef) if you link this file to your own program.
+ */
+//#define CAIRO_JPEG_MAIN
+//
+/*! Define this to use an alternate implementation of
+ * cairo_image_surface_create_from_jpeg() which fstat(3)s the file before
+ * reading (see below). For huge files this /may/ be slightly faster.
+ */
+#undef CAIRO_JPEG_USE_FSTAT
+
+/*! This is the read block size for the stream reader
+ * cairo_image_surface_create_from_jpeg_stream().
+ */
+#ifdef USE_CAIRO_READ_FUNC_LEN_T
+#define CAIRO_JPEG_IO_BLOCK_SIZE 4096
+#else
+/*! Block size has to be one if cairo_read_func_t is in use because of the lack
+ * to detect EOF (truncated reads).
+ */
+#define CAIRO_JPEG_IO_BLOCK_SIZE 1
+/*! In case of original cairo_read_func_t is used fstat() should be used for
+ * performance reasons (see CAIRO_JPEG_USE_FSTAT above).
+ */
+#define CAIRO_JPEG_USE_FSTAT
+#endif
+
+/*! Define this to test jpeg creation with non-image surfaces. This is only for
+ * testing and is to be used together with CAIRO_JPEG_MAIN.  
+ */
+#undef CAIRO_JPEG_TEST_SIMILAR
+#if defined(CAIRO_JPEG_TEST_SIMILAR) && defined(CAIRO_JPEG_MAIN)
+#include <cairo-pdf.h>
+#endif
+
+
+#ifndef LIBJPEG_TURBO_VERSION
+/*! This function makes a covnersion for "odd" pixel sizes which typically is a
+ * conversion from a 3-byte to a 4-byte (or more) pixel size or vice versa.
+ * The conversion is done from the source buffer src to the destination buffer
+ * dst. The caller MUST ensure that src and dst have the correct memory size.
+ * This is dw * num for dst and sw * num for src. src and dst may point to the
+ * same memory address.
+ * @param dst Pointer to destination buffer.
+ * @param dw Pixel width (in bytes) of pixels in destination buffer, dw >= 3.
+ * @param src Pointer to source buffer.
+ * @param sw Pixel width (in bytes) of pixels in source buffer, sw >= 3.
+ * @param num Number of pixels to convert, num >= 1;
+ */
+static void pix_conv(unsigned char *dst, int dw, const unsigned char *src, int sw, int num)
+{
+   int si, di;
+
+   // safety check
+   if (dw < 3 || sw < 3 || dst == NULL || src == NULL)
+      return;
+
+   num--;
+   for (si = num * sw, di = num * dw; si >= 0; si -= sw, di -= dw)
+   {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+      dst[di + 2] = src[si    ];
+      dst[di + 1] = src[si + 1];
+      dst[di + 0] = src[si + 2];
+#else
+      // FIXME: This is untested, it may be wrong.
+      dst[di - 3] = src[si - 3];
+      dst[di - 2] = src[si - 2];
+      dst[di - 1] = src[si - 1];
+#endif
+   }
+}
+#endif
+
+
+/*! This function creates a JPEG file in memory from a Cairo image surface.
+ * @param sfc Pointer to a Cairo surface. It should be an image surface of
+ * either CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are
+ * converted to CAIRO_FORMAT_RGB24 before compression.
+ * Please note that this may give unexpected results because JPEG does not
+ * support transparency. Thus, default background color is used to replace
+ * transparent regions. The default background color is black if not specified
+ * explicitly. Thus converting e.g. PDF surfaces without having any specific
+ * background color set will apear with black background and not white as you
+ * might expect. In such cases it is suggested to manually convert the surface
+ * to RGB24 before calling this function.
+ * @param data Pointer to a memory pointer. This parameter receives a pointer
+ * to the memory area where the final JPEG data is found in memory. This
+ * function reserves the memory properly and it has to be freed by the caller
+ * with free(3).
+ * @param len Pointer to a variable of type size_t which will receive the final
+ * lenght of the memory buffer.
+ * @param quality Compression quality, 0-100.
+ * @return On success the function returns CAIRO_STATUS_SUCCESS. In case of
+ * error CAIRO_STATUS_INVALID_FORMAT is returned.
+ */
+cairo_status_t cairo_image_surface_write_to_jpeg_mem(cairo_surface_t *sfc, unsigned char **data, size_t *len, int quality)
+{
+   struct jpeg_compress_struct cinfo;
+   struct jpeg_error_mgr jerr;
+   JSAMPROW row_pointer[1];
+   cairo_surface_t *other = NULL;
+
+   // check valid input format (must be IMAGE_SURFACE && (ARGB32 || RGB24))
+   if (cairo_surface_get_type(sfc) != CAIRO_SURFACE_TYPE_IMAGE ||
+         (cairo_image_surface_get_format(sfc) != CAIRO_FORMAT_ARGB32 &&
+         cairo_image_surface_get_format(sfc) != CAIRO_FORMAT_RGB24))
+   {
+      // create a similar surface with a proper format if supplied input format
+      // does not fulfill the requirements
+      double x1, y1, x2, y2;
+      other = sfc;
+      cairo_t *ctx = cairo_create(other);
+      // get extents of original surface
+      cairo_clip_extents(ctx, &x1, &y1, &x2, &y2);
+      cairo_destroy(ctx);
+
+      // create new image surface
+      sfc = cairo_surface_create_similar_image(other, CAIRO_FORMAT_RGB24, x2 - x1, y2 - y1);
+      if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS)
+         return CAIRO_STATUS_INVALID_FORMAT;
+
+      // paint original surface to new surface
+      ctx = cairo_create(sfc);
+      cairo_set_source_surface(ctx, other, 0, 0);
+      cairo_paint(ctx);
+      cairo_destroy(ctx);
+   }
+
+   // finish queued drawing operations
+   cairo_surface_flush(sfc);
+
+   // init jpeg compression structures
+   cinfo.err = jpeg_std_error(&jerr);
+   jpeg_create_compress(&cinfo);
+
+   // set compression parameters
+   unsigned long targetSize;
+   jpeg_mem_dest(&cinfo, data, &targetSize);
+
+   cinfo.image_width = cairo_image_surface_get_width(sfc);
+   cinfo.image_height = cairo_image_surface_get_height(sfc);
+#ifdef LIBJPEG_TURBO_VERSION
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+   //cinfo.in_color_space = JCS_EXT_BGRX;
+   cinfo.in_color_space = cairo_image_surface_get_format(sfc) == CAIRO_FORMAT_ARGB32 ? JCS_EXT_BGRA : JCS_EXT_BGRX;
+#else
+   //cinfo.in_color_space = JCS_EXT_XRGB;
+   cinfo.in_color_space = cairo_image_surface_get_format(sfc) == CAIRO_FORMAT_ARGB32 ? JCS_EXT_ARGB : JCS_EXT_XRGB;
+#endif
+   cinfo.input_components = 4;
+#else
+   cinfo.in_color_space = JCS_RGB;
+   cinfo.input_components = 3;
+#endif
+   jpeg_set_defaults(&cinfo);
+   jpeg_set_quality(&cinfo, quality, TRUE);
+
+   // start compressor
+   jpeg_start_compress(&cinfo, TRUE);
+
+   // loop over all lines and compress
+   while (cinfo.next_scanline < cinfo.image_height)
+   {
+#ifdef LIBJPEG_TURBO_VERSION
+      row_pointer[0] = cairo_image_surface_get_data(sfc) + (cinfo.next_scanline
+            * cairo_image_surface_get_stride(sfc));
+#else
+      unsigned char row_buf[3 * cinfo.image_width];
+      pix_conv(row_buf, 3, cairo_image_surface_get_data(sfc) +
+            (cinfo.next_scanline * cairo_image_surface_get_stride(sfc)), 4, cinfo.image_width);
+      row_pointer[0] = row_buf;
+#endif
+      (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+   }
+
+   // finalize and close everything
+   jpeg_finish_compress(&cinfo);
+   jpeg_destroy_compress(&cinfo);
+
+   // destroy temporary image surface (if available)
+   if (other != NULL)
+      cairo_surface_destroy(sfc);
+
+   *len = targetSize;
+   return CAIRO_STATUS_SUCCESS;
+}
+
+#endif
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..4ec8b96bbbddf8a7b042f53a8068754a384fc7ad
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Microsoft. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <cairo.h>
+
+cairo_status_t cairo_image_surface_write_to_jpeg_mem(cairo_surface_t *sfc, unsigned char **data, size_t *len, int quality);
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ec063e2f3757046c6677208f9da60f464d2fac63
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
@@ -0,0 +1,302 @@
+/*
+ * 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 <pal/crypto/CryptoDigest.h>
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <WebCore/NotImplemented.h>
+#include <wtf/RunLoop.h>
+#include <wtf/UUID.h>
+#include <wtf/text/Base64.h>
+
+#if USE(CAIRO)
+#include "CairoJpegEncoder.h"
+#include "DrawingAreaProxyCoordinatedGraphics.h"
+#include "DrawingAreaProxy.h"
+#endif
+
+#if PLATFORM(MAC)
+#include <WebCore/ImageBufferUtilitiesCG.h>
+#endif
+
+namespace WebKit {
+
+const int kMaxFramesInFlight = 1;
+
+using namespace Inspector;
+
+InspectorScreencastAgent::InspectorScreencastAgent(BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page)
+    : InspectorAgentBase("Screencast"_s)
+    , m_frontendDispatcher(makeUnique<ScreencastFrontendDispatcher>(frontendRouter))
+    , 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 PLATFORM(WPE)
+    // Get actual image size (in device pixels).
+    WebCore::IntSize displaySize(cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface));
+
+    WebCore::IntSize drawingAreaSize = m_page.drawingArea()->size();
+    drawingAreaSize.scale(m_page.deviceScaleFactor());
+    if (drawingAreaSize != displaySize) {
+        return;
+    }
+
+#else
+    WebCore::IntSize displaySize = m_page.drawingArea()->size();
+#endif
+    if (m_encoder)
+        m_encoder->encodeFrame(surface, displaySize);
+    if (m_screencast) {
+
+        {
+            // Do not send the same frame over and over.
+            unsigned char *data = cairo_image_surface_get_data(surface);
+            int stride = cairo_image_surface_get_stride(surface);
+            int height = cairo_image_surface_get_height(surface);
+            auto cryptoDigest = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_1);
+            cryptoDigest->addBytes(data, stride * height);
+            auto digest = cryptoDigest->computeHash();
+            if (m_lastFrameDigest == digest)
+                return;
+            m_lastFrameDigest = digest;
+        }
+
+        if (m_screencastFramesInFlight > kMaxFramesInFlight)
+            return;
+        // Scale image to fit width / height
+        double scale = std::min(m_screencastWidth / displaySize.width(), m_screencastHeight / displaySize.height());
+        RefPtr<cairo_surface_t> scaledSurface;
+        if (scale < 1) {
+            WebCore::IntSize scaledSize = displaySize;
+            scaledSize.scale(scale);
+            cairo_matrix_t transform;
+            cairo_matrix_init_scale(&transform, scale, scale);
+            scaledSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, scaledSize.width(), scaledSize.height()));
+            RefPtr<cairo_t> cr = adoptRef(cairo_create(scaledSurface.get()));
+            cairo_transform(cr.get(), &transform);
+            cairo_set_source_surface(cr.get(), surface, 0, 0);
+            cairo_paint(cr.get());
+            surface = scaledSurface.get();
+        }
+        unsigned char *data = nullptr;
+        size_t len = 0;
+        cairo_image_surface_write_to_jpeg_mem(surface, &data, &len, m_screencastQuality);
+        String result = base64EncodeToString(data, len);
+        ++m_screencastFramesInFlight;
+        m_frontendDispatcher->screencastFrame(result, displaySize.width(), displaySize.height());
+    }
+}
+#endif
+
+Inspector::Protocol::ErrorStringOr<String /* screencastID */> InspectorScreencastAgent::startVideo(const String& file, int width, int height, int toolbarHeight)
+{
+    if (m_encoder)
+        return makeUnexpected("Already recording"_s);
+
+    if (width < 10 || width > 10000 || height < 10 || height > 10000)
+        return makeUnexpected("Invalid size"_s);
+
+    String errorString;
+    m_encoder = ScreencastEncoder::create(errorString, file, WebCore::IntSize(width, height));
+    if (!m_encoder)
+        return makeUnexpected(errorString);
+
+    m_currentScreencastID = createCanonicalUUIDString();
+
+#if PLATFORM(MAC)
+    m_encoder->setOffsetTop(toolbarHeight);
+#endif
+
+    kickFramesStarted();
+    return { { m_currentScreencastID } };
+}
+
+void InspectorScreencastAgent::stopVideo(Ref<StopVideoCallback>&& 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 (!m_screencast)
+      m_framesAreGoing = false;
+}
+
+Inspector::Protocol::ErrorStringOr<int /* generation */> InspectorScreencastAgent::startScreencast(int width, int height, int toolbarHeight, int quality)
+{
+    if (m_screencast)
+        return makeUnexpected("Already screencasting"_s);
+    m_screencast = true;
+    m_screencastWidth = width;
+    m_screencastHeight = height;
+    m_screencastQuality = quality;
+    m_screencastToolbarHeight = toolbarHeight;
+    m_screencastFramesInFlight = 0;
+    ++m_screencastGeneration;
+    kickFramesStarted();
+    return m_screencastGeneration;
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorScreencastAgent::screencastFrameAck(int generation)
+{
+    if (m_screencastGeneration != generation)
+        return { };
+    --m_screencastFramesInFlight;
+    return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorScreencastAgent::stopScreencast()
+{
+    if (!m_screencast)
+        return makeUnexpected("Not screencasting"_s);
+    m_screencast = false;
+    if (!m_encoder)
+      m_framesAreGoing = false;
+    return { };
+}
+
+void InspectorScreencastAgent::kickFramesStarted()
+{
+    if (!m_framesAreGoing) {
+        m_framesAreGoing = true;
+#if !PLATFORM(WPE)
+        scheduleFrameEncoding();
+#endif
+    }
+    m_page.forceRepaint([] { });
+}
+
+#if !PLATFORM(WPE)
+void InspectorScreencastAgent::scheduleFrameEncoding()
+{
+    if (!m_encoder && !m_screencast)
+        return;
+
+    RunLoop::main().dispatchAfter(Seconds(1.0 / ScreencastEncoder::fps), [agent = WeakPtr { this }]() mutable {
+        if (!agent)
+            return;
+
+        agent->encodeFrame();
+        agent->scheduleFrameEncoding();
+    });
+}
+#endif
+
+#if PLATFORM(MAC)
+void InspectorScreencastAgent::encodeFrame()
+{
+    if (!m_encoder && !m_screencast)
+        return;
+    RetainPtr<CGImageRef> imageRef = m_page.pageClient().takeSnapshotForAutomation();
+    if (m_screencast && m_screencastFramesInFlight <= kMaxFramesInFlight) {
+        CGImage* imagePtr = imageRef.get();
+        WebCore::IntSize imageSize(CGImageGetWidth(imagePtr), CGImageGetHeight(imagePtr));
+        WebCore::IntSize displaySize = imageSize;
+        displaySize.contract(0, m_screencastToolbarHeight);
+        double scale = std::min(m_screencastWidth / displaySize.width(), m_screencastHeight / displaySize.height());
+        RetainPtr<CGImageRef> scaledImageRef;
+        if (scale < 1 || m_screencastToolbarHeight) {
+            WebCore::IntSize screencastSize = displaySize;
+            screencastSize.scale(scale);
+            WebCore::IntSize scaledImageSize = imageSize;
+            scaledImageSize.scale(scale);
+            auto colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
+            auto context = adoptCF(CGBitmapContextCreate(nullptr, screencastSize.width(), screencastSize.height(), 8, 4 * screencastSize.width(), colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+            CGContextDrawImage(context.get(), CGRectMake(0, 0, scaledImageSize.width(), scaledImageSize.height()), imagePtr);
+            scaledImageRef = adoptCF(CGBitmapContextCreateImage(context.get()));
+            imagePtr = scaledImageRef.get();
+        }
+        auto data = WebCore::data(imagePtr, WebCore::jpegUTI(), m_screencastQuality * 0.1);
+
+        // Do not send the same frame over and over.
+        auto cryptoDigest = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_1);
+        cryptoDigest->addBytes(data.data(), data.size());
+        auto digest = cryptoDigest->computeHash();
+        if (m_lastFrameDigest != digest) {
+            String base64Data = base64EncodeToString(data);
+            ++m_screencastFramesInFlight;
+            m_frontendDispatcher->screencastFrame(base64Data, displaySize.width(), displaySize.height());
+            m_lastFrameDigest = digest;
+        }
+    }
+    if (m_encoder)
+        m_encoder->encodeFrame(WTFMove(imageRef));
+}
+#endif
+
+#if USE(CAIRO) && !PLATFORM(WPE)
+void InspectorScreencastAgent::encodeFrame()
+{
+    if (!m_encoder && !m_screencast)
+        return;
+
+    if (auto* drawingArea = m_page.drawingArea())
+        static_cast<DrawingAreaProxyCoordinatedGraphics*>(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..d28dde452275f18739e3b1c8d709185c9bf0f40e
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h
@@ -0,0 +1,97 @@
+/*
+ * 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 <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+#include <JavaScriptCore/InspectorFrontendDispatchers.h>
+
+#if USE(CAIRO)
+#include <cairo.h>
+#endif
+
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/WeakPtr.h>
+
+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<InspectorScreencastAgent> {
+    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<String /* screencastID */> startVideo(const String& file, int width, int height, int toolbarHeight) override;
+    void stopVideo(Ref<StopVideoCallback>&&) override;
+
+    Inspector::Protocol::ErrorStringOr<int /* generation */> startScreencast(int width, int height, int toolbarHeight, int quality) override;
+    Inspector::Protocol::ErrorStringOr<void> screencastFrameAck(int generation) override;
+    Inspector::Protocol::ErrorStringOr<void> stopScreencast() override;
+
+private:
+#if !PLATFORM(WPE)
+    void scheduleFrameEncoding();
+    void encodeFrame();
+#endif
+
+    void kickFramesStarted();
+
+    std::unique_ptr<Inspector::ScreencastFrontendDispatcher> m_frontendDispatcher;
+    Ref<Inspector::ScreencastBackendDispatcher> m_backendDispatcher;
+    WebPageProxy& m_page;
+    Vector<uint8_t> m_lastFrameDigest;
+    RefPtr<ScreencastEncoder> m_encoder;
+    bool m_screencast = false;
+    bool m_framesAreGoing = false;
+    double m_screencastWidth = 0;
+    double m_screencastHeight = 0;
+    int m_screencastQuality = 0;
+    int m_screencastToolbarHeight = 0;
+    int m_screencastGeneration = 0;
+    int m_screencastFramesInFlight = 0;
+    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..a3eebdc92962a46a4861e75cd9a7f931722748ff
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
@@ -0,0 +1,379 @@
+/*
+ * 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 <algorithm>
+#include <libyuv.h>
+#include <vpx/vp8.h>
+#include <vpx/vp8cx.h>
+#include <vpx/vpx_encoder.h>
+#include <wtf/RunLoop.h>
+#include <wtf/UniqueArray.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/text/StringConcatenateNumbers.h>
+
+#if USE(CAIRO)
+#include <WebCore/RefPtrCairo.h>
+#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<vpx_image_t>& out_image,
+                 std::unique_ptr<uint8_t[]>& out_image_buffer) {
+  std::unique_ptr<vpx_image_t> 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<uint8_t[]> 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<unsigned char*>(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<cairo_surface_t>&& surface)
+        : m_surface(WTFMove(surface))
+    { }
+#elif PLATFORM(MAC)
+    VPXFrame(RetainPtr<CGImageRef> windowImage, int offsetTop)
+        : m_windowImage(WTFMove(windowImage))
+        , 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<uint8_t> buffer = makeUniqueArray<uint8_t>(argb_stride * image->h);
+        uint8_t* argb_data = buffer.get();
+        ScreencastEncoder::imageToARGB(m_windowImage.get(), argb_data, image->w, image->h, 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<cairo_surface_t> m_surface;
+#elif PLATFORM(MAC)
+    RetainPtr<CGImageRef> m_windowImage;
+    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<VPXFrame>&& 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<int>(1, frameCount * timeScale));
+        });
+    }
+
+    void finishAsync(Function<void()>&& 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;
+                m_pts += pkt->data.frame.duration;
+            }
+        }
+
+        return gotPkts;
+    }
+
+    void finish()
+    {
+        // Flush encoder.
+        while (encodeFrame(nullptr, 1))
+            ++m_frameCount;
+
+        m_writer->finish();
+        fclose(m_file);
+    }
+
+    Ref<WorkQueue> m_encoderQueue;
+    vpx_codec_ctx_t m_codec;
+    vpx_codec_enc_cfg_t m_cfg;
+    FILE* m_file { nullptr };
+    std::unique_ptr<WebMFileWriter> m_writer;
+    int m_frameCount { 0 };
+    int64_t m_pts { 0 };
+    std::unique_ptr<uint8_t[]> m_imageBuffer;
+    std::unique_ptr<vpx_image_t> m_image;
+};
+
+ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec>&& vpxCodec, IntSize size)
+    : m_vpxCodec(WTFMove(vpxCodec))
+    , m_size(size)
+{
+    ASSERT(!size.isZero());
+}
+
+ScreencastEncoder::~ScreencastEncoder()
+{
+}
+
+RefPtr<ScreencastEncoder> ScreencastEncoder::create(String& errorString, const String& filePath, IntSize size)
+{
+    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> vpxCodec(new VPXCodec(codec, cfg, file));
+    return adoptRef(new ScreencastEncoder(WTFMove(vpxCodec), size));
+}
+
+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)
+{
+    flushLastFrame();
+    // Note that in WPE drawing area size is updated asynchronously and may differ from acutal
+    // size of the surface.
+    if (size.isZero()) {
+        return;
+    }
+
+    RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m_size.width(), m_size.height()));
+    {
+        RefPtr<cairo_t> cr = adoptRef(cairo_create(surface.get()));
+
+        cairo_matrix_t transform;
+        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<double>(m_size.width()) / size.width(),
+                                    static_cast<double>(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<VPXFrame>(WTFMove(surface));
+}
+#elif PLATFORM(MAC)
+void ScreencastEncoder::encodeFrame(RetainPtr<CGImageRef>&& windowImage)
+{
+    flushLastFrame();
+
+    m_lastFrame = makeUnique<VPXFrame>(WTFMove(windowImage), m_offsetTop);
+}
+#endif
+
+void ScreencastEncoder::finish(Function<void()>&& callback)
+{
+    if (!m_vpxCodec) {
+        callback();
+        return;
+    }
+
+    flushLastFrame();
+    m_vpxCodec->finishAsync([protectRef = Ref { *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..36df6131950ca95f74dc191628376fc589dbcb33
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
@@ -0,0 +1,80 @@
+/*
+ * 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 <WebCore/IntSize.h>
+#include <wtf/Forward.h>
+#include <wtf/MonotonicTime.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/WeakPtr.h>
+
+#if USE(CAIRO)
+#include <cairo.h>
+#endif
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class ScreencastEncoder : public ThreadSafeRefCounted<ScreencastEncoder> {
+    WTF_MAKE_NONCOPYABLE(ScreencastEncoder);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static constexpr int fps = 25;
+
+    static RefPtr<ScreencastEncoder> create(String& errorString, const String& filePath, WebCore::IntSize);
+
+    class VPXCodec;
+    ScreencastEncoder(std::unique_ptr<VPXCodec>&&, WebCore::IntSize);
+    ~ScreencastEncoder();
+
+#if USE(CAIRO)
+    void encodeFrame(cairo_surface_t*, WebCore::IntSize);
+#elif PLATFORM(MAC)
+    void encodeFrame(RetainPtr<CGImageRef>&&);
+    void setOffsetTop(int offset) { m_offsetTop = offset;}
+#endif
+
+    void finish(Function<void()>&& callback);
+
+private:
+    void flushLastFrame();
+#if PLATFORM(MAC)
+    static void imageToARGB(CGImageRef, uint8_t* rgba_data, int width, int height, int offsetTop);
+#endif
+
+    std::unique_ptr<VPXCodec> m_vpxCodec;
+    const WebCore::IntSize m_size;
+    MonotonicTime m_lastFrameTimestamp;
+    class VPXFrame;
+    std::unique_ptr<VPXFrame> 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 <string>
+#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<int>(m_cfg->g_w), static_cast<int>(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<uint8_t*>(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 <memory>
+#include <stdio.h>
+#include <stdlib.h>
+#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<mkvmuxer::MkvWriter> m_writer;
+    std::unique_ptr<mkvmuxer::Segment> 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 cfcacce0122bb03fa47fd8580cfbedfb2ad37d48..5619cbd7e4e842be0d8e2db2c64a7e0028838808 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> InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type)
 {
-    return makeUnique<InspectorTargetProxy>(page, targetId, type);
+    return makeUnique<InspectorTargetProxy>(page, nullptr, targetId, type);
 }
 
-std::unique_ptr<InspectorTargetProxy> InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId, Inspector::InspectorTargetType type)
+std::unique_ptr<InspectorTargetProxy> InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId)
 {
-    auto target = InspectorTargetProxy::create(provisionalPage.page(), targetId, type);
-    target->m_provisionalPage = provisionalPage;
-    return target;
+    return makeUnique<InspectorTargetProxy>(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(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<InspectorTargetProxy> create(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
-    static std::unique_ptr<InspectorTargetProxy> create(ProvisionalPageProxy&, const String& targetId, Inspector::InspectorTargetType);
-    InspectorTargetProxy(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
+    static std::unique_ptr<InspectorTargetProxy> 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<ProvisionalPageProxy> m_provisionalPage;
     String m_identifier;
     Inspector::InspectorTargetType m_type;
-    WeakPtr<ProvisionalPageProxy> m_provisionalPage;
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
index ed4e6f30b8c35966075573dccee801daceec865e..81e10124a8a745727fc25316345cda01201a5dba 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 <WebCore/ResourceError.h>
+#include <WebCore/WindowFeatures.h>
 #include <JavaScriptCore/InspectorAgentBase.h>
 #include <JavaScriptCore/InspectorBackendDispatcher.h>
 #include <JavaScriptCore/InspectorBackendDispatchers.h>
@@ -49,27 +57,114 @@ 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<InspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
-    m_targetAgent = targetAgent.get();
-    m_agents.append(WTFMove(targetAgent));
 }
 
 void WebPageInspectorController::init()
 {
+    auto targetAgent = makeUnique<InspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
+    m_targetAgent = targetAgent.get();
+    m_agents.append(WTFMove(targetAgent));
+    auto emulationAgent = makeUnique<WebPageInspectorEmulationAgent>(m_backendDispatcher.get(), m_inspectedPage);
+    m_emulationAgent = emulationAgent.get();
+    m_agents.append(WTFMove(emulationAgent));
+    auto inputAgent = makeUnique<WebPageInspectorInputAgent>(m_backendDispatcher.get(), m_inspectedPage);
+    m_inputAgent = inputAgent.get();
+    m_agents.append(WTFMove(inputAgent));
+    m_agents.append(makeUnique<InspectorDialogAgent>(m_backendDispatcher.get(), m_frontendRouter.get(), m_inspectedPage));
+    auto screencastAgent = makeUnique<InspectorScreencastAgent>(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();
+}
+
+void WebPageInspectorController::didProcessAllPendingWheelEvents()
+{
+    if (m_frontendRouter->hasFrontends())
+        m_inputAgent->didProcessAllPendingWheelEvents();
 }
 
 bool WebPageInspectorController::hasLocalFrontend() const
@@ -83,6 +178,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 +207,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 +233,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 +261,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 +340,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<void()>&& 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 +385,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 +463,27 @@ void WebPageInspectorController::browserExtensionsDisabled(HashSet<String>&& 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);
+
+    // Enable media stream.
+    if (!m_inspectedPage.preferences().mediaStreamEnabled()) {
+        m_inspectedPage.preferences().setMediaDevicesEnabled(true);
+        m_inspectedPage.preferences().setMediaStreamEnabled(true);
+        m_inspectedPage.preferences().setPeerConnectionEnabled(true);
+    }
+}
+
 } // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
index 8c1339345d451874502b271f6aa2eca3fa0d3faf..1f8f5e74c86b61c1c5a16ac33d48afdd0e59a2e9 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 <JavaScriptCore/InspectorAgentRegistry.h>
 #include <JavaScriptCore/InspectorTargetAgent.h>
 #include <WebCore/PageIdentifier.h>
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/text/WTFString.h>
+#include <wtf/URL.h>
+
+#if USE(CAIRO)
+#include <cairo.h>
+#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,21 @@ 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();
+    void didProcessAllPendingWheelEvents();
 
     bool hasLocalFrontend() const;
 
@@ -64,11 +113,25 @@ public:
 #if ENABLE(REMOTE_INSPECTOR)
     void setIndicating(bool);
 #endif
+#if USE(CAIRO)
+    void didPaint(cairo_surface_t*);
+#endif
+    using NavigationHandler = Function<void(const String&, uint64_t)>;
+    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<void()>&&);
+
     bool shouldPauseLoading(const ProvisionalPageProxy&) const;
     void setContinueLoadingCallback(const ProvisionalPageProxy&, WTF::Function<void()>&&);
 
@@ -87,6 +150,7 @@ private:
     void createLazyAgents();
 
     void addTarget(std::unique_ptr<InspectorTargetProxy>&&);
+    void adjustPageSettings();
 
     Ref<Inspector::FrontendRouter> m_frontendRouter;
     Ref<Inspector::BackendDispatcher> m_backendDispatcher;
@@ -95,11 +159,17 @@ private:
     WebPageProxy& m_inspectedPage;
 
     Inspector::InspectorTargetAgent* m_targetAgent { nullptr };
+    WebPageInspectorEmulationAgent* m_emulationAgent { nullptr };
+    WebPageInspectorInputAgent* m_inputAgent { nullptr };
+    InspectorScreencastAgent* m_screecastAgent { nullptr };
     HashMap<String, std::unique_ptr<InspectorTargetProxy>> m_targets;
 
     InspectorBrowserAgent* m_enabledBrowserAgent;
 
     bool m_didCreateLazyAgents { false };
+    HashMap<uint64_t, NavigationHandler> 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..235e9a3f8455f1113109631b54c7e90cfad8a614
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/mac/ScreencastEncoderMac.mm
@@ -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 "ScreencastEncoder.h"
+
+#include <algorithm>
+#include <CoreGraphics/CoreGraphics.h>
+#include <wtf/RetainPtr.h>
+
+namespace WebKit {
+
+void ScreencastEncoder::imageToARGB(CGImageRef image, uint8_t* argb_data, int width, int height, int offsetTop)
+{
+    size_t bitsPerComponent = 8;
+    size_t bytesPerPixel = 4;
+    size_t bytesPerRow = bytesPerPixel * width;
+    RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
+    RetainPtr<CGContextRef> context = adoptCF(CGBitmapContextCreate(argb_data, width, height, bitsPerComponent, bytesPerRow, colorSpace.get(), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little));
+    double imageWidth = CGImageGetWidth(image);
+    double imageHeight = CGImageGetHeight(image);
+    double pageHeight = imageHeight - offsetTop;
+    double ratio = 1;
+    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 <JavaScriptCore/InspectorFrontendRouter.h>
+
+
+namespace WebKit {
+
+using namespace Inspector;
+
+InspectorDialogAgent::InspectorDialogAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page)
+    : InspectorAgentBase("Dialog"_s)
+    , m_frontendDispatcher(makeUnique<DialogFrontendDispatcher>(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<void> InspectorDialogAgent::enable()
+{
+    if (m_page.inspectorDialogAgent())
+        return makeUnexpected("Dialog domain is already enabled."_s);
+
+    m_page.setInspectorDialogAgent(this);
+    return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorDialogAgent::disable()
+{
+    if (m_page.inspectorDialogAgent() != this)
+        return { };
+
+    m_page.setInspectorDialogAgent(nullptr);
+    return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> 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 <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+#include <JavaScriptCore/InspectorFrontendDispatchers.h>
+
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+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<void> enable() override;
+    Inspector::Protocol::ErrorStringOr<void> disable() override;
+    Inspector::Protocol::ErrorStringOr<void> 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<Inspector::DialogFrontendDispatcher> m_frontendDispatcher;
+    Ref<Inspector::DialogBackendDispatcher> 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..a07142981fbfb5d304fc8a485fb5cb4177509412
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp
@@ -0,0 +1,1010 @@
+/*
+ * 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 "StorageNamespaceIdentifier.h"
+#include "WebAutomationSession.h"
+#include "WebGeolocationManagerProxy.h"
+#include "WebGeolocationPosition.h"
+#include "WebInspectorUtilities.h"
+#include "WebPageGroup.h"
+#include "WebPageInspectorController.h"
+#include "WebPageInspectorTarget.h"
+#include "WebPageProxy.h"
+#include "WebProcessPool.h"
+#include "WebProcessProxy.h"
+#include "WebsiteDataRecord.h"
+#include <WebCore/FrameIdentifier.h>
+#include <WebCore/GeolocationPositionData.h>
+#include <WebCore/InspectorPageAgent.h>
+#include <WebCore/ProcessIdentifier.h>
+#include <WebCore/ResourceRequest.h>
+#include <WebCore/SecurityOriginData.h>
+#include <WebCore/WindowFeatures.h>
+#include <JavaScriptCore/InspectorBackendDispatcher.h>
+#include <JavaScriptCore/InspectorFrontendChannel.h>
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <pal/SessionID.h>
+#include <stdlib.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/HexNumber.h>
+#include <wtf/URL.h>
+
+
+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<JSON::Value> parsedMessage = JSON::Value::parseJSON(message);
+        if (!parsedMessage)
+            return message;
+
+        RefPtr<JSON::Object> 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<JSON::ArrayOf<String>> getEnabledWindowFeatures(const WebCore::WindowFeatures& features) {
+  auto result = JSON::ArrayOf<String>::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<Inspector::Protocol::Playwright::Cookie> 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.value_or(-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<BrowserContext>&& context, size_t numberOfPages, Ref<DeleteContextCallback>&& 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<BrowserContext> m_browserContext;
+    size_t m_numberOfPages;
+    Ref<DeleteContextCallback> m_callback;
+};
+
+
+InspectorPlaywrightAgent::InspectorPlaywrightAgent(std::unique_ptr<InspectorPlaywrightAgentClient> client)
+    : m_frontendChannel(nullptr)
+    , m_frontendRouter(FrontendRouter::create())
+    , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
+    , m_client(std::move(client))
+    , m_frontendDispatcher(makeUnique<PlaywrightFrontendDispatcher>(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<JSON::Object>& messageObject) {
+        RefPtr<JSON::Value> idValue;
+        if (!messageObject->getValue("id"_s, idValue))
+            return BackendDispatcher::InterceptionResult::Continue;
+        RefPtr<JSON::Value> 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;
+        }
+
+        std::optional<int> 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<PageProxyChannel>(*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<void> InspectorPlaywrightAgent::enable()
+{
+    if (m_isEnabled)
+        return { };
+
+    m_isEnabled = true;
+
+    auto* defaultDataStore = findDefaultWebsiteDataStore();
+    if (!m_defaultContext && defaultDataStore) {
+        auto context = std::make_unique<BrowserContext>();
+        m_defaultContext = context.get();
+        context->processPool = WebProcessPool::allProcessPools().first().ptr();
+        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<void> 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(std::optional<bool>(), String());
+    });
+    for (auto& it : m_browserContexts) {
+        it.value->dataStore->setDownloadInstrumentation(nullptr);
+        it.value->pages.clear();
+    }
+    m_browserContextDeletions.clear();
+    return { };
+}
+
+void InspectorPlaywrightAgent::close(Ref<CloseCallback>&& callback)
+{
+    closeImpl([callback = WTFMove(callback)] (String error) {
+        if (!callback->isActive())
+            return;
+        if (error.isNull())
+            callback->sendSuccess();
+        else
+            callback->sendFailure(error);
+    });
+}
+
+void InspectorPlaywrightAgent::closeImpl(Function<void(String)>&& callback)
+{
+    Vector<WebPageProxy*> 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 (!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<String /* browserContextID */> InspectorPlaywrightAgent::createContext(const String& proxyServer, const String& proxyBypassList)
+{
+    String errorString;
+    std::unique_ptr<BrowserContext> 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<DeleteContextCallback>&& 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<BrowserContextDeletion>(WTFMove(contextHolder), pages.size(), WTFMove(callback)));
+        for (auto* page : pages)
+            page->closePage();
+    }
+    m_client->deleteBrowserContext(errorString, sessionID);
+}
+
+void InspectorPlaywrightAgent::getLocalStorageData(const String& browserContextID, Ref<GetLocalStorageDataCallback>&& callback)
+{
+    String errorString;
+    BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+    if (!lookupBrowserContext(errorString, browserContextID)) {
+        callback->sendFailure(errorString);
+        return;
+    }
+    PAL::SessionID sessionID = browserContext->dataStore->sessionID();
+    NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess();
+    networkProcess.sendWithAsyncReply(Messages::NetworkProcess::GetLocalStorageData(sessionID),
+        [callback = WTFMove(callback)](Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>>&& data) {
+            if (!callback->isActive())
+                return;
+            auto origins = JSON::ArrayOf<Inspector::Protocol::Playwright::OriginStorage>::create();
+            for (const auto& originData : data) {
+                auto items = JSON::ArrayOf<Inspector::Protocol::Playwright::NameValue>::create();
+                for (const auto& entry : originData.second) {
+                    items->addItem(Inspector::Protocol::Playwright::NameValue::create()
+                        .setName(entry.key)
+                        .setValue(entry.value)
+                        .release());
+                }
+                origins->addItem(Inspector::Protocol::Playwright::OriginStorage::create()
+                    .setOrigin(originData.first.toString())
+                    .setItems(WTFMove(items))
+                    .release());
+            }
+            callback->sendSuccess(WTFMove(origins));
+        }, 0);
+}
+
+void InspectorPlaywrightAgent::setLocalStorageData(const String& browserContextID, Ref<JSON::Array>&& origins, Ref<SetLocalStorageDataCallback>&& callback)
+{
+    String errorString;
+    BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+    if (!lookupBrowserContext(errorString, browserContextID)) {
+        callback->sendFailure(errorString);
+        return;
+    }
+
+    PAL::SessionID sessionID = browserContext->dataStore->sessionID();
+    NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess();
+    if (!networkProcess.hasConnection()) {
+       callback->sendFailure("No connection to the nework process");
+       return;
+    }
+
+    WebKit::PageGroupIdentifier pageGroupID = browserContext->processPool->defaultPageGroup().pageGroupID();
+    auto storageNamespaceID = makeObjectIdentifier<StorageNamespaceIdentifierType>(pageGroupID.toUInt64());
+
+    Vector<std::pair<WebCore::SecurityOriginData, HashMap<String, String>>> data;
+    for (const auto& value : origins.get()) {
+        auto obj = value->asObject();
+        if (!obj) {
+            callback->sendFailure("Invalid OriginStorage format"_s);
+            return;
+        }
+
+        String origin = obj->getString("origin");
+        if (origin.isEmpty()) {
+            callback->sendFailure("Empty origin"_s);
+            return;
+        }
+
+        auto url = URL(URL(), origin);
+        if (!url.isValid()) {
+            callback->sendFailure("Invalid origin URL"_s);
+            return;
+        }
+
+        auto items = obj->getArray("items");
+        if (!items) {
+            callback->sendFailure("Invalid item array format"_s);
+            return;
+        }
+
+        HashMap<String, String> map;
+        for (const auto& item : *items) {
+            auto itemObj = item->asObject();
+            if (!itemObj) {
+                callback->sendFailure("Invalid item format"_s);
+                return;
+            }
+
+            String name = itemObj->getString("name");
+            String value = itemObj->getString("value");;
+            if (name.isEmpty()) {
+                callback->sendFailure("Item name cannot be empty"_s);
+                return;
+            }
+
+            map.set(name, value);
+        }
+        data.append({ WebCore::SecurityOriginData::fromURL(url), WTFMove(map) });
+    }
+
+    networkProcess.sendWithAsyncReply(Messages::NetworkProcess::SetLocalStorageData(sessionID, storageNamespaceID, data), [callback = WTFMove(callback)] (const String& error) {
+        if (error.isEmpty())
+            callback->sendSuccess();
+        else
+            callback->sendFailure(error);
+    });
+}
+
+Inspector::Protocol::ErrorStringOr<String /* pageProxyID */> InspectorPlaywrightAgent::createPage(const String& browserContextID)
+{
+    String errorString;
+    BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+    if (!browserContext)
+        return makeUnexpected(errorString);
+
+    RefPtr<WebPageProxy> 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<WebCore::ProcessIdentifierType>(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<WebCore::FrameIdentifierType>(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<NavigateCallback>&& 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<void> 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<GetAllCookiesCallback>&& 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<WebCore::Cookie> allCookies) {
+            if (!callback->isActive())
+                return;
+            auto cookies = JSON::ArrayOf<Inspector::Protocol::Playwright::Cookie>::create();
+            for (const auto& cookie : allCookies)
+                cookies->addItem(buildObjectForCookie(cookie));
+            callback->sendSuccess(WTFMove(cookies));
+        }, 0);
+}
+
+void InspectorPlaywrightAgent::setCookies(const String& browserContextID, Ref<JSON::Array>&& in_cookies, Ref<SetCookiesCallback>&& 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<WebCore::Cookie> cookies;
+    for (unsigned i = 0; i < in_cookies->length(); ++i) {
+        RefPtr<JSON::Value> item = in_cookies->get(i);
+        RefPtr<JSON::Object> 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;
+        }
+
+        std::optional<double> expires = obj->getDouble("expires");
+        if (expires && *expires != -1)
+            cookie.expires = *expires;
+        if (std::optional<bool> value = obj->getBoolean("httpOnly"))
+            cookie.httpOnly = *value;
+        if (std::optional<bool> value = obj->getBoolean("secure"))
+            cookie.secure = *value;
+        if (std::optional<bool> 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<DeleteAllCookiesCallback>&& 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<void> InspectorPlaywrightAgent::setLanguages(Ref<JSON::Array>&& languages, const String& browserContextID)
+{
+    String errorString;
+    BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+    if (!errorString.isEmpty())
+        return makeUnexpected(errorString);
+
+    Vector<String> 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<void> InspectorPlaywrightAgent::setDownloadBehavior(const String& behavior, const String& downloadPath, const String& browserContextID)
+{
+    String errorString;
+    BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+    if (!errorString.isEmpty())
+        return makeUnexpected(errorString);
+
+    std::optional<bool> allow;
+    if (behavior == "allow"_s)
+      allow = true;
+    if (behavior == "deny"_s)
+      allow = false;
+    browserContext->dataStore->setDownloadForAutomation(allow, downloadPath);
+    return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorPlaywrightAgent::setGeolocationOverride(const String& browserContextID, RefPtr<JSON::Object>&& geolocation)
+{
+    String errorString;
+    BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+    if (!errorString.isEmpty())
+        return makeUnexpected(errorString);
+
+    auto* geoManager = browserContext->processPool->supplement<WebGeolocationManagerProxy>();
+    if (!geoManager)
+        return makeUnexpected("Internal error: geolocation manager is not available."_s);
+
+    if (geolocation) {
+        std::optional<double> timestamp = geolocation->getDouble("timestamp");
+        std::optional<double> latitude = geolocation->getDouble("latitude");
+        std::optional<double> longitude = geolocation->getDouble("longitude");
+        std::optional<double> 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, RefPtr<DownloadProxy> download)
+{
+    if (!m_isEnabled)
+        return;
+    String frameID = WebCore::InspectorPageAgent::makeFrameID(page->process().coreProcessIdentifier(), frameInfoData.frameID ? *frameInfoData.frameID : page->mainFrame()->frameID());
+    m_downloads.set(uuid, download);
+    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);
+    m_downloads.remove(uuid);
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorPlaywrightAgent::cancelDownload(const String& uuid)
+{
+    if (!m_isEnabled)
+        return { };
+    auto download = m_downloads.get(uuid);
+    if (!download)
+        return { };
+    download->cancel([] (auto*) {});
+    return { };
+}
+
+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..1d1f360f01740c001507acac6b1ba90598934917
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h
@@ -0,0 +1,129 @@
+/*
+ * 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 <JavaScriptCore/InspectorBackendDispatchers.h>
+#include "WebPageInspectorController.h"
+#include "WebProcessPool.h"
+#include "DownloadProxy.h"
+#include <wtf/HashMap.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+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<InspectorPlaywrightAgentClient> 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<void> enable() override;
+    Inspector::Protocol::ErrorStringOr<void> disable() override;
+    void close(Ref<CloseCallback>&&) override;
+    Inspector::Protocol::ErrorStringOr<String /* browserContextID */> createContext(const String& proxyServer, const String& proxyBypassList) override;
+    void deleteContext(const String& browserContextID, Ref<DeleteContextCallback>&& callback) override;
+    Inspector::Protocol::ErrorStringOr<String /* pageProxyID */> createPage(const String& browserContextID) override;
+    void navigate(const String& url, const String& pageProxyID, const String& frameId, const String& referrer, Ref<NavigateCallback>&&) override;
+    Inspector::Protocol::ErrorStringOr<void> setIgnoreCertificateErrors(const String& browserContextID, bool ignore) override;
+
+    void getAllCookies(const String& browserContextID, Ref<GetAllCookiesCallback>&&) override;
+    void setCookies(const String& browserContextID, Ref<JSON::Array>&& in_cookies, Ref<SetCookiesCallback>&&) override;
+    void deleteAllCookies(const String& browserContextID, Ref<DeleteAllCookiesCallback>&&) override;
+
+    void getLocalStorageData(const String& browserContextID, Ref<GetLocalStorageDataCallback>&&) override;
+    void setLocalStorageData(const String& browserContextID, Ref<JSON::Array>&& origins, Ref<SetLocalStorageDataCallback>&&) override;
+
+    Inspector::Protocol::ErrorStringOr<void> setGeolocationOverride(const String& browserContextID, RefPtr<JSON::Object>&& geolocation) override;
+    Inspector::Protocol::ErrorStringOr<void> setLanguages(Ref<JSON::Array>&& languages, const String& browserContextID) override;
+    Inspector::Protocol::ErrorStringOr<void> setDownloadBehavior(const String& behavior, const String& downloadPath, const String& browserContextID) override;
+    Inspector::Protocol::ErrorStringOr<void> cancelDownload(const String& uuid) override;
+
+    // DownloadInstrumentation
+    void downloadCreated(const String& uuid, const WebCore::ResourceRequest&, const FrameInfoData& frameInfoData, WebPageProxy* page, RefPtr<DownloadProxy> download) 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<void(String)>&&);
+
+    Inspector::FrontendChannel* m_frontendChannel { nullptr };
+    Ref<Inspector::FrontendRouter> m_frontendRouter;
+    Ref<Inspector::BackendDispatcher> m_backendDispatcher;
+    std::unique_ptr<InspectorPlaywrightAgentClient> m_client;
+    std::unique_ptr<Inspector::PlaywrightFrontendDispatcher> m_frontendDispatcher;
+    Ref<Inspector::PlaywrightBackendDispatcher> m_playwrightDispatcher;
+    HashMap<String, std::unique_ptr<PageProxyChannel>> m_pageProxyChannels;
+    BrowserContext* m_defaultContext;
+    HashMap<String, RefPtr<DownloadProxy>> m_downloads;
+    HashMap<String, std::unique_ptr<BrowserContext>> m_browserContexts;
+    HashMap<String, std::unique_ptr<BrowserContextDeletion>> 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 <memory>
+#include <pal/SessionID.h>
+#include <wtf/Forward.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/RefCounted.h>
+
+namespace WebKit {
+
+class WebsiteDataStore;
+class WebPageProxy;
+class WebProcessPool;
+
+class BrowserContext {
+    WTF_MAKE_NONCOPYABLE(BrowserContext);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    BrowserContext();
+    ~BrowserContext();
+
+    RefPtr<WebsiteDataStore> dataStore;
+    RefPtr<WebProcessPool> processPool;
+    HashSet<WebPageProxy*> pages;
+};
+
+class InspectorPlaywrightAgentClient {
+public:
+    virtual ~InspectorPlaywrightAgentClient() = default;
+    virtual RefPtr<WebKit::WebPageProxy> createPage(WTF::String& error, const BrowserContext& context) = 0;
+    virtual void closeBrowser() = 0;
+    virtual std::unique_ptr<BrowserContext> 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 c485c7fc313ea0833fc606267169d692a8240928..fc378501a80d01d597c904be6258ba7fa4fc91fb 100644
--- a/Source/WebKit/UIProcess/PageClient.h
+++ b/Source/WebKit/UIProcess/PageClient.h
@@ -323,6 +323,11 @@ public:
     virtual void selectionDidChange() = 0;
 #endif
 
+// Paywright begin
+#if PLATFORM(COCOA)
+    virtual RetainPtr<CGImageRef> takeSnapshotForAutomation() = 0;
+#endif
+// Paywright end
 #if PLATFORM(COCOA) || PLATFORM(GTK)
     virtual RefPtr<ViewSnapshot> takeViewSnapshot(std::optional<WebCore::IntRect>&&) = 0;
 #endif
diff --git a/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp b/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
index f7ca4d2bc236d99d0fc512e8f51d20ba3b83a3e9..08f13a1e37adac5589f2559f983bd17eb25d9a8b 100644
--- a/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
+++ b/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
@@ -645,3 +645,5 @@ bool ProvisionalPageProxy::sendMessage(UniqueRef<IPC::Encoder>&& encoder, Option
 }
 
 } // namespace WebKit
+
+#undef MESSAGE_CHECK
diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dd8b28e692dca4078eb710b2a97e61716126a4cb
--- /dev/null
+++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp
@@ -0,0 +1,224 @@
+/*
+ * 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 <JavaScriptCore/InspectorFrontendChannel.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+#include <wtf/UniqueArray.h>
+#include <wtf/Vector.h>
+#include <wtf/WorkQueue.h>
+
+#if OS(UNIX)
+#include <stdio.h>
+#include <unistd.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <io.h>
+#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<char*>(buffer) + bytesRead,
+            size - bytesRead, &sizeRead, nullptr);
+#else
+        int sizeRead = read(readFD, static_cast<char*>(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<DWORD>(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<WorkQueue> m_senderQueue;
+};
+
+RemoteInspectorPipe::RemoteInspectorPipe(InspectorPlaywrightAgent& playwrightAgent)
+    : m_playwrightAgent(playwrightAgent)
+{
+    m_remoteFrontendChannel = makeUnique<RemoteFrontendChannel>();
+    start();
+}
+
+RemoteInspectorPipe::~RemoteInspectorPipe()
+{
+    stop();
+}
+
+bool RemoteInspectorPipe::start()
+{
+    if (m_receiverThread)
+        return true;
+
+#if PLATFORM(WIN)
+    readHandle = reinterpret_cast<HANDLE>(_get_osfhandle(readFD));
+    writeHandle = reinterpret_cast<HANDLE>(_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<char>(bufSize);
+    Vector<char> 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 = WTFMove(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 <wtf/Ref.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Threading.h>
+
+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<Thread> m_receiverThread;
+    std::atomic<bool> m_terminated { false };
+    std::unique_ptr<Inspector::FrontendChannel> 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 f5a6164e831c968995e332ef0269c0b8c18cf9f2..d69ae8cdca3c77d6325c703e65bd97136587f3bb 100644
--- a/Source/WebKit/UIProcess/SpeechRecognitionRemoteRealtimeMediaSource.cpp
+++ b/Source/WebKit/UIProcess/SpeechRecognitionRemoteRealtimeMediaSource.cpp
@@ -37,6 +37,8 @@
 #include <WebCore/WebAudioBufferList.h>
 #endif
 
+using namespace WebCore;
+
 namespace WebKit {
 
 Ref<WebCore::RealtimeMediaSource> 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 684b9616573761123fbcc0d94be29de519ecced6..51ff18323ece0ee15c87d63a1d6fd604377ee968 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 <WebCore/AuthenticatorAssertionResponse.h>
 #include <WebCore/MockWebAuthenticationConfiguration.h>
 
 namespace WebKit {
diff --git a/Source/WebKit/UIProcess/WebContextMenuProxy.h b/Source/WebKit/UIProcess/WebContextMenuProxy.h
index 630bf1170da176dcc65d659c1fdf7c05185910e5..ec12ef12dfc7e7c00ed69e2afb10367cb02a1edf 100644
--- a/Source/WebKit/UIProcess/WebContextMenuProxy.h
+++ b/Source/WebKit/UIProcess/WebContextMenuProxy.h
@@ -37,6 +37,7 @@
 #include "QuickLookPreviewActivity.h"
 #endif
 
+OBJC_CLASS NSArray;
 OBJC_CLASS NSMenu;
 
 namespace WebKit {
@@ -49,6 +50,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..ae45b4212bdb3f6a004cc80a1d91146b540f86f5
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.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 "WebPageInspectorEmulationAgent.h"
+
+#include "APIPageConfiguration.h"
+#include "WebPageProxy.h"
+#include "WebPreferences.h"
+#include "PageClient.h"
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <WebCore/Credential.h>
+
+
+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, bool fixedlayout, std::optional<double>&& deviceScaleFactor, Ref<SetDeviceMetricsOverrideCallback>&& 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
+
+    if (deviceScaleFactor)
+        m_page.setCustomDeviceScaleFactor(deviceScaleFactor.value());
+    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<SetDeviceMetricsOverrideCallback>&& callback)
+{
+    platformSetSize(width, height, [callback = WTFMove(callback)](const String& error) {
+        if (error.isEmpty())
+            callback->sendSuccess();
+        else
+            callback->sendFailure(error);
+    });
+}
+
+Inspector::Protocol::ErrorStringOr<void> WebPageInspectorEmulationAgent::setJavaScriptEnabled(bool enabled)
+{
+    auto copy = m_page.preferences().copy();
+    copy->setJavaScriptEnabled(enabled);
+    m_page.setPreferences(copy);
+    return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> WebPageInspectorEmulationAgent::setAuthCredentials(const String& username, const String& password)
+{
+    if (!!username && !!password)
+        m_page.setAuthCredentialsForAutomation(WebCore::Credential(username, password, CredentialPersistencePermanent));
+    else
+        m_page.setAuthCredentialsForAutomation(std::optional<WebCore::Credential>());
+    return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> WebPageInspectorEmulationAgent::setActiveAndFocused(std::optional<bool>&& active)
+{
+    m_page.setActiveForAutomation(WTFMove(active));
+    return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> WebPageInspectorEmulationAgent::grantPermissions(const String& origin, Ref<JSON::Array>&& values)
+{
+    HashSet<String> 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<void> 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..b3bb4880a866ee6132b8b26acf8dad81afe14d85
--- /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 <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+
+#include <wtf/Forward.h>
+#include <wtf/Function.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+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, bool fixedlayout, std::optional<double>&& deviceScaleFactor, Ref<SetDeviceMetricsOverrideCallback>&&) override;
+    Inspector::Protocol::ErrorStringOr<void> setJavaScriptEnabled(bool enabled) override;
+    Inspector::Protocol::ErrorStringOr<void> setAuthCredentials(const String&, const String&) override;
+    Inspector::Protocol::ErrorStringOr<void> setActiveAndFocused(std::optional<bool>&&) override;
+    Inspector::Protocol::ErrorStringOr<void> grantPermissions(const String& origin, Ref<JSON::Array>&& permissions) override;
+    Inspector::Protocol::ErrorStringOr<void> resetPermissions() override;
+
+    void didShowPage();
+
+private:
+    void setSize(int width, int height, Ref<SetDeviceMetricsOverrideCallback>&& callback);
+    void platformSetSize(int width, int height, Function<void (const String& error)>&&);
+
+    Ref<Inspector::EmulationBackendDispatcher> m_backendDispatcher;
+    WebPageProxy& m_page;
+    Vector<Function<void()>> m_commandsToRunWhenShown;
+    HashMap<String, HashSet<String>> m_permissions;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a4dd654b36b2765acd18cf3bc3b1805bc65272c6
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp
@@ -0,0 +1,329 @@
+/*
+ * 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 "NativeWebWheelEvent.h"
+#include "WebWheelEvent.h"
+#include "WebPageProxy.h"
+#include <wtf/MathExtras.h>
+#include <wtf/HexNumber.h>
+
+#include "WebPageMessages.h"
+
+namespace WebKit {
+
+using namespace Inspector;
+
+namespace {
+
+template<class T>
+class CallbackList {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ~CallbackList()
+    {
+        for (const auto& callback : m_callbacks)
+            callback->sendFailure("Page closed");
+    }
+
+    void append(Ref<T>&& callback)
+    {
+        m_callbacks.append(WTFMove(callback));
+    }
+
+    void sendSuccess()
+    {
+        for (const auto& callback : m_callbacks)
+            callback->sendSuccess();
+        m_callbacks.clear();
+    }
+
+private:
+    Vector<Ref<T>> m_callbacks;
+};
+
+} // namespace
+
+class WebPageInspectorInputAgent::KeyboardCallbacks : public CallbackList<Inspector::InputBackendDispatcherHandler::DispatchKeyEventCallback> {
+};
+
+class WebPageInspectorInputAgent::MouseCallbacks : public CallbackList<Inspector::InputBackendDispatcherHandler::DispatchMouseEventCallback> {
+};
+
+class WebPageInspectorInputAgent::WheelCallbacks : public CallbackList<Inspector::InputBackendDispatcherHandler::DispatchWheelEventCallback> {
+};
+
+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::didProcessAllPendingWheelEvents()
+{
+    m_wheelCallbacks->sendSuccess();
+}
+
+void WebPageInspectorInputAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
+{
+    m_keyboardCallbacks = makeUnique<KeyboardCallbacks>();
+    m_mouseCallbacks = makeUnique<MouseCallbacks>();
+    m_wheelCallbacks = makeUnique<WheelCallbacks>();
+}
+
+void WebPageInspectorInputAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
+{
+    m_keyboardCallbacks = nullptr;
+    m_mouseCallbacks = nullptr;
+    m_wheelCallbacks = 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, std::optional<int>&& modifiers, const String& text, const String& unmodifiedText, const String& code, const String& key, std::optional<int>&& windowsVirtualKeyCode, std::optional<int>&& nativeVirtualKeyCode, std::optional<bool>&& autoRepeat, std::optional<bool>&& isKeypad, std::optional<bool>&& isSystemKey, RefPtr<JSON::Array>&& commands, Ref<Inspector::InputBackendDispatcherHandler::DispatchKeyEventCallback>&& 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<WebEvent::Modifier> eventModifiers;
+    if (modifiers)
+        eventModifiers = eventModifiers.fromRaw(*modifiers);
+    int eventWindowsVirtualKeyCode = 0;
+    if (windowsVirtualKeyCode)
+        eventWindowsVirtualKeyCode = *windowsVirtualKeyCode;
+    int eventNativeVirtualKeyCode = 0;
+    if (nativeVirtualKeyCode)
+        eventNativeVirtualKeyCode = *nativeVirtualKeyCode;
+    Vector<String> 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, std::optional<int>&& modifiers, const String& button, std::optional<int>&& buttons, std::optional<int>&& clickCount, std::optional<int>&& deltaX, std::optional<int>&& deltaY, Ref<DispatchMouseEventCallback>&& 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<WebEvent::Modifier> 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), eventButtons);
+#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, std::optional<int>&& modifiers, Ref<DispatchTapEventCallback>&& callback) {
+    m_page.sendWithAsyncReply(Messages::WebPage::FakeTouchTap(WebCore::IntPoint(x, y), modifiers ? *modifiers : 0), [callback]() {
+        callback->sendSuccess();
+    });
+}
+
+void WebPageInspectorInputAgent::dispatchWheelEvent(int x, int y, std::optional<int>&& modifiers, std::optional<int>&& deltaX, std::optional<int>&& deltaY, Ref<DispatchWheelEventCallback>&& callback)
+{
+    OptionSet<WebEvent::Modifier> eventModifiers;
+    if (modifiers)
+        eventModifiers = eventModifiers.fromRaw(*modifiers);
+
+    float eventDeltaX = 0.0f;
+    if (deltaX)
+        eventDeltaX = *deltaX;
+    float eventDeltaY = 0.0f;
+    if (deltaY)
+        eventDeltaY = *deltaY;
+    m_wheelCallbacks->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));
+
+    WallTime timestamp = WallTime::now();
+    WebCore::FloatSize delta = {-eventDeltaX, -eventDeltaY};
+    WebCore::FloatSize wheelTicks = delta;
+    wheelTicks.scale(1.0f / WebCore::Scrollbar::pixelsPerLineStep());
+    WebWheelEvent webEvent(WebEvent::Wheel, {x, y}, {x, y}, delta, wheelTicks, WebWheelEvent::ScrollByPixelWheelEvent, eventModifiers, timestamp);
+    NativeWebWheelEvent event(webEvent);
+    m_page.handleWheelEvent(event);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..48c9ccc420c1b4ae3259e1d5ba17fd8fbea24b96
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h
@@ -0,0 +1,86 @@
+/*
+ * 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 <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+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 didProcessAllPendingWheelEvents();
+
+    void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+    void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+    // Protocol handler
+    void dispatchKeyEvent(const String& type, std::optional<int>&& modifiers, const String& text, const String& unmodifiedText, const String& code, const String& key, std::optional<int>&& windowsVirtualKeyCode, std::optional<int>&& nativeVirtualKeyCode, std::optional<bool>&& autoRepeat, std::optional<bool>&& isKeypad, std::optional<bool>&& isSystemKey, RefPtr<JSON::Array>&&, Ref<DispatchKeyEventCallback>&& callback) override;
+    void dispatchMouseEvent(const String& type, int x, int y, std::optional<int>&& modifiers, const String& button, std::optional<int>&& buttons, std::optional<int>&& clickCount, std::optional<int>&& deltaX, std::optional<int>&& deltaY, Ref<DispatchMouseEventCallback>&& callback) override;
+    void dispatchTapEvent(int x, int y, std::optional<int>&& modifiers, Ref<DispatchTapEventCallback>&& callback) override;
+    void dispatchWheelEvent(int x, int y, std::optional<int>&& modifiers, std::optional<int>&& deltaX, std::optional<int>&& deltaY, Ref<DispatchWheelEventCallback>&& 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<WebEvent::Modifier> modifiers, Vector<String>& commands, WallTime timestamp);
+#if PLATFORM(MAC)
+    void platformDispatchMouseEvent(const String& type, int x, int y, std::optional<int>&& modifier, const String& button, std::optional<int>&& clickCount, unsigned short buttons);
+#endif
+
+    Ref<Inspector::InputBackendDispatcher> 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<KeyboardCallbacks> m_keyboardCallbacks;
+    class MouseCallbacks;
+    std::unique_ptr<MouseCallbacks> m_mouseCallbacks;
+    class WheelCallbacks;
+    std::unique_ptr<WheelCallbacks> m_wheelCallbacks;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp
index 9ca6815eeaafecb6fb01b345edb594391877eadd..6726ed4c9f8dc3122d419db692450ecde056b542 100644
--- a/Source/WebKit/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp
@@ -245,6 +245,9 @@
 
 #if PLATFORM(GTK)
 #include "GtkSettingsManager.h"
+#endif
+
+#if PLATFORM(GTK) || PLATFORM(WPE)
 #include <WebCore/SelectionData.h>
 #endif
 
@@ -618,6 +621,10 @@ WebPageProxy::~WebPageProxy()
     if (m_preferences->mediaSessionCoordinatorEnabled())
         GroupActivitiesSessionNotifier::sharedNotifier().removeWebPage(*this);
 #endif
+
+#if PLATFORM(COCOA)
+    releaseInspectorDragPasteboard();
+#endif
 }
 
 void WebPageProxy::addAllMessageReceivers()
@@ -1018,6 +1025,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason)
     m_pageLoadState.didSwapWebProcesses();
     if (reason != ProcessLaunchReason::InitialProcess)
         m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
+    m_inspectorController->didFinishAttachingToWebProcess();
 }
 
 void WebPageProxy::didAttachToRunningProcess()
@@ -1371,6 +1379,21 @@ WebProcessProxy& WebPageProxy::ensureRunningProcess()
     return m_process;
 }
 
+RefPtr<API::Navigation> 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 = ShouldTreatAsContinuingLoad::No;
+    m_process->send(Messages::WebPage::LoadRequestInFrameForInspector(loadParameters, frame->frameID()),  m_webPageID);
+    return navigation;
+}
+
 RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData)
 {
     if (m_isClosed)
@@ -1919,6 +1942,31 @@ void WebPageProxy::setControlledByAutomation(bool controlled)
     websiteDataStore().networkProcess().send(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation), 0);
 }
 
+void WebPageProxy::setAuthCredentialsForAutomation(std::optional<WebCore::Credential>&& credentials)
+{
+    m_credentialsForAutomation = WTFMove(credentials);
+}
+
+void WebPageProxy::setPermissionsForAutomation(const HashMap<String, HashSet<String>>& permissions)
+{
+    m_permissionsForAutomation = permissions;
+}
+
+void WebPageProxy::setActiveForAutomation(std::optional<bool> active) {
+    m_activeForAutomation = active;
+    OptionSet<ActivityState::Flag> 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());
@@ -2109,6 +2157,25 @@ void WebPageProxy::updateActivityState(OptionSet<ActivityState::Flag> 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())
@@ -2681,6 +2748,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);
@@ -2691,6 +2760,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));
@@ -2706,18 +2777,41 @@ void WebPageProxy::didPerformDragControllerAction(std::optional<WebCore::DragOpe
     m_currentDragCaretEditableElementRect = editableElementRect;
     setDragCaretRect(insertionRect);
     pageClient().didPerformDragControllerAction();
+    m_dragEventsQueued--;
+    if (m_dragEventsQueued == 0 && m_mouseEventQueue.isEmpty())
+        m_inspectorController->didProcessAllPendingMouseEvents();
+
 }
 
-#if PLATFORM(GTK)
+#if PLATFORM(GTK) || PLATFORM(WPE)
 void WebPageProxy::startDrag(SelectionData&& selectionData, OptionSet<WebCore::DragOperation> dragOperationMask, const ShareableBitmap::Handle& dragImageHandle)
 {
-    RefPtr<ShareableBitmap> 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<ShareableBitmap> 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<WebCore::DragOperation> dragOperationMask)
 {
     if (!hasRunningProcess())
@@ -2726,6 +2820,24 @@ void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& glo
     setDragCaretRect({ });
 }
 
+bool WebPageProxy::cancelDragIfNeeded() {
+    if (!m_dragSelectionData)
+        return false;
+    m_dragSelectionData = std::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);
@@ -2738,8 +2850,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())
@@ -2844,16 +2966,38 @@ void WebPageProxy::processNextQueuedMouseEvent()
         m_process->startResponsivenessTimer();
     }
 
-    std::optional<Vector<SandboxExtension::Handle>> sandboxExtensions;
+    m_lastMousePositionForDrag = event.position();
+    if (!m_dragSelectionData) {
+        std::optional<Vector<SandboxExtension::Handle>> 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 }, std::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 }, std::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;
+                Vector<SandboxExtension::Handle> sandboxExtensionsForUpload;
+
+                performDragOperation(dragData, "", WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionsForUpload));
+            }
+            m_dragSelectionData = std::nullopt;
+            dragEnded(event.position(), event.globalPosition(), m_dragSourceOperationMask);
+        }
+        didReceiveEvent(eventType, true);
+    }
 }
 
 void WebPageProxy::doAfterProcessingAllPendingMouseEvents(WTF::Function<void ()>&& action)
@@ -3017,7 +3161,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();
@@ -3050,7 +3194,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
@@ -3439,6 +3583,8 @@ void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, A
         policyAction = PolicyAction::Download;
 
     if (policyAction != PolicyAction::Use || !frame.isMainFrame() || !navigation) {
+        if (policyAction == PolicyAction::Download && navigation)
+            m_decidePolicyForResponseRequest = navigation->currentRequest();
         receivedPolicyDecision(policyAction, navigation, WTFMove(policies), WTFMove(navigationAction), WTFMove(sender));
         return;
     }
@@ -3507,6 +3653,7 @@ void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, A
 
 void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, RefPtr<API::WebsitePolicies>&& websitePolicies, std::variant<Ref<API::NavigationResponse>, Ref<API::NavigationAction>>&& navigationActionOrResponse, Ref<PolicyDecisionSender>&& sender, std::optional<SandboxExtension::Handle> sandboxExtensionHandle, WillContinueLoadInNewProcess willContinueLoadInNewProcess)
 {
+    m_inspectorController->didReceivePolicyDecision(action, navigation ? navigation->navigationID() : 0);
     if (!hasRunningProcess()) {
         sender->send(PolicyDecision { sender->identifier(), isNavigatingToAppBoundDomain(), PolicyAction::Ignore, 0, std::nullopt, std::nullopt });
         return;
@@ -4243,6 +4390,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;
@@ -4586,6 +4738,7 @@ void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
         return;
 
     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)
@@ -4810,6 +4963,8 @@ void WebPageProxy::didFailProvisionalLoadForFrameShared(Ref<WebProcessProxy>&& 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;
@@ -5278,7 +5433,14 @@ void WebPageProxy::decidePolicyForNavigationActionAsync(FrameIdentifier frameID,
     NavigationActionData&& navigationActionData, FrameInfoData&& originatingFrameInfo, std::optional<WebPageProxyIdentifier> 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 = Ref { *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<WebProcessProxy>&& process, PageIdentifier webPageID, FrameIdentifier frameID, FrameInfoData&& frameInfo,
@@ -5839,6 +6001,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 = Ref { *this }, mainFrameURL, request, reply = WTFMove(reply), privateClickMeasurement = navigationActionData.privateClickMeasurement] (RefPtr<WebPageProxy> newPage) mutable {
         if (!newPage) {
             reply(std::nullopt, std::nullopt);
@@ -5882,6 +6045,7 @@ void WebPageProxy::createNewPage(FrameInfoData&& originatingFrameInfoData, WebPa
 void WebPageProxy::showPage()
 {
     m_uiClient->showPage(this);
+    m_inspectorController->didShowPage();
 }
 
 void WebPageProxy::exitFullscreenImmediately()
@@ -5917,6 +6081,10 @@ void WebPageProxy::closePage()
     if (isClosed())
         return;
 
+#if ENABLE(CONTEXT_MENUS)
+    if (m_activeContextMenu)
+        m_activeContextMenu->hide();
+#endif
     WEBPAGEPROXY_RELEASE_LOG(Process, "closePage:");
     pageClient().clearAllEditCommands();
     m_uiClient->close(this);
@@ -5953,6 +6121,8 @@ void WebPageProxy::runJavaScriptAlert(FrameIdentifier frameID, FrameInfoData&& f
     }
 
     runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), message, [reply = WTFMove(reply)](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, const String& message, CompletionHandler<void()>&& completion) mutable {
+        if (page.m_inspectorDialogAgent)
+            page.m_inspectorDialogAgent->javascriptDialogOpening("alert"_s, message);
         page.m_uiClient->runJavaScriptAlert(page, message, frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)]() mutable {
             reply();
             completion();
@@ -5974,6 +6144,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);
 
     runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), message, [reply = WTFMove(reply)](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, const String& message, CompletionHandler<void()>&& completion) mutable {
         page.m_uiClient->runJavaScriptConfirm(page, message, frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)](bool result) mutable {
@@ -5997,6 +6169,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);
 
     runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), message, [reply = WTFMove(reply), defaultValue](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, const String& message, CompletionHandler<void()>&& completion) mutable {
         page.m_uiClient->runJavaScriptPrompt(page, message, defaultValue, frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)](auto& result) mutable {
@@ -6124,6 +6298,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();
@@ -7363,6 +7539,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;
     }
@@ -7377,10 +7555,13 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
             pageClient().wheelEventWasNotHandledByWebCore(oldestProcessedEvent);
         }
 
-        if (auto eventToSend = wheelEventCoalescer().nextEventToDispatch())
+        if (auto eventToSend = wheelEventCoalescer().nextEventToDispatch()) {
             sendWheelEvent(*eventToSend);
-        else if (auto* automationSession = process().processPool().automationSession())
-            automationSession->wheelEventsFlushedForPage(*this);
+        } else {
+            if (auto* automationSession = process().processPool().automationSession())
+                automationSession->wheelEventsFlushedForPage(*this);
+            m_inspectorController->didProcessAllPendingWheelEvents();
+        }
         break;
     }
 
@@ -7389,7 +7570,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());
@@ -7408,7 +7588,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
         // The call to doneWithKeyEvent may close this WebPage.
         // Protect against this being destroyed.
         Ref<WebPageProxy> protect(*this);
-
         pageClient().doneWithKeyEvent(event, handled);
         if (!handled)
             m_uiClient->didNotHandleKeyEvent(this, event);
@@ -7417,6 +7596,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
         if (!canProcessMoreKeyEvents) {
             if (auto* automationSession = process().processPool().automationSession())
                 automationSession->keyboardEventsFlushedForPage(*this);
+            m_inspectorController->didProcessAllPendingKeyboardEvents();
         }
         break;
     }
@@ -7771,7 +7951,10 @@ void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason)
 {
     WEBPAGEPROXY_RELEASE_LOG_ERROR(Loading, "dispatchProcessDidTerminate: reason=%{public}s", processTerminationReasonToString(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
@@ -8158,6 +8341,7 @@ static const Vector<ASCIILiteral>& mediaRelatedIOKitClasses()
 
 WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& process, DrawingAreaProxy& drawingArea, RefPtr<API::WebsitePolicies>&& websitePolicies)
 {
+
     WebPageCreationParameters parameters;
 
     parameters.processDisplayName = configuration().processDisplayName();
@@ -8353,6 +8537,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc
     parameters.shouldRelaxThirdPartyCookieBlocking = m_configuration->shouldRelaxThirdPartyCookieBlocking();
     parameters.canUseCredentialStorage = m_canUseCredentialStorage;
 
+    parameters.shouldPauseInInspectorWhenShown = m_inspectorController->shouldPauseLoading();
+
 #if PLATFORM(GTK)
     parameters.gtkSettings = GtkSettingsManager::singleton().settingsState();
 #endif
@@ -8434,6 +8620,14 @@ void WebPageProxy::gamepadActivity(const Vector<GamepadData>& gamepadDatas, Even
 
 void WebPageProxy::didReceiveAuthenticationChallengeProxy(Ref<AuthenticationChallengeProxy>&& authenticationChallenge, NegotiatedLegacyTLS negotiatedLegacyTLS)
 {
+    if (m_credentialsForAutomation.has_value()) {
+        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 = Ref { *this }, authenticationChallenge] (bool shouldAllowLegacyTLS) {
             if (shouldAllowLegacyTLS)
@@ -8527,6 +8721,15 @@ void WebPageProxy::requestGeolocationPermissionForFrame(GeolocationIdentifier ge
             request->deny();
     };
 
+    auto securityOrigin = frameInfo.securityOrigin.securityOrigin();
+    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 9a816fdb3183a19b679e87703a0f440e5ab90903..41caa2fd63a4ad7dc756be17d26b4a7f4f3ef1bb 100644
--- a/Source/WebKit/UIProcess/WebPageProxy.h
+++ b/Source/WebKit/UIProcess/WebPageProxy.h
@@ -39,6 +39,7 @@
 #include "GeolocationPermissionRequestManagerProxy.h"
 #include "HiddenPageThrottlingAutoIncreasesCounter.h"
 #include "IdentifierTypes.h"
+#include "InspectorDialogAgent.h"
 #include "LayerTreeContext.h"
 #include "MediaKeySystemPermissionRequestManagerProxy.h"
 #include "MediaPlaybackState.h"
@@ -148,8 +149,11 @@
 #include "EndowmentStateTracker.h"
 #endif
 
+OBJC_CLASS NSPasteboard;
+
 #if ENABLE(DRAG_SUPPORT)
 #include <WebCore/DragActions.h>
+#include <WebCore/DragData.h>
 #endif
 
 #if ENABLE(TOUCH_EVENTS)
@@ -170,6 +174,14 @@
 #include "ArgumentCodersGtk.h"
 #endif
 
+#if PLATFORM(WPE)
+#include "ArgumentCodersWPE.h"
+#endif
+
+#if PLATFORM(GTK) || PLATFORM(WPE)
+#include <WebCore/SelectionData.h>
+#endif
+
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
 #include <WebCore/MediaPlaybackTargetPicker.h>
 #include <WebCore/WebMediaSessionManagerClient.h>
@@ -251,6 +263,7 @@ class AuthenticationChallenge;
 class CertificateInfo;
 class Cursor;
 class DragData;
+typedef HashMap<unsigned, Vector<String>> DragDataMap;
 class FloatRect;
 class FontAttributeChanges;
 class FontChanges;
@@ -258,7 +271,6 @@ class GraphicsLayer;
 class IntSize;
 class ProtectionSpace;
 class RunLoopObserver;
-class SelectionData;
 class SharedBuffer;
 class SpeechRecognitionRequest;
 class TextIndicator;
@@ -542,6 +554,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();
@@ -645,6 +659,11 @@ public:
 
     void setPageLoadStateObserver(std::unique_ptr<PageLoadState::Observer>&&);
 
+    void setAuthCredentialsForAutomation(std::optional<WebCore::Credential>&&);
+    void setPermissionsForAutomation(const HashMap<String, HashSet<String>>&);
+    void setActiveForAutomation(std::optional<bool> active);
+    void logToStderr(const String& str);
+
     void initializeWebPage();
     void setDrawingArea(std::unique_ptr<DrawingAreaProxy>&&);
 
@@ -672,6 +691,7 @@ public:
     void closePage();
 
     void addPlatformLoadParameters(WebProcessProxy&, LoadParameters&);
+    RefPtr<API::Navigation> loadRequestForInspector(WebCore::ResourceRequest&&, WebFrameProxy*);
     RefPtr<API::Navigation> loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemesButNotAppLinks, API::Object* userData = nullptr);
     RefPtr<API::Navigation> loadFile(const String& fileURL, const String& resourceDirectoryURL, bool isAppInitiated = true, API::Object* userData = nullptr);
     RefPtr<API::Navigation> loadData(const IPC::DataReference&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData = nullptr, WebCore::ShouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow);
@@ -1193,6 +1213,7 @@ public:
 #endif
 
     void pageScaleFactorDidChange(double);
+    void viewScaleFactorDidChange(double);
     void pluginScaleFactorDidChange(double);
     void pluginZoomFactorDidChange(double);
 
@@ -1269,14 +1290,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<WebCore::DragOperation>, const ShareableBitmap::Handle& dragImage);
 #endif
+#if PLATFORM(WIN)
+    void startDrag(WebCore::DragDataMap& dragDataMap);
+#endif
 #endif
 
     void processDidBecomeUnresponsive();
@@ -1523,6 +1550,8 @@ public:
 
 #if PLATFORM(COCOA) || PLATFORM(GTK)
     RefPtr<ViewSnapshot> takeViewSnapshot(std::optional<WebCore::IntRect>&&);
+#elif PLATFORM(WPE)
+    RefPtr<ViewSnapshot> takeViewSnapshot(std::optional<WebCore::IntRect>&&) { return nullptr; }
 #endif
 
 #if ENABLE(WEB_CRYPTO)
@@ -2645,6 +2674,7 @@ private:
     String m_overrideContentSecurityPolicy;
 
     RefPtr<WebInspectorUIProxy> m_inspector;
+    InspectorDialogAgent* m_inspectorDialogAgent { nullptr };
 
 #if PLATFORM(COCOA)
     WeakObjCPtr<WKWebView> m_cocoaView;
@@ -2909,6 +2939,20 @@ private:
     unsigned m_currentDragNumberOfFilesToBeAccepted { 0 };
     WebCore::IntRect m_currentDragCaretRect;
     WebCore::IntRect m_currentDragCaretEditableElementRect;
+    bool m_interceptDrags { false };
+    OptionSet<WebCore::DragOperation> m_dragSourceOperationMask;
+    WebCore::IntPoint m_lastMousePositionForDrag;
+    int m_dragEventsQueued = 0;
+#if PLATFORM(COCOA)
+    std::optional<String> m_dragSelectionData;
+    String m_overrideDragPasteboardName;
+#endif
+#if PLATFORM(GTK) || PLATFORM(WPE)
+    std::optional<WebCore::SelectionData> m_dragSelectionData;
+#endif
+#if PLATFORM(WIN)
+    std::optional<WebCore::DragDataMap> m_dragSelectionData;
+#endif
 #endif
 
     PageLoadState m_pageLoadState;
@@ -3121,6 +3165,9 @@ private:
         RefPtr<API::Object> messageBody;
     };
     Vector<InjectedBundleMessage> m_pendingInjectedBundleMessages;
+    std::optional<WebCore::Credential> m_credentialsForAutomation;
+    HashMap<String, HashSet<String>> m_permissionsForAutomation;
+    std::optional<bool> m_activeForAutomation;
         
 #if PLATFORM(IOS_FAMILY) && ENABLE(DEVICE_ORIENTATION)
     std::unique_ptr<WebDeviceOrientationUpdateProviderProxy> m_webDeviceOrientationUpdateProviderProxy;
diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in
index d5636a3a62c7af84d72d498afdae1f32b8f4b554..bad5a699c6f0d3ab74d3da88cfbfc5140b6af27c 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(WEBGL)
     WebGLPolicyForURL(URL url) -> (enum:uint8_t WebCore::WebGLLoadPolicy loadPolicy) Synchronous
@@ -174,6 +175,7 @@ messages -> WebPageProxy {
 #endif
 
     PageScaleFactorDidChange(double scaleFactor)
+    ViewScaleFactorDidChange(double scaleFactor)
     PluginScaleFactorDidChange(double zoomFactor)
     PluginZoomFactorDidChange(double zoomFactor)
 
@@ -302,10 +304,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<WebCore::DragOperation> dragOperationMask, WebKit::ShareableBitmap::Handle dragImage)
 #endif
-
+#if PLATFORM(WIN) && ENABLE(DRAG_SUPPORT)
+    StartDrag(HashMap<unsigned, Vector<String>> 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 0961367a61e89647c40c03962a4ba3d0ea6b1ab9..fd2b1c6e37a933ffb8b9e4467c7eca8ff6a88580 100644
--- a/Source/WebKit/UIProcess/WebProcessPool.cpp
+++ b/Source/WebKit/UIProcess/WebProcessPool.cpp
@@ -523,6 +523,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 };
@@ -795,8 +803,12 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa
 #endif
 
     parameters.cacheModel = LegacyGlobalSettings::singleton().cacheModel();
-    parameters.overrideLanguages = configuration().overrideLanguages();
-    LOG_WITH_STREAM(Language, stream << "WebProcessPool is initializing a new web process with overrideLanguages: " << parameters.overrideLanguages);
+    if (websiteDataStore && websiteDataStore->languagesForAutomation().size())
+        parameters.overrideLanguages = websiteDataStore->languagesForAutomation();
+    else {
+        parameters.overrideLanguages = configuration().overrideLanguages();
+        LOG_WITH_STREAM(Language, stream << "WebProcessPool is initializing a new web process with overrideLanguages: " << parameters.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 6656e2dddd3b42cc707e8a28b5da9ada708099fb..89b9538d8d0076052509996cc915c5679c0ac6d2 100644
--- a/Source/WebKit/UIProcess/WebProcessProxy.cpp
+++ b/Source/WebKit/UIProcess/WebProcessProxy.cpp
@@ -144,6 +144,11 @@ HashMap<ProcessIdentifier, WebProcessProxy*>& WebProcessProxy::allProcesses()
     return map;
 }
 
+Vector<WebProcessProxy*> 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 f74480ffa7cc9f1806521e5bb0551f4466be57e4..4a27ca15723c90f046b3a63c55fcd5538995103d 100644
--- a/Source/WebKit/UIProcess/WebProcessProxy.h
+++ b/Source/WebKit/UIProcess/WebProcessProxy.h
@@ -143,6 +143,7 @@ public:
     ~WebProcessProxy();
 
     static void forWebPagesWithOrigin(PAL::SessionID, const WebCore::SecurityOriginData&, const Function<void(WebPageProxy&)>&);
+    static Vector<WebProcessProxy*> 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 909793e37568c042b1002a26aa0274784a91e4ca..d46ee8c3aa5835b2789a6566a040c7b4612b26a4 100644
--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
@@ -2035,6 +2035,17 @@ void WebsiteDataStore::renameOriginInWebsiteData(URL&& oldName, URL&& newName, O
     networkProcess().renameOriginInWebsiteData(m_sessionID, oldName, newName, dataTypes, WTFMove(completionHandler));
 }
 
+void WebsiteDataStore::setLanguagesForAutomation(Vector<String>&& languages)
+{
+    m_languagesForAutomation = WTFMove(languages);
+}
+
+void WebsiteDataStore::setDownloadForAutomation(std::optional<bool> allow, const String& downloadPath)
+{
+    m_allowDownloadForAutomation = allow;
+    m_downloadPathForAutomation = downloadPath;
+}
+
 #if ENABLE(APP_BOUND_DOMAINS)
 void WebsiteDataStore::hasAppBoundSession(CompletionHandler<void(bool)>&& completionHandler) const
 {
diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
index 1de25a66057f2d66c6299e5ebbb8146bee9b81e3..126b238365b8f9113028636ead95091186888826 100644
--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
@@ -88,6 +88,7 @@ class SecKeyProxyStore;
 class DeviceIdHashSaltStorage;
 class NetworkProcessProxy;
 class SOAuthorizationCoordinator;
+class DownloadProxy;
 class VirtualAuthenticatorManager;
 class WebPageProxy;
 class WebProcessPool;
@@ -97,6 +98,7 @@ enum class CacheModel : uint8_t;
 enum class WebsiteDataFetchOption : uint8_t;
 enum class WebsiteDataType : uint32_t;
 
+struct FrameInfoData;
 struct NetworkProcessConnectionInfo;
 struct WebsiteDataRecord;
 struct WebsiteDataStoreParameters;
@@ -107,6 +109,14 @@ enum class StorageAccessStatus : uint8_t;
 enum class StorageAccessPromptStatus;
 #endif
 
+class DownloadInstrumentation {
+public:
+    virtual void downloadCreated(const String& uuid, const WebCore::ResourceRequest&, const FrameInfoData& frameInfoData, WebPageProxy* page, RefPtr<DownloadProxy> download) = 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<API::Object::Type::WebsiteDataStore>, public Identified<WebsiteDataStore>, public CanMakeWeakPtr<WebsiteDataStore>  {
 public:
     static Ref<WebsiteDataStore> defaultDataStore();
@@ -289,11 +299,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; }
     void setCookiePersistentStorage(const String&, SoupCookiePersistentStorageType);
@@ -354,6 +366,14 @@ public:
     static WTF::String defaultJavaScriptConfigurationDirectory();
     static bool http3Enabled();
 
+    void setLanguagesForAutomation(Vector<String>&&);
+    Vector<String>& languagesForAutomation() { return m_languagesForAutomation; };
+    void setDownloadForAutomation(std::optional<bool> allow, const String& downloadPath);
+    std::optional<bool> allowDownloadForAutomation() { return m_allowDownloadForAutomation; };
+    String downloadPathForAutomation() { return m_downloadPathForAutomation; };
+    void setDownloadInstrumentation(DownloadInstrumentation* instrumentation) { m_downloadInstrumentation = instrumentation; };
+    DownloadInstrumentation* downloadInstrumentation() { return m_downloadInstrumentation; };
+
     void resetQuota(CompletionHandler<void()>&&);
     void clearStorage(CompletionHandler<void()>&&);
 
@@ -437,9 +457,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;
     String m_cookiePersistentStoragePath;
     SoupCookiePersistentStorageType m_cookiePersistentStorageType { SoupCookiePersistentStorageType::SQLite };
@@ -467,6 +489,11 @@ private:
     RefPtr<API::HTTPCookieStore> m_cookieStore;
     RefPtr<NetworkProcessProxy> m_networkProcess;
 
+    Vector<String> m_languagesForAutomation;
+    std::optional<bool> m_allowDownloadForAutomation;
+    String m_downloadPathForAutomation;
+    DownloadInstrumentation* m_downloadInstrumentation { nullptr };
+
 #if HAVE(APP_SSO)
     UniqueRef<SOAuthorizationCoordinator> m_soAuthorizationCoordinator;
 #endif
diff --git a/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp b/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp
index 0b2fc0019ffa2c05383dc4b4e480b4d380aa9fd5..79773452d246f3bcdf42122a3bf8f67685e45fdc 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 <WebCore/BackingStoreBackendCairoImpl.h>
 #include <WebCore/CairoUtilities.h>
 #include <WebCore/GraphicsContextCairo.h>
@@ -61,6 +63,13 @@ std::unique_ptr<BackingStoreBackendCairo> BackingStore::createBackend()
     return makeUnique<BackingStoreBackendCairoImpl>(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 692a45a48fa027f9221338d74f5351bef4baf00f..db8c761c71cc7009be66255c2668de4eff36dee0 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 b5e48e6c61a8a3f4b40b84112c4010101c4d5f41..46747b1d78bfe0270178609867c0d710807fa668 100644
--- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h
+++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h
@@ -71,6 +71,9 @@ private:
     GRefPtr<GDBusProxy> m_manager;
     GRefPtr<GDBusProxy> m_client;
     GRefPtr<GCancellable> m_cancellable;
+    GRefPtr<GCancellable> m_cancellable_start;
+    GRefPtr<GCancellable> m_cancellable_setup;
+    GRefPtr<GCancellable> m_cancellable_create;
     UpdateNotifyFunction m_updateNotifyFunction;
     RunLoop::Timer<GeoclueGeolocationProvider> 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 <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/StringView.h>
+#include <wtf/text/WTFString.h>
+
+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<char**>(ignoreHosts)));
+    return settings;
+}
+
+static WebCore::SoupNetworkProxySettings parseProxySettings(const String& proxyServer, const String& proxyBypassList)
+{
+    Vector<const char*> ignoreHosts;
+    if (!proxyBypassList.isEmpty()) {
+        Vector<String> tokens = proxyBypassList.split(',');
+        Vector<CString> 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<WebPageProxy> 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<WebPageProxy> 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<BrowserContext> InspectorPlaywrightAgentClientGlib::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList)
+{
+    GRefPtr<WebKitWebsiteDataManager> data_manager = adoptGRef(webkit_website_data_manager_new_ephemeral());
+    GRefPtr<WebKitWebContext> 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>();
+    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 <WebCore/SoupNetworkProxySettings.h>
+#include "WebKitWebContext.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebKit {
+
+class InspectorPlaywrightAgentClientGlib : public InspectorPlaywrightAgentClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    InspectorPlaywrightAgentClientGlib(const WTF::String& proxyURI, const char* const* ignoreHosts);
+    ~InspectorPlaywrightAgentClientGlib() override = default;
+
+    RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
+    void closeBrowser() override;
+    std::unique_ptr<BrowserContext> 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<PAL::SessionID, GRefPtr<WebKitWebContext>> m_idToContext;
+    WebCore::SoupNetworkProxySettings m_proxySettings;
+};
+
+} // namespace API
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/glib/WebPageProxyGLib.cpp b/Source/WebKit/UIProcess/glib/WebPageProxyGLib.cpp
index 521df7840ab6d376c25130e87ea500942398c8b6..c733d9d5cd304889640e5af4423860717be94725 100644
--- a/Source/WebKit/UIProcess/glib/WebPageProxyGLib.cpp
+++ b/Source/WebKit/UIProcess/glib/WebPageProxyGLib.cpp
@@ -57,4 +57,34 @@ void WebPageProxy::loadRecentSearches(const String&, CompletionHandler<void(Vect
     completionHandler({ });
 }
 
+#if ENABLE(SPEECH_SYNTHESIS)
+void WebPageProxy::didStartSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
+{
+}
+
+void WebPageProxy::didFinishSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
+{
+}
+
+void WebPageProxy::didPauseSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
+{
+}
+
+void WebPageProxy::didResumeSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
+{
+}
+
+void WebPageProxy::speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&)
+{
+}
+
+void WebPageProxy::boundaryEventOccurred(WebCore::PlatformSpeechSynthesisUtterance&, WebCore::SpeechBoundary speechBoundary, unsigned charIndex)
+{
+}
+
+void WebPageProxy::voicesDidChange()
+{
+}
+#endif // ENABLE(SPEECH_SYNTHESIS)
+
 }
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 <wtf/Noncopyable.h>
 
 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<cairo_surface_t> 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 <WebCore/GtkUtilities.h>
+#include <gtk/gtk.h>
+
+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/WebDateTimePickerGtk.cpp b/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp
index 40ebef5dc078f5933056a63c498bd6f8e7f1d857..82a1500bbe3e1fe24d2d0806e46b67f58bfe8067 100644
--- a/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp
+++ b/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp
@@ -34,6 +34,8 @@
 #include <wtf/SetForScope.h>
 #include <wtf/glib/GRefPtr.h>
 
+using namespace WebCore;
+
 namespace WebKit {
 
 Ref<WebDateTimePickerGtk> WebDateTimePickerGtk::create(WebPageProxy& page)
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 <WebCore/IntSize.h>
+#include <gtk/gtk.h>
+
+namespace WebKit {
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& 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<DrawingAreaProxyCoordinatedGraphics*>(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 <WebCore/PlatformKeyboardEvent.h>
+
+namespace WebKit {
+
+static Vector<String> commandsForKeyEvent(GdkEventType type, unsigned keyVal, unsigned state)
+{
+    ASSERT(type == GDK_KEY_PRESS || type == GDK_KEY_RELEASE);
+
+    GUniquePtr<GdkEvent> 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<GdkKeymapKey> 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<WebEvent::Modifier> 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<WebEvent::Modifier> modifiers, Vector<String>& macCommands, WallTime timestamp)
+{
+    Vector<String> 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 32d1f89c058b9b40a18e8f67bc7be9f0a102508b..5d9184da8c5f5a172fa71d31b31010840f273031 100644
--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
@@ -437,6 +437,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 <wtf/Forward.h>
+
+OBJC_PROTOCOL(_WKBrowserInspectorDelegate);
+
+namespace WebKit {
+
+class InspectorPlaywrightAgentClientMac : public InspectorPlaywrightAgentClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    InspectorPlaywrightAgentClientMac(_WKBrowserInspectorDelegate* delegate);
+    ~InspectorPlaywrightAgentClientMac() override = default;
+
+    RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
+    void closeBrowser() override;
+    std::unique_ptr<BrowserContext> 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 <wtf/RefPtr.h>
+#import <wtf/text/WTFString.h>
+#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<WebPageProxy> 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<BrowserContext> 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>();
+    browserContext->processPool = &static_cast<WebProcessPool&>([[wkBrowserContext processPool] _apiObject]);
+    browserContext->dataStore = &static_cast<WebsiteDataStore&>([[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 d2238fdc9d16f77f8c3d302ca9976fe83f1b3f37..0be14a01d922cb3b705433f9d1a7c5ceff337827 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();
 
@@ -165,6 +167,9 @@ private:
     void updateAcceleratedCompositingMode(const LayerTreeContext&) override;
     void didFirstLayerFlush(const LayerTreeContext&) override;
 
+// Paywright begin
+    RetainPtr<CGImageRef> takeSnapshotForAutomation() override;
+// Paywright end
     RefPtr<ViewSnapshot> takeViewSnapshot(std::optional<WebCore::IntRect>&&) override;
     void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&) override;
 #if ENABLE(MAC_GESTURE_EVENTS)
@@ -218,6 +223,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 a4112135f2ef19015a52f1e1b03ae30a1f223d2a..3cc260a1ed20e5f010639651260bd97987e66139 100644
--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm
+++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm
@@ -81,6 +81,7 @@
 #import <WebCore/TextUndoInsertionMarkupMac.h>
 #import <WebCore/ValidationBubble.h>
 #import <WebCore/WebCoreCALayerExtras.h>
+#import <WebCore/NotImplemented.h>
 #import <pal/spi/mac/NSApplicationSPI.h>
 #import <wtf/ProcessPrivilege.h>
 #import <wtf/RetainPtr.h>
@@ -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)
@@ -475,6 +493,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);
 }
 
@@ -494,6 +514,8 @@ void PageClientImpl::computeHasImageAnalysisResults(const URL& imageURL, Shareab
 
 RefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy& page)
 {
+    if (_headless)
+        return nullptr;
     return WebPopupMenuProxyMac::create(m_view, page);
 }
 
@@ -625,6 +647,12 @@ CALayer *PageClientImpl::acceleratedCompositingRootLayer() const
     return m_impl->acceleratedCompositingRootLayer();
 }
 
+// Paywright begin
+RetainPtr<CGImageRef> PageClientImpl::takeSnapshotForAutomation() {
+    return m_impl->takeSnapshotForAutomation();
+}
+// Paywright begin
+
 RefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot(std::optional<WebCore::IntRect>&&)
 {
     return m_impl->takeViewSnapshot();
@@ -798,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);
@@ -975,6 +1010,9 @@ void PageClientImpl::requestScrollToRect(const WebCore::FloatRect& targetRect, c
 
 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 34e2d00746ebb079719becbe781f5bc6cea1d480..bf496a6327b962f8f40c207c9e2023d2152aded1 100644
--- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h
+++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h
@@ -70,6 +70,7 @@ private:
     void show() override;
     void showContextMenuWithItems(Vector<Ref<WebContextMenuItem>>&&) override;
     void useContextMenuItems(Vector<Ref<WebContextMenuItem>>&&) override;
+    void hide() override;
 
     void getContextMenuItem(const WebContextMenuItemData&, CompletionHandler<void(NSMenuItem *)>&&);
     void getContextMenuFromItems(const Vector<WebContextMenuItemData>&, CompletionHandler<void(NSMenu *)>&&);
diff --git a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm
index 049753f867d959f5db176c48824e2f551c646026..633136c091bea0566e03d7997a38af8ca7a2253b 100644
--- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm
+++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm
@@ -363,6 +363,12 @@ void WebContextMenuProxyMac::getShareMenuItem(CompletionHandler<void(NSMenuItem
 }
 #endif
 
+void WebContextMenuProxyMac::hide()
+{
+    if (m_menu)
+        [m_menu cancelTracking];
+}
+
 void WebContextMenuProxyMac::show()
 {
 #if ENABLE(SERVICE_CONTROLS)
diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..6113f4cd60a5d72b8ead61176cb43200803478ed
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm
@@ -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.
+ */
+
+#import "config.h"
+#import "WebPageInspectorEmulationAgent.h"
+
+#import "WebPageProxy.h"
+
+namespace WebKit {
+
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& 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..cbcc097c924d0a04c5a2265a8027347fe12d0449
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm
@@ -0,0 +1,125 @@
+/*
+ * 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 <WebCore/IntPoint.h>
+#import <WebCore/IntSize.h>
+#import "NativeWebKeyboardEvent.h"
+
+namespace WebKit {
+
+using namespace WebCore;
+
+void WebPageInspectorInputAgent::platformDispatchMouseEvent(const String& type, int x, int y, std::optional<int>&& optionalModifiers, const String& button, std::optional<int>&& optionalClickCount, unsigned short buttons) {
+    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]);
+        nativeEvent.playwrightSetButtons(buttons);
+        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<WebEvent::Modifier> modifiers, Vector<String>& commands, WallTime timestamp)
+{
+    Vector<WebCore::KeypressCommand> 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 <WebCore/CurlProxySettings.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/StringView.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+InspectorPlaywrightAgentClientWin::InspectorPlaywrightAgentClientWin(ConfigureDataStoreCallback configureDataStore, CreatePageCallback createPage, QuitCallback quit)
+    : m_configureDataStore(configureDataStore)
+    , m_createPage(createPage)
+    , m_quit(quit)
+{
+}
+
+RefPtr<WebPageProxy> 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<BrowserContext> InspectorPlaywrightAgentClientWin::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList)
+{
+    auto config = API::ProcessPoolConfiguration::create();
+    auto browserContext = std::make_unique<BrowserContext>();
+    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 <WebKit/WKInspector.h>
+#include <wtf/Forward.h>
+#include <wtf/text/StringHash.h>
+
+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<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
+    void closeBrowser() override;
+    std::unique_ptr<BrowserContext> 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<Ref<WebContextMenuItem>>&&) 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<void (const String& error)>&& 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 <WebCore/PlatformKeyboardEvent.h>
+
+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<WebEvent::Modifier> modifiers, Vector<String>& 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 <wpe/wpe.h>
+
+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/WebColorPickerWPE.cpp b/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2433afca5cdbac71d11ae1fce223766091b5c843
--- /dev/null
+++ b/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebColorPickerWPE.h"
+
+#if ENABLE(INPUT_TYPE_COLOR)
+
+#include "WebPageProxy.h"
+
+namespace WebKit {
+using namespace WebCore;
+
+Ref<WebColorPickerWPE> WebColorPickerWPE::create(WebPageProxy& page, const Color& initialColor, const IntRect& rect)
+{
+    return adoptRef(*new WebColorPickerWPE(page, initialColor, rect));
+}
+
+WebColorPickerWPE::WebColorPickerWPE(WebPageProxy& page, const Color& initialColor, const IntRect&)
+    : WebColorPicker(&page)
+{
+}
+
+WebColorPickerWPE::~WebColorPickerWPE()
+{
+    endPicker();
+}
+
+void WebColorPickerWPE::endPicker()
+{
+}
+
+void WebColorPickerWPE::showColorPicker(const Color& color)
+{
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(INPUT_TYPE_COLOR)
diff --git a/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.h b/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.h
new file mode 100644
index 0000000000000000000000000000000000000000..7edc93b3873dd42a7f877626551ec994395baae9
--- /dev/null
+++ b/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebColorPickerWPE_h
+#define WebColorPickerWPE_h
+
+#if ENABLE(INPUT_TYPE_COLOR)
+
+#include "WebColorPicker.h"
+
+typedef struct _GtkColorChooser GtkColorChooser;
+
+namespace WebCore {
+class Color;
+class IntRect;
+}
+
+namespace WebKit {
+
+class WebColorPickerWPE : public WebColorPicker {
+public:
+    static Ref<WebColorPickerWPE> create(WebPageProxy&, const WebCore::Color&, const WebCore::IntRect&);
+    virtual ~WebColorPickerWPE();
+
+    void endPicker() override;
+    void showColorPicker(const WebCore::Color&) override;
+
+protected:
+    WebColorPickerWPE(WebPageProxy&, const WebCore::Color&, const WebCore::IntRect&);
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(INPUT_TYPE_COLOR)
+#endif // WebColorPickerWPE_h
diff --git a/Source/WebKit/UIProcess/wpe/WebDateTimePickerWPE.cpp b/Source/WebKit/UIProcess/wpe/WebDateTimePickerWPE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a44463faf011fbab08f87bb7007a5e71c2a73758
--- /dev/null
+++ b/Source/WebKit/UIProcess/wpe/WebDateTimePickerWPE.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ * Copyright (C) 2021 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 "WebDateTimePickerWPE.h"
+
+#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
+
+using namespace WebCore;
+
+namespace WebKit {
+
+Ref<WebDateTimePickerWPE> WebDateTimePickerWPE::create(WebPageProxy& page)
+{
+    return adoptRef(*new WebDateTimePickerWPE(page));
+}
+
+WebDateTimePickerWPE::~WebDateTimePickerWPE()
+{
+}
+
+WebDateTimePickerWPE::WebDateTimePickerWPE(WebPageProxy& page)
+    : WebDateTimePicker(page)
+{
+}
+
+void WebDateTimePickerWPE::showDateTimePicker(WebCore::DateTimeChooserParameters&& params)
+{
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(DATE_AND_TIME_INPUT_TYPES)
diff --git a/Source/WebKit/UIProcess/wpe/WebDateTimePickerWPE.h b/Source/WebKit/UIProcess/wpe/WebDateTimePickerWPE.h
new file mode 100644
index 0000000000000000000000000000000000000000..0c0e3fce33b06ee72c4c29d2a4abe9644f4cc895
--- /dev/null
+++ b/Source/WebKit/UIProcess/wpe/WebDateTimePickerWPE.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ * Copyright (C) 2021 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
+
+#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
+
+#include "WebDateTimePicker.h"
+#include <WebCore/DateComponents.h>
+#include <WebCore/DateTimeChooserParameters.h>
+
+namespace WebKit {
+
+class WebDateTimePickerWPE final : public WebDateTimePicker {
+public:
+    static Ref<WebDateTimePickerWPE> create(WebPageProxy&);
+    ~WebDateTimePickerWPE();
+
+private:
+    WebDateTimePickerWPE(WebPageProxy&);
+
+    void showDateTimePicker(WebCore::DateTimeChooserParameters&&) final;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(DATE_AND_TIME_INPUT_TYPES)
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 <wpe/wpe.h>
+
+namespace WebKit {
+
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& 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 <WebCore/PlatformKeyboardEvent.h>
+#include <wpe/wpe.h>
+
+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<WebEvent::Modifier> modifiers, Vector<String>& 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/UnifiedSources-output.xcfilelist b/Source/WebKit/UnifiedSources-output.xcfilelist
index 50898e4630173194ae4ef7cce43ae8eb4673a86b..2ad79645d6ef683dad4eb076f5dd72472bf860b8 100644
--- a/Source/WebKit/UnifiedSources-output.xcfilelist
+++ b/Source/WebKit/UnifiedSources-output.xcfilelist
@@ -17,6 +17,7 @@ $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/unified-sources/UnifiedSource11-mm.m
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/unified-sources/UnifiedSource11.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/unified-sources/UnifiedSource110.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/unified-sources/UnifiedSource111.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/unified-sources/UnifiedSource112.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/unified-sources/UnifiedSource12-mm.mm
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/unified-sources/UnifiedSource12.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/unified-sources/UnifiedSource13-mm.mm
diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
index fbf4879e8cc363ace8aadb131758e171bf544b7a..cab8962206072d4d747cca16c50ade83d338a94a 100644
--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj
+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
@@ -395,6 +395,7 @@
 		1CA8B946127C882A00576C2B /* WebInspectorUIProxyMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CA8B944127C882A00576C2B /* WebInspectorUIProxyMessages.h */; };
 		1CAECB6527465AE400AB78D0 /* UnifiedSource109.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CAECB5D27465AE300AB78D0 /* UnifiedSource109.cpp */; };
 		1CAECB6627465AE400AB78D0 /* UnifiedSource111.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CAECB5E27465AE300AB78D0 /* UnifiedSource111.cpp */; };
+		BF2C49ED7AD83CB7BC93CC92 /* UnifiedSource112.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1D7178FBC4EDB168CDB0B04D /* UnifiedSource112.cpp */; };
 		1CAECB6727465AE400AB78D0 /* UnifiedSource108.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CAECB5F27465AE300AB78D0 /* UnifiedSource108.cpp */; };
 		1CAECB6827465AE400AB78D0 /* UnifiedSource110.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CAECB6027465AE300AB78D0 /* UnifiedSource110.cpp */; };
 		1CAECB6927465AE400AB78D0 /* UnifiedSource104.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CAECB6127465AE300AB78D0 /* UnifiedSource104.cpp */; };
@@ -1953,6 +1954,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 */; };
@@ -2009,6 +2022,9 @@
 		E5CB07DC20E1678F0022C183 /* WKFormColorControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E5CB07DA20E1678F0022C183 /* WKFormColorControl.h */; };
 		E5DEFA6826F8F42600AB68DB /* PhotosUISPI.h in Headers */ = {isa = PBXBuildFile; fileRef = E5DEFA6726F8F42600AB68DB /* PhotosUISPI.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 */; };
 		F409BA181E6E64BC009DA28E /* WKDragDestinationAction.h in Headers */ = {isa = PBXBuildFile; fileRef = F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F4299507270E234D0032298B /* StreamMessageReceiver.h in Headers */ = {isa = PBXBuildFile; fileRef = F4299506270E234C0032298B /* StreamMessageReceiver.h */; };
 		F42D634122A0EFDF00D2FB3A /* WebAutocorrectionData.h in Headers */ = {isa = PBXBuildFile; fileRef = F42D633F22A0EFD300D2FB3A /* WebAutocorrectionData.h */; };
@@ -3195,6 +3211,7 @@
 		1CAECB6227465AE400AB78D0 /* UnifiedSource105.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = UnifiedSource105.cpp; path = "DerivedSources/WebKit/unified-sources/UnifiedSource105.cpp"; sourceTree = BUILT_PRODUCTS_DIR; };
 		1CAECB6327465AE400AB78D0 /* UnifiedSource106.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = UnifiedSource106.cpp; path = "DerivedSources/WebKit/unified-sources/UnifiedSource106.cpp"; sourceTree = BUILT_PRODUCTS_DIR; };
 		1CAECB6427465AE400AB78D0 /* UnifiedSource107.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = UnifiedSource107.cpp; path = "DerivedSources/WebKit/unified-sources/UnifiedSource107.cpp"; sourceTree = BUILT_PRODUCTS_DIR; };
+		1D7178FBC4EDB168CDB0B04D /* UnifiedSource112.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = UnifiedSource112.cpp; path = "DerivedSources/WebKit/unified-sources/UnifiedSource112.cpp"; sourceTree = BUILT_PRODUCTS_DIR; };
 		1CB7461A27436EE400F19874 /* RemoteTextureViewProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteTextureViewProxy.h; sourceTree = "<group>"; };
 		1CB7461B27436EE400F19874 /* RemoteBindGroupLayoutProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteBindGroupLayoutProxy.h; sourceTree = "<group>"; };
 		1CB7461C27436EE500F19874 /* RemoteCommandBufferProxy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteCommandBufferProxy.cpp; sourceTree = "<group>"; };
@@ -6257,6 +6274,19 @@
 		DF0C5F24252ECB8D00D921DB /* WKDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownload.h; sourceTree = "<group>"; };
 		DF0C5F25252ECB8E00D921DB /* WKDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownloadInternal.h; sourceTree = "<group>"; };
 		DF0C5F26252ECB8E00D921DB /* WKDownloadDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownloadDelegate.h; sourceTree = "<group>"; };
+		D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBrowserInspector.h; sourceTree = "<group>"; };
+		D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorPlaywrightAgentClientMac.h; sourceTree = "<group>"; };
+		D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorPlaywrightAgentClient.h; sourceTree = "<group>"; };
+		D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteInspectorPipe.h; sourceTree = "<group>"; };
+		D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorEmulationAgent.h; sourceTree = "<group>"; };
+		D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorInputAgent.h; sourceTree = "<group>"; };
+		D71A94492372290B002C4D9E /* _WKBrowserInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKBrowserInspector.h; sourceTree = "<group>"; };
+		D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrowserInspectorPipe.h; sourceTree = "<group>"; };
+		D76D6887238DBD80008D314B /* InspectorDialogAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDialogAgent.h; sourceTree = "<group>"; };
+		D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorEmulationAgentMac.mm; sourceTree = "<group>"; };
+		D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorTargetProxyMac.mm; sourceTree = "<group>"; };
+		D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorInputAgentMac.mm; sourceTree = "<group>"; };
+		D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorPlaywrightAgentClientMac.mm; sourceTree = "<group>"; };
 		DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKHTTPCookieStorePrivate.h; sourceTree = "<group>"; };
 		DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContentWorldPrivate.h; sourceTree = "<group>"; };
 		DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebWheelEvent.h; sourceTree = "<group>"; };
@@ -6378,6 +6408,14 @@
 		ECA680D31E6904B500731D20 /* ExtraPrivateSymbolsForTAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtraPrivateSymbolsForTAPI.h; sourceTree = "<group>"; };
 		ECBFC1DB1E6A4D66000300C7 /* ExtraPublicSymbolsForTAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtraPublicSymbolsForTAPI.h; sourceTree = "<group>"; };
 		F036978715F4BF0500C3A80E /* WebColorPicker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebColorPicker.cpp; sourceTree = "<group>"; };
+		F303B847249A8D3A0031DE5C /* ScreencastEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScreencastEncoder.cpp; sourceTree = "<group>"; };
+		F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreencastEncoder.h; sourceTree = "<group>"; };
+		F31E2DA424C76E4B004B2775 /* WebMFileWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebMFileWriter.cpp; sourceTree = "<group>"; };
+		F31E2DA524C76E4C004B2775 /* WebMFileWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebMFileWriter.h; sourceTree = "<group>"; };
+		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 = "<group>"; };
+		F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorScreencastAgent.h; sourceTree = "<group>"; };
+		F3970344249BD4CE003E1A22 /* ScreencastEncoderMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScreencastEncoderMac.mm; sourceTree = "<group>"; };
 		F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDragDestinationAction.h; sourceTree = "<group>"; };
 		F40D1B68220BDC0F00B49A01 /* WebAutocorrectionContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebAutocorrectionContext.h; path = ios/WebAutocorrectionContext.h; sourceTree = "<group>"; };
 		F41056612130699A0092281D /* APIAttachmentCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = APIAttachmentCocoa.mm; sourceTree = "<group>"; };
@@ -6520,6 +6558,7 @@
 				3766F9EF189A1244003CF19B /* QuartzCore.framework in Frameworks */,
 				37694525184FC6B600CDE21F /* Security.framework in Frameworks */,
 				37BEC4DD1948FC6A008B4286 /* WebCore.framework in Frameworks */,
+				F33C7AC7249AD79C0018BE41 /* libwebrtc.dylib in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -8209,6 +8248,7 @@
 				1CAECB5D27465AE300AB78D0 /* UnifiedSource109.cpp */,
 				1CAECB6027465AE300AB78D0 /* UnifiedSource110.cpp */,
 				1CAECB5E27465AE300AB78D0 /* UnifiedSource111.cpp */,
+				1D7178FBC4EDB168CDB0B04D /* UnifiedSource112.cpp */,
 			);
 			name = "unified-sources";
 			path = "DerivedSources/WebKit/unified-sources";
@@ -8569,6 +8609,7 @@
 		37C4C08318149C2A003688B9 /* Cocoa */ = {
 			isa = PBXGroup;
 			children = (
+				D71A94492372290B002C4D9E /* _WKBrowserInspector.h */,
 				1A43E826188F38E2009E4D30 /* Deprecated */,
 				37A5E01218BBF937000A081E /* _WKActivatedElementInfo.h */,
 				37A5E01118BBF937000A081E /* _WKActivatedElementInfo.mm */,
@@ -9701,6 +9742,7 @@
 			isa = PBXGroup;
 			children = (
 				57A9FF15252C6AEF006A2040 /* libWTF.a */,
+				F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */,
 				5750F32A2032D4E500389347 /* LocalAuthentication.framework */,
 				570DAAB0230273D200E8FC04 /* NearField.framework */,
 				51F7BB7E274564A100C45A72 /* Security.framework */,
@@ -10209,6 +10251,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 = "<group>";
@@ -10217,6 +10265,7 @@
 			isa = PBXGroup;
 			children = (
 				A5D3504D1D78F0D2005124A9 /* RemoteWebInspectorUIProxyMac.mm */,
+				F3970344249BD4CE003E1A22 /* ScreencastEncoderMac.mm */,
 				1CA8B935127C774E00576C2B /* WebInspectorUIProxyMac.mm */,
 				99A7ACE326012919006D57FD /* WKInspectorResourceURLSchemeHandler.h */,
 				99A7ACE42601291A006D57FD /* WKInspectorResourceURLSchemeHandler.mm */,
@@ -10748,6 +10797,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 */,
@@ -11053,6 +11108,7 @@
 		BC0C376610F807660076D7CB /* C */ = {
 			isa = PBXGroup;
 			children = (
+				D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */,
 				5123CF18133D25E60056F800 /* cg */,
 				6EE849C41368D9040038D481 /* mac */,
 				BCB63477116BF10600603215 /* WebKit2_C.h */,
@@ -11641,6 +11697,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 */,
@@ -12565,6 +12626,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 */,
@@ -12872,6 +12934,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 */,
@@ -12887,6 +12950,7 @@
 				410F0D4C2701EFF900F96DFC /* GPUProcessConnectionInitializationParameters.h in Headers */,
 				4614F13225DED875007006E7 /* GPUProcessConnectionParameters.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 */,
@@ -13031,6 +13095,7 @@
 				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 */,
 				93085DE026E5BCFD000EC6A7 /* NetworkStorageManager.h in Headers */,
@@ -13096,6 +13161,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 */,
 				2D279E1926955768004B3EEB /* PrototypeToolsSPI.h in Headers */,
 				517B5F81275E97B6002DC22D /* PushAppBundle.h in Headers */,
@@ -13120,6 +13186,7 @@
 				CDAC20CA23FC2F750021DEE3 /* RemoteCDMInstanceSession.h in Headers */,
 				CDAC20C923FC2F750021DEE3 /* RemoteCDMInstanceSessionIdentifier.h in Headers */,
 				F451C0FE2703B263002BA03B /* RemoteDisplayListRecorderProxy.h in Headers */,
+				D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */,
 				2D47B56D1810714E003A3AEE /* RemoteLayerBackingStore.h in Headers */,
 				2DDF731518E95060004F5A66 /* RemoteLayerBackingStoreCollection.h in Headers */,
 				1AB16AEA164B3A8800290D62 /* RemoteLayerTreeContext.h in Headers */,
@@ -13448,6 +13515,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 */,
@@ -13583,6 +13651,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 */,
@@ -13636,6 +13705,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 */,
@@ -13792,6 +13862,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 */,
@@ -15182,6 +15253,8 @@
 				C1A152D724E5A29A00978C8B /* HandleXPCEndpointMessages.mm in Sources */,
 				2749F6442146561B008380BF /* InjectedBundleNodeHandle.cpp in Sources */,
 				2749F6452146561E008380BF /* InjectedBundleRangeHandle.cpp in Sources */,
+				D7EB04E72372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm in Sources */,
+				D79902B2236E9404005D6F7E /* InspectorTargetProxyMac.mm in Sources */,
 				9BF5EC642541145600984E77 /* JSIPCBinding.cpp in Sources */,
 				C14D37FE24ACE086007FF014 /* LaunchServicesDatabaseManager.mm in Sources */,
 				C1710CF724AA643200D7C112 /* LaunchServicesDatabaseObserver.mm in Sources */,
@@ -15201,6 +15274,7 @@
 				517B5F84275E97B6002DC22D /* MockAppBundleForTesting.mm in Sources */,
 				517B5F86275E97B6002DC22D /* MockAppBundleRegistry.mm in Sources */,
 				2D92A77A212B6A6100F493FD /* Module.cpp in Sources */,
+				D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */,
 				57B826452304F14000B72EB0 /* NearFieldSoftLink.mm in Sources */,
 				C1C1B30F2540F50D00D9100B /* NetworkConnectionToWebProcessMac.mm in Sources */,
 				51DD9F2816367DA2001578E9 /* NetworkConnectionToWebProcessMessageReceiver.cpp in Sources */,
@@ -15469,6 +15543,7 @@
 				1CAECB6527465AE400AB78D0 /* UnifiedSource109.cpp in Sources */,
 				1CAECB6827465AE400AB78D0 /* UnifiedSource110.cpp in Sources */,
 				1CAECB6627465AE400AB78D0 /* UnifiedSource111.cpp in Sources */,
+				BF2C49ED7AD83CB7BC93CC92 /* UnifiedSource112.cpp in Sources */,
 				E38A1FC023A551BF00D2374F /* UserInterfaceIdiom.mm in Sources */,
 				CD491B0D1E732E4D00009066 /* UserMediaCaptureManagerMessageReceiver.cpp in Sources */,
 				CD491B171E73525500009066 /* UserMediaCaptureManagerProxyMessageReceiver.cpp in Sources */,
@@ -15522,6 +15597,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 ec06a52d082fb54c3a128c202cf9fa4bc1f5b393..984702339cc8af73d77058b542a079a7bc4279af 100644
--- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
+++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
@@ -232,6 +232,11 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou
     }
 #endif
 
+    if (m_emulateOfflineState) {
+        scheduleInternallyFailedLoad(resourceLoader);
+        return;
+    }
+
     if (!tryLoadingUsingURLSchemeHandler(resourceLoader, trackingParameters)) {
         WEBLOADERSTRATEGY_RELEASE_LOG("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)
 {
     auto 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;
@@ -391,14 +396,11 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL
 
     if (loadParameters.options.mode != FetchOptions::Mode::Navigate) {
         ASSERT(loadParameters.sourceOrigin);
-        if (!loadParameters.sourceOrigin) {
-            WEBLOADERSTRATEGY_RELEASE_LOG_ERROR("scheduleLoad: no sourceOrigin (priority=%d)", static_cast<int>(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;
     if (loadParameters.isMainFrameNavigation && document)
@@ -430,6 +432,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("scheduleLoad: no sourceOrigin (priority=%d)", static_cast<int>(resourceLoader.request().priority()));
+        scheduleInternallyFailedLoad(resourceLoader);
+        return;
+    }
 
     std::optional<NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume;
     if (loadParameters.isMainFrameNavigation)
@@ -444,7 +457,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)
@@ -850,7 +863,7 @@ void WebLoaderStrategy::didFinishPreconnection(WebCore::ResourceLoaderIdentifier
 
 bool WebLoaderStrategy::isOnLine() const
 {
-    return m_isOnLine;
+    return m_emulateOfflineState ? false : m_isOnLine;
 }
 
 void WebLoaderStrategy::addOnlineStateChangeListener(Function<void(bool)>&& listener)
@@ -870,6 +883,11 @@ void WebLoaderStrategy::isResourceLoadFinished(CachedResource& resource, Complet
 
 void WebLoaderStrategy::setOnLineState(bool isOnLine)
 {
+    if (m_emulateOfflineState) {
+        m_isOnLine = isOnLine;
+        return;
+    }
+
     if (m_isOnLine == isOnLine)
         return;
 
@@ -878,6 +896,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 2290d987c36f68245b08fb2b86319d4d5a68e4a3..f22b3a7c855918b11582dd1ea9be00b2def665c9 100644
--- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h
+++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h
@@ -41,6 +41,7 @@ struct FetchOptions;
 namespace WebKit {
 
 class NetworkProcessConnection;
+class NetworkResourceLoadParameters;
 class WebFrame;
 class WebPage;
 class WebURLSchemeTaskProxy;
@@ -88,6 +89,9 @@ public:
     bool isOnLine() const final;
     void addOnlineStateChangeListener(Function<void(bool)>&&) final;
     void setOnLineState(bool);
+    void setEmulateOfflineState(bool) final;
+
+    static bool fillParametersForNetworkProcessLoad(WebCore::ResourceLoader&, const WebCore::ResourceRequest&, const WebResourceLoader::TrackingParameters&, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime, NetworkResourceLoadParameters&);
 
     void setExistingNetworkResourceLoadIdentifierToResume(std::optional<NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume) { m_existingNetworkResourceLoadIdentifierToResume = existingNetworkResourceLoadIdentifierToResume; }
 
@@ -137,6 +141,7 @@ private:
     Vector<Function<void(bool)>> m_onlineStateChangeListeners;
     std::optional<NetworkResourceLoadIdentifier> m_existingNetworkResourceLoadIdentifierToResume;
     bool m_isOnLine { true };
+    bool m_emulateOfflineState { false };
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp b/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp
index 259449423855fed3aaaab414819f8951a3b8b7ff..6ba9678f50190492ef5140d0793582a8017d97fc 100644
--- a/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp
+++ b/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp
@@ -163,9 +163,6 @@ void WebResourceLoader::didReceiveResponse(const ResourceResponse& response, boo
             }
 
             m_coreLoader->didReceiveResponse(inspectorResponse, [this, protectedThis = WTFMove(protectedThis), interceptedRequestIdentifier, policyDecisionCompletionHandler = WTFMove(policyDecisionCompletionHandler), overrideData = WTFMove(overrideData)]() mutable {
-                if (policyDecisionCompletionHandler)
-                    policyDecisionCompletionHandler();
-
                 if (!m_coreLoader || !m_coreLoader->identifier()) {
                     m_interceptController.continueResponse(interceptedRequestIdentifier);
                     return;
@@ -183,6 +180,8 @@ void WebResourceLoader::didReceiveResponse(const ResourceResponse& response, boo
                 }
             });
         });
+        if (policyDecisionCompletionHandler)
+          policyDecisionCompletionHandler();
         return;
     }
 
diff --git a/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp b/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp
index e00c722c2be5d505243d45f46001839d4eb8a977..33c0832cde6c292230397a13e70d90fb5984302d 100644
--- a/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp
+++ b/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp
@@ -88,7 +88,7 @@ void NotificationPermissionRequestManager::startRequest(const SecurityOriginData
 
     m_page->sendWithAsyncReply(Messages::WebPageProxy::RequestNotificationPermission(securityOrigin.toString()), [this, protectedThis = Ref { *this }, securityOrigin, permissionHandler = WTFMove(permissionHandler)](bool allowed) mutable {
 
-        auto innerPermissionHandler = [this, protectedThis = Ref { *this }, securityOrigin, permissionHandler = WTFMove(permissionHandler)] (bool allowed) mutable {
+        auto innerPermissionHandler = [this, protectedThis, securityOrigin, permissionHandler = WTFMove(permissionHandler)] (bool allowed) mutable {
             WebProcess::singleton().supplement<WebNotificationManager>()->didUpdateNotificationDecision(securityOrigin.toString(), allowed);
 
             auto permissionHandlers = m_requestsPerOrigin.take(securityOrigin);
diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
index 0b635ef5a182002773308de20fcf1714201cc30b..3466dbe5e3e7e5bb27b018e803fdcc0f840b85f2 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
@@ -417,6 +417,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);
 }
@@ -840,6 +842,13 @@ std::unique_ptr<DateTimeChooser> 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 <WebCore/DataTransfer.h>
+#include <WebCore/Pasteboard.h>
+#include "ShareableBitmap.h"
+
+#if PLATFORM(WPE)
+#include "ArgumentCodersWPE.h"
+#endif
 
 namespace WebKit {
 using namespace WebCore;
@@ -50,7 +57,7 @@ OptionSet<DragSourceAction> 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 4bdbbccd3fbc620e0754105cea09eddf05120b6b..f2f2c6eddfc6791647fcd197247197633f59a9dc 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
@@ -1574,13 +1574,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 a64c6a8b3c695e173364336bcb0f68dbdd9c2d21..041f428b297d492163b99b1ed1418879a17d13b5 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm
+++ b/Source/WebKit/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm
@@ -127,7 +127,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 <WebCore/DataTransfer.h>
+#include <WebCore/DragData.h>
+#include <WebCore/Pasteboard.h>
+#include <wtf/win/GDIObject.h>
+#include <WebCore/Frame.h>
+
+//#include <WebCore/SelectionData.h>
+
+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 <WebCore/DataTransfer.h>
+#include <WebCore/DragData.h>
+#include <WebCore/Pasteboard.h>
+#include <WebCore/SelectionData.h>
+
+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 712b7138a00419f32edc9fa1ee67b6b32bc46486..9dcaa5d97b6d693ac339e2c4ac8c697c768d89a0 100644
--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
+++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
@@ -38,6 +38,7 @@
 #include <WebCore/Frame.h>
 #include <WebCore/FrameView.h>
 #include <WebCore/GraphicsContext.h>
+#include <WebCore/InspectorController.h>
 #include <WebCore/Page.h>
 #include <WebCore/PageOverlayController.h>
 #include <WebCore/Region.h>
@@ -124,6 +125,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;
     }
@@ -256,6 +267,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.
@@ -669,6 +681,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()
@@ -718,6 +735,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 f3304d10f728128652c33426558e4dc4f6b659b5..79dbf60f6db0d45f84f5a4576be6f68aa7797e72 100644
--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp
+++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp
@@ -183,8 +183,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)
@@ -313,6 +321,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 4f727e418b082eebe86711294bb0f26f9c74d7d1..3e713db9bbd2a2bc78bdc464cfa02ca40d8a708f 100644
--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h
+++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h
@@ -104,6 +104,13 @@ public:
     void adjustTransientZoom(double, WebCore::FloatPoint);
     void commitTransientZoom(double, WebCore::FloatPoint);
 #endif
+
+// 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/DrawingArea.cpp b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp
index d1d2db8c0f1dcb033753b9f45ff86984a7890093..0e619b2541577790c3eb9ea3ec6c1100c03bb24b 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 @@ void DrawingArea::dispatchAfterEnsuringUpdatedScrollPosition(WTF::Function<void
     function();
 }
 
+#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 29d99aaf952b731e9b0235aa113acae8d9d5fea8..59cb0b3ccd3ed356e88a53f10e1878b12a57a3b9 100644
--- a/Source/WebKit/WebProcess/WebPage/DrawingArea.h
+++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.h
@@ -148,6 +148,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 9aab0800140df2620b360e0bb8c8c904d86977ef..8c89d89035ef097eefa3d177f7b7911889e1646a 100644
--- a/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp
+++ b/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp
@@ -37,6 +37,7 @@
 #include <WebCore/Frame.h>
 #include <WebCore/FrameLoader.h>
 #include <WebCore/FrameLoaderClient.h>
+#include <WebCore/ResourceLoader.h>
 #include <WebCore/Settings.h>
 #include <WebCore/StorageSessionProvider.h>
 
@@ -255,4 +256,10 @@ 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)
+{
+    const auto& request = loader.request();
+    WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCookieFromResponse(request.firstPartyForCookies(), SameSiteInfo::create(request), request.url(), setCookieValue), 0);
+}
+
 } // namespace WebKit
diff --git a/Source/WebKit/WebProcess/WebPage/WebCookieJar.h b/Source/WebKit/WebProcess/WebPage/WebCookieJar.h
index bc78502b18b994a3ffa47b933273ebdb84fafde9..f4c95fcbc0a1d618cc51f748a0df82b7ebe20cab 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<WebCore::Cookie>&);
     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 4ad677a3d06b2bc1309eb95ef645d8b6fb567bfe..f33c2b733545410500c4baa570f409fda89d1bfb 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
@@ -920,6 +920,9 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters)
     }
 #endif
 
+    if (parameters.shouldPauseInInspectorWhenShown)
+        m_page->inspectorController().pauseWhenShown();
+
     updateThrottleState();
 }
 
@@ -1688,6 +1691,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)
 {
     setLastNavigationWasAppInitiated(loadParameters.request.isAppInitiated());
@@ -1944,17 +1963,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())
@@ -1971,20 +1986,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));
@@ -1992,7 +2005,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg
     send(Messages::WebPageProxy::DidChangeViewportProperties(attr));
 #endif
 }
-#endif
 
 void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
 {
@@ -2287,6 +2299,7 @@ void WebPage::scaleView(double scale)
     }
 
     m_page->setViewScaleFactor(scale);
+    send(Messages::WebPageProxy::ViewScaleFactorDidChange(scale));
     scalePage(pageScale, scrollPositionAtNewScale);
 }
 
@@ -2391,17 +2404,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<WebCore::LayoutMilestone> milestones)
@@ -3293,6 +3302,104 @@ void WebPage::touchEvent(const WebTouchEvent& touchEvent)
 
     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
 }
+
+void WebPage::fakeTouchTap(const WebCore::IntPoint& position, uint8_t modifiers, CompletionHandler<void()>&& completionHandler)
+{
+    SetForScope<bool> 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<WebEvent::Modifier> eventModifiers;
+    eventModifiers = eventModifiers.fromRaw(modifiers);
+
+    {
+        Vector<WebPlatformTouchPoint> 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<WebPlatformTouchPoint> 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)
@@ -3369,6 +3476,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()
 {
     Ref frame = CheckedRef(m_page->focusController())->focusedOrMainFrame();
@@ -3607,6 +3719,7 @@ void WebPage::didCompletePageTransition()
 void WebPage::show()
 {
     send(Messages::WebPageProxy::ShowPage());
+    m_page->inspectorController().didShowNewWindow();
 }
 
 void WebPage::setIsTakingSnapshotsForApplicationSuspension(bool isTakingSnapshotsForApplicationSuspension)
@@ -4453,7 +4566,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<DragOperation> draggingSourceOperationMask, SelectionData&& selectionData, OptionSet<DragApplicationFlags> flags)
 {
     if (!m_page) {
@@ -6778,6 +6891,9 @@ Ref<DocumentLoader> WebPage::createDocumentLoader(Frame& frame, const ResourceRe
             WebsitePoliciesData::applyToDocumentLoader(WTFMove(*m_pendingWebsitePolicies), documentLoader);
             m_pendingWebsitePolicies = std::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 a5c42b32cd892fdf586f85e291643f4e71976190..d3065707ecbe78679556f035f5486c2611032fad 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.h
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h
@@ -122,6 +122,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
@@ -982,11 +986,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<WebCore::DragOperation> draggingSourceOperationMask, WebCore::SelectionData&&, OptionSet<WebCore::DragApplicationFlags>);
 #endif
 
-#if ENABLE(DRAG_SUPPORT) && !PLATFORM(GTK)
+#if ENABLE(DRAG_SUPPORT) && !PLATFORM(GTK) && !PLATFORM(WPE)
     void performDragControllerAction(DragControllerAction, const WebCore::DragData&, SandboxExtension::Handle&&, Vector<SandboxExtension::Handle>&&);
 #endif
 
@@ -1000,6 +1004,9 @@ public:
     void didStartDrag();
     void dragCancelled();
     OptionSet<WebCore::DragSourceAction> 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&);
@@ -1243,6 +1250,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();
 
@@ -1601,6 +1609,7 @@ private:
     // Actions
     void tryClose(CompletionHandler<void(bool)>&&);
     void platformDidReceiveLoadParameters(const LoadParameters&);
+    void loadRequestInFrameForInspector(LoadParameters&&, WebCore::FrameIdentifier);
     void loadRequest(LoadParameters&&);
     NO_RETURN void loadRequestWaitingForProcessLaunch(LoadParameters&&, URL&&, WebPageProxyIdentifier, bool);
     void loadData(LoadParameters&&);
@@ -1638,6 +1647,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<void()>&& completionHandler);
 #endif
 
     void cancelPointer(WebCore::PointerID, const WebCore::IntPoint&);
@@ -1762,9 +1772,7 @@ private:
     void findRectsForStringMatches(const String&, OptionSet<FindOptions>, uint32_t maxMatchCount, CompletionHandler<void(Vector<WebCore::FloatRect>&&)>&&);
     void hideFindIndicator();
 
-#if USE(COORDINATED_GRAPHICS)
     void sendViewportAttributesChanged(const WebCore::ViewportArguments&);
-#endif
 
     void didChangeSelectedIndexForActivePopupMenu(int32_t newIndex);
     void setTextForActivePopupMenu(int32_t index);
@@ -2300,6 +2308,7 @@ private:
     UserActivity m_userActivity;
 
     uint64_t m_pendingNavigationID { 0 };
+    uint64_t m_pendingFrameNavigationID { 0 };
     std::optional<WebsitePoliciesData> 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 68f91cd0426eb4c0259fb7cd75f3f5b8fe971593..d1bc0befd4a7be9f3839991b519be6582204f469 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
@@ -137,6 +137,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);
@@ -148,6 +149,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)
@@ -319,10 +322,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<WebCore::DragOperation> draggingSourceOperationMask, WebCore::SelectionData selection, OptionSet<WebCore::DragApplicationFlags> 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, Vector<WebKit::SandboxExtension::Handle> sandboxExtensionsForUpload)
 #endif
 #if ENABLE(DRAG_SUPPORT)
@@ -331,6 +334,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<WebCore::DragSourceAction> allowedActionsMask)
     RequestAdditionalItemsForDragSession(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet<WebCore::DragSourceAction> allowedActionsMask)
diff --git a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm
index 60f84a45c38035f2dce925cbee2c31992e64032f..102ab944141a6b6c2685d50aa56dc555fbc1bca4 100644
--- a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm
+++ b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm
@@ -842,21 +842,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
 }
 
 std::optional<PointerCharacteristics> WebPage::pointerCharacteristicsOfPrimaryPointingDevice() const
 {
+#if ENABLE(TOUCH_EVENTS)
+    if (screenIsTouchPrimaryInputDevice())
+        return PointerCharacteristics::Coarse;
+#endif
     return PointerCharacteristics::Fine;
 }
 
 OptionSet<PointerCharacteristics> 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 afad4f9b13ab16b092525a84baaed34933c8e51c..c432676686dae42905ef45dfd4957f959b513659 100644
--- a/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp
+++ b/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp
@@ -43,6 +43,7 @@
 #include <WebCore/NotImplemented.h>
 #include <WebCore/Page.h>
 #include <WebCore/PlatformKeyboardEvent.h>
+#include <WebCore/PlatformScreen.h>
 #include <WebCore/PointerCharacteristics.h>
 #include <WebCore/Settings.h>
 #include <WebCore/SharedBuffer.h>
@@ -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
 }
 
 std::optional<PointerCharacteristics> WebPage::pointerCharacteristicsOfPrimaryPointingDevice() const
 {
+#if ENABLE(TOUCH_EVENTS)
+    if (screenIsTouchPrimaryInputDevice())
+        return PointerCharacteristics::Coarse;
+#endif
     return PointerCharacteristics::Fine;
 }
 
 OptionSet<PointerCharacteristics> 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 105bc6ff8a245ffc10fd487139316c48acf2b005..81de336cb0ee6407f78c3eb2fbdc77baea2ccee0 100644
--- a/Source/WebKit/WebProcess/WebProcess.cpp
+++ b/Source/WebKit/WebProcess/WebProcess.cpp
@@ -89,6 +89,7 @@
 #include "WebsiteData.h"
 #include "WebsiteDataStoreParameters.h"
 #include "WebsiteDataType.h"
+#include <JavaScriptCore/IdentifiersFactory.h>
 #include <JavaScriptCore/JSLock.h>
 #include <JavaScriptCore/MemoryStatistics.h>
 #include <JavaScriptCore/WasmFaultSignalHandler.h>
@@ -352,6 +353,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 838e413381a8075a3d62459455267a5bbb55a991..e179a07490cc8fd579f219ff7ebb0ed5684e1353 100644
--- a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
+++ b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
@@ -4168,7 +4168,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 56642c222d6bc543af9e759b63932aa6ed838684..bfab1bc05b34ca5a2ddc283098c16229a279a679 100644
--- a/Source/WebKitLegacy/mac/WebView/WebView.mm
+++ b/Source/WebKitLegacy/mac/WebView/WebView.mm
@@ -4058,7 +4058,7 @@ IGNORE_WARNINGS_END
 }
 #endif // PLATFORM(IOS_FAMILY)
 
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(IOS_TOUCH_EVENTS)
 
 - (NSArray *)_touchEventRegions
 {
@@ -4100,7 +4100,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 62effccdba8207b37b8e0aa87897c7e931036e1b..7457bacbd1845cd51c77e244f21e965c81a62041 100644
--- a/Source/cmake/OptionsGTK.cmake
+++ b/Source/cmake/OptionsGTK.cmake
@@ -5,6 +5,7 @@ WEBKIT_OPTION_BEGIN()
 
 SET_PROJECT_VERSION(2 35 1)
 
+set(ENABLE_WEBKIT_LEGACY OFF)
 
 set(USER_AGENT_BRANDING "" CACHE STRING "Branding to add to user agent string")
 
@@ -28,6 +29,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_CAIRO TRUE)
@@ -60,16 +65,16 @@ WEBKIT_OPTION_DEFINE(ENABLE_JOURNALD_LOG "Whether to enable journald logging" PU
 WEBKIT_OPTION_DEFINE(ENABLE_QUARTZ_TARGET "Whether to enable support for the Quartz windowing target." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(ENABLE_WAYLAND_TARGET "Whether to enable support for the Wayland windowing target." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(ENABLE_X11_TARGET "Whether to enable support for the X11 windowing target." PUBLIC ON)
-WEBKIT_OPTION_DEFINE(USE_AVIF "Whether to enable support for AVIF images." PUBLIC ${ENABLE_EXPERIMENTAL_FEATURES})
+WEBKIT_OPTION_DEFINE(USE_AVIF "Whether to enable support for AVIF images." PUBLIC OFF)
 WEBKIT_OPTION_DEFINE(USE_GTK4 "Whether to enable usage of GTK4 instead of GTK3." PUBLIC OFF)
-WEBKIT_OPTION_DEFINE(USE_JPEGXL "Whether to enable support for JPEG-XL images." PUBLIC ${ENABLE_EXPERIMENTAL_FEATURES})
+WEBKIT_OPTION_DEFINE(USE_JPEGXL "Whether to enable support for JPEG-XL images." PUBLIC OFF)
 WEBKIT_OPTION_DEFINE(USE_LCMS "Whether to enable support for image color management using libcms2." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(USE_LIBHYPHEN "Whether to enable the default automatic hyphenation implementation." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(USE_LIBNOTIFY "Whether to enable the default web notification implementation." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(USE_LIBSECRET "Whether to enable the persistent credential storage using libsecret." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(USE_OPENGL_OR_ES "Whether to use OpenGL or ES." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(USE_OPENJPEG "Whether to enable support for JPEG2000 images." PUBLIC ON)
-WEBKIT_OPTION_DEFINE(USE_SOUP2 "Whether to enable usage of Soup 2 instead of Soup 3." PUBLIC OFF)
+WEBKIT_OPTION_DEFINE(USE_SOUP2 "Whether to enable usage of Soup 2 instead of Soup 3." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(USE_WOFF2 "Whether to enable support for WOFF2 Web Fonts." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(USE_WPE_RENDERER "Whether to enable WPE rendering" PUBLIC ON)
 
@@ -120,7 +125,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)
@@ -154,7 +159,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LAYER_BASED_SVG_ENGINE PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LAYOUT_FORMATTING_CONTEXT PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SESSION PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SESSION_PLAYLIST PRIVATE OFF)
-WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_STREAM PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_STREAM PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MHTML PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MOUSE_CURSOR_SCALE PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETSCAPE_PLUGIN_API PRIVATE OFF)
@@ -170,6 +175,16 @@ 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)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DEVICE_ORIENTATION PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPEECH_SYNTHESIS PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_POINTER_LOCK 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 4694eb3e715f8ed47b254b2280ecb69c3fbace6c..5febc60f49e56f0daa175ac574b1f81ea8cdc50a 100644
--- a/Source/cmake/OptionsWPE.cmake
+++ b/Source/cmake/OptionsWPE.cmake
@@ -3,6 +3,7 @@ include(VersioningUtils)
 
 SET_PROJECT_VERSION(2 35 1)
 
+set(ENABLE_WEBKIT_LEGACY OFF)
 set(USER_AGENT_BRANDING "" CACHE STRING "Branding to add to user agent string")
 
 find_package(Cairo 1.14.0 REQUIRED)
@@ -55,7 +56,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LAYER_BASED_SVG_ENGINE PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LAYOUT_FORMATTING_CONTEXT PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SESSION PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SESSION_PLAYLIST PRIVATE OFF)
-WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_STREAM PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_STREAM PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MHTML PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETSCAPE_PLUGIN_API PRIVATE OFF)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NOTIFICATIONS PRIVATE ON)
@@ -70,17 +71,36 @@ 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_DATALIST_ELEMENT PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DRAG_SUPPORT PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DEVICE_ORIENTATION PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_COLOR PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_DATE PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_DATETIMELOCAL PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_MONTH PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_TIME PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_WEEK PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPEECH_SYNTHESIS PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_POINTER_LOCK PRIVATE 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(ENABLE_JOURNALD_LOG "Whether to enable journald logging" 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(USE_AVIF "Whether to enable support for AVIF images." PUBLIC ${ENABLE_EXPERIMENTAL_FEATURES})
-WEBKIT_OPTION_DEFINE(USE_JPEGXL "Whether to enable support for JPEG-XL images." PUBLIC ${ENABLE_EXPERIMENTAL_FEATURES})
+WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC OFF)
+WEBKIT_OPTION_DEFINE(USE_AVIF "Whether to enable support for AVIF images." PUBLIC OFF)
+WEBKIT_OPTION_DEFINE(USE_JPEGXL "Whether to enable support for JPEG-XL images." PUBLIC OFF)
 WEBKIT_OPTION_DEFINE(USE_LCMS "Whether to enable support for image color management using libcms2." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(USE_OPENJPEG "Whether to enable support for JPEG2000 images." PUBLIC ON)
-WEBKIT_OPTION_DEFINE(USE_SOUP2 "Whether to enable usage of Soup 2 instead of Soup 3." PUBLIC OFF)
+WEBKIT_OPTION_DEFINE(USE_SOUP2 "Whether to enable usage of Soup 2 instead of Soup 3." PUBLIC ON)
 WEBKIT_OPTION_DEFINE(USE_WOFF2 "Whether to enable support for WOFF2 Web Fonts." PUBLIC ON)
 
 # Private options specific to the WPE port.
diff --git a/Source/cmake/OptionsWin.cmake b/Source/cmake/OptionsWin.cmake
index 04869b0d67226fb9f7951298f32f952c94cb2837..6ceb1dafd51d4f34c2f20f4f44a1dd99ca900d72 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 ()
 
@@ -27,11 +28,9 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_BOX_DECORATION_BREAK PUBLIC ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_SELECTORS_LEVEL4 PUBLIC ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PUBLIC ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DATALIST_ELEMENT PUBLIC OFF)
-WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DEVICE_ORIENTATION PUBLIC OFF)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DRAG_SUPPORT PUBLIC ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTL_JIT PUBLIC OFF)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FULLSCREEN_API PUBLIC ON)
-WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC OFF)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GEOLOCATION PUBLIC ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_COLOR PUBLIC OFF)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_DATE PUBLIC OFF)
@@ -47,7 +46,6 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_CONTROLS_SCRIPT PUBLIC ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SOURCE PUBLIC OFF)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_STATISTICS PUBLIC ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MOUSE_CURSOR_SCALE PUBLIC ON)
-WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NOTIFICATIONS PUBLIC OFF)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VIDEO PUBLIC ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBASSEMBLY PRIVATE OFF)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_AUDIO PUBLIC OFF)
@@ -90,6 +88,17 @@ 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_DEVICE_ORIENTATION PRIVATE ON)
+    WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON)
+    WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PRIVATE ON)
+    WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NOTIFICATIONS PRIVATE ON)
+    WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_POINTER_LOCK 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 54dc095d9f98cf0116a704e99e88333f1108c8a0..23216d79747d514c53e965618d5bf7ade8beb659 100644
--- a/Source/cmake/OptionsWinCairo.cmake
+++ b/Source/cmake/OptionsWinCairo.cmake
@@ -37,15 +37,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
+
 set(USE_ANGLE_EGL ON)
 set(USE_ANGLE_WEBGL ON)
 
diff --git a/Tools/MiniBrowser/gtk/BrowserTab.c b/Tools/MiniBrowser/gtk/BrowserTab.c
index 1c84f30b2ea96dd0c168918f9d63773b8e2548a3..55603437900a65de7bef70563c9ec0399c5f563c 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);
@@ -708,6 +713,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);
@@ -758,6 +764,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 881609c9fe8f2b5ed6158a5972438c14fd650cf5..4a032f5cc0808087405f2f9dd9614b5cbf85252a 100644
--- a/Tools/MiniBrowser/gtk/BrowserWindow.c
+++ b/Tools/MiniBrowser/gtk/BrowserWindow.c
@@ -70,7 +70,7 @@ struct _BrowserWindowClass {
     GtkApplicationWindowClass parent;
 };
 
-static const char *defaultWindowTitle = "WebKitGTK MiniBrowser";
+static const char *defaultWindowTitle = "🎭 Playwright";
 static const gdouble minimumZoomLevel = 0.5;
 static const gdouble maximumZoomLevel = 3;
 static const gdouble defaultZoomLevel = 1;
@@ -154,13 +154,11 @@ static void webViewURIChanged(WebKitWebView *webView, GParamSpec *pspec, Browser
 static void webViewTitleChanged(WebKitWebView *webView, GParamSpec *pspec, BrowserWindow *window)
 {
     const char *title = webkit_web_view_get_title(webView);
+    char *privateTitle = NULL;
     if (!title)
         title = defaultWindowTitle;
-    char *privateTitle = NULL;
-    if (webkit_web_view_is_controlled_by_automation(webView))
-        privateTitle = g_strdup_printf("[Automation] %s", title);
-    else if (webkit_web_view_is_ephemeral(webView))
-        privateTitle = g_strdup_printf("[Private] %s", title);
+    else
+        privateTitle = g_strdup_printf("🎭 Playwright: %s", title);
     gtk_window_set_title(GTK_WINDOW(window), privateTitle ? privateTitle : title);
     g_free(privateTitle);
 }
@@ -1445,6 +1443,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);
@@ -1458,6 +1462,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 9e7863b61b3e9db76e04e14f45116684dae44e37..fb47d231744d578bcbef125df9011a80fe3f263c 100644
--- a/Tools/MiniBrowser/gtk/main.c
+++ b/Tools/MiniBrowser/gtk/main.c
@@ -56,7 +56,12 @@ static gboolean enableITP;
 static gboolean enableSandbox;
 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
@@ -150,6 +155,10 @@ static const GOptionEntry commandLineOptions[] =
     { "enable-sandbox", 0, 0, G_OPTION_ARG_NONE, &enableSandbox, "Enable web process sandbox support", 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 }
 };
@@ -618,6 +627,57 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul
     g_main_loop_quit(data->mainLoop);
 }
 
+static WebKitSettings* createPlaywrightSettings() {
+    WebKitSettings* webkitSettings = webkit_settings_new();
+    // Playwright: revert to the default state before https://github.com/WebKit/WebKit/commit/a73a25b9ea9229987c8fa7b2e092e6324cb17913
+    webkit_settings_set_hardware_acceleration_policy(webkitSettings, WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER);
+    webkit_settings_set_hardware_acceleration_policy(webkitSettings, WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND);
+    return webkitSettings;
+}
+
+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,
+        "settings", createPlaywrightSettings(),
+        "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[] = {
@@ -648,10 +708,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);
@@ -675,6 +747,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings)
         "use-system-appearance-for-scrollbars", FALSE,
 #endif
         NULL);
+    persistentWebContext = webContext;
     g_object_unref(manager);
 
     if (enableSandbox)
@@ -756,9 +829,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);
@@ -802,7 +873,7 @@ int main(int argc, char *argv[])
     g_option_context_add_group(context, gtk_get_option_group(TRUE));
 #endif
 
-    WebKitSettings *webkitSettings = webkit_settings_new();
+    WebKitSettings *webkitSettings = createPlaywrightSettings();
     webkit_settings_set_enable_developer_extras(webkitSettings, TRUE);
     webkit_settings_set_enable_webgl(webkitSettings, TRUE);
     webkit_settings_set_enable_media_stream(webkitSettings, TRUE);
@@ -834,9 +905,11 @@ int main(int argc, char *argv[])
     }
 
     GtkApplication *application = gtk_application_new("org.webkitgtk.MiniBrowser", G_APPLICATION_NON_UNIQUE);
+    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 e01baba8002a4f6478e681f15aadaa1880e0214b..87fab30d048a6209ccc9b1c0f4fbd3f04f8a2d36 100644
--- a/Tools/MiniBrowser/wpe/main.cpp
+++ b/Tools/MiniBrowser/wpe/main.cpp
@@ -41,6 +41,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;
@@ -64,6 +67,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 }
 };
@@ -148,13 +154,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();
@@ -166,17 +193,66 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi
             delete static_cast<WPEToolingBackends::ViewBackend*>(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<WPEToolingBackends::HeadlessViewBackend*>(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<GMainLoop*>(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
@@ -208,6 +284,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();
@@ -217,7 +303,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) {
@@ -229,7 +323,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) {
@@ -288,7 +383,14 @@ int main(int argc, char *argv[])
     auto* viewBackend = webkit_web_view_backend_new(wpeBackend, [](gpointer data) {
         delete static_cast<WPEToolingBackends::ViewBackend*>(data);
     }, backend.release());
-
+// Playwright begin
+    if (headlessMode) {
+        webkit_web_view_backend_set_screenshot_callback(viewBackend,
+            [](gpointer data) {
+                return static_cast<WPEToolingBackends::HeadlessViewBackend*>(data)->snapshot();
+            });
+    }
+// Playwright end
     auto* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
         "backend", viewBackend,
         "web-context", webContext,
@@ -305,8 +407,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);
@@ -319,16 +419,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");
@@ -338,8 +431,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 1e3db5a4d3e39b8d54d1681e05bf6cccb7fcd061..e4b84ef77b85eeeed645701852330f421dc20126 100755
--- a/Tools/Scripts/build-webkit
+++ b/Tools/Scripts/build-webkit
@@ -253,7 +253,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 6d570521e0952e78ccf73eb01a15f7937a013a78..3b5013eb982a68741ef2be52842b56ef059bc321 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 b0f26645ea360cc7e55afbfbe2ceb4e5791a0fb7..e5401df8302bb7b1950d1c92caf9ae5851d9c8a4 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 ed2802fb1e766dc5de67c44d157661632c3931a3..3f1a19a33531ee5546eec0e9615bdffe0c040700 100644
--- a/Tools/WebKitTestRunner/TestController.cpp
+++ b/Tools/WebKitTestRunner/TestController.cpp
@@ -805,6 +805,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 7e7585e699663e5bdc8284e4e3540818742102ab..54d1853f259e824e5731bd39825c37629ab7ae5e 100644
--- a/Tools/WebKitTestRunner/mac/EventSenderProxy.mm
+++ b/Tools/WebKitTestRunner/mac/EventSenderProxy.mm
@@ -894,4 +894,51 @@ void EventSenderProxy::scaleGestureEnd(double scale)
 
 #endif // ENABLE(MAC_GESTURE_EVENTS)
 
+#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/glib/dependencies/apt b/Tools/glib/dependencies/apt
index 178e74ac90708b9571330c216a1ee07f7db3dff2..f33f29a9a26d1219aa5780b1860792353a70f4ee 100644
--- a/Tools/glib/dependencies/apt
+++ b/Tools/glib/dependencies/apt
@@ -45,9 +45,11 @@ PACKAGES=(
     libwayland-dev
     libwebp-dev
     libwoff-dev
+    libxcb-glx0-dev
     libxslt1-dev
     ninja-build
     patch
+    patchelf
     ruby
 
     # These are dependencies necessary for running tests.
diff --git a/Tools/win/DLLLauncher/DLLLauncherMain.cpp b/Tools/win/DLLLauncher/DLLLauncherMain.cpp
index 52605867b9302d1afcc56c5e9b0c54acf0827900..6edf24ab60249241ba2969531ef55f4b495dce9e 100644
--- a/Tools/win/DLLLauncher/DLLLauncherMain.cpp
+++ b/Tools/win/DLLLauncher/DLLLauncherMain.cpp
@@ -99,11 +99,9 @@ static bool prependPath(const std::wstring& directoryToPrepend)
 static int fatalError(const std::wstring& programName, const std::wstring& message)
 {
     std::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 39f0e26d1bb3cd486346a400c700a9d84e99bc2e..16bc0f9bf376c530082be6f20d5e5d247ceb6816 100644
--- a/Tools/wpe/backends/HeadlessViewBackend.cpp
+++ b/Tools/wpe/backends/HeadlessViewBackend.cpp
@@ -149,27 +149,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<uint32_t>(m_width, std::max(0, wl_shm_buffer_get_width(shmBuffer)));
-        uint32_t height = std::min<uint32_t>(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<uint8_t*>(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);
     }
 
@@ -177,7 +174,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,
