diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt index 08badc32775c2280a7a60dda6027eccc3343ef8d..1a34d0324feef99d9e497462b90299b8c0b2c4bd 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt @@ -1353,22 +1353,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 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& result, std::optional& 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 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& result, std::optional& wasThrown, std::optional& savedResultIndex) @@ -289,6 +287,10 @@ RefPtr InjectedScript::wrapObject(JSC::JSValue auto callResult = callFunctionWithEvalEnabled(wrapFunction); if (!callResult) return nullptr; + auto callResultValue = callResult.value(); + // callResultValue could be missing if the execution was terminated + if (!callResultValue) + return nullptr; auto resultValue = toInspectorValue(globalObject(), callResult.value()); if (!resultValue) diff --git a/Source/JavaScriptCore/inspector/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& result, std::optional& wasThrown, std::optional& 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& result, std::optional& wasThrown, std::optional& savedResultIndex); - void callFunctionOn(Protocol::ErrorString&, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr& result, std::optional& 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& result); void functionDetails(Protocol::ErrorString&, JSC::JSValue, RefPtr& result); void getPreview(Protocol::ErrorString&, const String& objectId, RefPtr& 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 protect(*this); @@ -146,6 +146,9 @@ void BackendDispatcher::dispatch(const String& message) requestId = *requestIdInt; } + if (interceptor && interceptor(messageObject) == InterceptionResult::Intercepted) + return; + { // We could be called re-entrantly from a nested run loop, so restore the previous id. SetForScope> scopedRequestId(m_currentRequestId, requestId); diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h index 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&)>; + void dispatch(const String& message, Interceptor&& interceptor = Interceptor()); // Note that 'unused' is a workaround so the compiler can pick the right sendResponse based on arity. // When is fixed or this class is renamed for the JSON::Object case, diff --git a/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp b/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp index d408d364f1986983161f9d44efbc8bc6f6898676..1375ce9990f0c63d7e6f33ee62930051d6cd44cb 100644 --- a/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp +++ b/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp @@ -49,7 +49,7 @@ void FrontendRouter::connectFrontend(FrontendChannel& connection) void FrontendRouter::disconnectFrontend(FrontendChannel& connection) { if (!m_connections.contains(&connection)) { - ASSERT_NOT_REACHED(); + ASSERT(m_connections.isEmpty()); return; } diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.cpp b/Source/JavaScriptCore/inspector/InspectorTarget.cpp index 0cc2127c9c12c2d82dea9550bad73f4ffb99ba24..8ca65cc042d435cbc0e05dcc5c5dfc958eb24f5a 100644 --- a/Source/JavaScriptCore/inspector/InspectorTarget.cpp +++ b/Source/JavaScriptCore/inspector/InspectorTarget.cpp @@ -44,6 +44,8 @@ void InspectorTarget::resume() ASSERT(m_isPaused); m_isPaused = false; + willResume(); + if (m_resumeCallback) { m_resumeCallback(); m_resumeCallback = nullptr; @@ -52,7 +54,6 @@ void InspectorTarget::resume() void InspectorTarget::setResumeCallback(WTF::Function&& callback) { - ASSERT(!m_resumeCallback); m_resumeCallback = WTFMove(callback); } diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.h b/Source/JavaScriptCore/inspector/InspectorTarget.h index 4b95964db4d902b4b7f4b0b4c40afea51654ff2f..966a5927702b65edb343369decafda7fc83eaec7 100644 --- a/Source/JavaScriptCore/inspector/InspectorTarget.h +++ b/Source/JavaScriptCore/inspector/InspectorTarget.h @@ -56,8 +56,12 @@ public: virtual void connect(FrontendChannel::ConnectionType) = 0; virtual void disconnect() = 0; virtual void sendMessageToTargetBackend(const String&) = 0; + virtual void activate(String& error) { error = "Target cannot be activated"; } + virtual void close(String& error, bool /* runBeforeUnload */) { error = "Target cannot be closed"; } private: + virtual void willResume() { } + WTF::Function m_resumeCallback; bool m_isPaused { false }; }; diff --git a/Source/JavaScriptCore/inspector/agents/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::optional /* wasThrown */>> InspectorRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& functionDeclaration, RefPtr&& arguments, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& /* emulateUserGesture */) +void InspectorRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& functionDeclaration, RefPtr&& arguments, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& /* emulateUserGesture */, std::optional&& awaitPromise, Ref&& callback) { Protocol::ErrorString errorString; InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); - if (injectedScript.hasNoValue()) - return makeUnexpected("Missing injected script for given objectId"_s); - - RefPtr result; - std::optional 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::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&& result, std::optional&& wasThrown, std::optional&&) { + 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> 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>> parse(const String& expression) final; Protocol::ErrorStringOr, std::optional /* wasThrown */, std::optional /* savedResultIndex */>> evaluate(const String& expression, const String& objectGroup, std::optional&& includeCommandLineAPI, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&&, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& saveResult, std::optional&& emulateUserGesture) override; void awaitPromise(const Protocol::Runtime::RemoteObjectId&, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& saveResult, Ref&&) final; - Protocol::ErrorStringOr, std::optional /* wasThrown */>> callFunctionOn(const Protocol::Runtime::RemoteObjectId&, const String& functionDeclaration, RefPtr&& arguments, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& emulateUserGesture) override; + void callFunctionOn(const Protocol::Runtime::RemoteObjectId&, const String& functionDeclaration, RefPtr&& arguments, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& emulateUserGesture, std::optional&& awaitPromise, Ref&&) override; Protocol::ErrorStringOr releaseObject(const Protocol::Runtime::RemoteObjectId&) final; Protocol::ErrorStringOr> getPreview(const Protocol::Runtime::RemoteObjectId&) final; Protocol::ErrorStringOr>, RefPtr>>> getProperties(const Protocol::Runtime::RemoteObjectId&, std::optional&& ownProperties, std::optional&& fetchStart, std::optional&& fetchCount, std::optional&& 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 InspectorTargetAgent::sendMessageToTarget(const St return { }; } +Protocol::ErrorStringOr InspectorTargetAgent::activate(const String& targetId) +{ + InspectorTarget* target = m_targets.get(targetId); + if (!target) + return makeUnexpected("Missing target for given targetId"_s); + + String errorString; + target->activate(errorString); + if (!errorString.isEmpty()) + return makeUnexpected(errorString); + + return { }; +} + +Protocol::ErrorStringOr InspectorTargetAgent::close(const String& targetId, std::optional&& runBeforeUnload) +{ + InspectorTarget* target = m_targets.get(targetId); + if (!target) + return makeUnexpected("Missing target for given targetId"_s); + + String errorString; + target->close(errorString, runBeforeUnload && *runBeforeUnload); + if (!errorString.isEmpty()) + return makeUnexpected(errorString); + + return { }; +} + void InspectorTargetAgent::sendMessageFromTargetToFrontend(const String& targetId, const String& message) { ASSERT_WITH_MESSAGE(m_targets.get(targetId), "Sending a message from an untracked target to the frontend."); @@ -144,7 +172,17 @@ void InspectorTargetAgent::targetDestroyed(InspectorTarget& target) if (!m_isConnected) return; - m_frontendDispatcher->targetDestroyed(target.identifier()); + m_frontendDispatcher->targetDestroyed(target.identifier(), false); +} + +void InspectorTargetAgent::targetCrashed(InspectorTarget& target) +{ + m_targets.remove(target.identifier()); + + if (!m_isConnected) + return; + + m_frontendDispatcher->targetDestroyed(target.identifier(), true); } void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID) @@ -159,6 +197,18 @@ void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID, m_frontendDispatcher->didCommitProvisionalTarget(oldTargetID, committedTargetID); } +void InspectorTargetAgent::ensureConnected(const String& targetID) +{ + if (!m_isConnected) + return; + + auto* target = m_targets.get(targetID); + if (!target) + return; + + target->connect(connectionType()); +} + FrontendChannel::ConnectionType InspectorTargetAgent::connectionType() const { return m_router.hasLocalFrontend() ? Inspector::FrontendChannel::ConnectionType::Local : Inspector::FrontendChannel::ConnectionType::Remote; diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h index e81573fd0fffaaf6fd2af36635c78fcdf8608c69..4169e227b5fb5a3a7fb51396c4679100f495719c 100644 --- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h +++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h @@ -50,15 +50,21 @@ public: Protocol::ErrorStringOr setPauseOnStart(bool) final; Protocol::ErrorStringOr resume(const String& targetId) final; Protocol::ErrorStringOr sendMessageToTarget(const String& targetId, const String& message) final; + Protocol::ErrorStringOr activate(const String& targetId) override; + Protocol::ErrorStringOr close(const String& targetId, std::optional&& runBeforeUnload) override; // Target lifecycle. void targetCreated(InspectorTarget&); void targetDestroyed(InspectorTarget&); + void targetCrashed(InspectorTarget&); void didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID); + void ensureConnected(const String& targetID); // Target messages. void sendMessageFromTargetToFrontend(const String& targetId, const String& message); + bool isConnected() { return m_isConnected; } + private: // FrontendChannel FrontendChannel::ConnectionType connectionType() const; diff --git a/Source/JavaScriptCore/inspector/protocol/DOM.json b/Source/JavaScriptCore/inspector/protocol/DOM.json index 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 ", + "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 .", + "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..f6c541d63c0b8251874eaf8818aabe0e0449401d --- /dev/null +++ b/Source/JavaScriptCore/inspector/protocol/Screencast.json @@ -0,0 +1,65 @@ +{ + "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" }, + { "name": "scale", "type": "number", "optional": true } + ], + "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 #include #include +#include #include #include 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 #include +#include #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 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 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 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(cache); #else + if (!override.isEmpty()) { + auto* timezone = icu::TimeZone::createTimeZone(override.utf8().data()); + m_timeZoneCache = std::unique_ptr(bitwise_cast(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(bitwise_cast(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 = ""; }; CDFD2F9624C4B2F90048DAC3 /* vp9_header_parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vp9_header_parser.h; sourceTree = ""; }; CDFD2F9A24C4B2F90048DAC3 /* vp9_header_parser.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = vp9_header_parser.cc; sourceTree = ""; }; + F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvmuxerutil.cc; path = mkvmuxer/mkvmuxerutil.cc; sourceTree = ""; }; + F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvmuxer.cc; path = mkvmuxer/mkvmuxer.cc; sourceTree = ""; }; + F3B7819824C7CC5200FCB122 /* mkvwriter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvwriter.cc; path = mkvmuxer/mkvwriter.cc; sourceTree = ""; }; FB39D0D11200F0E300088E69 /* libwebrtc.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libwebrtc.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -15289,6 +15295,7 @@ isa = PBXGroup; children = ( CDFD2F9224C4B2F90048DAC3 /* common */, + F3B7819524C7CC1300FCB122 /* mkvmuxer */, CDEBB19224C0191800ADBD44 /* webm_parser */, ); path = libwebm; @@ -15423,6 +15430,16 @@ path = common; sourceTree = ""; }; + F3B7819524C7CC1300FCB122 /* mkvmuxer */ = { + isa = PBXGroup; + children = ( + F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */, + F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */, + F3B7819824C7CC5200FCB122 /* mkvwriter.cc */, + ); + name = mkvmuxer; + sourceTree = ""; + }; FB39D06E1200ED9200088E69 = { isa = PBXGroup; children = ( @@ -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 ec82bf5b5a299d712070348ec41bbd9b636769e2..ad4f609159399f4994743a12cc45d0faec16bdde 100644 --- a/Source/WTF/Scripts/Preferences/WebPreferences.yaml +++ b/Source/WTF/Scripts/Preferences/WebPreferences.yaml @@ -1031,7 +1031,7 @@ InspectorStartsAttached: exposed: [ WebKit ] defaultValue: WebKit: - default: true + default: false InspectorWindowFrame: type: String @@ -1771,6 +1771,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 d14c4b4aae5e9f998ff36aef56103704f2e20e85..5d448c01d9c8d70a3ad42d4831a8f3ffa2b2aafb 100644 --- a/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml +++ b/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml @@ -432,7 +432,7 @@ CrossOriginOpenerPolicyEnabled: WebKitLegacy: default: false WebKit: - default: true + default: false WebCore: default: false @@ -811,9 +811,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: @@ -1273,7 +1273,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 #include #include +#include #include #include +#include +#include +#include #include +#include #if OS(WINDOWS) #include @@ -92,6 +97,18 @@ template inline bool startsWithLettersIgnoringASCIICase(const c return equalLettersIgnoringASCIICase(string, lowercaseLetters, length - 1); } +struct TimeZoneForAutomation { + UCalendar* cal; + String id; + String displayName; +}; + +static TimeZoneForAutomation& innerTimeZoneForAutomation() +{ + static NeverDestroyed> timeZoneForAutomation; + return *timeZoneForAutomation.get(); +} + /* Constants */ const char* const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; @@ -318,6 +335,14 @@ static double calculateDSTOffset(time_t localTime, double utcOffset) // Returns combined offset in millisecond (UTC + DST). LocalTimeOffset calculateLocalTimeOffset(double ms, TimeType inputTimeType) { + TimeZoneForAutomation& tz = innerTimeZoneForAutomation(); + if (tz.cal) { + UErrorCode status = U_ZERO_ERROR; + ucal_setMillis(tz.cal, ms, &status); + int32_t offset = ucal_get(tz.cal, UCAL_ZONE_OFFSET, &status); + int32_t dstOffset = ucal_get(tz.cal, UCAL_DST_OFFSET, &status); + return LocalTimeOffset(dstOffset, offset + dstOffset); + } #if HAVE(TM_GMTOFF) double localToUTCTimeOffset = inputTimeType == LocalTime ? calculateUTCOffset() : 0; #else @@ -1016,4 +1041,65 @@ String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, u return stringBuilder.toString(); } +bool setTimeZoneForAutomation(const String& timeZone) +{ + innerTimeZoneForAutomation().displayName = String(); + if (innerTimeZoneForAutomation().cal) { + ucal_close(innerTimeZoneForAutomation().cal); + innerTimeZoneForAutomation().cal = nullptr; + } + if (timeZone.isEmpty()) { + innerTimeZoneForAutomation().id = String(); + return true; + } + + // Timezone is ascii. + Vector buffer(timeZone.length()); + UChar* bufferStart = buffer.data(); + CString ctz = timeZone.utf8(); + if (!Unicode::convertUTF8ToUTF16(ctz.data(), ctz.data() + ctz.length(), &bufferStart, bufferStart + timeZone.length())) + return false; + + Vector canonicalBuffer(32); + UErrorCode status = U_ZERO_ERROR; + auto canonicalLength = ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalBuffer.size(), nullptr, &status); + if (status == U_BUFFER_OVERFLOW_ERROR) { + status = U_ZERO_ERROR; + canonicalBuffer.grow(canonicalLength); + ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalLength, nullptr, &status); + } + if (!U_SUCCESS(status)) + return false; + + UCalendar* cal = ucal_open(canonicalBuffer.data(), canonicalLength, nullptr, UCAL_TRADITIONAL, &status); + if (!U_SUCCESS(status)) + return false; + + Vector displayNameBuffer(32); + auto displayNameLength = ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameBuffer.size(), &status); + if (status == U_BUFFER_OVERFLOW_ERROR) { + status = U_ZERO_ERROR; + displayNameBuffer.grow(displayNameLength); + ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameLength, &status); + } + if (!U_SUCCESS(status)) + return false; + + TimeZoneForAutomation& tzfa = innerTimeZoneForAutomation(); + tzfa.cal = cal; + tzfa.id = String(canonicalBuffer.data(), canonicalLength); + tzfa.displayName = String(displayNameBuffer.data(), displayNameLength); + return true; +} + +String timeZoneForAutomation() +{ + return innerTimeZoneForAutomation().id; +} + +String timeZoneDisplayNameForAutomation() +{ + return innerTimeZoneForAutomation().displayName; +} + } // namespace WTF diff --git a/Source/WTF/wtf/DateMath.h b/Source/WTF/wtf/DateMath.h index 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 24cc44a5c88de5f78cd96404f23060ee514301ec..c922489288e827ebd0b249e64609459c2bbe2752 100644 --- a/Source/WTF/wtf/PlatformEnable.h +++ b/Source/WTF/wtf/PlatformEnable.h @@ -408,7 +408,7 @@ #endif #if !defined(ENABLE_ORIENTATION_EVENTS) -#define ENABLE_ORIENTATION_EVENTS 0 +#define ENABLE_ORIENTATION_EVENTS 1 #endif #if OS(WINDOWS) @@ -469,7 +469,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 7e807beda588a540b477e185e41e367f7a333702..9322d1e5b425c9bbafa89083a1df7eaada2bbe68 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 ccec1efd11d29875919255fee7a6ac2364376681..9239b35fb7b1b59f26070d79bcfa96ee095aa530 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 dde6444061d22332b41a0387191080ff6111be90..a30f29deff3646b36a2104fd3557992ec5313c95 100644 --- a/Source/WebCore/DerivedSources.make +++ b/Source/WebCore/DerivedSources.make @@ -940,6 +940,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 \ @@ -1480,9 +1484,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 1a46686f78cdcb238bad5f2ac32a72c5417463de..c625a5cba18006f1c2290712c1ccb54c1c513ced 100644 --- a/Source/WebCore/SourcesCocoa.txt +++ b/Source/WebCore/SourcesCocoa.txt @@ -608,3 +608,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 77a71256512d1728c86e378591685edcbcdcc569..7fb305a28a3d95d7c42845a176ae407b153f7385 100644 --- a/Source/WebCore/SourcesGTK.txt +++ b/Source/WebCore/SourcesGTK.txt @@ -100,7 +100,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 0aca7c32c4568b43e4b901bdbd72c5f5a0bfcd3c..d1f134304639ae3dd9c862cf1f82b0254597714a 100644 --- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj @@ -5422,6 +5422,14 @@ EDE3A5000C7A430600956A37 /* ColorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = EDE3A4FF0C7A430600956A37 /* ColorMac.h */; settings = {ATTRIBUTES = (Private, ); }; }; EDEC98030AED7E170059137F /* WebCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EDEC98020AED7E170059137F /* WebCorePrefix.h */; }; EFCC6C8F20FE914400A2321B /* CanvasActivityRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16923AD660C0011CE47 /* Touch.cpp */; }; + F050E16D23AD66630011CE47 /* TouchList.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16B23AD66620011CE47 /* TouchList.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F050E16E23AD66630011CE47 /* TouchList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16C23AD66630011CE47 /* TouchList.cpp */; }; + F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16F23AD669E0011CE47 /* TouchEvent.cpp */; }; + F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17023AD669F0011CE47 /* TouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F050E17423AD6A800011CE47 /* DocumentTouch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E17323AD6A800011CE47 /* DocumentTouch.cpp */; }; + F050E17823AD70C50011CE47 /* PlatformTouchPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; F12171F616A8CF0B000053CA /* WebVTTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = F12171F416A8BC63000053CA /* WebVTTElement.h */; }; F32BDCD92363AACA0073B6AE /* UserGestureEmulationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = F32BDCD72363AACA0073B6AE /* UserGestureEmulationScope.h */; }; F344C7141125B82C00F26EEE /* InspectorFrontendClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F344C7121125B82C00F26EEE /* InspectorFrontendClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -17252,6 +17260,14 @@ EDEC98020AED7E170059137F /* WebCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCorePrefix.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; EFB7287B2124C73D005C2558 /* CanvasActivityRecord.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CanvasActivityRecord.cpp; sourceTree = ""; }; EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanvasActivityRecord.h; sourceTree = ""; }; + F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchEvent.h; sourceTree = ""; }; + F050E16923AD660C0011CE47 /* Touch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Touch.cpp; path = dom/Touch.cpp; sourceTree = SOURCE_ROOT; }; + F050E16B23AD66620011CE47 /* TouchList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TouchList.h; path = dom/TouchList.h; sourceTree = SOURCE_ROOT; }; + F050E16C23AD66630011CE47 /* TouchList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TouchList.cpp; path = dom/TouchList.cpp; sourceTree = SOURCE_ROOT; }; + F050E16F23AD669E0011CE47 /* TouchEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TouchEvent.cpp; path = dom/TouchEvent.cpp; sourceTree = SOURCE_ROOT; }; + F050E17023AD669F0011CE47 /* TouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TouchEvent.h; path = dom/TouchEvent.h; sourceTree = SOURCE_ROOT; }; + F050E17323AD6A800011CE47 /* DocumentTouch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentTouch.cpp; sourceTree = ""; }; + F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchPoint.h; sourceTree = ""; }; F12171F316A8BC63000053CA /* WebVTTElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebVTTElement.cpp; sourceTree = ""; }; F12171F416A8BC63000053CA /* WebVTTElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebVTTElement.h; sourceTree = ""; }; F32BDCD52363AAC90073B6AE /* UserGestureEmulationScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserGestureEmulationScope.cpp; sourceTree = ""; }; @@ -23201,7 +23217,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 */, @@ -29143,6 +29164,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 */, @@ -31402,6 +31425,7 @@ BCCFBAE70B5152ED0001F1D7 /* DocumentParser.h */, AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */, AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */, + F050E17323AD6A800011CE47 /* DocumentTouch.cpp */, 6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */, 6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */, 7CE7FA5B1EF882300060C9D6 /* DocumentTouch.cpp */, @@ -32419,6 +32443,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 */, @@ -34517,6 +34542,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 */, @@ -36648,9 +36674,11 @@ B2C3DA3A0D006C1D00EF6F26 /* TextCodec.h in Headers */, 26E98A10130A9FCA008EB7B2 /* TextCodecASCIIFastPath.h in Headers */, DF95B14A24FDAFD300B1F4D7 /* TextCodecCJK.h in Headers */, + F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */, B2C3DA3C0D006C1D00EF6F26 /* TextCodecICU.h in Headers */, B2C3DA3E0D006C1D00EF6F26 /* TextCodecLatin1.h in Headers */, 57EF5E601D20C83900171E60 /* TextCodecReplacement.h in Headers */, + F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */, B2C3DA400D006C1D00EF6F26 /* TextCodecUserDefined.h in Headers */, B2C3DA420D006C1D00EF6F26 /* TextCodecUTF16.h in Headers */, 9343CB8212F25E510033C5EE /* TextCodecUTF8.h in Headers */, @@ -37613,6 +37641,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 */, @@ -37682,6 +37711,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 */, @@ -37730,6 +37760,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 */, @@ -38262,6 +38293,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 10ba9f976d3cdf26c9cca2b7d08b2b24c341782b..e11d39157f67c35f843ba5e485f3d51ee0e2e66b 100644 --- a/Source/WebCore/accessibility/AccessibilityObject.cpp +++ b/Source/WebCore/accessibility/AccessibilityObject.cpp @@ -60,6 +60,7 @@ #include "HTMLParserIdioms.h" #include "HTMLTextAreaElement.h" #include "HitTestResult.h" +#include "InspectorInstrumentation.h" #include "LocalizedStrings.h" #include "MathMLNames.h" #include "NodeList.h" @@ -3530,10 +3531,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 eb43545d9b501810cb1db2bdff05f4c6fc1432dc..57a61dcee5a7b580ca5d31d392b24c006715359c 100644 --- a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h +++ b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h @@ -109,6 +109,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 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::createForDrag(const Document& document) return adoptRef(*new DataTransfer(StoreMode::ReadWrite, Pasteboard::createForDragAndDrop(PagePasteboardContext::create(document.pageID())), Type::DragAndDropData)); } +#if PLATFORM(MAC) +Ref DataTransfer::createForDrag(const Document& document, const String& pasteboardName) +{ + return adoptRef(*new DataTransfer(StoreMode::ReadWrite, makeUnique(PagePasteboardContext::create(document.pageID()), pasteboardName), Type::DragAndDropData)); +} +#endif + + Ref DataTransfer::createForDragStartEvent(const Document& document) { auto dataTransfer = adoptRef(*new DataTransfer(StoreMode::ReadWrite, makeUnique(), Type::DragAndDropData)); diff --git a/Source/WebCore/dom/DataTransfer.h b/Source/WebCore/dom/DataTransfer.h index b084ee416512652220e43a6d4bcccaff7c666d5a..b250f3d0161817efef7e2634a16713b0a0f1fa71 100644 --- a/Source/WebCore/dom/DataTransfer.h +++ b/Source/WebCore/dom/DataTransfer.h @@ -90,6 +90,9 @@ public: #if ENABLE(DRAG_SUPPORT) static Ref createForDrag(const Document&); +#if PLATFORM(MAC) + static Ref createForDrag(const Document&, const String& pasteboardName); +#endif static Ref createForDragStartEvent(const Document&); static Ref createForDrop(const Document&, std::unique_ptr&&, OptionSet, bool draggingFiles); static Ref createForUpdatingDropTarget(const Document&, std::unique_ptr&&, OptionSet, bool draggingFiles); diff --git a/Source/WebCore/dom/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::create(const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref&& view) +{ + const auto& type = pointerEventType(event.touchPoints().at(index).state()); + return adoptRef(*new PointerEvent(type, event, typeIsCancelable(type), index, isPrimary, WTFMove(view))); +} + +Ref PointerEvent::create(const String& type, const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref&& view) +{ + return adoptRef(*new PointerEvent(type, event, typeIsCancelable(type), index, isPrimary, WTFMove(view))); +} + +PointerEvent::PointerEvent(const AtomString& type, const PlatformTouchEvent& event, IsCancelable isCancelable, unsigned index, bool isPrimary, Ref&& view) + : MouseEvent(type, typeCanBubble(type), isCancelable, typeIsComposed(type), event.timestamp().approximateMonotonicTime(), WTFMove(view), 0, event.touchPoints().at(index).pos(), event.touchPoints().at(index).pos(), { }, event.modifiers(), buttonForType(type), buttonsForType(type), nullptr, 0, 0, IsSimulated::No, IsTrusted::Yes) + , m_pointerId(2) + , m_width(2 * event.touchPoints().at(index).radiusX()) + , m_height(2 * event.touchPoints().at(index).radiusY()) + , m_pressure(event.touchPoints().at(index).force()) + , m_pointerType(touchPointerEventType()) + , m_isPrimary(isPrimary) +{ +} + +#endif // ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS_FAMILY) + } // namespace WebCore diff --git a/Source/WebCore/dom/PointerEvent.h b/Source/WebCore/dom/PointerEvent.h index 9d60b85152f378566118574663701c25b001df3d..9811ce9aa6f066c57acf65f629d2ab8155c090e1 100644 --- a/Source/WebCore/dom/PointerEvent.h +++ b/Source/WebCore/dom/PointerEvent.h @@ -33,6 +33,8 @@ #if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) #include "PlatformTouchEventIOS.h" +#else +#include "PlatformTouchEvent.h" #endif namespace WebCore { @@ -81,7 +83,7 @@ public: static Ref create(const String& type, short button, const MouseEvent&, PointerID, const String& pointerType); static Ref create(const String& type, PointerID, const String& pointerType, IsPrimary = IsPrimary::No); -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) +#if ENABLE(TOUCH_EVENTS) static Ref create(const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref&&); static Ref create(const String& type, const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref&&); #endif @@ -121,7 +123,7 @@ private: PointerEvent(const AtomString&, Init&&); PointerEvent(const AtomString& type, short button, const MouseEvent&, PointerID, const String& pointerType); PointerEvent(const AtomString& type, PointerID, const String& pointerType, IsPrimary); -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) +#if ENABLE(TOUCH_EVENTS) PointerEvent(const AtomString& type, const PlatformTouchEvent&, IsCancelable isCancelable, unsigned touchIndex, bool isPrimary, Ref&&); #endif diff --git a/Source/WebCore/editing/libwpe/EditorLibWPE.cpp b/Source/WebCore/editing/libwpe/EditorLibWPE.cpp index 9dd41d6366512fd385937a7608bd3fc9b5b90f60..d6bb529fb891a65c8f6dcc6cff1e718c7a40b8dd 100644 --- a/Source/WebCore/editing/libwpe/EditorLibWPE.cpp +++ b/Source/WebCore/editing/libwpe/EditorLibWPE.cpp @@ -33,6 +33,7 @@ #include "NotImplemented.h" #include "Pasteboard.h" #include "Settings.h" +#include "WebContentReader.h" #include "markup.h" namespace WebCore { @@ -91,6 +92,14 @@ void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet pasteAsFragment(*fragment, canSmartReplaceWithPasteboard(*pasteboard), chosePlainText, options.contains(PasteOption::IgnoreMailBlockquote) ? MailBlockquoteHandling::IgnoreBlockquote : MailBlockquoteHandling::RespectBlockquote); } +RefPtr Editor::webContentFromPasteboard(Pasteboard& pasteboard, const SimpleRange& context, bool allowPlainText, bool& chosePlainText) +{ + WebContentReader reader(*m_document.frame(), context, allowPlainText); + pasteboard.read(reader); + chosePlainText = reader.madeFragmentFromPlainText; + return WTFMove(reader.fragment); +} + } // namespace WebCore #endif // USE(LIBWPE) diff --git a/Source/WebCore/html/FileInputType.cpp b/Source/WebCore/html/FileInputType.cpp index b0c9fae7d3da54711a7259f05e3460b46acf4edb..0fc3b7fb34a82c74bc07c554d2ed85859a08c848 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" @@ -213,6 +214,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(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 d2c0cb6cfd184f158c4a62d8be2efb5750192c3c..264d13c746524b7147be3ff7662b9c413e6f7af7 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 parseColor(RefPtr&& colorObject) +// static +std::optional InspectorDOMAgent::parseColor(RefPtr&& colorObject) { if (!colorObject) return std::nullopt; @@ -150,7 +158,7 @@ static std::optional parseColor(RefPtr&& 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&& quadArray, FloatQuad* quad) @@ -431,6 +439,20 @@ Node* InspectorDOMAgent::assertNode(Protocol::ErrorString& errorString, Protocol return node; } +Node* InspectorDOMAgent::assertNode(Protocol::ErrorString& errorString, std::optional&& nodeId, const String& objectId) +{ + Node* node = nullptr; + if (nodeId) { + node = assertNode(errorString, *nodeId); + } else if (!!objectId) { + node = nodeForObjectId(objectId); + if (!node) + errorString = "Missing node for given objectId"_s; + } else + errorString = "Either nodeId or objectId must be specified"_s; + return node; +} + Document* InspectorDOMAgent::assertDocument(Protocol::ErrorString& errorString, Protocol::DOM::NodeId nodeId) { Node* node = assertNode(errorString, nodeId); @@ -1384,16 +1406,7 @@ Protocol::ErrorStringOr InspectorDOMAgent::highlightSelector(Ref InspectorDOMAgent::highlightNode(Ref&& highlightInspectorObject, std::optional&& nodeId, const Protocol::Runtime::RemoteObjectId& objectId) { Protocol::ErrorString errorString; - - Node* node = nullptr; - if (nodeId) - node = assertNode(errorString, *nodeId); - else if (!!objectId) { - node = nodeForObjectId(objectId); - errorString = "Missing node for given objectId"_s; - } else - errorString = "Either nodeId or objectId must be specified"_s; - + Node* node = assertNode(errorString, WTFMove(nodeId), objectId); if (!node) return makeUnexpected(errorString); @@ -1595,15 +1608,136 @@ Protocol::ErrorStringOr InspectorDOMAgent::setInspectedNode(Protocol::DOM: return { }; } -Protocol::ErrorStringOr> InspectorDOMAgent::resolveNode(Protocol::DOM::NodeId nodeId, const String& objectGroup) +static FloatPoint contentsToRootView(FrameView& containingView, const FloatPoint& point) { - Protocol::ErrorString errorString; + return containingView.convertToRootView(point - toFloatSize(containingView.documentScrollPositionRelativeToViewOrigin())); +} - Node* node = assertNode(errorString, nodeId); +static void frameQuadToViewport(FrameView& containingView, FloatQuad& quad, float pageScaleFactor) +{ + // Return css (not dip) coordinates by scaling back. + quad.setP1(contentsToRootView(containingView, quad.p1()).scaled(1 / pageScaleFactor)); + quad.setP2(contentsToRootView(containingView, quad.p2()).scaled(1 / pageScaleFactor)); + quad.setP3(contentsToRootView(containingView, quad.p3()).scaled(1 / pageScaleFactor)); + quad.setP4(contentsToRootView(containingView, quad.p4()).scaled(1 / pageScaleFactor)); +} + +static Ref buildObjectForQuad(const FloatQuad& quad) +{ + auto result = Inspector::Protocol::DOM::Quad::create(); + result->addItem(quad.p1().x()); + result->addItem(quad.p1().y()); + result->addItem(quad.p2().x()); + result->addItem(quad.p2().y()); + result->addItem(quad.p3().x()); + result->addItem(quad.p3().y()); + result->addItem(quad.p4().x()); + result->addItem(quad.p4().y()); + return result; +} + +static Ref> buildArrayOfQuads(const Vector& quads) +{ + auto result = JSON::ArrayOf::create(); + for (const auto& quad : quads) + result->addItem(buildObjectForQuad(quad)); + return result; +} + +Inspector::Protocol::ErrorStringOr> InspectorDOMAgent::describeNode(const String& objectId) +{ + Node* node = nodeForObjectId(objectId); + if (!node) + return makeUnexpected("Node not found"_s); + + auto* pageAgent = m_instrumentingAgents.enabledPageAgent(); + if (!pageAgent) + return makeUnexpected("Page agent must be enabled"_s); + + String ownerFrameId; + String frameId = pageAgent->frameId(node->document().frame()); + if (!frameId.isEmpty()) + ownerFrameId = frameId; + + String contentFrameId; + if (is(*node)) { + const auto& frameOwner = downcast(*node); + String frameId = pageAgent->frameId(frameOwner.contentFrame()); + if (!frameId.isEmpty()) + contentFrameId = frameId; + } + + return { { contentFrameId, ownerFrameId } }; +} + +Protocol::ErrorStringOr InspectorDOMAgent::scrollIntoViewIfNeeded(const String& objectId, RefPtr&& rect) +{ + Node* node = nodeForObjectId(objectId); + if (!node) + return makeUnexpected("Node not found"_s); + + m_inspectedPage.isolatedUpdateRendering(); + if (!node->isConnected()) + return makeUnexpected("Node is detached from document"_s); + + RenderObject* renderer = node->renderer(); + if (!renderer) + return makeUnexpected("Node does not have a layout object"_s); + + bool insideFixed; + LayoutRect absoluteBounds = renderer->absoluteBoundingBoxRect(true, &insideFixed); + if (rect) { + std::optional x = rect->getDouble("x"); + std::optional y = rect->getDouble("y"); + std::optional width = rect->getDouble("width"); + std::optional height = rect->getDouble("height"); + if (!x || !y || !width || !height) + return makeUnexpected("Malformed rect"_s); + + absoluteBounds.setX(absoluteBounds.x() + LayoutUnit(*x)); + absoluteBounds.setY(absoluteBounds.y() + LayoutUnit(*y)); + absoluteBounds.setWidth(LayoutUnit(std::max(*width, 1.0))); + absoluteBounds.setHeight(LayoutUnit(std::max(*height, 1.0))); + } + ScrollAlignment alignment = ScrollAlignment::alignCenterIfNeeded; + alignment.m_disableMinThreshold = true; // Disable RenderLayer minium horizontal scroll threshold. + renderer->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, alignment, alignment, ShouldAllowCrossOriginScrolling::Yes }); + return { }; +} + +Protocol::ErrorStringOr>> InspectorDOMAgent::getContentQuads(const String& objectId) +{ + Node* node = nodeForObjectId(objectId); + if (!node) + return makeUnexpected("Node not found"_s); + + RenderObject* renderer = node->renderer(); + if (!renderer) + return makeUnexpected("Node doesn't have renderer"_s); + + // Ensure quads are up to date. + m_inspectedPage.isolatedUpdateRendering(); + + Frame* containingFrame = renderer->document().frame(); + FrameView* containingView = containingFrame ? containingFrame->view() : nullptr; + if (!containingView) + return makeUnexpected("Internal error: no containing view"_s); + + Vector quads; + renderer->absoluteQuads(quads); + for (auto& quad : quads) + frameQuadToViewport(*containingView, quad, m_inspectedPage.pageScaleFactor()); + return buildArrayOfQuads(quads); +} + +Protocol::ErrorStringOr> InspectorDOMAgent::resolveNode(std::optional&& nodeId, const String& objectId, std::optional&& contextId, const String& objectGroup) +{ + Protocol::ErrorString errorString; + Node* node = assertNode(errorString, WTFMove(nodeId), objectId); if (!node) return makeUnexpected(errorString); - auto object = resolveNode(node, objectGroup); + auto object = resolveNode(node, objectGroup, WTFMove(contextId)); if (!object) return makeUnexpected("Missing injected script for given nodeId"_s); @@ -2837,7 +2971,7 @@ Protocol::ErrorStringOr InspectorDOMAgent::pushNodeByPath return makeUnexpected("Missing node for given path"_s); } -RefPtr InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup) +RefPtr InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup, std::optional&& contextId) { Document* document = &node->document(); if (auto* templateHost = document->templateDocumentHost()) @@ -2846,12 +2980,16 @@ RefPtr InspectorDOMAgent::resolveNode(Node* nod if (!frame) return nullptr; - auto& state = *mainWorldExecState(frame); - auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state); + InjectedScript injectedScript; + if (contextId) { + injectedScript = m_injectedScriptManager.injectedScriptForId(*contextId); + } else { + injectedScript = m_injectedScriptManager.injectedScriptFor(mainWorldExecState(frame)); + } if (injectedScript.hasNoValue()) return nullptr; - return injectedScript.wrapObject(nodeAsScriptValue(state, node), objectGroup); + return injectedScript.wrapObject(nodeAsScriptValue(*injectedScript.globalObject(), node), objectGroup); } Node* InspectorDOMAgent::scriptValueAsNode(JSC::JSValue value) @@ -2874,4 +3012,42 @@ Protocol::ErrorStringOr InspectorDOMAgent::setAllowEditingUserAgentShadowT return { }; } +Protocol::ErrorStringOr InspectorDOMAgent::setInputFiles(const String& objectId, Ref&& files) { + InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); + if (injectedScript.hasNoValue()) + return makeUnexpected("Can not find element's context for given id"_s); + + Node* node = scriptValueAsNode(injectedScript.findObjectById(objectId)); + if (!node) + return makeUnexpected("Can not find element for given id"_s); + + if (node->nodeType() != Node::ELEMENT_NODE || node->nodeName() != "INPUT") + return makeUnexpected("Not an input node"_s); + + HTMLInputElement* element = static_cast(node); + Vector> fileObjects; + for (unsigned i = 0; i < files->length(); ++i) { + RefPtr item = files->get(i); + RefPtr obj = item->asObject(); + if (!obj) + return makeUnexpected("Invalid file payload format"_s); + + String name; + String type; + String data; + if (!obj->getString("name", name) || !obj->getString("type", type) || !obj->getString("data", data)) + return makeUnexpected("Invalid file payload format"_s); + + std::optional> 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::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 parseColor(RefPtr&&); // We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently. // We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics. @@ -129,7 +131,7 @@ public: Inspector::Protocol::ErrorStringOr> performSearch(const String& query, RefPtr&& nodeIds, std::optional&& caseSensitive); Inspector::Protocol::ErrorStringOr>> getSearchResults(const String& searchId, int fromIndex, int toIndex); Inspector::Protocol::ErrorStringOr discardSearchResults(const String& searchId); - Inspector::Protocol::ErrorStringOr> resolveNode(Inspector::Protocol::DOM::NodeId, const String& objectGroup); + Inspector::Protocol::ErrorStringOr> resolveNode(std::optional&& nodeId, const String& objectId, std::optional&& contextId, const String& objectGroup); Inspector::Protocol::ErrorStringOr>> getAttributes(Inspector::Protocol::DOM::NodeId); #if PLATFORM(IOS_FAMILY) Inspector::Protocol::ErrorStringOr setInspectModeEnabled(bool, RefPtr&& highlightConfig); @@ -154,6 +156,10 @@ public: Inspector::Protocol::ErrorStringOr focus(Inspector::Protocol::DOM::NodeId); Inspector::Protocol::ErrorStringOr setInspectedNode(Inspector::Protocol::DOM::NodeId); Inspector::Protocol::ErrorStringOr setAllowEditingUserAgentShadowTrees(bool); + Inspector::Protocol::ErrorStringOr> describeNode(const String& objectId); + Inspector::Protocol::ErrorStringOr scrollIntoViewIfNeeded(const String& objectId, RefPtr&& rect); + Inspector::Protocol::ErrorStringOr>> getContentQuads(const String& objectId); + Inspector::Protocol::ErrorStringOr setInputFiles(const String& objectId, Ref&& files); // InspectorInstrumentation Inspector::Protocol::DOM::NodeId identifierForNode(Node&); @@ -191,7 +197,7 @@ public: Node* nodeForId(Inspector::Protocol::DOM::NodeId); Inspector::Protocol::DOM::NodeId boundNodeId(const Node*); - RefPtr resolveNode(Node*, const String& objectGroup); + RefPtr resolveNode(Node*, const String& objectGroup, std::optional&& 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&& nodeId, const String& objectId); Element* assertElement(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId); Document* assertDocument(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId); RefPtr breakpointForEventListener(EventTarget&, const AtomString& eventType, EventListener&, bool capture); Inspector::Protocol::DOM::EventListenerId idForEventListener(EventTarget&, const AtomString& eventType, EventListener&, bool capture); + Node* nodeForObjectId(const Inspector::Protocol::Runtime::RemoteObjectId&); + private: #if ENABLE(VIDEO) void mediaMetricsTimerFired(); @@ -236,7 +245,6 @@ private: void processAccessibilityChildren(AXCoreObject&, JSON::ArrayOf&); Node* nodeForPath(const String& path); - Node* nodeForObjectId(const Inspector::Protocol::Runtime::RemoteObjectId&); void discardBindings(); diff --git a/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h b/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h index 3386cb879f1178c1b9635775c9a0e864f5b94c52..d2350182f5f061855e8ca172779ad60ee73b39fb 100644 --- a/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h +++ b/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h @@ -40,6 +40,7 @@ class DOMStorageFrontendDispatcher; namespace WebCore { +class Color; class Frame; class Page; class SecurityOrigin; diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp index 44e084a28842fbc562893761d71e4c74274ebb18..ba401dc8edbe4033f372d2abe00c5c3d0236bf8d 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 buildObjectForResourceRequest(const Resou .setHeaders(buildObjectForHeaders(request.httpHeaderFields())) .release(); if (request.httpBody() && !request.httpBody()->isEmpty()) { - auto bytes = request.httpBody()->flatten(); - requestObject->setPostData(String::fromUTF8WithLatin1Fallback(bytes.data(), bytes.size())); + Vector bytes = request.httpBody()->flatten(); + requestObject->setPostData(base64EncodeToString(bytes)); } return requestObject; } @@ -353,6 +355,8 @@ RefPtr 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 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 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 InspectorNetworkAgent::interceptRequestWithError(c return { }; } +Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setEmulateOfflineState(bool offline) +{ + platformStrategies()->loaderStrategy()->setEmulateOfflineState(offline); + return { }; +} + bool InspectorNetworkAgent::shouldTreatAsText(const String& mimeType) { return startsWithLettersIgnoringASCIICase(mimeType, "text/") @@ -1378,6 +1408,12 @@ std::optional 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 #include @@ -72,6 +74,7 @@ public: static Ref createTextDecoder(const String& mimeType, const String& textEncodingName); static std::optional 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 interceptWithResponse(const Inspector::Protocol::Network::RequestId&, const String& content, bool base64Encoded, const String& mimeType, std::optional&& status, const String& statusText, RefPtr&& headers) final; Inspector::Protocol::ErrorStringOr interceptRequestWithResponse(const Inspector::Protocol::Network::RequestId&, const String& content, bool base64Encoded, const String& mimeType, int status, const String& statusText, Ref&& headers) final; Inspector::Protocol::ErrorStringOr interceptRequestWithError(const Inspector::Protocol::Network::RequestId&, Inspector::Protocol::Network::ResourceErrorType) final; + Inspector::Protocol::ErrorStringOr setEmulateOfflineState(bool offline) final; // InspectorInstrumentation void willRecalculateStyle(); diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp index 3dafe6437df1210405fefbf375785fecd5eac472..4c3870ebcd370ceb13772c5be967548732073804 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 "TextEncoding.h" +#include "TextIterator.h" +#include "TypingCommand.h" #include "UserGestureIndicator.h" #include #include +#include #include +#include #include +#include +#include +#include #include #include #include @@ -81,11 +100,15 @@ #include "LegacyWebArchive.h" #endif - namespace WebCore { using namespace Inspector; +static HashMap>& createdUserWorlds() { + static NeverDestroyed>> 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(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 InspectorPageAgent::enable() defaultAppearanceDidChange(m_inspectedPage.defaultUseDarkAppearance()); #endif + if (!createdUserWorlds().isEmpty()) { + Vector worlds; + for (const auto& world : createdUserWorlds().values()) + worlds.append(world.ptr()); + ensureUserWorldsExistInAllFrames(worlds); + } return { }; } Protocol::ErrorStringOr InspectorPageAgent::disable() { m_instrumentingAgents.setEnabledPageAgent(nullptr); + m_interceptFileChooserDialog = false; + m_bypassCSP = false; setShowPaintRects(false); #if !PLATFORM(IOS_FAMILY) @@ -407,6 +441,22 @@ Protocol::ErrorStringOr InspectorPageAgent::reload(std::optional&& i return { }; } +Protocol::ErrorStringOr InspectorPageAgent::goBack() +{ + if (!m_inspectedPage.backForward().goBack()) + return makeUnexpected("Failed to go back"_s); + + return { }; +} + +Protocol::ErrorStringOr InspectorPageAgent::goForward() +{ + if (!m_inspectedPage.backForward().goForward()) + return makeUnexpected("Failed to go forward"_s); + + return { }; +} + Protocol::ErrorStringOr InspectorPageAgent::navigate(const String& url) { UserGestureIndicator indicator { ProcessingUserGesture }; @@ -427,6 +477,13 @@ Protocol::ErrorStringOr InspectorPageAgent::overrideUserAgent(const String return { }; } +Protocol::ErrorStringOr InspectorPageAgent::overridePlatform(const String& value) +{ + m_platformOverride = value; + + return { }; +} + Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Protocol::Page::Setting setting, std::optional&& value) { auto& inspectedPageSettings = m_inspectedPage.settings(); @@ -440,6 +497,12 @@ Protocol::ErrorStringOr 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 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 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> InspectorP return { { content, base64Encoded } }; } -Protocol::ErrorStringOr InspectorPageAgent::setBootstrapScript(const String& source) +Protocol::ErrorStringOr 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 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 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 InspectorPageAgent::snapshotNode(Protocol::DOM:: return snapshot->toDataURL("image/png"_s, std::nullopt, PreserveResolution::Yes); } -Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int x, int y, int width, int height, Protocol::Page::CoordinateSystem coordinateSystem) +Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int x, int y, int width, int height, Protocol::Page::CoordinateSystem coordinateSystem, std::optional&& 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 InspectorPageAgent::snapshotRect(int x, int y, i return snapshot->toDataURL("image/png"_s, std::nullopt, PreserveResolution::Yes); } +Protocol::ErrorStringOr InspectorPageAgent::setForcedReducedMotion(std::optional&& 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 InspectorPageAgent::setTimeZone(const String& timeZone) +{ + bool success = WTF::setTimeZoneForAutomation(timeZone); + if (!success) + return makeUnexpected("Invalid time zone " + timeZone); + + return { }; +} + +Protocol::ErrorStringOr InspectorPageAgent::setTouchEmulationEnabled(bool enabled) +{ +#if ENABLE(TOUCH_EVENTS) + RuntimeEnabledFeatures::sharedFeatures().setTouchEventsEnabled(enabled); + return { }; +#else + UNUSED_PARAM(enabled); + return makeUnexpected("Not supported"_s); +#endif +} + + #if ENABLE(WEB_ARCHIVE) && USE(CF) Protocol::ErrorStringOr InspectorPageAgent::archive() { @@ -1107,7 +1324,6 @@ Protocol::ErrorStringOr InspectorPageAgent::archive() } #endif -#if !PLATFORM(COCOA) Protocol::ErrorStringOr InspectorPageAgent::setScreenSizeOverride(std::optional&& width, std::optional&& height) { if (width.has_value() != height.has_value()) @@ -1122,6 +1338,628 @@ Protocol::ErrorStringOr InspectorPageAgent::setScreenSizeOverride(std::opt m_inspectedPage.mainFrame().setOverrideScreenSize(FloatSize(width.value_or(0), height.value_or(0))); return { }; } + +Protocol::ErrorStringOr 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 InspectorPageAgent::setComposition(const String& text, int selectionStart, int selectionLength, std::optional&& replacementStart, std::optional&& replacementLength) +{ + Frame& frame = m_inspectedPage.focusController().focusedOrMainFrame(); + + UserGestureIndicator indicator { ProcessingUserGesture }; + + if (!frame.selection().selection().isContentEditable()) + return { }; + if (replacementStart) { + WebCore::CharacterRange range { static_cast(*replacementStart), replacementLength ? static_cast(*replacementLength) : 0 }; + auto* element = frame.selection().rootEditableElementOrDocumentElement(); + if (element) + frame.selection().setSelection(VisibleSelection(resolveCharacterRange(makeRangeSelectingNodeContents(*element), range))); + } + frame.editor().setComposition(text, { }, { }, static_cast(selectionStart), selectionStart + selectionLength); + return { }; +} + +static String roleFromObject(RefPtr axObject) +{ + String computedRoleString = axObject->computedRoleString(); + if (!computedRoleString.isEmpty()) + return computedRoleString; + AccessibilityRole role = axObject->roleValue(); + switch(role) { + case AccessibilityRole::Annotation: + return "Annotation"; + case AccessibilityRole::Application: + return "Application"; + case AccessibilityRole::ApplicationAlert: + return "ApplicationAlert"; + case AccessibilityRole::ApplicationAlertDialog: + return "ApplicationAlertDialog"; + case AccessibilityRole::ApplicationDialog: + return "ApplicationDialog"; + case AccessibilityRole::ApplicationGroup: + return "ApplicationGroup"; + case AccessibilityRole::ApplicationLog: + return "ApplicationLog"; + case AccessibilityRole::ApplicationMarquee: + return "ApplicationMarquee"; + case AccessibilityRole::ApplicationStatus: + return "ApplicationStatus"; + case AccessibilityRole::ApplicationTextGroup: + return "ApplicationTextGroup"; + case AccessibilityRole::ApplicationTimer: + return "ApplicationTimer"; + case AccessibilityRole::Audio: + return "Audio"; + case AccessibilityRole::Blockquote: + return "Blockquote"; + case AccessibilityRole::Browser: + return "Browser"; + case AccessibilityRole::BusyIndicator: + return "BusyIndicator"; + case AccessibilityRole::Button: + return "Button"; + case AccessibilityRole::Canvas: + return "Canvas"; + case AccessibilityRole::Caption: + return "Caption"; + case AccessibilityRole::Cell: + return "Cell"; + case AccessibilityRole::CheckBox: + return "CheckBox"; + case AccessibilityRole::ColorWell: + return "ColorWell"; + case AccessibilityRole::Column: + return "Column"; + case AccessibilityRole::ColumnHeader: + return "ColumnHeader"; + case AccessibilityRole::ComboBox: + return "ComboBox"; + case AccessibilityRole::Definition: + return "Definition"; + case AccessibilityRole::Deletion: + return "Deletion"; + case AccessibilityRole::DescriptionList: + return "DescriptionList"; + case AccessibilityRole::DescriptionListTerm: + return "DescriptionListTerm"; + case AccessibilityRole::DescriptionListDetail: + return "DescriptionListDetail"; + case AccessibilityRole::Details: + return "Details"; + case AccessibilityRole::Directory: + return "Directory"; + case AccessibilityRole::DisclosureTriangle: + return "DisclosureTriangle"; + case AccessibilityRole::Div: + return "Div"; + case AccessibilityRole::Document: + return "Document"; + case AccessibilityRole::DocumentArticle: + return "DocumentArticle"; + case AccessibilityRole::DocumentMath: + return "DocumentMath"; + case AccessibilityRole::DocumentNote: + return "DocumentNote"; + case AccessibilityRole::Drawer: + return "Drawer"; + case AccessibilityRole::EditableText: + return "EditableText"; + case AccessibilityRole::Feed: + return "Feed"; + case AccessibilityRole::Figure: + return "Figure"; + case AccessibilityRole::Footer: + return "Footer"; + case AccessibilityRole::Footnote: + return "Footnote"; + case AccessibilityRole::Form: + return "Form"; + case AccessibilityRole::GraphicsDocument: + return "GraphicsDocument"; + case AccessibilityRole::GraphicsObject: + return "GraphicsObject"; + case AccessibilityRole::GraphicsSymbol: + return "GraphicsSymbol"; + case AccessibilityRole::Grid: + return "Grid"; + case AccessibilityRole::GridCell: + return "GridCell"; + case AccessibilityRole::Group: + return "Group"; + case AccessibilityRole::GrowArea: + return "GrowArea"; + case AccessibilityRole::Heading: + return "Heading"; + case AccessibilityRole::HelpTag: + return "HelpTag"; + case AccessibilityRole::HorizontalRule: + return "HorizontalRule"; + case AccessibilityRole::Ignored: + return "Ignored"; + case AccessibilityRole::Inline: + return "Inline"; + case AccessibilityRole::Image: + return "Image"; + case AccessibilityRole::ImageMap: + return "ImageMap"; + case AccessibilityRole::ImageMapLink: + return "ImageMapLink"; + case AccessibilityRole::Incrementor: + return "Incrementor"; + case AccessibilityRole::Insertion: + return "Insertion"; + case AccessibilityRole::Label: + return "Label"; + case AccessibilityRole::LandmarkBanner: + return "LandmarkBanner"; + case AccessibilityRole::LandmarkComplementary: + return "LandmarkComplementary"; + case AccessibilityRole::LandmarkContentInfo: + return "LandmarkContentInfo"; + case AccessibilityRole::LandmarkDocRegion: + return "LandmarkDocRegion"; + case AccessibilityRole::LandmarkMain: + return "LandmarkMain"; + case AccessibilityRole::LandmarkNavigation: + return "LandmarkNavigation"; + case AccessibilityRole::LandmarkRegion: + return "LandmarkRegion"; + case AccessibilityRole::LandmarkSearch: + return "LandmarkSearch"; + case AccessibilityRole::Legend: + return "Legend"; + case AccessibilityRole::Link: + return "Link"; + case AccessibilityRole::List: + return "List"; + case AccessibilityRole::ListBox: + return "ListBox"; + case AccessibilityRole::ListBoxOption: + return "ListBoxOption"; + case AccessibilityRole::ListItem: + return "ListItem"; + case AccessibilityRole::ListMarker: + return "ListMarker"; + case AccessibilityRole::Mark: + return "Mark"; + case AccessibilityRole::MathElement: + return "MathElement"; + case AccessibilityRole::Matte: + return "Matte"; + case AccessibilityRole::Menu: + return "Menu"; + case AccessibilityRole::MenuBar: + return "MenuBar"; + case AccessibilityRole::MenuButton: + return "MenuButton"; + case AccessibilityRole::MenuItem: + return "MenuItem"; + case AccessibilityRole::MenuItemCheckbox: + return "MenuItemCheckbox"; + case AccessibilityRole::MenuItemRadio: + return "MenuItemRadio"; + case AccessibilityRole::MenuListPopup: + return "MenuListPopup"; + case AccessibilityRole::MenuListOption: + return "MenuListOption"; + case AccessibilityRole::Meter: + return "Meter"; + case AccessibilityRole::Outline: + return "Outline"; + case AccessibilityRole::Paragraph: + return "Paragraph"; + case AccessibilityRole::PopUpButton: + return "PopUpButton"; + case AccessibilityRole::Pre: + return "Pre"; + case AccessibilityRole::Presentational: + return "Presentational"; + case AccessibilityRole::ProgressIndicator: + return "ProgressIndicator"; + case AccessibilityRole::RadioButton: + return "RadioButton"; + case AccessibilityRole::RadioGroup: + return "RadioGroup"; + case AccessibilityRole::RowHeader: + return "RowHeader"; + case AccessibilityRole::Row: + return "Row"; + case AccessibilityRole::RowGroup: + return "RowGroup"; + case AccessibilityRole::RubyBase: + return "RubyBase"; + case AccessibilityRole::RubyBlock: + return "RubyBlock"; + case AccessibilityRole::RubyInline: + return "RubyInline"; + case AccessibilityRole::RubyRun: + return "RubyRun"; + case AccessibilityRole::RubyText: + return "RubyText"; + case AccessibilityRole::Ruler: + return "Ruler"; + case AccessibilityRole::RulerMarker: + return "RulerMarker"; + case AccessibilityRole::ScrollArea: + return "ScrollArea"; + case AccessibilityRole::ScrollBar: + return "ScrollBar"; + case AccessibilityRole::SearchField: + return "SearchField"; + case AccessibilityRole::Sheet: + return "Sheet"; + case AccessibilityRole::Slider: + return "Slider"; + case AccessibilityRole::SliderThumb: + return "SliderThumb"; + case AccessibilityRole::SpinButton: + return "SpinButton"; + case AccessibilityRole::SpinButtonPart: + return "SpinButtonPart"; + case AccessibilityRole::SplitGroup: + return "SplitGroup"; + case AccessibilityRole::Splitter: + return "Splitter"; + case AccessibilityRole::StaticText: + return "StaticText"; + case AccessibilityRole::Subscript: + return "Subscript"; + case AccessibilityRole::Summary: + return "Summary"; + case AccessibilityRole::Superscript: + return "Superscript"; + case AccessibilityRole::Switch: + return "Switch"; + case AccessibilityRole::SystemWide: + return "SystemWide"; + case AccessibilityRole::SVGRoot: + return "SVGRoot"; + case AccessibilityRole::SVGText: + return "SVGText"; + case AccessibilityRole::SVGTSpan: + return "SVGTSpan"; + case AccessibilityRole::SVGTextPath: + return "SVGTextPath"; + case AccessibilityRole::TabGroup: + return "TabGroup"; + case AccessibilityRole::TabList: + return "TabList"; + case AccessibilityRole::TabPanel: + return "TabPanel"; + case AccessibilityRole::Tab: + return "Tab"; + case AccessibilityRole::Table: + return "Table"; + case AccessibilityRole::TableHeaderContainer: + return "TableHeaderContainer"; + case AccessibilityRole::TextArea: + return "TextArea"; + case AccessibilityRole::TextGroup: + return "TextGroup"; + case AccessibilityRole::Term: + return "Term"; + case AccessibilityRole::Time: + return "Time"; + case AccessibilityRole::Tree: + return "Tree"; + case AccessibilityRole::TreeGrid: + return "TreeGrid"; + case AccessibilityRole::TreeItem: + return "TreeItem"; + case AccessibilityRole::TextField: + return "TextField"; + case AccessibilityRole::ToggleButton: + return "ToggleButton"; + case AccessibilityRole::Toolbar: + return "Toolbar"; + case AccessibilityRole::Unknown: + return "Unknown"; + case AccessibilityRole::UserInterfaceTooltip: + return "UserInterfaceTooltip"; + case AccessibilityRole::ValueIndicator: + return "ValueIndicator"; + case AccessibilityRole::Video: + return "Video"; + case AccessibilityRole::WebApplication: + return "WebApplication"; + case AccessibilityRole::WebArea: + return "WebArea"; + case AccessibilityRole::WebCoreLink: + return "WebCoreLink"; + case AccessibilityRole::Window: + return "Window"; + }; + return "Unknown"; +} + +static Ref snapshotForAXObject(RefPtr axObject, Node* nodeToFind) +{ + auto axNode = Inspector::Protocol::Page::AXNode::create() + .setRole(roleFromObject(axObject)) + .release(); + + if (!axObject->computedLabel().isEmpty()) + axNode->setName(axObject->computedLabel()); + if (!axObject->stringValue().isEmpty()) + axNode->setValue(JSON::Value::create(axObject->stringValue())); + if (!axObject->accessibilityDescription().isEmpty()) + axNode->setDescription(axObject->accessibilityDescription()); + if (!axObject->keyShortcutsValue().isEmpty()) + axNode->setKeyshortcuts(axObject->keyShortcutsValue()); + if (!axObject->valueDescription().isEmpty()) + axNode->setValuetext(axObject->valueDescription()); + if (!axObject->roleDescription().isEmpty()) + axNode->setRoledescription(axObject->roleDescription()); + if (!axObject->isEnabled()) + axNode->setDisabled(!axObject->isEnabled()); + if (axObject->supportsExpanded()) + axNode->setExpanded(axObject->isExpanded()); + if (axObject->isFocused()) + axNode->setFocused(axObject->isFocused()); + if (axObject->isModalNode()) + axNode->setModal(axObject->isModalNode()); + bool multiline = axObject->ariaIsMultiline() || axObject->roleValue() == AccessibilityRole::TextArea; + if (multiline) + axNode->setMultiline(multiline); + if (axObject->isMultiSelectable()) + axNode->setMultiselectable(axObject->isMultiSelectable()); + if (axObject->supportsReadOnly() && !axObject->canSetValueAttribute() && axObject->isEnabled()) + axNode->setReadonly(true); + if (axObject->supportsRequiredAttribute()) + axNode->setRequired(axObject->isRequired()); + if (axObject->isSelected()) + axNode->setSelected(axObject->isSelected()); + if (axObject->supportsChecked()) { + AccessibilityButtonState checkedState = axObject->checkboxOrRadioValue(); + switch (checkedState) { + case AccessibilityButtonState::On: + axNode->setChecked(Inspector::Protocol::Page::AXNode::Checked::True); + break; + case AccessibilityButtonState::Off: + axNode->setChecked(Inspector::Protocol::Page::AXNode::Checked::False); + break; + case AccessibilityButtonState::Mixed: + axNode->setChecked(Inspector::Protocol::Page::AXNode::Checked::Mixed); + break; + } + } + if (axObject->supportsPressed()) { + AccessibilityButtonState checkedState = axObject->checkboxOrRadioValue(); + switch (checkedState) { + case AccessibilityButtonState::On: + axNode->setPressed(Inspector::Protocol::Page::AXNode::Pressed::True); + break; + case AccessibilityButtonState::Off: + axNode->setPressed(Inspector::Protocol::Page::AXNode::Pressed::False); + break; + case AccessibilityButtonState::Mixed: + axNode->setPressed(Inspector::Protocol::Page::AXNode::Pressed::Mixed); + break; + } + } + unsigned level = axObject->hierarchicalLevel() ? axObject->hierarchicalLevel() : axObject->headingLevel(); + if (level) + axNode->setLevel(level); + if (axObject->minValueForRange() != 0) + axNode->setValuemin(axObject->minValueForRange()); + if (axObject->maxValueForRange() != 0) + axNode->setValuemax(axObject->maxValueForRange()); + if (axObject->supportsAutoComplete()) + axNode->setAutocomplete(axObject->autoCompleteValue()); + if (axObject->hasPopup()) + axNode->setHaspopup(axObject->popupValue()); + + String invalidValue = axObject->invalidStatus(); + if (invalidValue != "false") { + if (invalidValue == "grammar") + axNode->setInvalid(Inspector::Protocol::Page::AXNode::Invalid::Grammar); + else if (invalidValue == "spelling") + axNode->setInvalid(Inspector::Protocol::Page::AXNode::Invalid::Spelling); + else // Future versions of ARIA may allow additional truthy values. Ex. format, order, or size. + axNode->setInvalid(Inspector::Protocol::Page::AXNode::Invalid::True); + } + switch (axObject->orientation()) { + case AccessibilityOrientation::Undefined: + break; + case AccessibilityOrientation::Vertical: + axNode->setOrientation("vertical"_s); + break; + case AccessibilityOrientation::Horizontal: + axNode->setOrientation("horizontal"_s); + break; + } + + if (axObject->isKeyboardFocusable()) + axNode->setFocusable(axObject->isKeyboardFocusable()); + + if (nodeToFind && axObject->node() == nodeToFind) + axNode->setFound(true); + + if (!axObject->children().isEmpty()) { + Ref> children = JSON::ArrayOf::create(); + for (auto& childObject : axObject->children()) + children->addItem(snapshotForAXObject(childObject, nodeToFind)); + axNode->setChildren(WTFMove(children)); + } + return axNode; +} + + +Protocol::ErrorStringOr> InspectorPageAgent::accessibilitySnapshot(const String& objectId) +{ + if (!WebCore::AXObjectCache::accessibilityEnabled()) + WebCore::AXObjectCache::enableAccessibility(); + 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 axNode = snapshotForAXObject(RefPtr { axObject }, node); + m_doingAccessibilitySnapshot = false; + return axNode; +} + +Protocol::ErrorStringOr InspectorPageAgent::setInterceptFileChooserDialog(bool enabled) +{ + m_interceptFileChooserDialog = enabled; + return { }; +} + +Protocol::ErrorStringOr InspectorPageAgent::setDefaultBackgroundColorOverride(RefPtr&& color) +{ + FrameView* view = m_inspectedPage.mainFrame().view(); + if (!view) + return makeUnexpected("Internal error: No frame view to set color two"_s); + + if (!color) { + view->updateBackgroundRecursively(std::optional()); + return { }; + } + + view->updateBackgroundRecursively(InspectorDOMAgent::parseColor(WTFMove(color))); + return { }; +} + +Protocol::ErrorStringOr InspectorPageAgent::createUserWorld(const String& name) +{ + if (createdUserWorlds().contains(name)) + return makeUnexpected("World with the given name already exists"_s); + + Ref world = ScriptController::createWorld(name, ScriptController::WorldType::User); + ensureUserWorldsExistInAllFrames({world.ptr()}); + createdUserWorlds().set(name, WTFMove(world)); + return { }; +} + +void InspectorPageAgent::ensureUserWorldsExistInAllFrames(const Vector& worlds) +{ + for (Frame* frame = &m_inspectedPage.mainFrame(); frame; frame = frame->tree().traverseNext()) { + for (auto* world : worlds) + frame->windowProxy().jsWindowProxy(*world)->window(); + } +} + +Protocol::ErrorStringOr InspectorPageAgent::setBypassCSP(bool enabled) +{ + m_bypassCSP = enabled; + return { }; +} + +Protocol::ErrorStringOr InspectorPageAgent::crash() +{ + CRASH(); + return { }; +} + +Protocol::ErrorStringOr InspectorPageAgent::setOrientationOverride(std::optional&& angle) +{ +#if ENABLE(ORIENTATION_EVENTS) + m_inspectedPage.setOverrideOrientation(WTFMove(angle)); + return { }; +#else + UNUSED_PARAM(angle); + return makeUnexpected("Orientation events are disabled in this build"); #endif +} + +static std::optional parseInsets(RefPtr&& insets) +{ + std::optional top = insets->getDouble("top"); + std::optional right = insets->getDouble("right"); + std::optional bottom = insets->getDouble("bottom"); + std::optional left = insets->getDouble("left"); + if (top && right && bottom && left) + return FloatBoxExtent(static_cast(*top), static_cast(*right), static_cast(*bottom), static_cast(*left)); + return std::optional(); +} + +static std::optional parseRect(RefPtr&& insets) +{ + std::optional x = insets->getDouble("x"); + std::optional y = insets->getDouble("y"); + std::optional width = insets->getDouble("width"); + std::optional height = insets->getDouble("height"); + if (x && y && width && height) + return FloatRect(static_cast(*x), static_cast(*y), static_cast(*width), static_cast(*height)); + return std::optional(); +} + +Protocol::ErrorStringOr InspectorPageAgent::setVisibleContentRects(RefPtr&& unobscuredContentRect, RefPtr&& contentInsets, RefPtr&& obscuredInsets, RefPtr&& 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 ucr = parseRect(WTFMove(unobscuredContentRect)); + if (!ucr) + return makeUnexpected("Invalid unobscured content rect"); + + view->setUnobscuredContentSize(FloatSize(ucr->width(), ucr->height())); + } + + if (contentInsets) { + std::optional ci = parseInsets(WTFMove(contentInsets)); + if (!ci) + return makeUnexpected("Invalid content insets"); + + m_inspectedPage.setContentInsets(*ci); + } + + if (obscuredInsets) { + std::optional oi = parseInsets(WTFMove(obscuredInsets)); + if (!oi) + return makeUnexpected("Invalid obscured insets"); + + m_inspectedPage.setObscuredInsets(*oi); + } + + if (unobscuredInsets) { + std::optional ui = parseInsets(WTFMove(unobscuredInsets)); + if (!ui) + return makeUnexpected("Invalid unobscured insets"); + + m_inspectedPage.setUnobscuredSafeAreaInsets(*ui); + } + return {}; +} + +Protocol::ErrorStringOr 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 #include #include #include #include +namespace Inspector { +class InjectedScriptManager; +} + namespace WebCore { class DOMWrapperWorld; class DocumentLoader; class Frame; +class HTMLInputElement; class InspectorClient; class InspectorOverlay; class Page; @@ -69,12 +75,14 @@ public: PingResource, BeaconResource, WebSocketResource, + EventSource, #if ENABLE(APPLICATION_MANIFEST) ApplicationManifestResource, #endif OtherResource, }; + WEBCORE_EXPORT static String makeFrameID(ProcessIdentifier processID, FrameIdentifier frameID); static bool sharedBufferContent(RefPtr&&, const String& textEncodingName, bool withBase64Encode, String* result); static Vector cachedResourcesForFrame(Frame*); static void resourceContent(Inspector::Protocol::ErrorString&, Frame*, const URL&, String* result, bool* base64Encoded); @@ -95,15 +103,18 @@ public: Inspector::Protocol::ErrorStringOr enable(); Inspector::Protocol::ErrorStringOr disable(); Inspector::Protocol::ErrorStringOr reload(std::optional&& ignoreCache, std::optional&& revalidateAllResources); + Inspector::Protocol::ErrorStringOr goBack(); + Inspector::Protocol::ErrorStringOr goForward(); Inspector::Protocol::ErrorStringOr navigate(const String& url); Inspector::Protocol::ErrorStringOr overrideUserAgent(const String&); + Inspector::Protocol::ErrorStringOr overridePlatform(const String&); Inspector::Protocol::ErrorStringOr overrideSetting(Inspector::Protocol::Page::Setting, std::optional&& value); Inspector::Protocol::ErrorStringOr>> getCookies(); Inspector::Protocol::ErrorStringOr setCookie(Ref&&); Inspector::Protocol::ErrorStringOr deleteCookie(const String& cookieName, const String& url); Inspector::Protocol::ErrorStringOr> getResourceTree(); Inspector::Protocol::ErrorStringOr> getResourceContent(const Inspector::Protocol::Network::FrameId&, const String& url); - Inspector::Protocol::ErrorStringOr setBootstrapScript(const String& source); + Inspector::Protocol::ErrorStringOr setBootstrapScript(const String& source, const String& worldName); Inspector::Protocol::ErrorStringOr>> searchInResource(const Inspector::Protocol::Network::FrameId&, const String& url, const String& query, std::optional&& caseSensitive, std::optional&& isRegex, const Inspector::Protocol::Network::RequestId&); Inspector::Protocol::ErrorStringOr>> searchInResources(const String&, std::optional&& caseSensitive, std::optional&& isRegex); #if !PLATFORM(IOS_FAMILY) @@ -114,35 +125,55 @@ public: #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) Inspector::Protocol::ErrorStringOr setForcedAppearance(std::optional&&); #endif + Inspector::Protocol::ErrorStringOr setForcedReducedMotion(std::optional&&); + Inspector::Protocol::ErrorStringOr setTimeZone(const String&); + Inspector::Protocol::ErrorStringOr setTouchEmulationEnabled(bool); Inspector::Protocol::ErrorStringOr snapshotNode(Inspector::Protocol::DOM::NodeId); - Inspector::Protocol::ErrorStringOr snapshotRect(int x, int y, int width, int height, Inspector::Protocol::Page::CoordinateSystem); + Inspector::Protocol::ErrorStringOr snapshotRect(int x, int y, int width, int height, Inspector::Protocol::Page::CoordinateSystem, std::optional&& omitDeviceScaleFactor); #if ENABLE(WEB_ARCHIVE) && USE(CF) Inspector::Protocol::ErrorStringOr archive(); #endif -#if !PLATFORM(COCOA) Inspector::Protocol::ErrorStringOr setScreenSizeOverride(std::optional&& width, std::optional&& height); -#endif + + Inspector::Protocol::ErrorStringOr insertText(const String& text); + Inspector::Protocol::ErrorStringOr setComposition(const String& text, int selectionStart, int selectionLength, std::optional&& replacementStart, std::optional&& replacementLength); + Inspector::Protocol::ErrorStringOr> accessibilitySnapshot(const String& objectId); + Inspector::Protocol::ErrorStringOr setInterceptFileChooserDialog(bool enabled); + Inspector::Protocol::ErrorStringOr setDefaultBackgroundColorOverride(RefPtr&&); + Inspector::Protocol::ErrorStringOr createUserWorld(const String&); + Inspector::Protocol::ErrorStringOr setBypassCSP(bool); + Inspector::Protocol::ErrorStringOr crash(); + Inspector::Protocol::ErrorStringOr setOrientationOverride(std::optional&& angle); + Inspector::Protocol::ErrorStringOr setVisibleContentRects(RefPtr&& unobscuredContentRect, RefPtr&& contentInsets, RefPtr&& obscuredInsets, RefPtr&& unobscuredInsets); + Inspector::Protocol::ErrorStringOr 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&); 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 m_backendDispatcher; Page& m_inspectedPage; + Inspector::InjectedScriptManager& m_injectedScriptManager; InspectorClient* m_client { nullptr }; InspectorOverlay* m_overlay { nullptr }; - // FIXME: Make a WeakHashMap and use it for m_frameToIdentifier and m_loaderToIdentifier. - HashMap m_frameToIdentifier; HashMap> m_identifierToFrame; - HashMap m_loaderToIdentifier; + HashMap 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(proxy.scriptExecutionContext())); + Document& document = downcast(*proxy.scriptExecutionContext()); + auto* pageAgent = m_instrumentingAgents.enabledPageAgent(); + m_frontendDispatcher->workerCreated(proxy.identifier(), proxy.url().string(), proxy.name(), + pageAgent ? pageAgent->frameId(document.frame()) : emptyString()); } void InspectorWorkerAgent::disconnectFromWorkerInspectorProxy(WorkerInspectorProxy& proxy) diff --git a/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp b/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp index 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::optional /* wasThrown */, std::optional /* savedResultIndex */>> PageDebuggerAgent::evaluateOnCallFrame(const Protocol::Debugger::CallFrameId& callFrameId, const String& expression, const String& objectGroup, std::optional&& includeCommandLineAPI, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& saveResult, std::optional&& emulateUserGesture) { - UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture); + InjectedScript injectedScript = injectedScriptManager().injectedScriptForObjectId(callFrameId); + JSC::JSGlobalObject* globalObject = injectedScript.globalObject(); + Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr; + auto shouldEmulateUserGesture = emulateUserGesture && *emulateUserGesture; + UserGestureEmulationScope userGestureScope(m_inspectedPage, shouldEmulateUserGesture, document); return WebDebuggerAgent::evaluateOnCallFrame(callFrameId, expression, objectGroup, WTFMove(includeCommandLineAPI), WTFMove(doNotPauseOnExceptionsAndMuteConsole), WTFMove(returnByValue), WTFMove(generatePreview), WTFMove(saveResult), WTFMove(emulateUserGesture)); } @@ -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(m_inspectedPage, true)); + m_breakpointActionUserGestureEmulationScopeStack.append(makeUniqueRef(m_inspectedPage, true, nullptr)); } void PageDebuggerAgent::debuggerDidEvaluate(JSC::Debugger&, const JSC::Breakpoint::Action& action) diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp index 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&& executionContextId) { if (!executionContextId) { @@ -191,14 +202,24 @@ void PageRuntimeAgent::notifyContextCreated(const Protocol::Network::FrameId& fr Protocol::ErrorStringOr, std::optional /* wasThrown */, std::optional /* savedResultIndex */>> PageRuntimeAgent::evaluate(const String& expression, const String& objectGroup, std::optional&& includeCommandLineAPI, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& executionContextId, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& saveResult, std::optional&& emulateUserGesture) { - UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture); + String errorString; + InjectedScript injectedScript = injectedScriptForEval(errorString, std::optional(executionContextId)); + if (!errorString.isEmpty()) + return makeUnexpected(errorString); + + JSC::JSGlobalObject* globalObject = injectedScript.globalObject(); + Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr; + UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture, document); return InspectorRuntimeAgent::evaluate(expression, objectGroup, WTFMove(includeCommandLineAPI), WTFMove(doNotPauseOnExceptionsAndMuteConsole), WTFMove(executionContextId), WTFMove(returnByValue), WTFMove(generatePreview), WTFMove(saveResult), WTFMove(emulateUserGesture)); } -Protocol::ErrorStringOr, std::optional /* wasThrown */>> PageRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& expression, RefPtr&& optionalArguments, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& emulateUserGesture) +void PageRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& expression, RefPtr&& optionalArguments, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& emulateUserGesture, std::optional&& awaitPromise, Ref&& 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 enable(); - Inspector::Protocol::ErrorStringOr disable(); - Inspector::Protocol::ErrorStringOr, std::optional /* wasThrown */, std::optional /* savedResultIndex */>> evaluate(const String& expression, const String& objectGroup, std::optional&& includeCommandLineAPI, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&&, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& saveResult, std::optional&& emulateUserGesture); - Inspector::Protocol::ErrorStringOr, std::optional /* wasThrown */>> callFunctionOn(const Inspector::Protocol::Runtime::RemoteObjectId&, const String& expression, RefPtr&& arguments, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& emulateUserGesture); + Inspector::Protocol::ErrorStringOr enable() override; + Inspector::Protocol::ErrorStringOr disable() override; + Inspector::Protocol::ErrorStringOr, std::optional /* wasThrown */, std::optional /* savedResultIndex */>> evaluate(const String& expression, const String& objectGroup, std::optional&& includeCommandLineAPI, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&&, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& saveResult, std::optional&& emulateUserGesture) override; + void callFunctionOn(const Inspector::Protocol::Runtime::RemoteObjectId&, const String& functionDeclaration, RefPtr&& arguments, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& emulateUserGesture, std::optional&& awaitPromise, Ref&&) override; // InspectorInstrumentation void frameNavigated(Frame&); void didClearWindowObjectInWorld(Frame&, DOMWrapperWorld&); + void didReceiveMainResourceError(Frame&); private: - Inspector::InjectedScript injectedScriptForEval(Inspector::Protocol::ErrorString&, std::optional&&); - void muteConsole(); - void unmuteConsole(); + Inspector::InjectedScript injectedScriptForEval(Inspector::Protocol::ErrorString&, std::optional&&) 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 m_frontendDispatcher; RefPtr m_backendDispatcher; - InstrumentingAgents& m_instrumentingAgents; Page& m_inspectedPage; diff --git a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp index 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(ProcessingUserGesture) : std::nullopt) + , m_gestureIndicator(emulateUserGesture ? std::optional(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 { 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 c3d8450f71c2c373d2af1cccfb215ad81bf80d0b..fe236968bb014fb055b45ad61ba221c7d8110148 100644 --- a/Source/WebCore/loader/DocumentLoader.cpp +++ b/Source/WebCore/loader/DocumentLoader.cpp @@ -1471,8 +1471,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 fbf545c460e4e489d87b25c0e85eccca4cbf3c87..89e3cbe6a430d019a5acf59899551a9a80d827ab 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 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 5661083805664e0119f11ffc32ea7e1927fc657b..51c1bff669efa35f54f8f0b75a0527bb97071ab3 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 { *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, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler&& 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 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() @@ -3195,6 +3204,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) @@ -3962,9 +3973,6 @@ String FrameLoader::referrer() const void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() { - if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript)) - return; - Vector> worlds; ScriptController::getAllWorlds(worlds); for (auto& world : worlds) @@ -3973,13 +3981,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&&) = 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 @@ -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 f239145706d0b1905410ad8e66cfe9900cdc76ee..c1fbeb8ce16a31c756f2f85babcdd58497b64140 100644 --- a/Source/WebCore/page/ChromeClient.h +++ b/Source/WebCore/page/ChromeClient.h @@ -307,7 +307,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 ec3e420e79bb1b5dcf701355d1ace69bf8864151..7ba5d7e5db457bb3eb0f4ecef6d95b8ae70540dc 100644 --- a/Source/WebCore/page/EventHandler.cpp +++ b/Source/WebCore/page/EventHandler.cpp @@ -139,6 +139,7 @@ #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS) #include "PlatformTouchEvent.h" +#include "PointerCaptureController.h" #endif #if ENABLE(MAC_GESTURE_EVENTS) @@ -798,9 +799,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; @@ -840,8 +839,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 @@ -863,8 +860,10 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e Ref protectedFrame(m_frame); +#if ENABLE(DRAG_SUPPORT) if (handleDrag(event, checkDragHysteresis)) return true; +#endif RefPtr targetNode = event.targetNode(); if (event.event().button() != LeftButton || !targetNode) @@ -885,7 +884,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); @@ -902,6 +903,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 @@ -933,6 +936,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()) @@ -1027,7 +1032,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() { @@ -1075,9 +1079,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; @@ -2044,10 +2046,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; } @@ -4108,7 +4108,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) { @@ -4515,7 +4522,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()); @@ -4642,6 +4650,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 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 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, UniqueRefinit(); + InspectorInstrumentation::frameAttached(this); } Ref Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, UniqueRef&& 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 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 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(unscaledSearchRadius * ppiFactor / scale); + + if (approximateNode && shouldApproximate == ShouldApproximate::Yes) { + const float testOffsets[] = { + -.3f, -.3f, + -.6f, -.6f, + +.3f, +.3f, + -.9f, -.9f, + }; + + Node* originalApproximateNode = approximateNode; + for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) { + IntSize testOffset(testOffsets[n] * searchRadius, testOffsets[n + 1] * searchRadius); + IntPoint testPoint = testCenter + testOffset; + + constexpr OptionSet hitType { HitTestRequest::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(node)) + return false; + + auto& element = downcast(node); + if (element.isMouseFocusable()) + return true; + + if (RefPtr shadowRoot = element.shadowRoot()) { + if (shadowRoot->delegatesFocus()) { + for (auto& node : composedTreeDescendants(element)) { + if (is(node) && downcast(node).isMouseFocusable()) + return true; + } + } + } + + return false; +} + +static bool nodeWillRespondToMouseEvents(Node& node) +{ + return node.willRespondToMouseClickEvents() || node.willRespondToMouseMoveEvents() || nodeIsMouseFocusable(node); +} + +Node* Frame::approximateNodeAtViewportLocationLegacy(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation) +{ + // This function is only used for UIWebView. + auto&& ancestorRespondingToClickEvents = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { + bool bodyHasBeenReached = false; + bool pointerCursorStillValid = true; + + if (nodeBounds) + *nodeBounds = IntRect(); + + auto node = hitTestResult.innerNode(); + if (!node) + return nullptr; + + Node* pointerCursorNode = nullptr; + for (; node && node != terminationNode; node = node->parentInComposedTree()) { + // We only accept pointer nodes before reaching the body tag. + if (node->hasTagName(HTMLNames::bodyTag)) { + // Make sure we cover the case of an empty editable body. + if (!pointerCursorNode && node->isContentEditable()) + pointerCursorNode = node; + bodyHasBeenReached = true; + pointerCursorStillValid = false; + } + + // If we already have a pointer, and we reach a table, don't accept it. + if (pointerCursorNode && (node->hasTagName(HTMLNames::tableTag) || node->hasTagName(HTMLNames::tbodyTag))) + pointerCursorStillValid = false; + + // If we haven't reached the body, and we are still paying attention to pointer cursors, and the node has a pointer cursor. + if (pointerCursorStillValid && node->renderStyle() && node->renderStyle()->cursor() == CursorType::Pointer) + pointerCursorNode = node; + else if (pointerCursorNode) { + // We want the lowest unbroken chain of pointer cursors. + pointerCursorStillValid = false; + } + + if (nodeWillRespondToMouseEvents(*node)) { + // If we're at the body or higher, use the pointer cursor node (which may be null). + if (bodyHasBeenReached) + node = pointerCursorNode; + + // If we are interested about the frame, use it. + if (nodeBounds) { + // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check. + if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && is(*node)) + *nodeBounds = snappedIntRect(downcast(*node).computeRect(hitTestResult.innerNonSharedNode()->renderer())); + else if (node && node->renderer()) + *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true); + } + + return node; + } + } + + return nullptr; + }; + + return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToClickEvents), ShouldApproximate::Yes); +} + +static inline NodeQualifier ancestorRespondingToClickEventsNodeQualifier(SecurityOrigin* securityOrigin = nullptr) +{ + return [securityOrigin](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { + if (nodeBounds) + *nodeBounds = IntRect(); + + auto node = hitTestResult.innerNode(); + if (!node || (securityOrigin && !securityOrigin->isSameOriginAs(node->document().securityOrigin()))) + return nullptr; + + for (; node && node != terminationNode; node = node->parentInComposedTree()) { + if (nodeWillRespondToMouseEvents(*node)) { + // If we are interested about the frame, use it. + if (nodeBounds) { + // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check. + if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && is(*node)) + *nodeBounds = snappedIntRect(downcast(*node).computeRect(hitTestResult.innerNonSharedNode()->renderer())); + else if (node && node->renderer()) + *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true); + } + + return node; + } + } + + return nullptr; + }; +} + +Node* Frame::nodeRespondingToClickEvents(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, SecurityOrigin* securityOrigin) +{ + return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, ancestorRespondingToClickEventsNodeQualifier(securityOrigin), ShouldApproximate::Yes); +} + +Node* Frame::nodeRespondingToDoubleClickEvent(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation) +{ + auto&& ancestorRespondingToDoubleClickEvent = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { + if (nodeBounds) + *nodeBounds = IntRect(); + + auto* node = hitTestResult.innerNode(); + if (!node) + return nullptr; + + for (; node && node != terminationNode; node = node->parentInComposedTree()) { + if (!node->hasEventListeners(eventNames().dblclickEvent)) + continue; +#if ENABLE(TOUCH_EVENTS) + if (!node->allowsDoubleTapGesture()) + continue; +#endif + if (nodeBounds && node->renderer()) + *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true); + return node; + } + return nullptr; + }; + + return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToDoubleClickEvent), ShouldApproximate::Yes); +} + +Node* Frame::nodeRespondingToInteraction(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation) +{ + return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, ancestorRespondingToClickEventsNodeQualifier(), ShouldApproximate::Yes, ShouldFindRootEditableElement::No); +} + +Node* Frame::nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation) +{ + auto&& ancestorRespondingToScrollWheelEvents = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { + if (nodeBounds) + *nodeBounds = IntRect(); + + Node* scrollingAncestor = nullptr; + for (Node* node = hitTestResult.innerNode(); node && node != terminationNode && !node->hasTagName(HTMLNames::bodyTag); node = node->parentNode()) { + RenderObject* renderer = node->renderer(); + if (!renderer) + continue; + + if ((renderer->isTextField() || renderer->isTextArea()) && downcast(*renderer).canScroll()) { + scrollingAncestor = node; + continue; + } + + auto& style = renderer->style(); + + if (renderer->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; #endif +using NodeQualifier = Function; // 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 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 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 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 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 History::stateObjectAdded(RefPtr&& data if (!urlString.isEmpty()) frame->document()->updateURLForPushOrReplaceState(fullURL); + InspectorInstrumentation::didNavigateWithinPage(*frame); if (stateObjectType == StateObjectType::Push) { frame->loader().history().pushState(WTFMove(data), title, fullURL.string()); diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp index 5706ad8628fb9bb2c4986535c632d9d2dac913ef..cf5423977557246093b0fced615919d9e740d04c 100644 --- a/Source/WebCore/page/Page.cpp +++ b/Source/WebCore/page/Page.cpp @@ -468,6 +468,37 @@ void Page::setOverrideViewportArguments(const std::optional& document->updateViewportArguments(); } +FloatSize Page::screenSize() +{ + return m_overrideScreenSize.value_or(screenRect(mainFrame().view()).size()); +} + +void Page::setOverrideScreenSize(std::optional size) +{ + if (size == m_overrideScreenSize) + return; + + m_overrideScreenSize = size; + if (auto* document = mainFrame().document()) + document->updateViewportArguments(); +} + +#if ENABLE(ORIENTATION_EVENTS) +int Page::orientation() const +{ + return m_overrideOrientation.value_or(chrome().client().deviceOrientation()); +} + +void Page::setOverrideOrientation(std::optional orientation) +{ + if (orientation == m_overrideOrientation) + return; + + m_overrideOrientation = orientation; + mainFrame().orientationChanged(); +} +#endif + ScrollingCoordinator* Page::scrollingCoordinator() { if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) { @@ -1304,10 +1335,6 @@ void Page::didCommitLoad() m_isEditableRegionEnabled = false; #endif -#if HAVE(OS_DARK_MODE_SUPPORT) - setUseDarkAppearanceOverride(std::nullopt); -#endif - resetSeenPlugins(); resetSeenMediaEngines(); @@ -3311,6 +3338,16 @@ void Page::setUseDarkAppearanceOverride(std::optional valueOverride) #endif } +void Page::setUseReducedMotionOverride(std::optional 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 f1e08bc4fec074916a3733adff62071da4ed3856..2872273bc99139f04c2b6e3fed90090aa48100db 100644 --- a/Source/WebCore/page/Page.h +++ b/Source/WebCore/page/Page.h @@ -270,6 +270,9 @@ public: const std::optional& overrideViewportArguments() const { return m_overrideViewportArguments; } WEBCORE_EXPORT void setOverrideViewportArguments(const std::optional&); + WEBCORE_EXPORT FloatSize screenSize(); + void setOverrideScreenSize(std::optional size); + static void refreshPlugins(bool reload); WEBCORE_EXPORT PluginData& pluginData(); void clearPluginData(); @@ -322,6 +325,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) @@ -482,6 +489,8 @@ public: WEBCORE_EXPORT void effectiveAppearanceDidChange(bool useDarkAppearance, bool useElevatedUserInterfaceLevel); bool defaultUseDarkAppearance() const { return m_useDarkAppearance; } void setUseDarkAppearanceOverride(std::optional); + std::optional useReducedMotionOverride() const { return m_useReducedMotionOverride; } + void setUseReducedMotionOverride(std::optional); #if ENABLE(TEXT_AUTOSIZING) float textAutosizingWidth() const { return m_textAutosizingWidth; } @@ -877,6 +886,11 @@ public: WEBCORE_EXPORT Vector> editableElementsInRect(const FloatRect&) const; +#if ENABLE(ORIENTATION_EVENTS) + int orientation() const; + void setOverrideOrientation(std::optional); +#endif + #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) DeviceOrientationUpdateProvider* deviceOrientationUpdateProvider() const { return m_deviceOrientationUpdateProvider.get(); } #endif @@ -970,6 +984,9 @@ private: #if ENABLE(DRAG_SUPPORT) const std::unique_ptr m_dragController; +#if PLATFORM(MAC) + String m_overrideDragPasteboardName; +#endif #endif const std::unique_ptr m_focusController; #if ENABLE(CONTEXT_MENUS) @@ -1049,6 +1066,7 @@ private: bool m_useElevatedUserInterfaceLevel { false }; bool m_useDarkAppearance { false }; std::optional m_useDarkAppearanceOverride; + std::optional m_useReducedMotionOverride; #if ENABLE(TEXT_AUTOSIZING) float m_textAutosizingWidth { 0 }; @@ -1222,6 +1240,11 @@ private: #endif std::optional m_overrideViewportArguments; + std::optional m_overrideScreenSize; + +#if ENABLE(ORIENTATION_EVENTS) + std::optional m_overrideOrientation; +#endif #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) RefPtr m_deviceOrientationUpdateProvider; diff --git a/Source/WebCore/page/PointerCaptureController.cpp b/Source/WebCore/page/PointerCaptureController.cpp index 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 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 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 pendingTargetOverride; RefPtr targetOverride; -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) +#if ENABLE(TOUCH_EVENTS) RefPtr previousTarget; #endif bool hasAnyElement() const { diff --git a/Source/WebCore/page/RuntimeEnabledFeatures.cpp b/Source/WebCore/page/RuntimeEnabledFeatures.cpp index f90b8e6de036986779294cbb03c753ffcaf71801..af9672ae6605c341f2cbda8559e5441c1988a988 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 04bf9eee8a886cb14835cb9c7c4c0da3e0b898da..b32088fb96144fa7848a79f722af14a6ef873e2f 100644 --- a/Source/WebCore/page/RuntimeEnabledFeatures.h +++ b/Source/WebCore/page/RuntimeEnabledFeatures.h @@ -193,6 +193,7 @@ public: void setMouseEventsSimulationEnabled(bool isEnabled) { m_mouseEventsSimulationEnabled = isEnabled; } bool touchEventsEnabled() const; void setTouchEventsEnabled(bool isEnabled) { m_touchEventsEnabled = isEnabled; } + bool isTouchPrimaryInputDevice() const; #endif bool pageAtRuleSupportEnabled() const { return m_pageAtRuleSupportEnabled; } diff --git a/Source/WebCore/page/Screen.cpp b/Source/WebCore/page/Screen.cpp index 7ac11c8289347e3a2f3e7316cf9e32932b9544ed..764b2d4fe36ac2e5588bd22595424ac11d42acd0 100644 --- a/Source/WebCore/page/Screen.cpp +++ b/Source/WebCore/page/Screen.cpp @@ -102,6 +102,8 @@ int Screen::availLeft() const return 0; if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::AvailLeft); + if (frame->hasScreenSizeOverride()) + return 0; return static_cast(screenAvailableRect(frame->view()).x()); } @@ -112,6 +114,8 @@ int Screen::availTop() const return 0; if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::AvailTop); + if (frame->hasScreenSizeOverride()) + return 0; return static_cast(screenAvailableRect(frame->view()).y()); } @@ -122,6 +126,8 @@ unsigned Screen::availHeight() const return 0; if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::AvailHeight); + if (frame->hasScreenSizeOverride()) + return static_cast(frame->screenSize().height()); return static_cast(screenAvailableRect(frame->view()).height()); } @@ -132,6 +138,8 @@ unsigned Screen::availWidth() const return 0; if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::AvailWidth); + if (frame->hasScreenSizeOverride()) + return static_cast(frame->screenSize().width()); return static_cast(screenAvailableRect(frame->view()).width()); } diff --git a/Source/WebCore/page/SocketProvider.cpp b/Source/WebCore/page/SocketProvider.cpp index 3bec0aef174336939838fb1069fffbcb9f3d5604..566ef3806be3c5ccf1bb951251c2a90dba7071a3 100644 --- a/Source/WebCore/page/SocketProvider.cpp +++ b/Source/WebCore/page/SocketProvider.cpp @@ -33,7 +33,7 @@ namespace WebCore { Ref SocketProvider::createSocketStreamHandle(const URL& url, SocketStreamHandleClient& client, WebSocketIdentifier, PAL::SessionID sessionID, const String& credentialPartition, const StorageSessionProvider* provider) { - return SocketStreamHandleImpl::create(url, client, sessionID, credentialPartition, { }, provider); + return SocketStreamHandleImpl::create(url, false, client, sessionID, credentialPartition, { }, provider); } RefPtr SocketProvider::createWebSocketChannel(Document&, WebSocketChannelClient&) diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp index f15302bf8396b40ff1578c0cad124581a7736445..4a5271a0f7ece6baeef4e9e0c3f1f8df80c25be6 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 std::enable_if::value, bool>::type ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, Predicate&& predicate, Args&&... args) const { + if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext)) + return true; bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly; for (auto& policy : m_policies) { if (policy->isReportOnly() != isReportOnly) @@ -306,6 +308,8 @@ typename std::enable_if bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const { + if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext)) + return true; bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly; bool isAllowed = true; for (auto& policy : m_policies) { @@ -322,6 +326,8 @@ bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposit template bool ContentSecurityPolicy::allPoliciesAllow(ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const { + if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext)) + return true; bool isAllowed = true; for (auto& policy : m_policies) { if (const ContentSecurityPolicyDirective* violatedDirective = (policy.get()->*predicate)(std::forward(args)...)) { diff --git a/Source/WebCore/page/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 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 clientTypes; Vector> clientData; #endif -#if PLATFORM(GTK) +#if PLATFORM(GTK) || PLATFORM(WPE) String contentOrigin; bool canSmartCopyOrDelete; String text; String markup; #endif -#if USE(LIBWPE) - String text; - String markup; -#endif }; struct PasteboardURL { @@ -109,7 +105,7 @@ struct PasteboardURL { #if PLATFORM(MAC) String userVisibleForm; #endif -#if PLATFORM(GTK) +#if PLATFORM(GTK) || PLATFORM(WPE) String markup; #endif }; @@ -188,6 +184,11 @@ public: #endif #endif +#if PLATFORM(WPE) && ENABLE(DRAG_SUPPORT) + explicit Pasteboard(std::unique_ptr&&, SelectionData&); + explicit Pasteboard(std::unique_ptr&&, SelectionData&&); +#endif + #if PLATFORM(WIN) explicit Pasteboard(std::unique_ptr&&, IDataObject*); explicit Pasteboard(std::unique_ptr&&, WCDataObject*); @@ -253,6 +254,12 @@ public: static std::unique_ptr createForGlobalSelection(std::unique_ptr&&); #endif +#if PLATFORM(WPE) + const SelectionData& selectionData() const { + return *m_selectionData; + } +#endif + #if PLATFORM(IOS_FAMILY) explicit Pasteboard(std::unique_ptr&&, int64_t changeCount); explicit Pasteboard(std::unique_ptr&&, const String& pasteboardName); @@ -287,6 +294,7 @@ public: COMPtr dataObject() const { return m_dataObject; } void setExternalDataObject(IDataObject*); const DragDataMap& dragDataMap() const { return m_dragDataMap; } + WEBCORE_EXPORT DragDataMap createDragDataMap(); void writeURLToWritableDataObject(const URL&, const String&); COMPtr writableDataObject() const { return m_writableDataObject; } void writeImageToDataObject(Element&, const URL&); // FIXME: Layering violation. @@ -338,6 +346,10 @@ private: String m_name; #endif +#if PLATFORM(WPE) + std::optional m_selectionData; +#endif + #if PLATFORM(COCOA) String m_pasteboardName; int64_t m_changeCount; @@ -353,6 +365,7 @@ private: COMPtr m_dataObject; COMPtr m_writableDataObject; DragDataMap m_dragDataMap; + bool m_forDrag = false; #endif }; diff --git a/Source/WebCore/platform/PlatformKeyboardEvent.h b/Source/WebCore/platform/PlatformKeyboardEvent.h index 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&& 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 #endif +#if PLATFORM(WPE) || PLATFORM(WIN) +#include // Needed by jpeglib.h for FILE. +extern "C" { +#include "jpeglib.h" +} +#endif + namespace WebCore { #if !PLATFORM(GTK) @@ -65,8 +72,75 @@ static bool encodeImage(cairo_surface_t* image, const String& mimeType, Vector data(cairo_surface_t* image, const String& mimeType, std::optional) +static Vector encodeJpeg(cairo_surface_t* image, int quality) +{ + if (cairo_surface_get_type(image) != CAIRO_SURFACE_TYPE_IMAGE) { + fprintf(stderr, "Unexpected cairo surface type: %d\n", cairo_surface_get_type(image)); + return { }; + } + + if (cairo_image_surface_get_format(image) != CAIRO_FORMAT_ARGB32) { + fprintf(stderr, "Unexpected surface image format: %d\n", cairo_image_surface_get_format(image)); + return { }; + } + + struct jpeg_compress_struct info; + struct jpeg_error_mgr error; + info.err = jpeg_std_error(&error); + jpeg_create_compress(&info); + + unsigned char* bufferPtr = nullptr; + unsigned long bufferSize; + jpeg_mem_dest(&info, &bufferPtr, &bufferSize); + info.image_width = cairo_image_surface_get_width(image); + info.image_height = cairo_image_surface_get_height(image); + +#ifndef LIBJPEG_TURBO_VERSION + COMPILE_ASSERT(false, only_libjpeg_turbo_is_supported); +#endif + +#if CPU(LITTLE_ENDIAN) + info.in_color_space = JCS_EXT_BGRA; +#else + info.in_color_space = JCS_EXT_ARGB; +#endif + // # of color components in input image + info.input_components = 4; + + jpeg_set_defaults(&info); + jpeg_set_quality(&info, quality, true); + + jpeg_start_compress(&info, true); + + while (info.next_scanline < info.image_height) + { + JSAMPROW row = cairo_image_surface_get_data(image) + (info.next_scanline * cairo_image_surface_get_stride(image)); + if (jpeg_write_scanlines(&info, &row, 1) != 1) { + fprintf(stderr, "JPEG library failed to encode line\n"); + break; + } + } + + jpeg_finish_compress(&info); + jpeg_destroy_compress(&info); + + Vector output; + output.append(bufferPtr, bufferSize); + // Cannot use unique_ptr as bufferPtr changes during compression. GUniquePtr would work + // but it's under GLib and won't work on Windows. + free(bufferPtr); + return output; +} + +Vector data(cairo_surface_t* image, const String& mimeType, std::optional quality) { + if (mimeType == "image/jpeg") { + int qualityPercent = 100; + if (quality) + qualityPercent = static_cast(*quality * 100.0 + 0.5); + return encodeJpeg(image, qualityPercent); + } + Vector encodedImage; if (!image || !encodeImage(image, mimeType, &encodedImage)) return { }; diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h index 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 utiFromImageBufferMIMEType(const String&); -Vector data(CGImageRef, CFStringRef destinationUTI, std::optional quality); +WEBCORE_EXPORT Vector data(CGImageRef, CFStringRef destinationUTI, std::optional quality); Vector data(const PixelBuffer&, const String& mimeType, std::optional quality); WEBCORE_EXPORT String dataURL(CGImageRef, CFStringRef destinationUTI, const String& mimeType, std::optional quality); diff --git a/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h index 5e321c7193b9cad45721460c7eb438e0b70042b7..69ced7fa6ee71248a38a1b50d5dce4b56f1d906a 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/filters/software/FEConvolveMatrixSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.h index 24d6c08da79c177cad8717af8c9d2229c2defe81..17f49c8074df6d2b55ee5710b15117fe7c37b6b8 100644 --- a/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.h +++ b/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.h @@ -24,7 +24,10 @@ #pragma once #include "FilterEffectApplier.h" +#include "IntPoint.h" +#include "IntSize.h" #include +#include namespace WebCore { diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp index 2e46b61536c835dfcacf9f79e10e6d59ae7a3836..fa0c72d80d83c58a8407e78988de010fe97d7c38 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 stringIndicesFromClusters(const Vector& clusters, return stringIndices; } +static int compactScriptItemsIfNeeded(const UChar* cp, unsigned stringLength, Vector& items, int numItems, const Font* font) +{ + // https://bugs.webkit.org/show_bug.cgi?id=201214 + // Uniscribe is overly aggressive in separating the runs. It'll split "3d_rotation" into "3", "d", "_" and "rotation" and we + // will ScriptShape them separately. As a result, a ligature for "3d_rotation" in the Material icon set + // (https://www.materialui.co/icon/3d-rotation) will not be used. A quick and dirty hack is to glue them back here, only making + // this apply to the readable characters, digits and _. + + if (!numItems) + return numItems; + + if (font->platformData().isSystemFont() || font->platformData().hasVariations()) + return numItems; + + bool allGoodCharacters = true; + for (unsigned i = 0; allGoodCharacters && i < stringLength; ++i) { + const UChar c = cp[i]; + allGoodCharacters = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_'; + } + if (!allGoodCharacters) + return numItems; + + // Consume entire string into a single run. |items| is at least numItems + 1 long. + items[1] = items[numItems]; + return 1; +} + void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned stringLength, unsigned stringLocation, const Font* font) { if (!font) { @@ -201,6 +228,8 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, } items.resize(numItems + 1); + numItems = compactScriptItemsIfNeeded(cp, stringLength, items, numItems, font); + for (int i = 0; i < numItems; i++) { // Determine the string for this item. const UChar* str = cp + items[i].iCharPos; diff --git a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp index 0516e70973e0078de6ad0216375d34dd9ef51a8d..ffd9a02deb5518e0c8c77b156815c11eb4b16829 100644 --- a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp +++ b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp @@ -37,8 +37,10 @@ #include "WindowsKeyboardCodes.h" #include #include +#include #include #include +#include namespace WebCore { @@ -1294,6 +1296,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode) } +static const HashMap& gdkToWindowsKeyCodeMap() +{ + static HashMap* result; + static std::once_flag once; + std::call_once( + once, + [] { + const unsigned gdkKeyCodes[] = { + GDK_KEY_Cancel, + // FIXME: non-keypad keys should take precedence, so we skip GDK_KEY_KP_* + // GDK_KEY_KP_0, + // GDK_KEY_KP_1, + // GDK_KEY_KP_2, + // GDK_KEY_KP_3, + // GDK_KEY_KP_4, + // GDK_KEY_KP_5, + // GDK_KEY_KP_6, + // GDK_KEY_KP_7, + // GDK_KEY_KP_8, + // GDK_KEY_KP_9, + // GDK_KEY_KP_Multiply, + // GDK_KEY_KP_Add, + // GDK_KEY_KP_Subtract, + // GDK_KEY_KP_Decimal, + // GDK_KEY_KP_Divide, + // GDK_KEY_KP_Page_Up, + // GDK_KEY_KP_Page_Down, + // GDK_KEY_KP_End, + // GDK_KEY_KP_Home, + // GDK_KEY_KP_Left, + // GDK_KEY_KP_Up, + // GDK_KEY_KP_Right, + // GDK_KEY_KP_Down, + GDK_KEY_BackSpace, + // GDK_KEY_ISO_Left_Tab, + // GDK_KEY_3270_BackTab, + GDK_KEY_Tab, + GDK_KEY_Clear, + // GDK_KEY_ISO_Enter, + // GDK_KEY_KP_Enter, + GDK_KEY_Return, + GDK_KEY_Menu, + GDK_KEY_Pause, + GDK_KEY_AudioPause, + GDK_KEY_Caps_Lock, + GDK_KEY_Kana_Lock, + GDK_KEY_Kana_Shift, + GDK_KEY_Hangul, + GDK_KEY_Hangul_Hanja, + GDK_KEY_Kanji, + GDK_KEY_Escape, + GDK_KEY_space, + GDK_KEY_Page_Up, + GDK_KEY_Page_Down, + GDK_KEY_End, + GDK_KEY_Home, + GDK_KEY_Left, + GDK_KEY_Up, + GDK_KEY_Right, + GDK_KEY_Down, + GDK_KEY_Select, + GDK_KEY_Print, + GDK_KEY_Execute, + GDK_KEY_Insert, + GDK_KEY_KP_Insert, + GDK_KEY_Delete, + GDK_KEY_KP_Delete, + GDK_KEY_Help, + GDK_KEY_0, + GDK_KEY_parenright, + GDK_KEY_1, + GDK_KEY_exclam, + GDK_KEY_2, + GDK_KEY_at, + GDK_KEY_3, + GDK_KEY_numbersign, + GDK_KEY_4, + GDK_KEY_dollar, + GDK_KEY_5, + GDK_KEY_percent, + GDK_KEY_6, + GDK_KEY_asciicircum, + GDK_KEY_7, + GDK_KEY_ampersand, + GDK_KEY_8, + GDK_KEY_asterisk, + GDK_KEY_9, + GDK_KEY_parenleft, + GDK_KEY_a, + GDK_KEY_A, + GDK_KEY_b, + GDK_KEY_B, + GDK_KEY_c, + GDK_KEY_C, + GDK_KEY_d, + GDK_KEY_D, + GDK_KEY_e, + GDK_KEY_E, + GDK_KEY_f, + GDK_KEY_F, + GDK_KEY_g, + GDK_KEY_G, + GDK_KEY_h, + GDK_KEY_H, + GDK_KEY_i, + GDK_KEY_I, + GDK_KEY_j, + GDK_KEY_J, + GDK_KEY_k, + GDK_KEY_K, + GDK_KEY_l, + GDK_KEY_L, + GDK_KEY_m, + GDK_KEY_M, + GDK_KEY_n, + GDK_KEY_N, + GDK_KEY_o, + GDK_KEY_O, + GDK_KEY_p, + GDK_KEY_P, + GDK_KEY_q, + GDK_KEY_Q, + GDK_KEY_r, + GDK_KEY_R, + GDK_KEY_s, + GDK_KEY_S, + GDK_KEY_t, + GDK_KEY_T, + GDK_KEY_u, + GDK_KEY_U, + GDK_KEY_v, + GDK_KEY_V, + GDK_KEY_w, + GDK_KEY_W, + GDK_KEY_x, + GDK_KEY_X, + GDK_KEY_y, + GDK_KEY_Y, + GDK_KEY_z, + GDK_KEY_Z, + GDK_KEY_Meta_L, + GDK_KEY_Meta_R, + GDK_KEY_Sleep, + GDK_KEY_Num_Lock, + GDK_KEY_Scroll_Lock, + GDK_KEY_Shift_L, + GDK_KEY_Shift_R, + GDK_KEY_Control_L, + GDK_KEY_Control_R, + GDK_KEY_Alt_L, + GDK_KEY_Alt_R, + GDK_KEY_Back, + GDK_KEY_Forward, + GDK_KEY_Refresh, + GDK_KEY_Stop, + GDK_KEY_Search, + GDK_KEY_Favorites, + GDK_KEY_HomePage, + GDK_KEY_AudioMute, + GDK_KEY_AudioLowerVolume, + GDK_KEY_AudioRaiseVolume, + GDK_KEY_AudioNext, + GDK_KEY_AudioPrev, + GDK_KEY_AudioStop, + GDK_KEY_AudioMedia, + GDK_KEY_semicolon, + GDK_KEY_colon, + GDK_KEY_plus, + GDK_KEY_equal, + GDK_KEY_comma, + GDK_KEY_less, + GDK_KEY_minus, + GDK_KEY_underscore, + GDK_KEY_period, + GDK_KEY_greater, + GDK_KEY_slash, + GDK_KEY_question, + GDK_KEY_asciitilde, + GDK_KEY_quoteleft, + GDK_KEY_bracketleft, + GDK_KEY_braceleft, + GDK_KEY_backslash, + GDK_KEY_bar, + GDK_KEY_bracketright, + GDK_KEY_braceright, + GDK_KEY_quoteright, + GDK_KEY_quotedbl, + GDK_KEY_AudioRewind, + GDK_KEY_AudioForward, + GDK_KEY_AudioPlay, + GDK_KEY_F1, + GDK_KEY_F2, + GDK_KEY_F3, + GDK_KEY_F4, + GDK_KEY_F5, + GDK_KEY_F6, + GDK_KEY_F7, + GDK_KEY_F8, + GDK_KEY_F9, + GDK_KEY_F10, + GDK_KEY_F11, + GDK_KEY_F12, + GDK_KEY_F13, + GDK_KEY_F14, + GDK_KEY_F15, + GDK_KEY_F16, + GDK_KEY_F17, + GDK_KEY_F18, + GDK_KEY_F19, + GDK_KEY_F20, + GDK_KEY_F21, + GDK_KEY_F22, + GDK_KEY_F23, + GDK_KEY_F24, + GDK_KEY_VoidSymbol, + GDK_KEY_Red, + GDK_KEY_Green, + GDK_KEY_Yellow, + GDK_KEY_Blue, + GDK_KEY_PowerOff, + GDK_KEY_AudioRecord, + GDK_KEY_Display, + GDK_KEY_Subtitle, + GDK_KEY_Video + }; + result = new HashMap(); + for (unsigned gdkKeyCode : gdkKeyCodes) { + int winKeyCode = PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(gdkKeyCode); + // If several gdk key codes map to the same win key code first one is used. + result->add(winKeyCode, gdkKeyCode); + } + }); + return *result; +} + +unsigned PlatformKeyboardEvent::gdkKeyCodeForWindowsKeyCode(int keycode) +{ + return gdkToWindowsKeyCodeMap().get(keycode); +} + String PlatformKeyboardEvent::singleCharacterString(unsigned val) { switch (val) { diff --git a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp index 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::createForCopyAndPaste(std::unique_ptr&& 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) 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&& context, SelectionData&& selectionData) + : m_context(WTFMove(context)) + , m_selectionData(WTFMove(selectionData)) +{ +} + +Pasteboard::Pasteboard(std::unique_ptr&& context, SelectionData& selectionData) + : m_context(WTFMove(context)) + , m_selectionData(selectionData) +{ +} + +std::unique_ptr Pasteboard::createForDragAndDrop(std::unique_ptr&& context) +{ + return makeUnique(WTFMove(context), SelectionData()); +} + +std::unique_ptr Pasteboard::create(const DragData& dragData) +{ + RELEASE_ASSERT(dragData.platformData()); + return makeUnique(dragData.createPasteboardContext(), *dragData.platformData()); +} +void Pasteboard::setDragImage(DragImage, const IntPoint&) +{ +} +#endif + } // namespace WebCore #endif // USE(LIBWPE) diff --git a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp index a34dc220bbb9a92b40dfb463e8724e81ac745b2c..8ecedd5dae88469366a619b96960598c1232a32d 100644 --- a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp +++ b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp @@ -30,8 +30,10 @@ #include "WindowsKeyboardCodes.h" #include +#include #include #include +#include namespace WebCore { @@ -1291,6 +1293,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(unsigned keycode) return 0; } +static const HashMap& WPEToWindowsKeyCodeMap() +{ + static HashMap* result; + static std::once_flag once; + std::call_once( + once, + [] { + const unsigned WPEKeyCodes[] = { + WPE_KEY_Cancel, + // FIXME: non-keypad keys should take precedence, so we skip WPE_KEY_KP_* + // WPE_KEY_KP_0, + // WPE_KEY_KP_1, + // WPE_KEY_KP_2, + // WPE_KEY_KP_3, + // WPE_KEY_KP_4, + // WPE_KEY_KP_5, + // WPE_KEY_KP_6, + // WPE_KEY_KP_7, + // WPE_KEY_KP_8, + // WPE_KEY_KP_9, + // WPE_KEY_KP_Multiply, + // WPE_KEY_KP_Add, + // WPE_KEY_KP_Subtract, + // WPE_KEY_KP_Decimal, + // WPE_KEY_KP_Divide, + // WPE_KEY_KP_Page_Up, + // WPE_KEY_KP_Page_Down, + // WPE_KEY_KP_End, + // WPE_KEY_KP_Home, + // WPE_KEY_KP_Left, + // WPE_KEY_KP_Up, + // WPE_KEY_KP_Right, + // WPE_KEY_KP_Down, + WPE_KEY_BackSpace, + // WPE_KEY_ISO_Left_Tab, + // WPE_KEY_3270_BackTab, + WPE_KEY_Tab, + WPE_KEY_Clear, + // WPE_KEY_ISO_Enter, + // WPE_KEY_KP_Enter, + WPE_KEY_Return, + WPE_KEY_Menu, + WPE_KEY_Pause, + WPE_KEY_AudioPause, + WPE_KEY_Caps_Lock, + WPE_KEY_Kana_Lock, + WPE_KEY_Kana_Shift, + WPE_KEY_Hangul, + WPE_KEY_Hangul_Hanja, + WPE_KEY_Kanji, + WPE_KEY_Escape, + WPE_KEY_space, + WPE_KEY_Page_Up, + WPE_KEY_Page_Down, + WPE_KEY_End, + WPE_KEY_Home, + WPE_KEY_Left, + WPE_KEY_Up, + WPE_KEY_Right, + WPE_KEY_Down, + WPE_KEY_Select, + WPE_KEY_Print, + WPE_KEY_Execute, + WPE_KEY_Insert, + WPE_KEY_KP_Insert, + WPE_KEY_Delete, + WPE_KEY_KP_Delete, + WPE_KEY_Help, + WPE_KEY_0, + WPE_KEY_parenright, + WPE_KEY_1, + WPE_KEY_exclam, + WPE_KEY_2, + WPE_KEY_at, + WPE_KEY_3, + WPE_KEY_numbersign, + WPE_KEY_4, + WPE_KEY_dollar, + WPE_KEY_5, + WPE_KEY_percent, + WPE_KEY_6, + WPE_KEY_asciicircum, + WPE_KEY_7, + WPE_KEY_ampersand, + WPE_KEY_8, + WPE_KEY_asterisk, + WPE_KEY_9, + WPE_KEY_parenleft, + WPE_KEY_a, + WPE_KEY_A, + WPE_KEY_b, + WPE_KEY_B, + WPE_KEY_c, + WPE_KEY_C, + WPE_KEY_d, + WPE_KEY_D, + WPE_KEY_e, + WPE_KEY_E, + WPE_KEY_f, + WPE_KEY_F, + WPE_KEY_g, + WPE_KEY_G, + WPE_KEY_h, + WPE_KEY_H, + WPE_KEY_i, + WPE_KEY_I, + WPE_KEY_j, + WPE_KEY_J, + WPE_KEY_k, + WPE_KEY_K, + WPE_KEY_l, + WPE_KEY_L, + WPE_KEY_m, + WPE_KEY_M, + WPE_KEY_n, + WPE_KEY_N, + WPE_KEY_o, + WPE_KEY_O, + WPE_KEY_p, + WPE_KEY_P, + WPE_KEY_q, + WPE_KEY_Q, + WPE_KEY_r, + WPE_KEY_R, + WPE_KEY_s, + WPE_KEY_S, + WPE_KEY_t, + WPE_KEY_T, + WPE_KEY_u, + WPE_KEY_U, + WPE_KEY_v, + WPE_KEY_V, + WPE_KEY_w, + WPE_KEY_W, + WPE_KEY_x, + WPE_KEY_X, + WPE_KEY_y, + WPE_KEY_Y, + WPE_KEY_z, + WPE_KEY_Z, + WPE_KEY_Meta_L, + WPE_KEY_Meta_R, + WPE_KEY_Sleep, + WPE_KEY_Num_Lock, + WPE_KEY_Scroll_Lock, + WPE_KEY_Shift_L, + WPE_KEY_Shift_R, + WPE_KEY_Control_L, + WPE_KEY_Control_R, + WPE_KEY_Alt_L, + WPE_KEY_Alt_R, + WPE_KEY_Back, + WPE_KEY_Forward, + WPE_KEY_Refresh, + WPE_KEY_Stop, + WPE_KEY_Search, + WPE_KEY_Favorites, + WPE_KEY_HomePage, + WPE_KEY_AudioMute, + WPE_KEY_AudioLowerVolume, + WPE_KEY_AudioRaiseVolume, + WPE_KEY_AudioNext, + WPE_KEY_AudioPrev, + WPE_KEY_AudioStop, + WPE_KEY_AudioMedia, + WPE_KEY_semicolon, + WPE_KEY_colon, + WPE_KEY_plus, + WPE_KEY_equal, + WPE_KEY_comma, + WPE_KEY_less, + WPE_KEY_minus, + WPE_KEY_underscore, + WPE_KEY_period, + WPE_KEY_greater, + WPE_KEY_slash, + WPE_KEY_question, + WPE_KEY_asciitilde, + WPE_KEY_quoteleft, + WPE_KEY_bracketleft, + WPE_KEY_braceleft, + WPE_KEY_backslash, + WPE_KEY_bar, + WPE_KEY_bracketright, + WPE_KEY_braceright, + WPE_KEY_quoteright, + WPE_KEY_quotedbl, + WPE_KEY_AudioRewind, + WPE_KEY_AudioForward, + WPE_KEY_AudioPlay, + WPE_KEY_F1, + WPE_KEY_F2, + WPE_KEY_F3, + WPE_KEY_F4, + WPE_KEY_F5, + WPE_KEY_F6, + WPE_KEY_F7, + WPE_KEY_F8, + WPE_KEY_F9, + WPE_KEY_F10, + WPE_KEY_F11, + WPE_KEY_F12, + WPE_KEY_F13, + WPE_KEY_F14, + WPE_KEY_F15, + WPE_KEY_F16, + WPE_KEY_F17, + WPE_KEY_F18, + WPE_KEY_F19, + WPE_KEY_F20, + WPE_KEY_F21, + WPE_KEY_F22, + WPE_KEY_F23, + WPE_KEY_F24, + WPE_KEY_VoidSymbol, + WPE_KEY_Red, + WPE_KEY_Green, + WPE_KEY_Yellow, + WPE_KEY_Blue, + WPE_KEY_PowerOff, + WPE_KEY_AudioRecord, + WPE_KEY_Display, + WPE_KEY_Subtitle, + WPE_KEY_Video + }; + result = new HashMap(); + for (unsigned WPEKeyCode : WPEKeyCodes) { + int winKeyCode = PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(WPEKeyCode); + // If several gdk key codes map to the same win key code first one is used. + result->add(winKeyCode, WPEKeyCode); + } + }); + return *result; +} + +unsigned PlatformKeyboardEvent::WPEKeyCodeForWindowsKeyCode(int keycode) +{ + return WPEToWindowsKeyCodeMap().get(keycode); +} + String PlatformKeyboardEvent::singleCharacterString(unsigned val) { switch (val) { diff --git a/Source/WebCore/platform/network/HTTPHeaderMap.cpp b/Source/WebCore/platform/network/HTTPHeaderMap.cpp index 39cb560e54bf9efd2dad6e1fb60dd0f609daf6bf..91c132460d4b466f61a8c579f70329fdde3b130f 100644 --- a/Source/WebCore/platform/network/HTTPHeaderMap.cpp +++ b/Source/WebCore/platform/network/HTTPHeaderMap.cpp @@ -205,8 +205,11 @@ void HTTPHeaderMap::add(HTTPHeaderName name, const String& value) auto index = m_commonHeaders.findMatching([&](auto& header) { return header.key == name; }); + // Align with Chromium and Firefox, but just for SetCookies where it is critical: + // https://bit.ly/2HCa0iq + String separator = name == HTTPHeaderName::SetCookie ? "\n " : ", "; if (index != notFound) - m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, ", ", value); + m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, separator, value); else m_commonHeaders.append(CommonHeader { name, value }); } diff --git a/Source/WebCore/platform/network/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&, 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 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> 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 create(const URL& url, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, client, sessionID, credentialPartition, WTFMove(auditData), provider)); } + static Ref create(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, ignoreCertificateErrors, client, sessionID, credentialPartition, WTFMove(auditData), provider)); } virtual ~SocketStreamHandleImpl(); @@ -61,7 +61,7 @@ private: std::optional platformSendInternal(const uint8_t*, size_t); bool sendPendingData(); - WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String& credentialPartition, SourceApplicationAuditToken&&, const StorageSessionProvider*); + WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, bool ignoreCertificateErrors, SocketStreamHandleClient&, PAL::SessionID, const String& credentialPartition, SourceApplicationAuditToken&&, const StorageSessionProvider*); void createStreams(); void scheduleStreams(); void chooseProxy(); @@ -106,6 +106,7 @@ private: String m_credentialPartition; SourceApplicationAuditToken m_auditData; RefPtr m_storageSessionProvider; + bool m_ignoreCertificateErrors { false }; StreamBuffer m_buffer; static const unsigned maxBufferSize = 100 * 1024 * 1024; diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp b/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp index 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 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* 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 create(CurlStreamScheduler& scheduler, CurlStreamID streamID, URL&& url) + static std::unique_ptr create(CurlStreamScheduler& scheduler, CurlStreamID streamID, bool ignoreCertificateErrors, URL&& url) { - return makeUnique(scheduler, streamID, WTFMove(url)); + return makeUnique(scheduler, streamID, ignoreCertificateErrors, WTFMove(url)); } - CurlStream(CurlStreamScheduler&, CurlStreamID, URL&&); + CurlStream(CurlStreamScheduler&, CurlStreamID, bool ignoreCertificateErrors, URL&&); virtual ~CurlStream(); void send(UniqueArray&&, size_t); diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp index 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&&, 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 create(const URL& url, SocketStreamHandleClient& client, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, client, provider)); } + static Ref create(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, ignoreCertificateErrors, client, provider)); } virtual ~SocketStreamHandleImpl(); @@ -53,7 +53,7 @@ public: WEBCORE_EXPORT void platformClose() final; private: - WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&, const StorageSessionProvider*); + WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, bool ignoreCertificateErrors, SocketStreamHandleClient&, const StorageSessionProvider*); size_t bufferedAmount() final; std::optional platformSendInternal(const uint8_t*, size_t); diff --git a/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp b/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp index 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 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 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 create(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider*) + static Ref create(const URL&, bool, SocketStreamHandleClient&, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider*) { RELEASE_ASSERT_NOT_REACHED(); } diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp index 3e97e804e115e0e37814ddf670e9e3ba4b3bbc73..86a1b22913c9ed6563f0d56c7ebd74c16dc829b9 100644 --- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp +++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp @@ -38,6 +38,7 @@ #include #include #include +#include "Pasteboard.h" #if USE(CF) #include @@ -724,7 +725,10 @@ template void getStringData(IDataObject* data, FORMATETC* format, Ve STGMEDIUM store; if (FAILED(data->GetData(format, &store))) return; - dataStrings.append(String(static_cast(GlobalLock(store.hGlobal)), ::GlobalSize(store.hGlobal) / sizeof(T))); + // The string here should be null terminated, but it could come from another app so lets lock it + // to the size to prevent an overflow. + String rawString = String(static_cast(GlobalLock(store.hGlobal)), ::GlobalSize(store.hGlobal) / sizeof(T)); + dataStrings.append(String::fromUTF8(rawString.utf8().data())); GlobalUnlock(store.hGlobal); ReleaseStgMedium(&store); } diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.h b/Source/WebCore/platform/win/ClipboardUtilitiesWin.h index c50799b63e05adbe32bae3535d786c7d268f980f..9cf1cc7ec4eaae22947f80ba272dfae272167bd6 100644 --- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.h +++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.h @@ -34,6 +34,7 @@ namespace WebCore { class Document; class DocumentFragment; +class Pasteboard; HGLOBAL createGlobalData(const String&); HGLOBAL createGlobalData(const Vector&); diff --git a/Source/WebCore/platform/win/DragDataWin.cpp b/Source/WebCore/platform/win/DragDataWin.cpp index 579a112579af39fc12ef024979d81fc55af36c2b..82c566c9d2ced02a92902a90e7ff97c142fa1903 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 c5445385a77ac12c09ef24866473d62cb679455a..392b3825d81e53f020ef7276ec7681a49c9baade 100644 --- a/Source/WebCore/platform/win/PasteboardWin.cpp +++ b/Source/WebCore/platform/win/PasteboardWin.cpp @@ -1134,7 +1134,21 @@ void Pasteboard::writeCustomData(const Vector& data) } clear(); + if (m_dataObject) { + const auto& customData = data.first(); + customData.forEachPlatformString([&](auto& type, auto& string) { + writeString(type, string); + }); + if (customData.hasSameOriginCustomData() || !customData.origin().isEmpty()) { + customData.forEachCustomString([&](auto& type, auto& string) { + writeString(type, string); + }); + } + return; + } + + // this is the real real clipboard. Prbaobly need to be doing drag data stuff. if (::OpenClipboard(m_owner)) { const auto& customData = data.first(); customData.forEachPlatformStringOrBuffer([](auto& type, auto& stringOrBuffer) { @@ -1173,4 +1187,25 @@ void Pasteboard::write(const Color&) { } +DragDataMap Pasteboard::createDragDataMap() { + DragDataMap dragDataMap; + auto dragObject = dataObject(); + if (!dragObject) + return dragDataMap; + // Enumerate clipboard content and load it in the map. + COMPtr itr; + + if (FAILED(dragObject->EnumFormatEtc(DATADIR_GET, &itr)) || !itr) + return dragDataMap; + + FORMATETC dataFormat; + while (itr->Next(1, &dataFormat, 0) == S_OK) { + Vector dataStrings; + getClipboardData(dragObject.get(), &dataFormat, dataStrings); + if (!dataStrings.isEmpty()) + dragDataMap.set(dataFormat.cfFormat, dataStrings); + } + return dragDataMap; +} + } // namespace WebCore diff --git a/Source/WebCore/platform/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(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 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 +#include +#include + +namespace WebCore { + +static void replaceNonBreakingSpaceWithSpace(String& str) +{ + static const UChar NonBreakingSpaceCharacter = 0xA0; + static const UChar SpaceCharacter = ' '; + str.replace(NonBreakingSpaceCharacter, SpaceCharacter); +} + +void SelectionData::setText(const String& newText) +{ + m_text = newText; + replaceNonBreakingSpaceWithSpace(m_text); +} + +void SelectionData::setURIList(const String& uriListString) +{ + m_uriList = uriListString; + + // This code is originally from: platform/chromium/ChromiumDataObject.cpp. + // FIXME: We should make this code cross-platform eventually. + + // Line separator is \r\n per RFC 2483 - however, for compatibility + // reasons we also allow just \n here. + + // Process the input and copy the first valid URL into the url member. + // In case no URLs can be found, subsequent calls to getData("URL") + // will get an empty string. This is in line with the HTML5 spec (see + // "The DragEvent and DataTransfer interfaces"). Also extract all filenames + // from the URI list. + bool setURL = hasURL(); + for (auto& line : uriListString.split('\n')) { + line = line.stripWhiteSpace(); + if (line.isEmpty()) + continue; + if (line[0] == '#') + continue; + + URL url = URL(URL(), line); + if (url.isValid()) { + if (!setURL) { + m_url = url; + setURL = true; + } + + GUniqueOutPtr error; + GUniquePtr filename(g_filename_from_uri(line.utf8().data(), 0, &error.outPtr())); + if (!error && filename) + m_filenames.append(String::fromUTF8(filename.get())); + } + } +} + +void SelectionData::setURL(const URL& url, const String& label) +{ + m_url = url; + if (m_uriList.isEmpty()) + m_uriList = url.string(); + + if (!hasText()) + setText(url.string()); + + if (hasMarkup()) + return; + + String actualLabel(label); + if (actualLabel.isEmpty()) + actualLabel = url.string(); + + StringBuilder markup; + markup.append(""); + GUniquePtr escaped(g_markup_escape_text(actualLabel.utf8().data(), -1)); + markup.append(String::fromUTF8(escaped.get())); + markup.append(""); + setMarkup(markup.toString()); +} + +const String& SelectionData::urlLabel() const +{ + if (hasText()) + return text(); + + if (hasURL()) + return url().string(); + + return emptyString(); +} + +void SelectionData::clearAllExceptFilenames() +{ + clearText(); + clearMarkup(); + clearURIList(); + clearURL(); + clearImage(); + clearCustomData(); + + m_canSmartReplace = false; +} + +void SelectionData::clearAll() +{ + clearAllExceptFilenames(); + m_filenames.clear(); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/wpe/SelectionData.h b/Source/WebCore/platform/wpe/SelectionData.h new file mode 100644 index 0000000000000000000000000000000000000000..cf2b51f6f02837a1106f4d999f2f130e2580986a --- /dev/null +++ b/Source/WebCore/platform/wpe/SelectionData.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2009, Martin Robinson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "Image.h" +#include "SharedBuffer.h" +#include +#include +#include + +namespace WebCore { + +class SelectionData { + WTF_MAKE_FAST_ALLOCATED; +public: + void setText(const String&); + const String& text() const { return m_text; } + bool hasText() const { return !m_text.isEmpty(); } + void clearText() { m_text = emptyString(); } + + void setMarkup(const String& newMarkup) { m_markup = newMarkup; } + const String& markup() const { return m_markup; } + bool hasMarkup() const { return !m_markup.isEmpty(); } + void clearMarkup() { m_markup = emptyString(); } + + void setURL(const URL&, const String&); + const URL& url() const { return m_url; } + const String& urlLabel() const; + bool hasURL() const { return !m_url.isEmpty() && m_url.isValid(); } + void clearURL() { m_url = URL(); } + + void setURIList(const String&); + const String& uriList() const { return m_uriList; } + const Vector& filenames() const { return m_filenames; } + bool hasURIList() const { return !m_uriList.isEmpty(); } + bool hasFilenames() const { return !m_filenames.isEmpty(); } + void clearURIList() { m_uriList = emptyString(); } + + void setImage(Image* newImage) { m_image = newImage; } + Image* image() const { return m_image.get(); } + bool hasImage() const { return m_image; } + void clearImage() { m_image = nullptr; } + + void setCanSmartReplace(bool canSmartReplace) { m_canSmartReplace = canSmartReplace; } + bool canSmartReplace() const { return m_canSmartReplace; } + + void setCustomData(Ref&& buffer) { m_customData = WTFMove(buffer); } + SharedBuffer* customData() const { return m_customData.get(); } + bool hasCustomData() const { return !!m_customData; } + void clearCustomData() { m_customData = nullptr; } + + void clearAll(); + void clearAllExceptFilenames(); + +private: + String m_text; + String m_markup; + URL m_url; + String m_uriList; + Vector m_filenames; + RefPtr m_image; + bool m_canSmartReplace { false }; + RefPtr m_customData; +}; + +} // namespace WebCore diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp index 0925d828f8aa5a5b0cb4f2d27868b0fa2952baef..396f4dc4eaa2fe6a329b4fe709f7d4fb12b15e2f 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 #include +#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 666bcc1b21b95d0892b2f23fdc129fbae61fe321..1d4bd1ad2a05d1a1b831d083d85363edb641c13e 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" @@ -579,6 +578,59 @@ void NetworkProcess::destroySession(PAL::SessionID sessionID) removeStorageManagerForSession(sessionID); } +void NetworkProcess::getAllCookies(PAL::SessionID sessionID, CompletionHandler&&)>&& completionHandler) +{ + if (auto* networkStorageSession = storageSession(sessionID)) { + completionHandler(networkStorageSession->getAllCookies()); + return; + } + completionHandler({ }); +} + +void NetworkProcess::setCookies(PAL::SessionID sessionID, Vector cookies, CompletionHandler&& completionHandler) { + if (auto* networkStorageSession = storageSession(sessionID)) { + for (auto cookie : cookies) + networkStorageSession->setCookie(cookie); + completionHandler(true); + return; + } + completionHandler(false); +} + +void NetworkProcess::deleteAllCookies(PAL::SessionID sessionID, CompletionHandler&& completionHandler) +{ + if (auto* networkStorageSession = storageSession(sessionID)) { + networkStorageSession->deleteAllCookies(); + completionHandler(true); + return; + } + completionHandler(false); +} + +void NetworkProcess::getLocalStorageData(PAL::SessionID sessionID, CompletionHandler>>&&)>&& completionHandler) +{ + if (m_storageManagerSet->contains(sessionID)) { + m_storageManagerSet->getLocalStorageData(sessionID, WTFMove(completionHandler)); + return; + } + completionHandler(Vector>>()); +} + +void NetworkProcess::setLocalStorageData(PAL::SessionID sessionID, WebKit::StorageNamespaceIdentifier storageNamespaceID, Vector>>&& origins, CompletionHandler&& 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&& completionHandler) { diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h index 9d32d57973a0ebac1d07175c6df879d466ce68a8..0769edae24c8b22f69cb2b088bf7bb1c812ea4ed 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 setCookies(PAL::SessionID, Vector, CompletionHandler&&); + void deleteAllCookies(PAL::SessionID, CompletionHandler&&); + void setIgnoreCertificateErrors(PAL::SessionID, bool); + + void getLocalStorageData(PAL::SessionID sessionID, CompletionHandler>>&&)>&&); + void setLocalStorageData(PAL::SessionID sessionID, WebKit::StorageNamespaceIdentifier storageNamespaceID, Vector>>&& origins, CompletionHandler&&); + #if ENABLE(INTELLIGENT_TRACKING_PREVENTION) void clearPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler&&); void clearUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler&&); diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in index 32ab3840b66a7c78d53a35459120dddb2cf4e9bc..6172373ae7c1bbf968d748a2148b8b0dde2cfacd 100644 --- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in +++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in @@ -77,6 +77,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 isNavigatingToAppBoundDomain, enum:bool WebKit::LastNavigationWasAppInitiated lastNavigationWasAppInitiated); + GetAllCookies(PAL::SessionID sessionID) -> (Vector cookies) Async + SetCookies(PAL::SessionID sessionID, Vector cookies) -> (bool success) Async + DeleteAllCookies(PAL::SessionID sessionID) -> (bool success) Async + SetIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignoreTLSErrors) + + GetLocalStorageData(PAL::SessionID sessionID) -> (Vector>> origins) Async + SetLocalStorageData(PAL::SessionID sessionID, WebKit::StorageNamespaceIdentifier storageNamespaceID, Vector>> 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 3dddf4b3288d3b2741ea3aefd98d13f784c1eb74..ccb9aeb5461f40129ae26cf0da3f60dcff6703a6 100644 --- a/Source/WebKit/NetworkProcess/NetworkSession.h +++ b/Source/WebKit/NetworkProcess/NetworkSession.h @@ -169,6 +169,9 @@ public: bool isStaleWhileRevalidateEnabled() const { return m_isStaleWhileRevalidateEnabled; } + void setIgnoreCertificateErrors(bool ignore) { m_ignoreCertificateErrors = ignore; } + bool ignoreCertificateErrors() { return m_ignoreCertificateErrors; } + #if ENABLE(SERVICE_WORKER) void addSoftUpdateLoader(std::unique_ptr&& loader) { m_softUpdateLoaders.add(WTFMove(loader)); } void removeSoftUpdateLoader(ServiceWorkerSoftUpdateLoader* loader) { m_softUpdateLoaders.remove(loader); } @@ -225,6 +228,7 @@ protected: bool m_privateClickMeasurementDebugModeEnabled { false }; std::optional m_ephemeralMeasurement; bool m_isRunningEphemeralMeasurementTest { false }; + bool m_ignoreCertificateErrors { false }; HashSet> 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::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 +#include namespace WebKit { @@ -103,4 +104,11 @@ Vector LocalStorageNamespace::storageAreaIdentifiers() co return identifiers; } +void LocalStorageNamespace::forEachStorageArea(Function 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 -#include +#include #include #include @@ -58,6 +58,8 @@ public: Vector storageAreaIdentifiers() const; + void forEachStorageArea(Function) 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& 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& items, bool& quotaException); HashMap items() const; void clear(); diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp index 295b44c7fdeca5c34407dbf9a96a62a33b8ada47..e4eae9493caaabc5386edfae06ec734dbd4d41f7 100644 --- a/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp +++ b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp @@ -148,6 +148,19 @@ HashSet StorageManager::getLocalStorageOriginsCrossThreadCop return origins; } +Vector>> StorageManager::getLocalStorageDataCrossThreadCopy() const +{ + ASSERT(!RunLoop::isMain()); + + Vector>> result; + for (const auto& localStorageNameSpace : m_localStorageNamespaces.values()) { + localStorageNameSpace->forEachStorageArea([&] (const StorageArea& area) { + result.append({ area.securityOrigin().isolatedCopy(), area.items() }); + }); + } + return result; +} + Vector 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&); HashSet getLocalStorageOriginsCrossThreadCopy() const; + Vector>> getLocalStorageDataCrossThreadCopy() const; void deleteLocalStorageOriginsModifiedSince(WallTime); void deleteLocalStorageEntriesForOrigins(const Vector&); Vector getLocalStorageOriginDetailsCrossThreadCopy() const; diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.cpp b/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.cpp index 6fd703a5e5b2d01435985eab3aedc1e0d1a93b13..fada96efb033be24f8659019f2e11b697085c32a 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>>&& origins, CompletionHandler&& 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&)>; using GetOriginsCallback = CompletionHandler&&)>; using GetOriginDetailsCallback = CompletionHandler&&)>; +using GetLocalStorageDataCallback = CompletionHandler>>&&)>; using DeleteCallback = CompletionHandler; class StorageManagerSet : public IPC::Connection::WorkQueueMessageReceiver { @@ -73,6 +74,8 @@ public: void deleteLocalStorageModifiedSince(PAL::SessionID, WallTime, DeleteCallback&&); void deleteLocalStorageForOrigins(PAL::SessionID, const Vector&, DeleteCallback&&); void getLocalStorageOriginDetails(PAL::SessionID, GetOriginDetailsCallback&&); + void getLocalStorageData(PAL::SessionID, GetLocalStorageDataCallback&&); + void setLocalStorageData(PAL::SessionID sessionID, WebKit::StorageNamespaceIdentifier storageNamespaceID, Vector>>&& origins, CompletionHandler&&); void renameOrigin(PAL::SessionID, const URL&, const URL&, CompletionHandler&&); void didReceiveMessage(IPC::Connection&, IPC::Decoder&); diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm index e321f9f5ff2be81f5176a2039fc21c1ce45db89f..e0b87417fa6dac27d3028be6d12ebf7124c5e0db 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 8fc7b663e6f7562b2b35489398a2fe731be074f1..a1d7ef83a53c45a841caaf03673028ca11b74182 100644 --- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp +++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp @@ -26,9 +26,13 @@ #include "config.h" #include "NetworkDataTaskCurl.h" +#include "APIError.h" #include "AuthenticationChallengeDisposition.h" #include "AuthenticationManager.h" +#include "DataReference.h" +#include "Download.h" #include "NetworkSessionCurl.h" +#include "NetworkProcess.h" #include #include #include @@ -40,6 +44,7 @@ #include #include #include +#include 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::create(WTFMove(receivedResponse.networkLoadMetrics))); + m_response.m_httpRequestHeaderFields = request.resourceRequest().httpHeaderFields(); handleCookieHeaders(request.resourceRequest(), receivedResponse); @@ -177,7 +188,10 @@ void NetworkDataTaskCurl::curlDidReceiveBuffer(CurlRequest&, Ref&& 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(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 #include #include +#include #include 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 b20aa51a0f84f95ad8f0b7807d74171adc5205a3..902f52af2b6e590e769e0931ef029e96d553cba7 100644 --- a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp +++ b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp @@ -493,6 +493,8 @@ void NetworkDataTaskSoup::didSendRequest(GRefPtr&& 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(*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(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 NetworkSessionSoup::createWebSocketTask(WebPageProxyIdentifier, NetworkSocketChannel& channel, const ResourceRequest& request, const String& protocol) { GRefPtr soupMessage = request.createSoupMessage(blobRegistry()); @@ -127,14 +141,21 @@ std::unique_ptr 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(channel, request, soupSession(), soupMessage.get(), protocol); diff --git a/Source/WebKit/PlatformGTK.cmake b/Source/WebKit/PlatformGTK.cmake index 141705a204e028c18c442a0d9429431ae8881faf..2d9af691b23215442389e8330256b4220e14de26 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}/webkit2/WebKitEnumTypes.h) diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake index 87fa6e1bd9e5f8dbdef854021f7d8579591629b5..a0e9545900928f005110e83ef1248fa1235a64fa 100644 --- a/Source/WebKit/PlatformWPE.cmake +++ b/Source/WebKit/PlatformWPE.cmake @@ -166,6 +166,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 @@ -292,6 +293,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" @@ -314,8 +316,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 c67e2d1e3d5dd0b98a8775cea6ed9b78e593eb0a..7e5dd02f7e91e6264148d7024b3632750fb1bf50 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 #include +#include #include #include #include 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 OBJC_CLASS NSView; +OBJC_CLASS NSEvent; #endif #if PLATFORM(GTK) @@ -65,19 +66,35 @@ public: #if USE(APPKIT) // FIXME: Share iOS's HandledByInputMethod enum here instead of passing a boolean. NativeWebKeyboardEvent(NSEvent *, bool handledByInputMethod, bool replacesSoftSpace, const Vector&); + NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp, Vector&& commands) + : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp, WTFMove(commands)) + { + } #elif PLATFORM(GTK) NativeWebKeyboardEvent(const NativeWebKeyboardEvent&); NativeWebKeyboardEvent(GdkEvent*, const String&, Vector&& commands); NativeWebKeyboardEvent(const String&, std::optional>&&, std::optional&&); NativeWebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, Vector&& commands, bool isKeypad, OptionSet); + NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp, Vector&& commands) + : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp, WTFMove(commands)) + { + } #elif PLATFORM(IOS_FAMILY) enum class HandledByInputMethod : bool { No, Yes }; NativeWebKeyboardEvent(::WebEvent *, HandledByInputMethod); #elif USE(LIBWPE) enum class HandledByInputMethod : bool { No, Yes }; NativeWebKeyboardEvent(struct wpe_input_keyboard_event*, const String&, HandledByInputMethod, std::optional>&&, std::optional&&); + NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) + : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp) + { + } #elif PLATFORM(WIN) NativeWebKeyboardEvent(HWND, UINT message, WPARAM, LPARAM, Vector&& pendingCharEvents); + NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) + : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp) + { + } #endif #if USE(APPKIT) diff --git a/Source/WebKit/Shared/NativeWebMouseEvent.h b/Source/WebKit/Shared/NativeWebMouseEvent.h index 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 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 c0b6ef3fa3a2e1204c677ecf86aecbd19bb64d7b..e0f690d3714eb07aa204fcf66d095a289f3e9336 100644 --- a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp +++ b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp @@ -119,6 +119,10 @@ #include #endif +#if PLATFORM(WPE) +#include "ArgumentCodersWPE.h" +#endif + // FIXME: Seems like we could use std::tuple to cut down the code below a lot! namespace IPC { @@ -1379,6 +1383,9 @@ void ArgumentCoder::encode(Encoder& encoder, const WindowFeature encoder << windowFeatures.resizable; encoder << windowFeatures.fullscreen; encoder << windowFeatures.dialog; + encoder << windowFeatures.noopener; + encoder << windowFeatures.noreferrer; + encoder << windowFeatures.additionalFeatures; } bool ArgumentCoder::decode(Decoder& decoder, WindowFeatures& windowFeatures) @@ -1407,6 +1414,12 @@ bool ArgumentCoder::decode(Decoder& decoder, WindowFeatures& win return false; if (!decoder.decode(windowFeatures.dialog)) return false; + if (!decoder.decode(windowFeatures.noopener)) + return false; + if (!decoder.decode(windowFeatures.noreferrer)) + return false; + if (!decoder.decode(windowFeatures.additionalFeatures)) + return false; return true; } @@ -1420,6 +1433,11 @@ void ArgumentCoder::encode(Encoder& encoder, const DragData& dragData) #if PLATFORM(COCOA) encoder << dragData.pasteboardName(); encoder << dragData.fileNames(); +#endif +#if PLATFORM(WIN) + DragData dragDataCopy = dragData; + HashMap> hash = dragDataCopy.dragDataMap(); + encoder << hash; #endif encoder << dragData.dragDestinationActionMask(); encoder << dragData.pageID(); @@ -1443,9 +1461,16 @@ bool ArgumentCoder::decode(Decoder& decoder, DragData& dragData) if (!decoder.decode(applicationFlags)) return false; +#if PLATFORM(WIN) + DragDataMap dragDataMap; + if (!decoder.decode(dragDataMap)) + return false; +#else String pasteboardName; - Vector fileNames; +#endif + #if PLATFORM(COCOA) + Vector fileNames; if (!decoder.decode(pasteboardName)) return false; @@ -1461,8 +1486,14 @@ bool ArgumentCoder::decode(Decoder& decoder, DragData& dragData) if (!decoder.decode(pageID)) return false; +#if PLATFORM(WIN) + dragData = DragData(dragDataMap, clientPosition, globalPosition, draggingSourceOperationMask, applicationFlags, pageID); +#else dragData = DragData(pasteboardName, clientPosition, globalPosition, draggingSourceOperationMask, applicationFlags, dragDestinationActionMask, pageID); +#endif +#if PLATFORM(COCOA) dragData.setFileNames(fileNames); +#endif return true; } diff --git a/Source/WebKit/Shared/WebEvent.h b/Source/WebKit/Shared/WebEvent.h index 3ae6504779d3917a79f69f32b58260afeda270b4..72d44c33953cc13bf2ed7c762b4f9a7b88571b56 100644 --- a/Source/WebKit/Shared/WebEvent.h +++ b/Source/WebKit/Shared/WebEvent.h @@ -31,6 +31,7 @@ #include #include +#include #include #include diff --git a/Source/WebKit/Shared/WebKeyboardEvent.cpp b/Source/WebKit/Shared/WebKeyboardEvent.cpp index 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& commands, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) @@ -56,6 +57,24 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& ASSERT(isKeyboardEventType(type)); } +WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp, Vector&& commands) + : WebEvent(type, modifiers, timestamp) + , m_text(text) + , m_unmodifiedText(text) + , m_key(key) + , m_code(code) + , m_keyIdentifier(keyIdentifier) + , m_windowsVirtualKeyCode(windowsVirtualKeyCode) + , m_nativeVirtualKeyCode(nativeVirtualKeyCode) + , m_macCharCode(0) + , m_commands(WTFMove(commands)) + , m_isAutoRepeat(isAutoRepeat) + , m_isKeypad(isKeypad) + , m_isSystemKey(isSystemKey) +{ + ASSERT(isKeyboardEventType(type)); +} + #elif PLATFORM(GTK) WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, std::optional>&& preeditUnderlines, std::optional&& preeditSelectionRange, Vector&& commands, bool isKeypad, OptionSet modifiers, WallTime timestamp) @@ -79,6 +98,24 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& ASSERT(isKeyboardEventType(type)); } +WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp, Vector&& commands) + : WebEvent(type, modifiers, timestamp) + , m_text(text) + , m_unmodifiedText(text) + , m_key(key) + , m_code(code) + , m_keyIdentifier(keyIdentifier) + , m_windowsVirtualKeyCode(windowsVirtualKeyCode) + , m_nativeVirtualKeyCode(nativeVirtualKeyCode) + , m_macCharCode(0) + , m_commands(WTFMove(commands)) + , m_isAutoRepeat(isAutoRepeat) + , m_isKeypad(isKeypad) + , m_isSystemKey(isSystemKey) +{ + ASSERT(isKeyboardEventType(type)); +} + #elif PLATFORM(IOS_FAMILY) WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) @@ -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 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&, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); + WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp, Vector&& commands); #elif PLATFORM(GTK) WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, std::optional>&&, std::optional&&, Vector&& commands, bool isKeypad, OptionSet, WallTime timestamp); + WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp, Vector&& commands); #elif PLATFORM(IOS_FAMILY) WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); #elif USE(LIBWPE) WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, std::optional>&&, std::optional&&, bool isKeypad, OptionSet, WallTime timestamp); + WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); #else WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); + WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); #endif const String& text() const { return m_text; } diff --git a/Source/WebKit/Shared/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