diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt index ccef1afd45da19301c86a9f75722bada37c8310a..360189f0fb27bd4f45a072524e80a9c13cb41e1c 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt @@ -1142,16 +1142,20 @@ set(JavaScriptCore_INSPECTOR_DOMAINS ${JAVASCRIPTCORE_DIR}/inspector/protocol/Animation.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/ApplicationCache.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Audit.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Browser.json ${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/Input.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Inspector.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/LayerTree.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Network.json diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make index e2a36fa8764909abfd0e1896d3a9a7c361f1b23a..e3ed01ae7cf8ce68a4fd8308e0ea2819638a78d3 100644 --- a/Source/JavaScriptCore/DerivedSources.make +++ b/Source/JavaScriptCore/DerivedSources.make @@ -241,16 +241,20 @@ INSPECTOR_DOMAINS := \ $(JavaScriptCore)/inspector/protocol/Animation.json \ $(JavaScriptCore)/inspector/protocol/ApplicationCache.json \ $(JavaScriptCore)/inspector/protocol/Audit.json \ + $(JavaScriptCore)/inspector/protocol/Browser.json \ $(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/Input.json \ $(JavaScriptCore)/inspector/protocol/Inspector.json \ $(JavaScriptCore)/inspector/protocol/LayerTree.json \ $(JavaScriptCore)/inspector/protocol/Network.json \ diff --git a/Source/JavaScriptCore/bindings/ScriptValue.cpp b/Source/JavaScriptCore/bindings/ScriptValue.cpp index dece6ac51e3a85b1e094e405effc6203887ddfd4..9bf7519d894eceb06b40d754c4fb7940399eba84 100644 --- a/Source/JavaScriptCore/bindings/ScriptValue.cpp +++ b/Source/JavaScriptCore/bindings/ScriptValue.cpp @@ -81,7 +81,10 @@ static RefPtr jsToInspectorValue(JSGlobalObject* globalObject, JSVa PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); object.methodTable(vm)->getOwnPropertyNames(&object, globalObject, propertyNames, EnumerationMode()); 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(), WTFMove(inspectorValue)); diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp index 038cb646d31706905deff8935040d63c0afd00f9..2fca7b043f15a8cce3819cc827912fb719a345db 100644 --- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp +++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp @@ -102,7 +102,7 @@ void BackendDispatcher::registerDispatcherForDomain(const String& domain, Supple m_dispatchers.set(domain, dispatcher); } -void BackendDispatcher::dispatch(const String& message) +BackendDispatcher::DispatchResult BackendDispatcher::dispatch(const String& message, Mode mode, Interceptor&& interceptor) { Ref protect(*this); @@ -120,29 +120,32 @@ void BackendDispatcher::dispatch(const String& message) if (!JSON::Value::parseJSON(message, parsedMessage)) { reportProtocolError(ParseError, "Message must be in JSON format"_s); sendPendingErrors(); - return; + return DispatchResult::Finished; } if (!parsedMessage->asObject(messageObject)) { reportProtocolError(InvalidRequest, "Message must be a JSONified object"_s); sendPendingErrors(); - return; + return DispatchResult::Finished; } RefPtr requestIdValue; if (!messageObject->getValue("id"_s, requestIdValue)) { reportProtocolError(InvalidRequest, "'id' property was not found"_s); sendPendingErrors(); - return; + return DispatchResult::Finished; } if (!requestIdValue->asInteger(requestId)) { reportProtocolError(InvalidRequest, "The type of 'id' property must be integer"_s); sendPendingErrors(); - return; + return DispatchResult::Finished; } } + if (interceptor && interceptor(messageObject) == DispatchResult::Finished) + return DispatchResult::Finished; + { // We could be called re-entrantly from a nested run loop, so restore the previous id. SetForScope> scopedRequestId(m_currentRequestId, requestId); @@ -151,29 +154,31 @@ void BackendDispatcher::dispatch(const String& message) if (!messageObject->getValue("method"_s, methodValue)) { reportProtocolError(InvalidRequest, "'method' property wasn't found"_s); sendPendingErrors(); - return; + return DispatchResult::Finished; } String methodString; if (!methodValue->asString(methodString)) { reportProtocolError(InvalidRequest, "The type of 'method' property must be string"_s); sendPendingErrors(); - return; + return DispatchResult::Finished; } Vector domainAndMethod = methodString.splitAllowingEmptyEntries('.'); if (domainAndMethod.size() != 2 || !domainAndMethod[0].length() || !domainAndMethod[1].length()) { reportProtocolError(InvalidRequest, "The 'method' property was formatted incorrectly. It should be 'Domain.method'"_s); sendPendingErrors(); - return; + return DispatchResult::Finished; } String domain = domainAndMethod[0]; SupplementalBackendDispatcher* domainDispatcher = m_dispatchers.get(domain); if (!domainDispatcher) { + if (mode == Mode::ContinueIfDomainIsMissing) + return DispatchResult::Continue; reportProtocolError(MethodNotFound, "'" + domain + "' domain was not found"); sendPendingErrors(); - return; + return DispatchResult::Finished; } String method = domainAndMethod[1]; @@ -182,6 +187,7 @@ void BackendDispatcher::dispatch(const String& message) if (m_protocolErrors.size()) sendPendingErrors(); } + return DispatchResult::Finished; } // FIXME: remove this function when legacy InspectorObject symbols are no longer needed . diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h index 95d9d81188e735e8f1b70cc0deee2682cb6714f0..4c67ce34302f74e0d07f64ae53a4eaf18df6669a 100644 --- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h +++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h @@ -82,7 +82,11 @@ public: }; void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*); - void dispatch(const String& message); + + enum class DispatchResult { Finished, Continue }; + enum class Mode { FailIfDomainIsMissing, ContinueIfDomainIsMissing }; + using Interceptor = WTF::Function&)>; + DispatchResult dispatch(const String& message, Mode mode = Mode::FailIfDomainIsMissing, 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/InspectorTarget.h b/Source/JavaScriptCore/inspector/InspectorTarget.h index 4b95964db4d902b4b7f4b0b4c40afea51654ff2f..cecc44dd00bab6aa4f302274cc88af41bf0a8c03 100644 --- a/Source/JavaScriptCore/inspector/InspectorTarget.h +++ b/Source/JavaScriptCore/inspector/InspectorTarget.h @@ -45,8 +45,11 @@ public: // State. virtual String identifier() const = 0; virtual InspectorTargetType type() const = 0; + virtual String url() const = 0; virtual bool isProvisional() const { return false; } + virtual String oldTargetID() const { return String(); } + virtual String openerID() const { return String(); } bool isPaused() const { return m_isPaused; } void pause(); void resume(); @@ -56,6 +59,8 @@ 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: WTF::Function m_resumeCallback; diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp index 8fcb5a1e55750d325a84824d86c49cfe6fb04268..b0e22f247818f981e9dbd0981c09d46830cd338e 100644 --- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp +++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp @@ -30,11 +30,12 @@ namespace Inspector { -InspectorTargetAgent::InspectorTargetAgent(FrontendRouter& frontendRouter, BackendDispatcher& backendDispatcher) +InspectorTargetAgent::InspectorTargetAgent(FrontendRouter& frontendRouter, BackendDispatcher& backendDispatcher, const String& browserContextID) : InspectorAgentBase("Target"_s) , m_router(frontendRouter) , m_frontendDispatcher(makeUnique(frontendRouter)) , m_backendDispatcher(TargetBackendDispatcher::create(backendDispatcher, this)) + , m_browserContextID(browserContextID) { } @@ -87,6 +88,28 @@ void InspectorTargetAgent::sendMessageToTarget(ErrorString& errorString, const S target->sendMessageToTargetBackend(message); } +void InspectorTargetAgent::activate(ErrorString& errorString, const String& targetId) +{ + InspectorTarget* target = m_targets.get(targetId); + if (!target) { + errorString = "Missing target for given targetId"_s; + return; + } + + target->activate(errorString); +} + +void InspectorTargetAgent::close(ErrorString& errorString, const String& targetId, const bool* runBeforeUnload) +{ + InspectorTarget* target = m_targets.get(targetId); + if (!target) { + errorString = "Missing target for given targetId"_s; + return; + } + + target->close(errorString, runBeforeUnload && *runBeforeUnload); +} + 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."); @@ -109,16 +132,23 @@ static Protocol::Target::TargetInfo::Type targetTypeToProtocolType(InspectorTarg return Protocol::Target::TargetInfo::Type::Page; } -static Ref buildTargetInfoObject(const InspectorTarget& target) +static Ref buildTargetInfoObject(const InspectorTarget& target, const String& browserContextID) { auto result = Protocol::Target::TargetInfo::create() .setTargetId(target.identifier()) .setType(targetTypeToProtocolType(target.type())) + .setUrl(target.url()) .release(); - if (target.isProvisional()) + if (target.isProvisional()) { result->setIsProvisional(true); + result->setOldTargetId(target.oldTargetID()); + } if (target.isPaused()) result->setIsPaused(true); + if (!browserContextID.isEmpty()) + result->setBrowserContextId(browserContextID); + if (!target.openerID().isEmpty()) + result->setOpenerId(target.openerID()); return result; } @@ -134,7 +164,7 @@ void InspectorTargetAgent::targetCreated(InspectorTarget& target) target.pause(); target.connect(connectionType()); - m_frontendDispatcher->targetCreated(buildTargetInfoObject(target)); + m_frontendDispatcher->targetCreated(buildTargetInfoObject(target, m_browserContextID)); } void InspectorTargetAgent::targetDestroyed(InspectorTarget& target) @@ -144,7 +174,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 +199,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; @@ -168,7 +220,7 @@ void InspectorTargetAgent::connectToTargets() { for (InspectorTarget* target : m_targets.values()) { target->connect(connectionType()); - m_frontendDispatcher->targetCreated(buildTargetInfoObject(*target)); + m_frontendDispatcher->targetCreated(buildTargetInfoObject(*target, m_browserContextID)); } } diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h index 1eb7abb2fa21d7a8ec0833160f53e5c523ec4317..b10dd23de692fd5f447a9b845b5695ac369e8496 100644 --- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h +++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h @@ -41,7 +41,7 @@ class JS_EXPORT_PRIVATE InspectorTargetAgent : public InspectorAgentBase, public WTF_MAKE_NONCOPYABLE(InspectorTargetAgent); WTF_MAKE_FAST_ALLOCATED; public: - InspectorTargetAgent(FrontendRouter&, BackendDispatcher&); + InspectorTargetAgent(FrontendRouter&, BackendDispatcher&, const String& browserContextID); ~InspectorTargetAgent() override; // InspectorAgentBase @@ -52,15 +52,21 @@ public: void setPauseOnStart(ErrorString&, bool pauseOnStart) override; void resume(ErrorString&, const String& targetId) override; void sendMessageToTarget(ErrorString&, const String& targetId, const String& message) final; + void activate(ErrorString&, const String& targetId) override; + void close(ErrorString&, const String& targetId, const bool* runBeforeUnload) override; // Target lifecycle. void targetCreated(InspectorTarget&); void targetDestroyed(InspectorTarget&); + void targetCrashed(InspectorTarget&); void didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID); + void ensureConnected(const String& targetID); // Target messages. void sendMessageFromTargetToFrontend(const String& targetId, const String& message); + bool isConnected() { return m_isConnected; } + private: // FrontendChannel FrontendChannel::ConnectionType connectionType() const; @@ -70,6 +76,7 @@ private: Inspector::FrontendRouter& m_router; std::unique_ptr m_frontendDispatcher; Ref m_backendDispatcher; + const String m_browserContextID; HashMap m_targets; bool m_isConnected { false }; bool m_shouldPauseOnStart { false }; diff --git a/Source/JavaScriptCore/inspector/protocol/Browser.json b/Source/JavaScriptCore/inspector/protocol/Browser.json new file mode 100644 index 0000000000000000000000000000000000000000..a0b5806920078bbaa0bd5efb6f589bf1da461b4a --- /dev/null +++ b/Source/JavaScriptCore/inspector/protocol/Browser.json @@ -0,0 +1,177 @@ +{ + "domain": "Browser", + "availability": ["web"], + "types": [ + { + "id": "ContextID", + "type": "string", + "description": "Id of Browser context." + }, + { + "id": "PageProxyID", + "type": "string", + "description": "Id of WebPageProxy." + }, + { + "id": "PageProxyInfo", + "type": "object", + "description": "Tab info object", + "properties": [ + { "name": "pageProxyId", "$ref": "PageProxyID" }, + { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." } + ] + }, + { + "id": "CookieSameSitePolicy", + "type": "string", + "enum": ["None", "Lax", "Strict"], + "description": "Same-Site policy of a cookie." + }, + { + "id": "Cookie", + "type": "object", + "description": "Cookie object", + "properties": [ + { "name": "name", "type": "string", "description": "Cookie name." }, + { "name": "value", "type": "string", "description": "Cookie value." }, + { "name": "domain", "type": "string", "description": "Cookie domain." }, + { "name": "path", "type": "string", "description": "Cookie path." }, + { "name": "expires", "type": "number", "description": "Cookie expires." }, + { "name": "httpOnly", "type": "boolean", "description": "True if cookie is http-only." }, + { "name": "secure", "type": "boolean", "description": "True if cookie is secure." }, + { "name": "session", "type": "boolean", "description": "True if cookie is session cookie." }, + { "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." } + ] + }, + { + "id": "SetCookieParam", + "type": "object", + "description": "Cookie object", + "properties": [ + { "name": "name", "type": "string", "description": "Cookie name." }, + { "name": "value", "type": "string", "description": "Cookie value." }, + { "name": "domain", "type": "string", "description": "Cookie domain." }, + { "name": "path", "type": "string", "description": "Cookie path." }, + { "name": "expires", "type": "number", "optional": true, "description": "Cookie expires." }, + { "name": "httpOnly", "type": "boolean", "optional": true, "description": "True if cookie is http-only." }, + { "name": "secure", "type": "boolean", "optional": true, "description": "True if cookie is secure." }, + { "name": "session", "type": "boolean", "optional": true, "description": "True if cookie is session cookie." }, + { "name": "sameSite", "$ref": "CookieSameSitePolicy", "optional": true, "description": "Cookie Same-Site policy." } + ] + }, + { + "id": "Geolocation", + "type": "object", + "description": "Geolocation", + "properties": [ + { "name": "timestamp", "type": "number", "description": "Mock latitude" }, + { "name": "latitude", "type": "number", "description": "Mock latitude" }, + { "name": "longitude", "type": "number", "description": "Mock longitude" }, + { "name": "accuracy", "type": "number", "description": "Mock accuracy" } + ] + } + ], + "commands": [ + { + "name": "close", + "description": "Close browser." + }, + { + "name": "createContext", + "description": "Creates new ephemeral browser context.", + "returns": [ + { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." } + ] + }, + { + "name": "deleteContext", + "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": "targetId", "type": "string", "description": "Unique identifier for the page target." } + ] + }, + { + "name": "setIgnoreCertificateErrors", + "description": "Change whether all certificate errors should be ignored.", + "parameters": [ + { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }, + { "name": "ignore", "type": "boolean" } + ] + }, + { + "name": "getAllCookies", + "description": "Returns all cookies in the given browser context.", + "async": true, + "parameters": [ + { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." } + ], + "returns": [ + { "name": "cookies", "type": "array", "items": { "$ref": "Cookie" }, "description": "Cookies." } + ] + }, + { + "name": "setCookies", + "description": "Sets cookies in the given browser context.", + "async": true, + "parameters": [ + { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }, + { "name": "cookies", "type": "array", "items": { "$ref": "SetCookieParam" }, "description": "Cookies." } + ] + }, + { + "name": "deleteAllCookies", + "description": "Deletes cookies in the given browser context.", + "async": true, + "parameters": [ + { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." } + ] + }, + { + "name": "setGeolocationOverride", + "parameters": [ + { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }, + { "name": "geolocation", "$ref": "Geolocation", "optional": true, "description": "Geolocation to set, if missing emulates position unavailable." } + ], + "description": "Overrides the geolocation position or error." + }, + { + "name": "grantPermissions", + "parameters": [ + { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }, + { "name": "origin", "type": "string" }, + { "name": "permissions", "type": "array", "items": { "type": "string" } } + ], + "description": "Overrides the permissions." + }, + { + "name": "resetPermissions", + "parameters": [ + { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." } + ], + "description": "Clears permission overrides." + } + ], + "events": [ + { + "name": "pageProxyCreated", + "parameters": [ + { "name": "pageProxyInfo", "$ref": "PageProxyInfo" } + ] + }, + { + "name": "pageProxyDestroyed", + "parameters": [ + { "name": "pageProxyId", "$ref": "PageProxyID" } + ] + } + ] +} diff --git a/Source/JavaScriptCore/inspector/protocol/DOM.json b/Source/JavaScriptCore/inspector/protocol/DOM.json index 38cb48bedf2b168149ff79423b7fafc1e63ce8b3..3baff411b0a97b27146d130d4b1c77910372bd60 100644 --- a/Source/JavaScriptCore/inspector/protocol/DOM.json +++ b/Source/JavaScriptCore/inspector/protocol/DOM.json @@ -167,6 +167,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": [ @@ -481,7 +491,9 @@ "name": "resolveNode", "description": "Resolves JavaScript node object for given node id.", "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": [ @@ -542,6 +554,37 @@ "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": "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..bcf863e4bba3b99f66e75dabfc4d8c1289cc2b78 --- /dev/null +++ b/Source/JavaScriptCore/inspector/protocol/Emulation.json @@ -0,0 +1,32 @@ +{ + "domain": "Emulation", + "availability": ["web"], + "commands": [ + { + "name": "setDeviceMetricsOverride", + "description": "Overrides device metrics with provided values.", + "async": true, + "parameters": [ + { "name": "width", "type": "integer" }, + { "name": "height", "type": "integer" }, + { "name": "deviceScaleFactor", "type": "number" }, + { "name": "fixedLayout", "type": "boolean" } + ] + }, + { + "name": "setJavaScriptEnabled", + "description": "Allows to disable script execution for the page.", + "parameters": [ + { "name": "enabled", "type": "boolean" } + ] + }, + { + "name": "setAuthCredentials", + "description": "Credentials to use during HTTP authentication.", + "parameters": [ + { "name": "username", "type": "string", "optional": true }, + { "name": "password", "type": "string", "optional": true } + ] + } + ] +} diff --git a/Source/JavaScriptCore/inspector/protocol/Input.json b/Source/JavaScriptCore/inspector/protocol/Input.json new file mode 100644 index 0000000000000000000000000000000000000000..34909cce9f6d8d7c74be4c96e40f80cadb2f931d --- /dev/null +++ b/Source/JavaScriptCore/inspector/protocol/Input.json @@ -0,0 +1,165 @@ +{ + "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" + } + ] + } + ] +} diff --git a/Source/JavaScriptCore/inspector/protocol/Network.json b/Source/JavaScriptCore/inspector/protocol/Network.json index 658f14f8af68073b99a01dd7332628223b67fcd7..a8558f5093cedcec7884c6acc03b8bc3dc407163 100644 --- a/Source/JavaScriptCore/inspector/protocol/Network.json +++ b/Source/JavaScriptCore/inspector/protocol/Network.json @@ -258,7 +258,16 @@ "name": "interceptContinue", "description": "Continue an interception with no modifications.", "parameters": [ - { "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network request or response to continue." } + { "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network request or response to continue." }, + { "name": "headers", "$ref": "Headers", "optional": true, "description": "HTTP response headers. Pass through original values if unmodified." } + ] + }, + { + "name": "interceptAsError", + "description": "Abort the intercepted request with given reason.", + "parameters": [ + { "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network request." }, + { "name": "reason", "type": "string", "description": "Deliver error reason for the request." } ] }, { @@ -266,13 +275,20 @@ "description": "Provide response content for an intercepted response.", "parameters": [ { "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network response to modify." }, - { "name": "content", "type": "string" }, - { "name": "base64Encoded", "type": "boolean", "description": "True, if content was sent as base64." }, + { "name": "content", "type": "string", "optional": true }, + { "name": "base64Encoded", "type": "boolean", "optional": true, "description": "True, if content was sent as base64." }, { "name": "mimeType", "type": "string", "optional": true, "description": "MIME Type for the data." }, { "name": "status", "type": "integer", "optional": true, "description": "HTTP response status code. Pass through original values if unmodified." }, { "name": "statusText", "type": "string", "optional": true, "description": "HTTP response status text. Pass through original values if unmodified." }, { "name": "headers", "$ref": "Headers", "optional": true, "description": "HTTP response headers. Pass through original values if unmodified." } ] + }, + { + "name": "setEmulateOfflineState", + "description": "Emulate offline state overriding the actual state.", + "parameters": [ + { "name": "offline", "type": "boolean", "description": "True to emulate offline." } + ] } ], "events": [ @@ -356,6 +372,14 @@ { "name": "response", "$ref": "Response", "description": "Original response content that would proceed if this is continued." } ] }, + { + "name": "requestIntercepted", + "description": "Fired when HTTP request has been intercepted. The frontend must response with Network.interceptContinue or Network.interceptWithRespons` to continue this response.", + "parameters": [ + { "name": "requestId", "$ref": "RequestId", "description": "Identifier for this intercepted network. Corresponds with an earlier Network.requestWillBeSent." }, + { "name": "request", "$ref": "Request", "description": "Original request content that would proceed if this is continued." } + ] + }, { "name": "webSocketWillSendHandshakeRequest", "description": "Fired when WebSocket is about to initiate handshake.", diff --git a/Source/JavaScriptCore/inspector/protocol/Page.json b/Source/JavaScriptCore/inspector/protocol/Page.json index a8fc5332ac92424b00a3dec62152fd3c5f28544e..f68b0722868fbfb449354dead34def546edc3ca7 100644 --- a/Source/JavaScriptCore/inspector/protocol/Page.json +++ b/Source/JavaScriptCore/inspector/protocol/Page.json @@ -110,6 +110,40 @@ { "name": "session", "type": "boolean", "description": "True in case of session cookie." }, { "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."} + ] } ], "commands": [ @@ -129,11 +163,21 @@ { "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.", "parameters": [ - { "name": "url", "type": "string", "description": "URL to navigate the page to." } + { "name": "url", "type": "string", "description": "URL to navigate the page to." }, + { "name": "frameId", "$ref": "Network.FrameId", "optional": true, "description": "Id of the frame to navigate."}, + { "name": "referrer", "type": "string", "optional": true, "description": "Referrer URL." } ] }, { @@ -246,6 +290,13 @@ { "name": "appearance", "$ref": "Appearance", "description": "Appearance name to force. Empty string disables the override." } ] }, + { + "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.", @@ -276,19 +327,68 @@ "returns": [ { "name": "data", "type": "string", "description": "Base64-encoded web archive." } ] + }, + { + "name": "insertText", + "description": "Insert text into the current selection of the page.", + "parameters": [ + { "name": "text", "type": "string", "description": "Text to insert." } + ] + }, + { + "name": "accessibilitySnapshot", + "description": "Serializes and returns all of the accessibility nodes of the page.", + "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": "createIsolatedWorld", + "description": "Creates an isolated world for every loaded frame.", + "parameters": [ + { "name": "name", "type": "string", "description": "Isolated world name, will be used as an execution context name." }, + { "name": "source", "type": "string", "optional": true, "description": "Script to evaluate in the new world." } + ] + }, + { + "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" } ], "events": [ { "name": "domContentEventFired", "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", "parameters": [ - { "name": "timestamp", "type": "number" } + { "name": "timestamp", "type": "number" }, + { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired load event." } ] }, { @@ -298,6 +398,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.", @@ -334,12 +442,36 @@ { "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.", "parameters": [ { "name": "appearance", "$ref": "Appearance", "description": "Name of the appearance that is active (not considering any forced appearance.)" } ] + }, + { + "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/Target.json b/Source/JavaScriptCore/inspector/protocol/Target.json index 52920cded24a9c6b0ef6fb4e518664955db4f9fa..a1bf5f930ac3d58a97397a7a6b918919b4d55c60 100644 --- a/Source/JavaScriptCore/inspector/protocol/Target.json +++ b/Source/JavaScriptCore/inspector/protocol/Target.json @@ -10,8 +10,12 @@ "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": "isPaused", "type": "boolean", "optional": true, "description": "Whether the target is paused on start and has to be explicitely resumed by inspector." } + { "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": "oldTargetId", "type": "string", "optional": true, "description": "Unique identifier of the target which is going to be replaced if this target is committed. Only set for provisional targets." }, + { "name": "openerId", "type": "string", "optional": true, "description": "Unique identifier of the opening target. Only set for pages created by window.open()." }, + { "name": "isPaused", "type": "boolean", "optional": true, "description": "Whether the target is paused on start and has to be explicitely resumed by inspector." }, + { "name": "url", "type": "string" }, + { "name": "browserContextId", "$ref": "Browser.ContextID", "optional": true } ] } ], @@ -37,6 +41,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 +68,8 @@ { "name": "targetDestroyed", "parameters": [ - { "name": "targetId", "type": "string" } + { "name": "targetId", "type": "string" }, + { "name": "crashed", "type": "boolean" } ] }, { diff --git a/Source/WebCore/Modules/geolocation/Geolocation.cpp b/Source/WebCore/Modules/geolocation/Geolocation.cpp index a256d2f8a42548c42ae3c955d9502cc0ad893d91..7e30dfcec151304b21b39286a841e38e35fa3ecf 100644 --- a/Source/WebCore/Modules/geolocation/Geolocation.cpp +++ b/Source/WebCore/Modules/geolocation/Geolocation.cpp @@ -355,8 +355,9 @@ bool Geolocation::shouldBlockGeolocationRequests() bool isSecure = SecurityOrigin::isSecure(document()->url()); bool hasMixedContent = !document()->foundMixedContent().isEmpty(); bool isLocalOrigin = securityOrigin()->isLocal(); + bool isPotentiallyTrustworthy = securityOrigin()->isPotentiallyTrustworthy(); if (securityOrigin()->canRequestGeolocation()) { - if (isLocalOrigin || (isSecure && !hasMixedContent) || isRequestFromIBooks()) + if (isLocalOrigin || isPotentiallyTrustworthy || (isSecure && !hasMixedContent) || isRequestFromIBooks()) return false; } diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt index e453d89097e686b2c3352bad66ee712347c166b5..c53601cd782ffee6f9a215339d88fbcc642f2af2 100644 --- a/Source/WebCore/SourcesCocoa.txt +++ b/Source/WebCore/SourcesCocoa.txt @@ -641,7 +641,7 @@ WHLSLStandardLibraryFunctionMap.cpp #endif -#if ENABLE_IOS_TOUCH_EVENTS +#if ENABLE_TOUCH_EVENTS JSTouch.cpp JSTouchEvent.cpp diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj index d4fb0d3682becb5d4280a7fff26bcb5dda096285..50a2d02ef93418375137aede42c67a87d51ef1b8 100644 --- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj @@ -4930,6 +4930,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, ); }; }; F12171F516A8CED2000053CA /* WebVTTElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F12171F316A8BC63000053CA /* WebVTTElement.cpp */; }; F12171F616A8CF0B000053CA /* WebVTTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = F12171F416A8BC63000053CA /* WebVTTElement.h */; }; F32BDCD92363AACA0073B6AE /* UserGestureEmulationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = F32BDCD72363AACA0073B6AE /* UserGestureEmulationScope.h */; }; @@ -15392,6 +15400,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 = ""; }; @@ -20666,7 +20682,12 @@ 2D2E34A921A4E191004598B5 /* EditableImageReference.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 */, @@ -25861,7 +25882,9 @@ B2C3D9EC0D006C1D00EF6F26 /* text */, E188235F2031F50F00B42DF3 /* vr */, DFDB912CF8E88A6DA1AD264F /* AbortableTaskQueue.h */, + F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */, 49AE2D94134EE5F90072920A /* CalculationValue.cpp */, + F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */, 49AE2D95134EE5F90072920A /* CalculationValue.h */, C330A22113EC196B0000B45B /* ColorChooser.h */, C37CDEBC149EF2030042090D /* ColorChooserClient.h */, @@ -28082,6 +28105,7 @@ BCCFBAE70B5152ED0001F1D7 /* DocumentParser.h */, AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */, AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */, + F050E17323AD6A800011CE47 /* DocumentTouch.cpp */, 6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */, 6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */, 6BDB5DC5227CA0EB00919770 /* DocumentStorageAccess.idl */, @@ -28967,6 +28991,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 */, @@ -30793,6 +30818,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 */, @@ -32697,9 +32723,11 @@ A7DBF8DE1276919C006B6008 /* TextCheckingHelper.h in Headers */, B2C3DA3A0D006C1D00EF6F26 /* TextCodec.h in Headers */, 26E98A10130A9FCA008EB7B2 /* TextCodecASCIIFastPath.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 */, @@ -33588,6 +33616,7 @@ CDDE02ED18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm in Sources */, CDDE02F018B5651300CF7FF1 /* CDMSessionAVStreamSession.mm in Sources */, CDE5959D1BF2757100A1CBE8 /* CDMSessionMediaSourceAVFObjC.mm in Sources */, + F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */, A14090FB1AA51E1D0091191A /* ContentFilterUnblockHandlerCocoa.mm in Sources */, 07AFF4231EFB144900B545B3 /* CoreAudioCaptureSourceIOS.mm in Sources */, 46C696CC1E7205FC00597937 /* CPUMonitor.cpp in Sources */, @@ -33660,6 +33689,7 @@ 51058ADF1D67C229009A538C /* MockGamepad.cpp in Sources */, 51058AE11D67C229009A538C /* MockGamepadProvider.cpp in Sources */, CDF2B0121820540600F2B424 /* MockMediaPlayerMediaSource.cpp in Sources */, + F050E17423AD6A800011CE47 /* DocumentTouch.cpp in Sources */, CDF2B0141820540600F2B424 /* MockMediaSourcePrivate.cpp in Sources */, CDF2B0161820540700F2B424 /* MockSourceBufferPrivate.cpp in Sources */, 2D9BF7421DBFDC27007A7D99 /* NavigatorEME.cpp in Sources */, @@ -33744,6 +33774,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 */, @@ -34276,6 +34307,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/html/FileInputType.cpp b/Source/WebCore/html/FileInputType.cpp index 4e41fd3f807e8f34bfef3f63f0ba6119a619821e..1f7be602cb2134f8867bf95afe0c9337bce57055 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 "RenderFileUploadControl.h" #include "RuntimeEnabledFeatures.h" @@ -205,6 +206,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/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp index 4f18b58c6cd01e0b69a8953ad09a739c3520496a..3a032d9d14a8d5806103f86e687839a165212aa9 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.cpp +++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp @@ -121,7 +121,7 @@ static Frame* frameForScriptExecutionContext(ScriptExecutionContext& context) void InspectorInstrumentation::didClearWindowObjectInWorldImpl(InstrumentingAgents& instrumentingAgents, Frame& frame, DOMWrapperWorld& world) { - if (&world != &mainThreadNormalWorld()) + if (!world.isNormal()) return; if (auto* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent()) @@ -129,9 +129,6 @@ void InspectorInstrumentation::didClearWindowObjectInWorldImpl(InstrumentingAgen if (auto* pageRuntimeAgent = instrumentingAgents.pageRuntimeAgent()) pageRuntimeAgent->didClearWindowObjectInWorld(frame); - - if (auto* pageAgent = instrumentingAgents.inspectorPageAgent()) - pageAgent->didClearWindowObjectInWorld(frame); } bool InspectorInstrumentation::isDebuggerPausedImpl(InstrumentingAgents& instrumentingAgents) @@ -624,6 +621,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.pageRuntimeAgent()) + pageRuntimeAgent->didReceiveMainResourceError(frame); +} + void InspectorInstrumentation::willLoadXHRSynchronouslyImpl(InstrumentingAgents& instrumentingAgents) { if (InspectorNetworkAgent* networkAgent = instrumentingAgents.inspectorNetworkAgent()) @@ -656,20 +659,17 @@ void InspectorInstrumentation::didReceiveScriptResponseImpl(InstrumentingAgents& void InspectorInstrumentation::domContentLoadedEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) { - if (!frame.isMainFrame()) - return; - if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent()) - pageAgent->domContentEventFired(); + pageAgent->domContentEventFired(frame); } void InspectorInstrumentation::loadEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame* frame) { - if (!frame || !frame->isMainFrame()) + if (!frame) return; if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent()) - pageAgent->loadEventFired(); + pageAgent->loadEventFired(*frame); } void InspectorInstrumentation::frameDetachedFromParentImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) @@ -786,6 +786,12 @@ void InspectorInstrumentation::frameClearedScheduledNavigationImpl(Instrumenting inspectorPageAgent->frameClearedScheduledNavigation(frame); } +void InspectorInstrumentation::didNavigateWithinPageImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) +{ + if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.inspectorPageAgent()) + inspectorPageAgent->didNavigateWithinPage(frame); +} + void InspectorInstrumentation::defaultAppearanceDidChangeImpl(InstrumentingAgents& instrumentingAgents, bool useDarkAppearance) { if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.inspectorPageAgent()) @@ -1266,6 +1272,31 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents& ins layerTreeAgent->renderLayerDestroyed(renderLayer); } +void InspectorInstrumentation::runOpenPanelImpl(InstrumentingAgents& instrumentingAgents, HTMLInputElement* element, bool* intercept) +{ + if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent()) + pageAgent->runOpenPanel(element, intercept); +} + +void InspectorInstrumentation::frameAttachedImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) { + if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent()) + pageAgent->frameAttached(frame); +} + +bool InspectorInstrumentation::shouldBypassCSPImpl(InstrumentingAgents& instrumentingAgents) +{ + if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent()) + return pageAgent->shouldBypassCSP(); + return false; +} + +bool InspectorInstrumentation::interceptRequestImpl(InstrumentingAgents& instrumentingAgents, ResourceLoader& loader, CompletionHandler&& handler) +{ + if (InspectorNetworkAgent* networkAgent = instrumentingAgents.inspectorNetworkAgent()) + return networkAgent->interceptRequest(loader, WTFMove(handler)); + return false; +} + InstrumentingAgents& InspectorInstrumentation::instrumentingAgentsForWorkerGlobalScope(WorkerGlobalScope& workerGlobalScope) { return workerGlobalScope.inspectorController().m_instrumentingAgents; diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h index dbf82205db5bccbe169ed0e947d1ad83dd850fd6..c76c5f752684da94720b798591784323cd15f080 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.h +++ b/Source/WebCore/inspector/InspectorInstrumentation.h @@ -45,6 +45,7 @@ #include "HitTestResult.h" #include "InspectorInstrumentationPublic.h" #include "Page.h" +#include "ResourceLoader.h" #include "StorageArea.h" #include "WebAnimation.h" #include @@ -77,6 +78,7 @@ class DOMWrapperWorld; class Document; class DocumentLoader; class EventListener; +class HTMLInputElement; class HTTPHeaderMap; class InspectorTimelineAgent; class InstrumentingAgents; @@ -197,6 +199,7 @@ public: static void didReceiveData(Frame*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength); static void didFinishLoading(Frame*, DocumentLoader*, unsigned long identifier, const NetworkLoadMetrics&, ResourceLoader*); static void didFailLoading(Frame*, DocumentLoader*, unsigned long identifier, const ResourceError&); + static void didReceiveMainResourceError(Frame&, const ResourceError&); static void willSendRequest(WorkerGlobalScope&, unsigned long identifier, ResourceRequest&); static void didReceiveResourceResponse(WorkerGlobalScope&, unsigned long identifier, const ResourceResponse&); @@ -228,6 +231,7 @@ public: static void frameStoppedLoading(Frame&); static void frameScheduledNavigation(Frame&, Seconds delay); static void frameClearedScheduledNavigation(Frame&); + static void didNavigateWithinPage(Frame&); static void defaultAppearanceDidChange(Page&, bool useDarkAppearance); static void willDestroyCachedResource(CachedResource&); @@ -314,6 +318,11 @@ 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 bool interceptRequest(ResourceLoader&, CompletionHandler&&); + static void frontendCreated(); static void frontendDeleted(); static bool hasFrontends() { return InspectorInstrumentationPublic::hasFrontends(); } @@ -414,6 +423,7 @@ private: static void didReceiveDataImpl(InstrumentingAgents&, unsigned long identifier, const char* data, int dataLength, int encodedDataLength); static void didFinishLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, const NetworkLoadMetrics&, ResourceLoader*); static void didFailLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, const ResourceError&); + static void didReceiveMainResourceErrorImpl(InstrumentingAgents&, Frame&, const ResourceError&); static void willLoadXHRSynchronouslyImpl(InstrumentingAgents&); static void didLoadXHRSynchronouslyImpl(InstrumentingAgents&); static void scriptImportedImpl(InstrumentingAgents&, unsigned long identifier, const String& sourceString); @@ -429,6 +439,7 @@ private: static void frameStoppedLoadingImpl(InstrumentingAgents&, Frame&); static void frameScheduledNavigationImpl(InstrumentingAgents&, Frame&, Seconds delay); static void frameClearedScheduledNavigationImpl(InstrumentingAgents&, Frame&); + static void didNavigateWithinPageImpl(InstrumentingAgents&, Frame&); static void defaultAppearanceDidChangeImpl(InstrumentingAgents&, bool useDarkAppearance); static void willDestroyCachedResourceImpl(CachedResource&); @@ -511,6 +522,11 @@ 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 bool interceptRequestImpl(InstrumentingAgents&, ResourceLoader&, CompletionHandler&&); + static InstrumentingAgents& instrumentingAgentsForPage(Page&); static InstrumentingAgents& instrumentingAgentsForWorkerGlobalScope(WorkerGlobalScope&); @@ -1091,6 +1107,13 @@ inline void InspectorInstrumentation::didFailLoading(Frame* frame, DocumentLoade didFailLoadingImpl(*instrumentingAgents, identifier, loader, error); } +inline void InspectorInstrumentation::didReceiveMainResourceError(Frame& frame, const ResourceError& error) +{ + FAST_RETURN_IF_NO_FRONTENDS(void()); + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame)) + didReceiveMainResourceErrorImpl(*instrumentingAgents, frame, error); +} + inline void InspectorInstrumentation::didFailLoading(WorkerGlobalScope& workerGlobalScope, unsigned long identifier, const ResourceError& error) { didFailLoadingImpl(instrumentingAgentsForWorkerGlobalScope(workerGlobalScope), identifier, nullptr, error); @@ -1221,6 +1244,13 @@ inline void InspectorInstrumentation::frameClearedScheduledNavigation(Frame& fra frameClearedScheduledNavigationImpl(*instrumentingAgents, frame); } +inline void InspectorInstrumentation::didNavigateWithinPage(Frame& frame) +{ + FAST_RETURN_IF_NO_FRONTENDS(void()); + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame)) + didNavigateWithinPageImpl(*instrumentingAgents, frame); +} + inline void InspectorInstrumentation::defaultAppearanceDidChange(Page& page, bool useDarkAppearance) { FAST_RETURN_IF_NO_FRONTENDS(void()); @@ -1650,6 +1680,36 @@ inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const Ren renderLayerDestroyedImpl(*instrumentingAgents, renderLayer); } +inline void InspectorInstrumentation::runOpenPanel(Frame* frame, HTMLInputElement* element, bool* intercept) +{ + FAST_RETURN_IF_NO_FRONTENDS(void()); + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(*frame)) + runOpenPanelImpl(*instrumentingAgents, element, intercept); +} + +inline void InspectorInstrumentation::frameAttached(Frame* frame) +{ + FAST_RETURN_IF_NO_FRONTENDS(void()); + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame)) + frameAttachedImpl(*instrumentingAgents, *frame); +} + +inline bool InspectorInstrumentation::shouldBypassCSP(ScriptExecutionContext* context) +{ + FAST_RETURN_IF_NO_FRONTENDS(false); + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context)) + return shouldBypassCSPImpl(*instrumentingAgents); + return false; +} + +inline bool InspectorInstrumentation::interceptRequest(ResourceLoader& loader, CompletionHandler&& handler) +{ + FAST_RETURN_IF_NO_FRONTENDS(false); + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(loader.frame())) + return interceptRequestImpl(*instrumentingAgents, loader, WTFMove(handler)); + return false; +} + inline InstrumentingAgents* InspectorInstrumentation::instrumentingAgentsForContext(ScriptExecutionContext* context) { return context ? instrumentingAgentsForContext(*context) : nullptr; diff --git a/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp b/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp index 954aaf121a9fa507d83bc10ae37de1f128f7dcfc..043bfa8b5302e599e3fd2ad729e09acb211a0ec3 100644 --- a/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp +++ b/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp @@ -30,6 +30,11 @@ namespace WebCore { +bool InspectorInstrumentationWebKit::interceptRequestInternal(ResourceLoader& loader, CompletionHandler&& handler) +{ + return InspectorInstrumentation::interceptRequest(loader, WTFMove(handler)); +} + bool InspectorInstrumentationWebKit::shouldInterceptResponseInternal(const Frame& frame, const ResourceResponse& response) { return InspectorInstrumentation::shouldInterceptResponse(frame, response); diff --git a/Source/WebCore/inspector/InspectorInstrumentationWebKit.h b/Source/WebCore/inspector/InspectorInstrumentationWebKit.h index b67e89b80b4e7a8586cac81ade5d58a1bcb0d431..e7b2cebbe0054802fb5378f269570c28497ed0ff 100644 --- a/Source/WebCore/inspector/InspectorInstrumentationWebKit.h +++ b/Source/WebCore/inspector/InspectorInstrumentationWebKit.h @@ -36,14 +36,22 @@ class SharedBuffer; class WEBCORE_EXPORT InspectorInstrumentationWebKit { public: + static bool interceptRequest(ResourceLoader&, CompletionHandler&&); static bool shouldInterceptResponse(const Frame*, const ResourceResponse&); static void interceptResponse(const Frame*, const ResourceResponse&, unsigned long identifier, CompletionHandler)>&&); private: + static bool interceptRequestInternal(ResourceLoader&, CompletionHandler&&); static bool shouldInterceptResponseInternal(const Frame&, const ResourceResponse&); static void interceptResponseInternal(const Frame&, const ResourceResponse&, unsigned long identifier, CompletionHandler)>&&); }; +inline bool InspectorInstrumentationWebKit::interceptRequest(ResourceLoader& loader, CompletionHandler&& handler) +{ + FAST_RETURN_IF_NO_FRONTENDS(false); + return interceptRequestInternal(loader, WTFMove(handler)); +} + inline bool InspectorInstrumentationWebKit::shouldInterceptResponse(const Frame* frame, const ResourceResponse& response) { FAST_RETURN_IF_NO_FRONTENDS(false); diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp index aecc79bc0ca56fb65fe0330f08e4ee688bf81e89..7b78b5a90004786aee21161bee739c1270e4ba7c 100644 --- a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp @@ -61,12 +61,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" @@ -93,11 +97,13 @@ #include "Page.h" #include "Pasteboard.h" #include "PseudoElement.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" @@ -128,7 +134,8 @@ using namespace HTMLNames; static const size_t maxTextSize = 10000; static const UChar ellipsisUChar[] = { 0x2026, 0 }; -static Color parseColor(const JSON::Object* colorObject) +// static +Color InspectorDOMAgent::parseColor(const JSON::Object* colorObject) { if (!colorObject) return Color::transparent; @@ -157,7 +164,7 @@ static Color parseConfigColor(const String& fieldName, const JSON::Object* confi RefPtr colorObject; configObject->getObject(fieldName, colorObject); - return parseColor(colorObject.get()); + return InspectorDOMAgent::parseColor(colorObject.get()); } static bool parseQuad(const JSON::Array& quadArray, FloatQuad* quad) @@ -438,6 +445,20 @@ Node* InspectorDOMAgent::assertNode(ErrorString& errorString, int nodeId) return node; } +Node* InspectorDOMAgent::assertNode(ErrorString& errorString, const int* 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(ErrorString& errorString, int nodeId) { Node* node = assertNode(errorString, nodeId); @@ -1318,16 +1339,7 @@ void InspectorDOMAgent::highlightSelector(ErrorString& errorString, const JSON:: void InspectorDOMAgent::highlightNode(ErrorString& errorString, const JSON::Object& highlightInspectorObject, const int* 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; - + Node* node = assertNode(errorString, nodeId, objectId); if (!node) return; @@ -1475,18 +1487,103 @@ void InspectorDOMAgent::setInspectedNode(ErrorString& errorString, int nodeId) m_suppressEventListenerChangedEvent = false; } -void InspectorDOMAgent::resolveNode(ErrorString& errorString, int nodeId, const String* objectGroup, RefPtr& result) +static FloatPoint contentsToRootView(FrameView& containingView, const FloatPoint& point) { - String objectGroupName = objectGroup ? *objectGroup : emptyString(); - Node* node = assertNode(errorString, nodeId); + return containingView.convertToRootView(point - toFloatSize(containingView.documentScrollPositionRelativeToViewOrigin())); +} + +static void frameQuadToViewport(FrameView& containingView, FloatQuad& quad) +{ + quad.setP1(contentsToRootView(containingView, quad.p1())); + quad.setP2(contentsToRootView(containingView, quad.p2())); + quad.setP3(contentsToRootView(containingView, quad.p3())); + quad.setP4(contentsToRootView(containingView, quad.p4())); +} + +static RefPtr 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 RefPtr> buildArrayOfQuads(const Vector& quads) +{ + auto result = JSON::ArrayOf::create(); + for (const auto& quad : quads) + result->addItem(buildObjectForQuad(quad)); + return result; +} + +void InspectorDOMAgent::describeNode(ErrorString& errorString, const String& objectId, Optional& contentFrameId, Optional& ownerFrameId) +{ + Node* node = nodeForObjectId(objectId); + if (!node) { + errorString = "Node not found"_s; + return; + } + + auto* pageAgent = m_instrumentingAgents.inspectorPageAgent(); + if (!pageAgent) { + errorString = "Page agent must be enabled"_s; + return; + } + + String frameId = pageAgent->frameId(node->document().frame()); + if (!frameId.isEmpty()) + ownerFrameId = frameId; + + if (is(*node)) { + const auto& frameOwner = downcast(*node); + String frameId = pageAgent->frameId(frameOwner.contentFrame()); + if (!frameId.isEmpty()) + contentFrameId = frameId; + } +} + +void InspectorDOMAgent::getContentQuads(ErrorString& errorString, const String& objectId, RefPtr>& contentQuads) +{ + Node* node = nodeForObjectId(objectId); + if (!node) { + errorString = "Node not found"_s; + return; + } + RenderObject* renderer = node->renderer(); + if (!renderer) { + errorString = "Node doesn't have renderer"_s; + return; + } + Frame* containingFrame = renderer->document().frame(); + FrameView* containingView = containingFrame ? containingFrame->view() : nullptr; + if (!containingView) { + errorString = "Internal error: no containing view"_s; + return; + } + Vector quads; + renderer->absoluteQuads(quads); + for (auto& quad : quads) + frameQuadToViewport(*containingView, quad); + contentQuads = buildArrayOfQuads(quads); +} + +void InspectorDOMAgent::resolveNode(ErrorString& errorString, const int* nodeId, const String* objectId, const int* contextId, const String* objectGroup, RefPtr& result) +{ + Node* node = assertNode(errorString, nodeId, objectId); if (!node) return; - RefPtr object = resolveNode(node, objectGroupName); - if (!object) { + String objectGroupName = objectGroup ? *objectGroup : emptyString(); + result = resolveNode(node, objectGroupName, contextId); + if (!result) { errorString = "Missing injected script for given nodeId"_s; return; } - result = object; } void InspectorDOMAgent::getAttributes(ErrorString& errorString, int nodeId, RefPtr>& result) @@ -2651,7 +2748,7 @@ void InspectorDOMAgent::pushNodeByPathToFrontend(ErrorString& errorString, const errorString = "Missing node for given path"_s; } -RefPtr InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup) +RefPtr InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup, const int* contextId) { Document* document = &node->document(); if (auto* templateHost = document->templateDocumentHost()) @@ -2660,12 +2757,16 @@ RefPtr InspectorDOMAgent::resolveNod 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) @@ -2686,4 +2787,46 @@ void InspectorDOMAgent::setAllowEditingUserAgentShadowTrees(ErrorString&, bool a m_allowEditingUserAgentShadowTrees = allow; } +void InspectorDOMAgent::setInputFiles(ErrorString& errorString, const String& objectId, const JSON::Array& files) { + InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); + if (injectedScript.hasNoValue()) { + errorString = "Can not find element's context for given id"_s; + return; + } + Node* node = scriptValueAsNode(injectedScript.findObjectById(objectId)); + if (!node) { + errorString = "Can not find element for given id"_s; + return; + } + if (node->nodeType() != Node::ELEMENT_NODE || node->nodeName() != "INPUT") { + errorString = "Not an input node"_s; + return; + } + HTMLInputElement* element = static_cast(node); + Vector> fileObjects; + for (unsigned i = 0; i < files.length(); ++i) { + RefPtr item = files.get(i); + RefPtr obj; + if (!item->asObject(obj)) { + errorString = "Invalid file payload format"_s; + return; + } + String name; + String type; + String data; + if (!obj->getString("name", name) || !obj->getString("type", type) || !obj->getString("data", data)) { + errorString = "Invalid file payload format"_s; + return; + } + Vector buffer; + if (!base64Decode(data, buffer)) { + errorString = "Unable to decode given content"_s; + return; + } + fileObjects.append(File::create(Blob::create(SharedBuffer::create(WTFMove(buffer)), type), name)); + } + RefPtr fileList = FileList::create(WTFMove(fileObjects)); + element->setFiles(WTFMove(fileList)); +} + } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.h b/Source/WebCore/inspector/agents/InspectorDOMAgent.h index 51639abeb84f4d95ded3f4fb6409ad8f62a2894e..d651c0ceb58774d446f0201fc1a1bc8646c04860 100644 --- a/Source/WebCore/inspector/agents/InspectorDOMAgent.h +++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.h @@ -54,6 +54,7 @@ namespace WebCore { class AXCoreObject; class CharacterData; +class Color; class DOMEditor; class Document; class Element; @@ -88,6 +89,7 @@ public: static String toErrorString(Exception&&); static String documentURLString(Document*); + static Color parseColor(const JSON::Object*); // We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently. // We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics. @@ -129,7 +131,7 @@ public: void performSearch(ErrorString&, const String& query, const JSON::Array* nodeIds, const bool* caseSensitive, String* searchId, int* resultCount) override; void getSearchResults(ErrorString&, const String& searchId, int fromIndex, int toIndex, RefPtr>&) override; void discardSearchResults(ErrorString&, const String& searchId) override; - void resolveNode(ErrorString&, int nodeId, const String* objectGroup, RefPtr& result) override; + void resolveNode(ErrorString&, const int* nodeId, const String* objectId, const int* contextId, const String* objectGroup, RefPtr& result) override; void getAttributes(ErrorString&, int nodeId, RefPtr>& result) override; void setInspectModeEnabled(ErrorString&, bool enabled, const JSON::Object* highlightConfig, const bool* showRulers) override; void requestNode(ErrorString&, const String& objectId, int* nodeId) override; @@ -148,6 +150,9 @@ public: void focus(ErrorString&, int nodeId) override; void setInspectedNode(ErrorString&, int nodeId) override; void setAllowEditingUserAgentShadowTrees(ErrorString&, bool allow) final; + void describeNode(ErrorString&, const String& objectId, Optional& contentFrameId, Optional& ownerFrameId) override; + void getContentQuads(ErrorString&, const String& objectId, RefPtr>&) override; + void setInputFiles(ErrorString&, const String& objectId, const JSON::Array& files) override; // InspectorInstrumentation int identifierForNode(Node&); @@ -183,7 +188,7 @@ public: Node* nodeForId(int nodeId); int boundNodeId(const Node*); - RefPtr resolveNode(Node*, const String& objectGroup); + RefPtr resolveNode(Node*, const String& objectGroup, const int* contextId); bool handleMousePress(); void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags); void inspect(Node*); @@ -194,6 +199,7 @@ public: void reset(); Node* assertNode(ErrorString&, int nodeId); + Node* assertNode(ErrorString&, const int* nodeId, const String* objectId); Element* assertElement(ErrorString&, int nodeId); Document* assertDocument(ErrorString&, int nodeId); diff --git a/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h b/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h index b578660fbb3ce176e4e0aeb5a22021dc880e47f0..a7c968bc9f88c7d26e1887bb53106b4af2464753 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 ca8f169d18a697a4dea405c933398e67feef01c6..25ec31140dd0f163f6e815428c0e4673c8d9b49c 100644 --- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp @@ -56,6 +56,7 @@ #include "MIMETypeRegistry.h" #include "MemoryCache.h" #include "NetworkResourcesData.h" +#include "NetworkStateNotifier.h" #include "Page.h" #include "PlatformStrategies.h" #include "ProgressTracker.h" @@ -99,6 +100,11 @@ using namespace Inspector; namespace { +String inspectorInitiatorPrefix() +{ + return "InspectorPageAgent.navigate referrer:"_s; +} + class InspectorThreadableLoaderClient final : public ThreadableLoaderClient { WTF_MAKE_NONCOPYABLE(InspectorThreadableLoaderClient); public: @@ -437,6 +443,13 @@ void InspectorNetworkAgent::willSendRequest(unsigned long identifier, DocumentLo for (auto& entry : m_extraRequestHeaders) request.setHTTPHeaderField(entry.key, entry.value); + if (request.initiatorIdentifier().startsWith(inspectorInitiatorPrefix())) { + String referrer = request.initiatorIdentifier().substring(inspectorInitiatorPrefix().length()); + if (!referrer.isEmpty()) + request.setHTTPReferrer(referrer); + request.setInitiatorIdentifier(String()); + } + auto protocolResourceType = InspectorPageAgent::resourceTypeJSON(type); Document* document = loader && loader->frame() ? loader->frame()->document() : nullptr; @@ -1109,19 +1122,117 @@ void InspectorNetworkAgent::interceptResponse(const ResourceResponse& response, m_frontendDispatcher->responseIntercepted(requestId, buildObjectForResourceResponse(response, nullptr)); } -void InspectorNetworkAgent::interceptContinue(ErrorString& errorString, const String& requestId) -{ +bool InspectorNetworkAgent::interceptRequest(ResourceLoader& loader, CompletionHandler&& handler) { + if (!m_interceptionEnabled) + return false; + String requestId = IdentifiersFactory::requestId(loader.identifier()); + auto pendingRequest = makeUnique(); + pendingRequest->m_loader = &loader; + pendingRequest->m_callback = WTFMove(handler); + m_pendingInterceptRequests.set(requestId, WTFMove(pendingRequest)); + m_frontendDispatcher->requestIntercepted(requestId, buildObjectForResourceRequest(loader.request())); + return true; +} + +void InspectorNetworkAgent::interceptContinue(ErrorString& errorString, const String& requestId, const JSON::Object* headers) +{ + auto pendingRequest = m_pendingInterceptRequests.take(requestId); + if (pendingRequest) { + ResourceLoader* loader = pendingRequest->m_loader.get(); + if (!loader->identifier()) { + // Do not throw upon continue of canceled requests. + return; + } + if (headers) { + // Safe to const cast at this point, we are only adjusting the headers. + ResourceRequest* request = const_cast(&loader->request()); + HTTPHeaderMap explicitHeaders; + for (auto& header : *headers) { + String headerValue; + if (header.value->asString(headerValue)) + explicitHeaders.add(header.key, headerValue); + } + request->setHTTPHeaderFields(WTFMove(explicitHeaders)); + } + pendingRequest->m_callback(false); + return; + } + auto pendingInterceptResponse = m_pendingInterceptResponses.take(requestId); - if (!pendingInterceptResponse) { - errorString = "Missing pending intercept response for given requestId"_s; + if (pendingInterceptResponse) { + pendingInterceptResponse->respondWithOriginalResponse(); return; } - pendingInterceptResponse->respondWithOriginalResponse(); + errorString = "Missing pending intercept response for given requestId"_s; } -void InspectorNetworkAgent::interceptWithResponse(ErrorString& errorString, const String& requestId, const String& content, bool base64Encoded, const String* mimeType, const int* status, const String* statusText, const JSON::Object* headers) +void InspectorNetworkAgent::interceptAsError(ErrorString& errorString, const String& requestId, const String& reason) { + auto pendingRequest = m_pendingInterceptRequests.take(requestId); + if (pendingRequest) { + ResourceLoader* loader = pendingRequest->m_loader.get(); + if (!loader->identifier()) { + errorString = "Unable to abort request, it has already been processed"_s; + return; + } + ResourceError error(errorDomainWebKitInternal, 0, loader->url(), "Request intercepted"_s, ResourceError::Type::General); + if (reason == "AccessControl") + error = ResourceError(errorDomainWebKitInternal, 0, loader->url(), "Access denied"_s, ResourceError::Type::AccessControl); + else if (reason == "Cancellation") + error = ResourceError(errorDomainWebKitInternal, 0, loader->url(), "Request canceled"_s, ResourceError::Type::Cancellation); + else if (reason == "Timeout") + error = ResourceError(errorDomainWebKitInternal, 0, loader->url(), "Request timed out"_s, ResourceError::Type::Timeout); + loader->didFail(error); + pendingRequest->m_callback(true); + return; + } + + errorString = "Missing pending intercept response for given requestId"_s; +} + +void InspectorNetworkAgent::interceptWithResponse(ErrorString& errorString, const String& requestId, const String* content, const bool* base64Encoded, const String* mimeType, const int* status, const String* statusText, const JSON::Object* headers) +{ + auto pendingRequest = m_pendingInterceptRequests.take(requestId); + if (pendingRequest && status && statusText && mimeType && headers) { + RefPtr loader = pendingRequest->m_loader.get(); + if (!loader->identifier()) { + errorString = "Unable to fulfill request, it has already been processed"_s; + return; + } + RefPtr data; + if (base64Encoded && *base64Encoded && content) { + Vector buffer; + if (!base64Decode(*content, buffer)) { + errorString = "Unable to decode given content"_s; + return; + } + data = SharedBuffer::create(WTFMove(buffer)); + } else if (content) { + data = SharedBuffer::create(content->utf8().data(), content->utf8().length()); + } + + ResourceResponse response(pendingRequest->m_loader->url(), *mimeType, data->size(), String()); + response.setSource(ResourceResponse::Source::InspectorOverride); + response.setHTTPStatusCode(*status); + response.setHTTPStatusText(*statusText); + HTTPHeaderMap explicitHeaders; + for (auto& header : *headers) { + String headerValue; + if (header.value->asString(headerValue)) + explicitHeaders.add(header.key, headerValue); + } + response.setHTTPHeaderFields(WTFMove(explicitHeaders)); + response.setHTTPHeaderField(HTTPHeaderName::ContentType, response.mimeType()); + loader->didReceiveResponse(response, [loader, data = data.releaseNonNull()]() mutable { + if (data->size()) + loader->didReceiveBuffer(WTFMove(data), data->size(), DataPayloadWholeResource); + loader->didFinishLoading(NetworkLoadMetrics()); + }); + pendingRequest->m_callback(true); + return; + } + auto pendingInterceptResponse = m_pendingInterceptResponses.take(requestId); if (!pendingInterceptResponse) { errorString = "Missing pending intercept response for given requestId"_s; @@ -1149,20 +1260,26 @@ void InspectorNetworkAgent::interceptWithResponse(ErrorString& errorString, cons } RefPtr overrideData; - if (base64Encoded) { + if (base64Encoded && *base64Encoded && content) { Vector buffer; - if (!base64Decode(content, buffer)) { + if (!base64Decode(*content, buffer)) { errorString = "Unable to decode given content"_s; pendingInterceptResponse->respondWithOriginalResponse(); return; } overrideData = SharedBuffer::create(WTFMove(buffer)); - } else - overrideData = SharedBuffer::create(content.utf8().data(), content.utf8().length()); + } else if (content) { + overrideData = SharedBuffer::create(content->utf8().data(), content->utf8().length()); + } pendingInterceptResponse->respond(overrideResponse, overrideData); } +void InspectorNetworkAgent::setEmulateOfflineState(ErrorString&, bool offline) +{ + platformStrategies()->loaderStrategy()->setEmulateOfflineState(offline); +} + bool InspectorNetworkAgent::shouldTreatAsText(const String& mimeType) { return startsWithLettersIgnoringASCIICase(mimeType, "text/") @@ -1292,6 +1409,11 @@ void InspectorNetworkAgent::searchInRequest(ErrorString& errorString, const Stri results = ContentSearchUtilities::searchInTextByLines(resourceData->content(), query, caseSensitive, isRegex); } +String InspectorNetworkAgent::createInitiatorIdentifierForInspectorNavigation(const String& referrer) +{ + return inspectorInitiatorPrefix() + referrer; +} + void InspectorNetworkAgent::mainFrameNavigated(DocumentLoader& loader) { m_resourcesData->clear(loaderIdentifier(&loader)); diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h index a68f84520736977c8b9216616c5a178fbf5275d6..c36811c04d95c78b7747e6e625bf79ea33cfa0d9 100644 --- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h +++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h @@ -90,8 +90,10 @@ public: void setInterceptionEnabled(ErrorString&, bool enabled) final; void addInterception(ErrorString&, const String& url, const bool* caseSensitive, const bool* isRegex, const String* networkStageString) final; void removeInterception(ErrorString&, const String& url, const bool* caseSensitive, const bool* isRegex, const String* networkStageString) final; - void interceptContinue(ErrorString&, const String& requestId) final; - void interceptWithResponse(ErrorString&, const String& requestId, const String& content, bool base64Encoded, const String* mimeType, const int* status, const String* statusText, const JSON::Object* headers) final; + void interceptContinue(ErrorString&, const String& requestId, const JSON::Object* headers) final; + void interceptAsError(ErrorString&, const String& requestId, const String& reason) final; + void interceptWithResponse(ErrorString&, const String& requestId, const String* content, const bool* base64Encoded, const String* mimeType, const int* status, const String* statusText, const JSON::Object* headers) final; + void setEmulateOfflineState(ErrorString&, bool offline) final; // InspectorInstrumentation void willRecalculateStyle(); @@ -121,10 +123,13 @@ public: bool willInterceptRequest(const ResourceRequest&); bool shouldInterceptResponse(const ResourceResponse&); void interceptResponse(const ResourceResponse&, unsigned long identifier, CompletionHandler)>&&); + bool interceptRequest(ResourceLoader& loader, CompletionHandler&&); void searchOtherRequests(const JSC::Yarr::RegularExpression&, RefPtr>&); void searchInRequest(ErrorString&, const String& requestId, const String& query, bool caseSensitive, bool isRegex, RefPtr>&); + static String createInitiatorIdentifierForInspectorNavigation(const String& referrer); + protected: InspectorNetworkAgent(WebAgentContext&); @@ -191,6 +196,15 @@ private: bool m_responded { false }; }; + class PendingInterceptRequest { + WTF_MAKE_NONCOPYABLE(PendingInterceptRequest); + WTF_MAKE_FAST_ALLOCATED; + public: + PendingInterceptRequest() = default; + RefPtr m_loader; + CompletionHandler m_callback; + }; + std::unique_ptr m_frontendDispatcher; RefPtr m_backendDispatcher; Inspector::InjectedScriptManager& m_injectedScriptManager; @@ -214,6 +228,7 @@ private: }; Vector m_intercepts; HashMap> m_pendingInterceptResponses; + HashMap> m_pendingInterceptRequests; // FIXME: InspectorNetworkAgent should not be aware of style recalculation. RefPtr m_styleRecalculationInitiator; diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp index d4e6b5d1f2151a1f4c16081b2695dd66da416ba2..8e54267226f5fe66c10f1dc7251be9c320b9b062 100644 --- a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp @@ -32,6 +32,8 @@ #include "config.h" #include "InspectorPageAgent.h" +#include "AXObjectCache.h" +#include "BackForwardController.h" #include "CachedResource.h" #include "CachedResourceLoader.h" #include "Cookie.h" @@ -39,12 +41,14 @@ #include "CustomHeaderFields.h" #include "Document.h" #include "DocumentLoader.h" +#include "FocusController.h" #include "Frame.h" #include "FrameLoadRequest.h" #include "FrameLoader.h" #include "FrameSnapshotting.h" #include "FrameView.h" #include "HTMLFrameOwnerElement.h" +#include "HTMLInputElement.h" #include "HTMLNames.h" #include "ImageBuffer.h" #include "InspectorClient.h" @@ -55,17 +59,22 @@ #include "MIMETypeRegistry.h" #include "MemoryCache.h" #include "Page.h" +#include "PageRuntimeAgent.h" #include "RenderObject.h" #include "RenderTheme.h" +#include "RuntimeEnabledFeatures.h" #include "ScriptController.h" #include "ScriptSourceCode.h" +#include "ScriptState.h" #include "SecurityOrigin.h" #include "Settings.h" #include "StyleScope.h" #include "TextEncoding.h" +#include "TypingCommand.h" #include "UserGestureIndicator.h" #include #include +#include #include #include #include @@ -339,6 +348,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) { @@ -377,6 +387,8 @@ void InspectorPageAgent::enable(ErrorString& errorString) void InspectorPageAgent::disable(ErrorString&) { m_instrumentingAgents.setInspectorPageAgent(nullptr); + m_interceptFileChooserDialog = false; + m_bypassCSP = false; ErrorString unused; setShowPaintRects(unused, false); @@ -384,6 +396,7 @@ void InspectorPageAgent::disable(ErrorString&) overrideUserAgent(unused, nullptr); setEmulatedMedia(unused, emptyString()); setForcedAppearance(unused, emptyString()); + m_isolatedWorldScripts.clear(); #define DISABLE_INSPECTOR_OVERRIDE_SETTING(name) \ m_inspectedPage.settings().set##name##InspectorOverride(WTF::nullopt); @@ -414,14 +427,36 @@ void InspectorPageAgent::reload(ErrorString&, const bool* optionalReloadFromOrig m_inspectedPage.mainFrame().loader().reload(reloadOptions); } -void InspectorPageAgent::navigate(ErrorString&, const String& url) +void InspectorPageAgent::goBack(ErrorString& errorString) +{ + if (!m_inspectedPage.backForward().goBack()) + errorString = "Failed to go back"_s; +} + +void InspectorPageAgent::goForward(ErrorString& errorString) +{ + if (!m_inspectedPage.backForward().goForward()) + errorString = "Failed to go forward"_s; +} + +void InspectorPageAgent::navigate(ErrorString& errorString, const String& url, const String* frameId, const String* referrer) { UserGestureIndicator indicator { ProcessingUserGesture }; - Frame& frame = m_inspectedPage.mainFrame(); + Frame* frame = frameId ? assertFrame(errorString, *frameId) : &m_inspectedPage.mainFrame(); + if (!frame) + return; + + ResourceRequest resourceRequest { frame->document()->completeURL(url) }; + + if (!resourceRequest.url().isValid()) { + errorString = "Cannot navigate to invalid URL"_s; + return; + } - ResourceRequest resourceRequest { frame.document()->completeURL(url) }; - FrameLoadRequest frameLoadRequest { *frame.document(), frame.document()->securityOrigin(), resourceRequest, "_self"_s, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown }; - frame.loader().changeLocation(WTFMove(frameLoadRequest)); + if (referrer) + resourceRequest.setInitiatorIdentifier(InspectorNetworkAgent::createInitiatorIdentifierForInspectorNavigation(*referrer)); + FrameLoadRequest frameLoadRequest { *frame->document(), frame->document()->securityOrigin(), resourceRequest, "_self"_s, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown }; + frame->loader().changeLocation(WTFMove(frameLoadRequest)); } void InspectorPageAgent::overrideUserAgent(ErrorString&, const String* value) @@ -682,15 +717,16 @@ void InspectorPageAgent::setShowPaintRects(ErrorString&, bool show) m_overlay->setShowPaintRects(show); } -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) @@ -765,17 +801,15 @@ void InspectorPageAgent::frameClearedScheduledNavigation(Frame& frame) m_frontendDispatcher->frameClearedScheduledNavigation(frameId(&frame)); } -void InspectorPageAgent::defaultAppearanceDidChange(bool useDarkAppearance) +void InspectorPageAgent::didNavigateWithinPage(Frame& frame) { - m_frontendDispatcher->defaultAppearanceDidChange(useDarkAppearance ? Inspector::Protocol::Page::Appearance::Dark : Inspector::Protocol::Page::Appearance::Light); + String url = frame.document()->url().string(); + m_frontendDispatcher->navigatedWithinDocument(frameId(&frame), url); } -void InspectorPageAgent::didClearWindowObjectInWorld(Frame& frame) +void InspectorPageAgent::defaultAppearanceDidChange(bool useDarkAppearance) { - if (m_bootstrapScript.isEmpty()) - return; - - frame.script().evaluateIgnoringException(ScriptSourceCode(m_bootstrapScript, URL { URL(), "web-inspector://bootstrap.js"_s })); + m_frontendDispatcher->defaultAppearanceDidChange(useDarkAppearance ? Inspector::Protocol::Page::Appearance::Dark : Inspector::Protocol::Page::Appearance::Light); } void InspectorPageAgent::didPaint(RenderObject& renderer, const LayoutRect& rect) @@ -819,6 +853,38 @@ 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; + + m_frontendDispatcher->fileChooserOpened(frameId(frame), injectedScript.wrapObject(InspectorDOMAgent::nodeAsScriptValue(state, element), WTF::String())); +} + +void InspectorPageAgent::frameAttached(Frame& frame) +{ + Frame* parent = frame.tree().parent(); + String parentFrameId = frameId(parent); + m_frontendDispatcher->frameAttached(frameId(&frame), parent ? &parentFrameId : nullptr); +} + +bool InspectorPageAgent::shouldBypassCSP() +{ + return m_bypassCSP; +} + Ref InspectorPageAgent::buildObjectForFrame(Frame* frame) { ASSERT_ARG(frame, frame); @@ -962,6 +1028,17 @@ void InspectorPageAgent::snapshotRect(ErrorString& errorString, int x, int y, in *outDataURL = snapshot->toDataURL("image/png"_s, WTF::nullopt, PreserveResolution::Yes); } +void InspectorPageAgent::setTouchEmulationEnabled(ErrorString& errorString, bool enabled) { +#if ENABLE(TOUCH_EVENTS) + RuntimeEnabledFeatures::sharedFeatures().setTouchEventsEnabled(enabled); + UNUSED_PARAM(errorString); +#else + UNUSED_PARAM(enabled); + errorString = "Not supported"_s; +#endif +} + + void InspectorPageAgent::archive(ErrorString& errorString, String* data) { #if ENABLE(WEB_ARCHIVE) && USE(CF) @@ -979,4 +1056,495 @@ void InspectorPageAgent::archive(ErrorString& errorString, String* data) #endif } +void InspectorPageAgent::insertText(ErrorString&, const String& text) { + UserGestureIndicator indicator { ProcessingUserGesture }; + Document* focusedDocument = m_inspectedPage.focusController().focusedOrMainFrame().document(); + TypingCommand::insertText(*focusedDocument, text, 0); +} + +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 RefPtr snapshotForAXObject(RefPtr axObject) { + 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->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()) + axNode->setReadonly(axObject->readOnlyValue() != "false"); + 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 (axObject->hasChildren()) { + RefPtr> children = JSON::ArrayOf::create(); + for (auto& childObject : axObject->children()) + children->addItem(snapshotForAXObject(childObject)); + axNode->setChildren(children); + } + return axNode; +} + + +void InspectorPageAgent::accessibilitySnapshot(ErrorString& errorString, RefPtr& out_axNode) { + if (!WebCore::AXObjectCache::accessibilityEnabled()) + WebCore::AXObjectCache::enableAccessibility(); + auto document = makeRefPtr(m_inspectedPage.mainFrame().document()); + if (!document) { + errorString = "No document for main frame"_s; + return; + } + AXObjectCache* axObjectCache = document->axObjectCache(); + if (!axObjectCache) { + errorString = "No AXObjectCache for main document"_s; + return; + } + AXCoreObject* axObject = axObjectCache->rootObject(); + if (!axObject) { + errorString = "No AXObject for main document"_s; + return; + } + + out_axNode = snapshotForAXObject(makeRefPtr(axObject)); +} + +void InspectorPageAgent::setInterceptFileChooserDialog(ErrorString&, bool enabled) { + m_interceptFileChooserDialog = enabled; +} + +void InspectorPageAgent::setDefaultBackgroundColorOverride(ErrorString& errorString, const JSON::Object* color) +{ + FrameView* view = m_inspectedPage.mainFrame().view(); + if (!view) { + errorString = "Internal error: No frame view to set color two"_s; + return; + } + if (!color) { + view->updateBackgroundRecursively(Optional()); + return; + } + view->updateBackgroundRecursively(InspectorDOMAgent::parseColor(color)); +} + +void InspectorPageAgent::createIsolatedWorld(ErrorString& errorString, const String& name, const String* optionalSource) { + if (m_isolatedWorldScripts.find(name) != m_isolatedWorldScripts.end()) { + errorString = "World with the given name already exists"_s; + return; + } + auto* pageRuntimeAgent = m_instrumentingAgents.pageRuntimeAgent(); + if (!pageRuntimeAgent) { + errorString = "Runtime agent must be enabled"_s; + return; + } + + String source = optionalSource ? *optionalSource : String(); + m_isolatedWorldScripts.set(name, source); + + for (Frame* frame = &m_inspectedPage.mainFrame(); frame; frame = frame->tree().traverseNext()) + pageRuntimeAgent->createIsolatedWorld(*frame, name, source); +} + +void InspectorPageAgent::setBypassCSP(ErrorString&, bool enabled) { + m_bypassCSP = enabled; +} + +void InspectorPageAgent::crash(ErrorString&) { + CRASH(); +} + } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.h b/Source/WebCore/inspector/agents/InspectorPageAgent.h index 3f3bbb8fce82044c1c230b0ae7186612cc5d45cf..1fcc543029bbc041a3a52e412b0b071e1070d36a 100644 --- a/Source/WebCore/inspector/agents/InspectorPageAgent.h +++ b/Source/WebCore/inspector/agents/InspectorPageAgent.h @@ -40,10 +40,15 @@ #include #include +namespace Inspector { +class InjectedScriptManager; +} + namespace WebCore { class DocumentLoader; class Frame; +class HTMLInputElement; class InspectorClient; class InspectorOverlay; class Page; @@ -96,7 +101,9 @@ public: void enable(ErrorString&) override; void disable(ErrorString&) override; void reload(ErrorString&, const bool* optionalReloadFromOrigin, const bool* optionalRevalidateAllResources) override; - void navigate(ErrorString&, const String& url) override; + void goBack(ErrorString&) override; + void goForward(ErrorString&) override; + void navigate(ErrorString&, const String& url, const String* frameId, const String* referrer) override; void overrideUserAgent(ErrorString&, const String* value) override; void overrideSetting(ErrorString&, const String& setting, const bool* value) override; void getCookies(ErrorString&, RefPtr>& cookies) override; @@ -110,13 +117,21 @@ public: void setShowPaintRects(ErrorString&, bool show) override; void setEmulatedMedia(ErrorString&, const String&) override; void setForcedAppearance(ErrorString&, const String&) override; + void setTouchEmulationEnabled(ErrorString&, bool) override; void snapshotNode(ErrorString&, int nodeId, String* outDataURL) override; - void snapshotRect(ErrorString&, int x, int y, int width, int height, const String& coordinateSystem, String* outDataURL) override; + void snapshotRect(ErrorString&, int x, int y, int width, int height, const String& coordinateSystem, String* outDataURL) override; void archive(ErrorString&, String* data) override; + void insertText(ErrorString&, const String& text) override; + void accessibilitySnapshot(ErrorString&, RefPtr& out_axNode) override; + void setInterceptFileChooserDialog(ErrorString&, bool enabled) override; + void setDefaultBackgroundColorOverride(ErrorString&, const JSON::Object*) override; + void createIsolatedWorld(ErrorString&, const String&, const String*) override; + void setBypassCSP(ErrorString&, bool) override; + void crash(ErrorString&) override; // InspectorInstrumentation - void domContentEventFired(); - void loadEventFired(); + void domContentEventFired(Frame&); + void loadEventFired(Frame&); void frameNavigated(Frame&); void frameDetached(Frame&); void loaderDetachedFromFrame(DocumentLoader&); @@ -124,19 +139,24 @@ public: void frameStoppedLoading(Frame&); void frameScheduledNavigation(Frame&, Seconds delay); void frameClearedScheduledNavigation(Frame&); + void didNavigateWithinPage(Frame&); void defaultAppearanceDidChange(bool useDarkAppearance); void applyUserAgentOverride(String&); void applyEmulatedMedia(String&); - void didClearWindowObjectInWorld(Frame&); void didPaint(RenderObject&, const LayoutRect&); void didLayout(); void didScroll(); void didRecalculateStyle(); + void runOpenPanel(HTMLInputElement* element, bool* intercept); + void frameAttached(Frame&); + bool shouldBypassCSP(); Frame* frameForId(const String& frameId); WEBCORE_EXPORT String frameId(Frame*); String loaderId(DocumentLoader*); Frame* assertFrame(ErrorString&, const String& frameId); + HashMap isolatedWorldScripts() { return m_isolatedWorldScripts; }; + String bootstrapScript() { return m_bootstrapScript; } private: double timestamp(); @@ -151,6 +171,7 @@ private: RefPtr m_backendDispatcher; Page& m_inspectedPage; + Inspector::InjectedScriptManager& m_injectedScriptManager; InspectorClient* m_client { nullptr }; InspectorOverlay* m_overlay { nullptr }; @@ -161,8 +182,11 @@ private: String m_emulatedMedia; String m_forcedAppearance; String m_bootstrapScript; + HashMap m_isolatedWorldScripts; bool m_isFirstLayoutAfterOnLoad { false }; bool m_showPaintRects { false }; + bool m_interceptFileChooserDialog { false }; + bool m_bypassCSP { false }; }; } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp index 864ce3cfe13994642495f2d7dfbdcc9a4cad9f24..50a4c389709d92a251214b24ba6068d96c2ea17b 100644 --- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp +++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp @@ -34,12 +34,14 @@ #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,9 +105,25 @@ void PageRuntimeAgent::didClearWindowObjectInWorld(Frame& frame) if (!pageAgent) return; - auto frameId = pageAgent->frameId(&frame); + // Force main world creation. auto* scriptState = mainWorldExecState(&frame); - notifyContextCreated(frameId, scriptState, nullptr, true); + Document* document = frame.document(); + String worldName = document ? document->securityOrigin().toRawString() : String(); + notifyContextCreated(frame, scriptState, worldName, true); + frame.script().evaluateIgnoringException(ScriptSourceCode(pageAgent->bootstrapScript(), URL { URL(), "web-inspector://bootstrap.js"_s })); + + // Create user worlds. + for (auto pair : pageAgent->isolatedWorldScripts()) + createIsolatedWorld(frame, pair.key, pair.value); +} + +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(ErrorString& errorString, const int* executionContextId) @@ -142,38 +160,38 @@ void PageRuntimeAgent::reportExecutionContextCreation() Vector> isolatedContexts; for (Frame* frame = &m_inspectedPage.mainFrame(); frame; frame = frame->tree().traverseNext()) { - if (!frame->script().canExecuteScripts(NotAboutToExecuteScript)) - continue; - - String frameId = pageAgent->frameId(frame); - JSC::JSGlobalObject* scriptState = mainWorldExecState(frame); - notifyContextCreated(frameId, scriptState, nullptr, true); + Document* document = frame->document(); + String worldName = document ? document->securityOrigin().toRawString() : String(); + notifyContextCreated(*frame, scriptState, worldName, true); frame->script().collectIsolatedContexts(isolatedContexts); if (isolatedContexts.isEmpty()) continue; for (auto& [globalObject, securityOrigin] : isolatedContexts) { - if (globalObject != scriptState) - notifyContextCreated(frameId, globalObject, securityOrigin, false); + if (globalObject == scriptState) + continue; + String name = securityOrigin ? securityOrigin->toRawString() : String(); + notifyContextCreated(*frame, globalObject, name, false); } isolatedContexts.clear(); } } -void PageRuntimeAgent::notifyContextCreated(const String& frameId, JSC::JSGlobalObject* scriptState, SecurityOrigin* securityOrigin, bool isPageContext) +void PageRuntimeAgent::notifyContextCreated(Frame& frame, JSC::JSGlobalObject* scriptState, const String& contextName, bool isPageContext) { - ASSERT(securityOrigin || isPageContext); - + auto* pageAgent = m_instrumentingAgents.inspectorPageAgent(); + if (!pageAgent) + return; + String frameId = pageAgent->frameId(&frame); InjectedScript result = injectedScriptManager().injectedScriptFor(scriptState); if (result.hasNoValue()) return; int executionContextId = injectedScriptManager().injectedScriptIdFor(scriptState); - String name = securityOrigin ? securityOrigin->toRawString() : String(); m_frontendDispatcher->executionContextCreated(ExecutionContextDescription::create() .setId(executionContextId) .setIsPageContext(isPageContext) - .setName(name) + .setName(contextName) .setFrameId(frameId) .release()); } @@ -190,4 +208,18 @@ void PageRuntimeAgent::callFunctionOn(ErrorString& errorString, const String& ob InspectorRuntimeAgent::callFunctionOn(errorString, objectId, expression, optionalArguments, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, emulateUserGesture, result, wasThrown); } +void PageRuntimeAgent::createIsolatedWorld(Frame& frame, const String& name, const String& source) { + auto* pageAgent = m_instrumentingAgents.inspectorPageAgent(); + if (!pageAgent) + return; + + Ref world = ScriptController::createWorld(); + frame.windowProxy().jsWindowProxy(world)->window(); + if (!source.isEmpty()) + frame.script().evaluateInWorldIgnoringException(ScriptSourceCode(source, URL { URL(), "web-inspector://isolate_world.js"_s }), world); + auto* scriptState = frame.windowProxy().jsWindowProxy(world)->window(); + notifyContextCreated(frame, scriptState, name, false); + frame.script().evaluateInWorldIgnoringException(ScriptSourceCode(pageAgent->bootstrapScript(), URL { URL(), "web-inspector://bootstrap.js"_s }), world); +} + } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h index 54a00e05828fbe10d7c69facf69bf0c302687786..df0aa6dbd784813514f59bf8c37d83700876399a 100644 --- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h +++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h @@ -62,17 +62,19 @@ public: // InspectorInstrumentation void frameNavigated(Frame&); void didClearWindowObjectInWorld(Frame&); + void didReceiveMainResourceError(Frame&); + + void createIsolatedWorld(Frame& frame, const String& name, const String& source); private: Inspector::InjectedScript injectedScriptForEval(ErrorString&, const int* executionContextId) override; void muteConsole() override; void unmuteConsole() override; void reportExecutionContextCreation(); - void notifyContextCreated(const String& frameId, JSC::JSGlobalObject*, SecurityOrigin*, bool isPageContext); + void notifyContextCreated(Frame&, JSC::JSGlobalObject*, const String&, bool isPageContext); std::unique_ptr m_frontendDispatcher; RefPtr m_backendDispatcher; - InstrumentingAgents& m_instrumentingAgents; Page& m_inspectedPage; diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp index 9a72b906215d3790814255ff0c5cd9c34d9f9f70..a79921cce6ca0fc0f64e8d7ea36a326db82ac4db 100644 --- a/Source/WebCore/loader/FrameLoader.cpp +++ b/Source/WebCore/loader/FrameLoader.cpp @@ -1177,6 +1177,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(); @@ -1362,6 +1363,8 @@ void FrameLoader::loadURL(FrameLoadRequest&& frameLoadRequest, const String& ref ASSERT(newLoadType != FrameLoadType::Same); + request.setInitiatorIdentifier(frameLoadRequest.resourceRequest().initiatorIdentifier()); + // The search for a target frame is done earlier in the case of form submission. Frame* targetFrame = isFormSubmission ? nullptr : findFrameForNavigation(effectiveFrameName); if (targetFrame && targetFrame != &m_frame) { @@ -3179,6 +3182,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) @@ -3945,9 +3950,6 @@ String FrameLoader::referrer() const void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() { - if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript)) - return; - Vector> worlds; ScriptController::getAllWorlds(worlds); for (auto& world : worlds) @@ -3956,13 +3958,12 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world) { - if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.windowProxy().existingJSWindowProxy(world)) - return; - - m_client.dispatchDidClearWindowObjectInWorld(world); + if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript) && m_frame.windowProxy().existingJSWindowProxy(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 0644fec509e60f7a4cf59a352f32335c2d164d99..acf628996ea020a8f0a2239ef72f5c241d108840 100644 --- a/Source/WebCore/loader/LoaderStrategy.h +++ b/Source/WebCore/loader/LoaderStrategy.h @@ -79,6 +79,7 @@ public: virtual bool isOnLine() const = 0; virtual void addOnlineStateChangeListener(WTF::Function&&) = 0; + virtual void setEmulateOfflineState(bool) {}; virtual bool shouldPerformSecurityChecks() const { return false; } virtual bool havePerformedSecurityChecks(const ResourceResponse&) const { return false; } diff --git a/Source/WebCore/loader/ProgressTracker.cpp b/Source/WebCore/loader/ProgressTracker.cpp index e24fded2225f1c1918f454017566717e20484eab..30e4b7a986418c4b4f6c799b858b608206e22bb5 100644 --- a/Source/WebCore/loader/ProgressTracker.cpp +++ b/Source/WebCore/loader/ProgressTracker.cpp @@ -154,6 +154,8 @@ void ProgressTracker::progressCompleted(Frame& frame) if (!m_numProgressTrackedFrames || m_originatingProgressFrame == &frame) finalProgressComplete(); + InspectorInstrumentation::frameStoppedLoading(frame); + m_client->didChangeEstimatedProgress(); } @@ -179,8 +181,6 @@ void ProgressTracker::finalProgressComplete() frame->loader().client().setMainFrameDocumentReady(true); m_client->progressFinished(*frame); frame->loader().loadProgressingStatusChanged(); - - InspectorInstrumentation::frameStoppedLoading(*frame); } void ProgressTracker::incrementProgress(unsigned long identifier, const ResourceResponse& response) diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp index 6f434d95832e2527aa2059e5907154bdf64bef63..563d961443ad3f28e32766302eeee144635154d0 100644 --- a/Source/WebCore/page/Frame.cpp +++ b/Source/WebCore/page/Frame.cpp @@ -180,6 +180,7 @@ Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient& void Frame::init() { m_loader->init(); + InspectorInstrumentation::frameAttached(this); } Ref Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client) diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp index 9c58b06f4c471130ce4815f11d14cb78f81b49a0..3d624733c36f09518b12095d91e67a2ae67879e2 100644 --- a/Source/WebCore/page/History.cpp +++ b/Source/WebCore/page/History.cpp @@ -259,6 +259,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/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp index ad6f5209c52e0842d93be267f8f5e99551dfe07c..0fcf4fe9877ba8a89a8dfb321e120f7954c6f69b 100644 --- a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp +++ b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp @@ -298,6 +298,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) @@ -311,6 +313,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) { @@ -327,6 +331,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/platform/PlatformKeyboardEvent.h b/Source/WebCore/platform/PlatformKeyboardEvent.h index f423a4a1d5399326fc48fe4d4a8a8fb9d4df861e..b4b60162d8b0d34113df052b04a1695d481d266e 100644 --- a/Source/WebCore/platform/PlatformKeyboardEvent.h +++ b/Source/WebCore/platform/PlatformKeyboardEvent.h @@ -138,6 +138,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 @@ -147,6 +148,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/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h index d7438c15cd51d6660c0f738ac2e97fabf5abdc23..f9c711e0ceb1a19cd839cb25a1a0ccaeefb4bacf 100644 --- a/Source/WebCore/platform/ScrollableArea.h +++ b/Source/WebCore/platform/ScrollableArea.h @@ -99,7 +99,7 @@ public: void updateScrollSnapState(); #if ENABLE(TOUCH_EVENTS) - virtual bool handleTouchEvent(const PlatformTouchEvent&); + WEBCORE_EXPORT virtual bool handleTouchEvent(const PlatformTouchEvent&); #endif #if PLATFORM(IOS_FAMILY) diff --git a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp index 269008b9053c8d8b6787cf22f13b44b46dace333..d3ba16947bc8964a7cfe746cabbf99d32a673cef 100644 --- a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp +++ b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp @@ -36,8 +36,10 @@ #include "WindowsKeyboardCodes.h" #include #include +#include #include #include +#include namespace WebCore { @@ -1293,6 +1295,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/libwpe/PlatformKeyboardEventLibWPE.cpp b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp index a34dc220bbb9a92b40dfb463e8724e81ac745b2c..9f62ef44b3d2ec93ac169b1b156c54f66d2a79b8 100644 --- a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp +++ b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp @@ -1291,6 +1291,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/NetworkStateNotifier.h b/Source/WebCore/platform/network/NetworkStateNotifier.h index 87930048f4fd18d6098af7de4da25be532df5931..2bb2afcf9473b0d5d97efbe18dd7b8145bc5f932 100644 --- a/Source/WebCore/platform/network/NetworkStateNotifier.h +++ b/Source/WebCore/platform/network/NetworkStateNotifier.h @@ -72,6 +72,7 @@ private: #endif Optional m_isOnLine; + Optional m_emulatedIsOnLine; Vector> m_listeners; Timer m_updateStateTimer; diff --git a/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp b/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp index 3fb8892c79fd5e4f670cac4884f9ef0b5371b2a5..974cd5d8cc3772a1964897f5134ec7b055252ebc 100644 --- a/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp +++ b/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp @@ -406,8 +406,13 @@ void NetworkStorageSession::getHostnamesWithCookies(HashSet& hostnames) Vector NetworkStorageSession::getAllCookies() { - // FIXME: Implement for WK2 to use. - return { }; + Vector cookies; + GUniquePtr cookiesList(soup_cookie_jar_all_cookies(cookieStorage())); + for (GSList* item = cookiesList.get(); item; item = g_slist_next(item)) { + GUniquePtr soupCookie(static_cast(item->data)); + cookies.append(WebCore::Cookie(soupCookie.get())); + } + return cookies; } Vector NetworkStorageSession::getCookies(const URL& url) diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.cpp b/Source/WebKit/NetworkProcess/NetworkProcess.cpp index 4da04add2fd22d551444059df5f3212aa9ab5dfe..399155b4a74a0b2b333137c59e903e6168b3b6a3 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" @@ -563,6 +562,35 @@ void NetworkProcess::destroySession(PAL::SessionID sessionID) m_storageManagerSet->remove(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); +} + #if ENABLE(RESOURCE_LOAD_STATISTICS) void NetworkProcess::dumpResourceLoadStatistics(PAL::SessionID sessionID, CompletionHandler&& completionHandler) { diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h index e08d5824da30420cf5c5d834f29bdf72c6c80d69..a17d3122b22cee54ea0948c0f8b93c0b543fee33 100644 --- a/Source/WebKit/NetworkProcess/NetworkProcess.h +++ b/Source/WebKit/NetworkProcess/NetworkProcess.h @@ -74,6 +74,7 @@ class SessionID; namespace WebCore { class CertificateInfo; +struct Cookie; class CurlProxySettings; class DownloadID; class ProtectionSpace; @@ -199,6 +200,10 @@ public: void addWebsiteDataStore(WebsiteDataStoreParameters&&); + void getAllCookies(PAL::SessionID, CompletionHandler&&)>&&); + void setCookies(PAL::SessionID, Vector, CompletionHandler&&); + void deleteAllCookies(PAL::SessionID, CompletionHandler&&); + #if ENABLE(RESOURCE_LOAD_STATISTICS) void clearPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler&&); void clearUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler&&); @@ -310,6 +315,7 @@ public: #if PLATFORM(COCOA) NetworkHTTPSUpgradeChecker& networkHTTPSUpgradeChecker(); + bool ignoreTLSErrors() const { return m_ignoreTLSErrors; } #endif const String& uiProcessBundleIdentifier() const { return m_uiProcessBundleIdentifier; } @@ -417,6 +423,9 @@ private: void syncAllCookies(); void didSyncAllCookies(); +#if PLATFORM(COCOA) + void setIgnoreTLSErrors(bool); +#endif #if USE(SOUP) void setIgnoreTLSErrors(bool); void userPreferredLanguagesChanged(const Vector&); @@ -565,6 +574,7 @@ private: #if PLATFORM(COCOA) std::unique_ptr m_networkHTTPSUpgradeChecker; + bool m_ignoreTLSErrors { false }; #endif #if ENABLE(RESOURCE_LOAD_STATISTICS) diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in index 2ad9881fcf7ea844d82bc77fac07f493d7c4de5e..571f21cfab8aed17e21dc1a8b770f87aae307a64 100644 --- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in +++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in @@ -27,8 +27,10 @@ messages -> NetworkProcess LegacyReceiver { # Creates a connection for communication with a WebProcess CreateNetworkConnectionToWebProcess(WebCore::ProcessIdentifier processIdentifier, PAL::SessionID sessionID) -> (Optional connectionIdentifier) Async -#if USE(SOUP) +#if USE(SOUP) || PLATFORM(COCOA) SetIgnoreTLSErrors(bool ignoreTLSErrors) +#endif +#if USE(SOUP) UserPreferredLanguagesChanged(Vector languages) SetNetworkProxySettings(struct WebCore::SoupNetworkProxySettings settings) PrefetchDNS(String hostname) @@ -80,6 +82,10 @@ messages -> NetworkProcess LegacyReceiver { PrepareToSuspend(bool isSuspensionImminent) -> () Async ProcessDidResume() + GetAllCookies(PAL::SessionID sessionID) -> (Vector cookies) Async + SetCookies(PAL::SessionID sessionID, Vector cookies) -> (bool success) Async + DeleteAllCookies(PAL::SessionID sessionID) -> (bool success) Async + #if ENABLE(RESOURCE_LOAD_STATISTICS) ClearPrevalentResource(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async ClearUserInteraction(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async diff --git a/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h b/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h index 2c0266ce5edc2ce5e902d315a8abf672ae3b2f51..1db8f9787b6276aa9a5106bb1b8030220ae8b206 100644 --- a/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h +++ b/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h @@ -74,9 +74,9 @@ struct NetworkProcessCreationParameters { WebsiteDataStoreParameters defaultDataStoreParameters; + bool ignoreTLSErrors { false }; #if USE(SOUP) HTTPCookieAcceptPolicy cookieAcceptPolicy { HTTPCookieAcceptPolicy::AlwaysAccept }; - bool ignoreTLSErrors { false }; Vector languages; WebCore::SoupNetworkProxySettings proxySettings; #endif diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm index 71b085a03b5262866b272e8504114838880bad5b..e371d45f6d22bff28bbf54f9cc4028ff7f3bd779 100644 --- a/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm +++ b/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm @@ -91,6 +91,8 @@ void NetworkProcess::platformInitializeNetworkProcessCocoa(const NetworkProcessC #endif #endif + setIgnoreTLSErrors(parameters.ignoreTLSErrors); + _CFNetworkSetATSContext(parameters.networkATSContext.get()); m_uiProcessBundleIdentifier = parameters.uiProcessBundleIdentifier; @@ -211,6 +213,7 @@ void NetworkProcess::syncAllCookies() }); } + #if HAVE(FOUNDATION_WITH_SAVE_COOKIES_WITH_COMPLETION_HANDLER) static void saveCookies(NSHTTPCookieStorage *cookieStorage, CompletionHandler&& completionHandler) { @@ -241,6 +244,11 @@ void NetworkProcess::platformSyncAllCookies(CompletionHandler&& completi ALLOW_DEPRECATED_DECLARATIONS_END } +void NetworkProcess::setIgnoreTLSErrors(bool ignoreTLSErrors) +{ + m_ignoreTLSErrors = ignoreTLSErrors; +} + void NetworkProcess::platformPrepareToSuspend(CompletionHandler&& completionHandler) { completionHandler(); diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h index d71b6e4082e34576329be6b5935d20d51a84b3ba..881c8dccbab1017b8bd8f658b00044a4353df3cf 100644 --- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h +++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h @@ -76,7 +76,7 @@ public: const String& dataConnectionServiceType() const; #endif - static bool allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge&); + bool allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge&); void continueDidReceiveChallenge(SessionWrapper&, const WebCore::AuthenticationChallenge&, NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*, CompletionHandler&&); diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm index fcb9e8ddb8c3a804aa27339cab1b0039eb136f53..633a4efd58ac5c6a8999fa8d75d88342d8d59a69 100644 --- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm +++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm @@ -628,7 +628,7 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa *session, Se } if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { - if (NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(challenge)) + if (sessionCocoa->allowsSpecificHTTPSCertificateForHost(challenge)) return completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]); // Handle server trust evaluation at platform-level if requested, for performance reasons and to use ATS defaults. @@ -1276,6 +1276,9 @@ static bool certificatesMatch(SecTrustRef trust1, SecTrustRef trust2) bool NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge& challenge) { + if (networkProcess().ignoreTLSErrors()) + return true; + const String& host = challenge.protectionSpace().host(); NSArray *certificates = [NSURLRequest allowsSpecificHTTPSCertificateForHost:host]; if (!certificates) diff --git a/Source/WebKit/Shared/API/c/wpe/WebKit.h b/Source/WebKit/Shared/API/c/wpe/WebKit.h index 898e30b370db8176e886fbbde0cd960e38a64818..74945e06fac0eb14936578de6a599a123364a63a 100644 --- a/Source/WebKit/Shared/API/c/wpe/WebKit.h +++ b/Source/WebKit/Shared/API/c/wpe/WebKit.h @@ -78,6 +78,7 @@ // From Source/WebKit/UIProcess/API/C #include #include +#include #include #include #include diff --git a/Source/WebKit/Shared/NativeWebKeyboardEvent.h b/Source/WebKit/Shared/NativeWebKeyboardEvent.h index f08c19fb95ec8c8cca8f4ca2aa4049885637febf..f3ec649261051e3c7fd50052dd988181ba065466 100644 --- a/Source/WebKit/Shared/NativeWebKeyboardEvent.h +++ b/Source/WebKit/Shared/NativeWebKeyboardEvent.h @@ -34,6 +34,7 @@ #if USE(APPKIT) #include OBJC_CLASS NSView; +OBJC_CLASS NSEvent; namespace WebCore { struct CompositionUnderline; @@ -67,10 +68,18 @@ 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&); enum class HandledByInputMethod : bool { No, Yes }; NativeWebKeyboardEvent(GdkEvent*, const String&, HandledByInputMethod, Optional>&&, Optional&&, Vector&& commands); + 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); diff --git a/Source/WebKit/Shared/NativeWebMouseEvent.h b/Source/WebKit/Shared/NativeWebMouseEvent.h index 0fa557e9faa34ba81a7a4f7da5e32f30cbfad5d2..60ebade975bd50f1e32ad0e02a696dd1c8b06bbe 100644 --- a/Source/WebKit/Shared/NativeWebMouseEvent.h +++ b/Source/WebKit/Shared/NativeWebMouseEvent.h @@ -61,6 +61,8 @@ public: #elif PLATFORM(GTK) NativeWebMouseEvent(const NativeWebMouseEvent&); NativeWebMouseEvent(GdkEvent*, int, Optional); + 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) { } #elif PLATFORM(IOS_FAMILY) NativeWebMouseEvent(::WebEvent *); NativeWebMouseEvent(Type, Button, unsigned short buttons, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, float deltaX, float deltaY, float deltaZ, int clickCount, OptionSet, WallTime timestamp, double force); diff --git a/Source/WebKit/Shared/WebEvent.h b/Source/WebKit/Shared/WebEvent.h index 93d0bf22b5083d5a0027458d11ce241627b10c3b..6ee97a5c8c028db59240658757c01699bacc9a3d 100644 --- a/Source/WebKit/Shared/WebEvent.h +++ b/Source/WebKit/Shared/WebEvent.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -258,8 +259,10 @@ public: #if USE(APPKIT) WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, const Vector&, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); + WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp, Vector&& commands); #elif PLATFORM(GTK) WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional>&&, Optional&&, Vector&& commands, bool isKeypad, OptionSet, WallTime timestamp); + WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp, Vector&& commands); #elif PLATFORM(IOS_FAMILY) WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); #elif USE(LIBWPE) @@ -307,7 +310,7 @@ private: int32_t m_nativeVirtualKeyCode; int32_t m_macCharCode; #if USE(APPKIT) || USE(UIKIT_KEYBOARD_ADDITIONS) || PLATFORM(GTK) || USE(LIBWPE) - bool m_handledByInputMethod; + bool m_handledByInputMethod = false; #endif #if PLATFORM(GTK) || USE(LIBWPE) Optional> m_preeditUnderlines; diff --git a/Source/WebKit/Shared/WebKeyboardEvent.cpp b/Source/WebKit/Shared/WebKeyboardEvent.cpp index cccb560418f32fad40587ac083b95f398eb1399d..e5af7920b1cbfca4bef6b17fa7b0f3226943b955 100644 --- a/Source/WebKit/Shared/WebKeyboardEvent.cpp +++ b/Source/WebKit/Shared/WebKeyboardEvent.cpp @@ -35,6 +35,7 @@ WebKeyboardEvent::WebKeyboardEvent() { } + #if USE(APPKIT) WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, const Vector& commands, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) @@ -56,6 +57,24 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& ASSERT(isKeyboardEventType(type)); } +WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp, Vector&& commands) + : WebEvent(type, modifiers, timestamp) + , m_text(text) + , m_unmodifiedText(text) + , m_key(key) + , m_code(code) + , m_keyIdentifier(keyIdentifier) + , m_windowsVirtualKeyCode(windowsVirtualKeyCode) + , m_nativeVirtualKeyCode(nativeVirtualKeyCode) + , m_macCharCode(0) + , m_commands(WTFMove(commands)) + , m_isAutoRepeat(isAutoRepeat) + , m_isKeypad(isKeypad) + , m_isSystemKey(isSystemKey) +{ + ASSERT(isKeyboardEventType(type)); +} + #elif PLATFORM(GTK) WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional>&& preeditUnderlines, Optional&& preeditSelectionRange, Vector&& commands, bool isKeypad, OptionSet modifiers, WallTime timestamp) @@ -79,6 +98,24 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& ASSERT(isKeyboardEventType(type)); } +WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp, Vector&& commands) + : WebEvent(type, modifiers, timestamp) + , m_text(text) + , m_unmodifiedText(text) + , m_key(key) + , m_code(code) + , m_keyIdentifier(keyIdentifier) + , m_windowsVirtualKeyCode(windowsVirtualKeyCode) + , m_nativeVirtualKeyCode(nativeVirtualKeyCode) + , m_macCharCode(0) + , m_commands(WTFMove(commands)) + , m_isAutoRepeat(isAutoRepeat) + , m_isKeypad(isKeypad) + , m_isSystemKey(isSystemKey) +{ + ASSERT(isKeyboardEventType(type)); +} + #elif PLATFORM(IOS_FAMILY) WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) diff --git a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp index 2357f3d58415fae78e48b0f8a25bddad85c786bf..f3941a74922f5a0a3bf59a11cd4c42fbfd33d0af 100644 --- a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp +++ b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp @@ -40,7 +40,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(GdkEvent* event, const String& te } NativeWebKeyboardEvent::NativeWebKeyboardEvent(const NativeWebKeyboardEvent& event) - : WebKeyboardEvent(WebEventFactory::createWebKeyboardEvent(event.nativeEvent(), event.text(), event.handledByInputMethod(), Optional>(event.preeditUnderlines()), Optional(event.preeditSelectionRange()), Vector(event.commands()))) + : WebKeyboardEvent(event) , m_nativeEvent(gdk_event_copy(event.nativeEvent())) { } diff --git a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp index 58e37fe3827cdb08d36ef0c85b8d4a968dee001a..429d245ea99fdee1b598a5caf51de8ce4b47fb02 100644 --- a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp +++ b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp @@ -38,8 +38,8 @@ NativeWebMouseEvent::NativeWebMouseEvent(GdkEvent* event, int eventClickCount, O } NativeWebMouseEvent::NativeWebMouseEvent(const NativeWebMouseEvent& event) - : WebMouseEvent(WebEventFactory::createWebMouseEvent(event.nativeEvent(), event.clickCount(), WebCore::IntPoint(event.deltaX(), event.deltaY()))) - , m_nativeEvent(gdk_event_copy(event.nativeEvent())) + : WebMouseEvent(event) + , m_nativeEvent(event.nativeEvent() ? gdk_event_copy(event.nativeEvent()) : nullptr) { } diff --git a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp index 7b5eb372880d8662544334cd4697276d543de45b..ba06ecbb2cf5088a4c8c0824b50cb7797605dc57 100644 --- a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp +++ b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "WebEvent.h" -#if ENABLE(TOUCH_EVENTS) +#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) #include "WebCoreArgumentCoders.h" @@ -79,4 +79,4 @@ Optional WebPlatformTouchPoint::decode(IPC::Decoder& deco } // namespace WebKit -#endif // ENABLE(TOUCH_EVENTS) +#endif // ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) diff --git a/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp b/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp index 45a56eb3b0fda13c3b78d57594a0092e4e1866f6..5e29e15813be6abe82790e6a98d3947e7a6fae44 100644 --- a/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp +++ b/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "WebEvent.h" -#if ENABLE(TOUCH_EVENTS) +#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) #include "ArgumentCoders.h" #include "WebCoreArgumentCoders.h" @@ -71,4 +71,4 @@ bool WebTouchEvent::decode(IPC::Decoder& decoder, WebTouchEvent& result) } // namespace WebKit -#endif // ENABLE(TOUCH_EVENTS) +#endif // ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt index ca52603ed5b07cc1a10721736ed46c6789413312..f9fc5d32e8f209490ea1774516f73c511ec4ebf7 100644 --- a/Source/WebKit/Sources.txt +++ b/Source/WebKit/Sources.txt @@ -254,17 +254,23 @@ Shared/WebsiteData/WebsiteData.cpp UIProcess/AuxiliaryProcessProxy.cpp UIProcess/BackgroundProcessResponsivenessTimer.cpp +UIProcess/BrowserInspectorController.cpp +UIProcess/BrowserInspectorPipe.cpp +UIProcess/BrowserInspectorTargetAgent.cpp UIProcess/DeviceIdHashSaltStorage.cpp UIProcess/DrawingAreaProxy.cpp UIProcess/FrameLoadState.cpp UIProcess/GeolocationPermissionRequestManagerProxy.cpp UIProcess/GeolocationPermissionRequestProxy.cpp +UIProcess/InspectorBrowserAgent.cpp +UIProcess/InspectorDialogAgent.cpp UIProcess/InspectorTargetProxy.cpp UIProcess/LegacyGlobalSettings.cpp UIProcess/PageLoadState.cpp UIProcess/ProcessAssertion.cpp UIProcess/ProcessThrottler.cpp UIProcess/ProvisionalPageProxy.cpp +UIProcess/RemoteInspectorPipe.cpp UIProcess/RemoteWebInspectorProxy.cpp UIProcess/ResponsivenessTimer.cpp UIProcess/StatisticsRequest.cpp @@ -306,6 +312,9 @@ UIProcess/WebPageDiagnosticLoggingClient.cpp UIProcess/WebPageGroup.cpp UIProcess/WebPageInjectedBundleClient.cpp UIProcess/WebPageInspectorController.cpp +UIProcess/WebPageInspectorEmulationAgent.cpp +UIProcess/WebPageInspectorInputAgent.cpp +UIProcess/WebPageInspectorTargetProxy.cpp UIProcess/WebPageProxy.cpp UIProcess/WebPasteboardProxy.cpp UIProcess/WebPreferences.cpp diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt index fe757953761b99f69b828c11bbc0f331aeefc191..4bec91c6eaaf7fdda6c0d89903a2fa6066c1dc9e 100644 --- a/Source/WebKit/SourcesCocoa.txt +++ b/Source/WebKit/SourcesCocoa.txt @@ -249,6 +249,7 @@ UIProcess/API/Cocoa/_WKApplicationManifest.mm UIProcess/API/Cocoa/_WKAttachment.mm UIProcess/API/Cocoa/_WKAutomationSession.mm UIProcess/API/Cocoa/_WKAutomationSessionConfiguration.mm +UIProcess/API/Cocoa/_WKBrowserInspector.mm UIProcess/API/Cocoa/_WKContentRuleListAction.mm UIProcess/API/Cocoa/_WKContextMenuElementInfo.mm UIProcess/API/Cocoa/_WKCustomHeaderFields.mm @no-unify diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt index 4038ad7baec95bd6f2da6421f9f1ed578719ea69..489f9e941837c5d48142917dec3d0e9e3331f9f3 100644 --- a/Source/WebKit/SourcesGTK.txt +++ b/Source/WebKit/SourcesGTK.txt @@ -129,6 +129,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify UIProcess/API/glib/WebKitBackForwardList.cpp @no-unify UIProcess/API/glib/WebKitBackForwardListItem.cpp @no-unify +UIProcess/API/glib/WebKitBrowserInspector.cpp @no-unify UIProcess/API/glib/WebKitContextMenuClient.cpp @no-unify UIProcess/API/glib/WebKitCookieManager.cpp @no-unify UIProcess/API/glib/WebKitCredential.cpp @no-unify @@ -229,6 +230,7 @@ UIProcess/WebsiteData/unix/WebsiteDataStoreUnix.cpp UIProcess/cairo/BackingStoreCairo.cpp @no-unify +UIProcess/glib/InspectorBrowserAgentClientGLib.cpp UIProcess/glib/RemoteInspectorClient.cpp UIProcess/glib/WebProcessPoolGLib.cpp UIProcess/glib/WebProcessProxyGLib.cpp @@ -256,6 +258,9 @@ UIProcess/gtk/WebColorPickerGtk.cpp UIProcess/gtk/WebContextMenuProxyGtk.cpp UIProcess/gtk/WebDataListSuggestionsDropdownGtk.cpp UIProcess/gtk/WebInspectorProxyGtk.cpp +UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp +UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp +UIProcess/gtk/WebPageInspectorTargetProxyGtk.cpp UIProcess/gtk/WebKitInspectorWindow.cpp UIProcess/gtk/WebPageProxyGtk.cpp @no-unify UIProcess/gtk/WebPasteboardProxyGtk.cpp diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt index f788d84d86953820df58fb3ddf6181d8ffbefb24..f79f97c1bad00fb780b79a910b8ea66470513196 100644 --- a/Source/WebKit/SourcesWPE.txt +++ b/Source/WebKit/SourcesWPE.txt @@ -117,6 +117,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify UIProcess/API/glib/WebKitBackForwardList.cpp @no-unify UIProcess/API/glib/WebKitBackForwardListItem.cpp @no-unify +UIProcess/API/glib/WebKitBrowserInspector.cpp @no-unify UIProcess/API/glib/WebKitContextMenuClient.cpp @no-unify UIProcess/API/glib/WebKitCookieManager.cpp @no-unify UIProcess/API/glib/WebKitCredential.cpp @no-unify @@ -188,7 +189,7 @@ UIProcess/Automation/wpe/WebAutomationSessionWPE.cpp UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp UIProcess/geoclue/GeoclueGeolocationProvider.cpp - +UIProcess/glib/InspectorBrowserAgentClientGLib.cpp UIProcess/glib/WebProcessPoolGLib.cpp UIProcess/glib/WebProcessProxyGLib.cpp UIProcess/glib/WebsiteDataStoreGLib.cpp @no-unify @@ -213,6 +214,9 @@ UIProcess/soup/WebProcessPoolSoup.cpp UIProcess/wpe/TextCheckerWPE.cpp UIProcess/wpe/WebInspectorProxyWPE.cpp UIProcess/wpe/WebPageProxyWPE.cpp +UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp +UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp +UIProcess/wpe/WebPageInspectorTargetProxyWPE.cpp UIProcess/wpe/WebPasteboardProxyWPE.cpp UIProcess/wpe/WebPreferencesWPE.cpp diff --git a/Source/WebKit/UIProcess/API/APIUIClient.h b/Source/WebKit/UIProcess/API/APIUIClient.h index 54513035b261bfd5e187ec945796198ed09d88b1..2d3200e4f6e90a16f248b255f75d2a7e17d895a5 100644 --- a/Source/WebKit/UIProcess/API/APIUIClient.h +++ b/Source/WebKit/UIProcess/API/APIUIClient.h @@ -97,6 +97,7 @@ public: virtual void runJavaScriptAlert(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebCore::SecurityOriginData&&, Function&& completionHandler) { completionHandler(); } virtual void runJavaScriptConfirm(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebCore::SecurityOriginData&&, Function&& completionHandler) { completionHandler(false); } virtual void runJavaScriptPrompt(WebKit::WebPageProxy&, const WTF::String&, const WTF::String&, WebKit::WebFrameProxy*, WebCore::SecurityOriginData&&, Function&& completionHandler) { completionHandler(WTF::String()); } + virtual void handleJavaScriptDialog(WebKit::WebPageProxy&, bool, const WTF::String&) { } virtual void setStatusText(WebKit::WebPageProxy*, const WTF::String&) { } virtual void mouseDidMoveOverElement(WebKit::WebPageProxy&, const WebKit::WebHitTestResultData&, OptionSet, Object*) { } diff --git a/Source/WebKit/UIProcess/API/C/WKPage.cpp b/Source/WebKit/UIProcess/API/C/WKPage.cpp index dd796b8332359e1c3b1e5575fd7a03353cb1fac2..283682a495e5bd114beec3e8351817465d39caab 100644 --- a/Source/WebKit/UIProcess/API/C/WKPage.cpp +++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp @@ -1675,6 +1675,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient completionHandler(String()); } + void handleJavaScriptDialog(WebPageProxy&, bool, const String&) final { } + void setStatusText(WebPageProxy* page, const String& text) final { if (!m_client.setStatusText) @@ -1735,6 +1737,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient { if (!m_client.didNotHandleKeyEvent) return; + if (!event.nativeEvent()) + return; m_client.didNotHandleKeyEvent(toAPI(page), event.nativeEvent(), m_client.base.clientInfo); } diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h index cad87f3ef2ab93d93a74cec0c34b47c695de6bc6..66145a384638b97ee08516e56e1e86a83713c634 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h +++ b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h @@ -123,6 +123,13 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler; +/*! @abstract Handle a JavaScript dialog. + @param webView The web view invoking the delegate method. + @param accept Whether to accept the dialog. + @param value Value to use for prompt dialog. + */ +- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(nullable NSString *)value; + #if TARGET_OS_IPHONE /*! @abstract Allows your app to determine whether or not the given element should show a preview. diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h index 726c4972aa0b32e0dc602e0ab2d71f6ae8ef93ae..c67f408797724cb6d68ed441c0ef1cccd33ca1e0 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h +++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h @@ -24,7 +24,6 @@ */ #import - #import NS_ASSUME_NONNULL_BEGIN @@ -78,6 +77,8 @@ WK_CLASS_AVAILABLE(macos(10.11), ios(9.0)) /*! @abstract Returns the cookie store representing HTTP cookies in this website data store. */ @property (nonatomic, readonly) WKHTTPCookieStore *httpCookieStore WK_API_AVAILABLE(macos(10.13), ios(11.0)); +- (uint64_t)sessionID; + @end NS_ASSUME_NONNULL_END diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm index 6cb574e5cbc2e7845d56f91a3161fa4e0165c343..a93dc45984d6a93536459c02225aeacbb9ff7957 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm +++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm @@ -44,6 +44,7 @@ #import "_WKWebsiteDataStoreDelegate.h" #import #import +#import #import #import #import @@ -184,6 +185,11 @@ static WallTime toSystemClockTime(NSDate *date) }); } +- (uint64_t) sessionID +{ + return _websiteDataStore->sessionID().toUInt64(); +} + static Vector toWebsiteDataRecords(NSArray *dataRecords) { Vector result; diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h new file mode 100644 index 0000000000000000000000000000000000000000..19b3c675368d27b2e1d7753f0c5041d40d273419 --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@class WKWebView; + +WK_CLASS_AVAILABLE(macos(10.14.0)) +@interface _WKBrowserContext : NSObject +@property (nonatomic, strong) WKWebsiteDataStore *dataStore; +@property (nonatomic, strong) WKProcessPool *processPool; +@end + +@protocol _WKBrowserInspectorDelegate +- (WKWebView *)createNewPage:(uint64_t)sessionID; +- (_WKBrowserContext *)createBrowserContext; +- (void)deleteBrowserContext:(uint64_t)sessionID; +- (void)quit; +@end + +WK_CLASS_AVAILABLE(macos(10.14.0)) +@interface _WKBrowserInspector : NSObject ++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless; +@end + + +NS_ASSUME_NONNULL_END + diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm new file mode 100644 index 0000000000000000000000000000000000000000..a6e20df84154613ea8bec3843ecfa6c6c72817b1 --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "_WKBrowserInspector.h" + +#include "BrowserInspectorPipe.h" +#include "InspectorBrowserAgentClientMac.h" +#include "PageClientImplMac.h" +#include "WebsiteDataStore.h" + +#import "WKWebView.h" + +using namespace WebKit; + +@implementation _WKBrowserInspector + ++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless +{ +#if ENABLE(REMOTE_INSPECTOR) + WebsiteDataStore::defaultDataStore(); + PageClientImpl::setHeadless(headless); + initializeBrowserInspectorPipe(makeUnique(delegate)); +#endif +} + +@end + +@implementation _WKBrowserContext +@end diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm index 2bdb8b9e7256f22096ebaa5d51959aa52389ca0a..2141d9d17497861a6c711f99306de10992a93ce8 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm @@ -25,6 +25,7 @@ #import "config.h" #import "_WKRemoteWebInspectorViewController.h" +#import "WKWebViewPrivate.h" #if PLATFORM(MAC) diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f3c7849817bbcc12ad97de1557a006159ff8b4c --- /dev/null +++ b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebKitBrowserInspector.h" + +#include "BrowserInspectorPipe.h" +#include "InspectorBrowserAgentClientGLib.h" +#include "WebKitBrowserInspectorPrivate.h" +#include "WebKitWebViewPrivate.h" +#include +#include + +/** + * SECTION: WebKitBrowserInspector + * @Short_description: Access to the WebKit browser inspector + * @Title: WebKitBrowserInspector + * + * The WebKit Browser Inspector is an experimental API that provides + * access to the inspector via the remote debugging protocol. The protocol + * allows to create ephemeral contexts and create pages in them and then + * manipulate them using the inspector commands. This may be useful for + * the browser automation or remote debugging. + * + * Currently the protocol can be exposed to the parent process via a unix + * pipe. + */ + +enum { + CREATE_NEW_PAGE, + + LAST_SIGNAL +}; + +struct _WebKitBrowserInspectorPrivate { + int unused { 0 }; +}; + +WEBKIT_DEFINE_TYPE(WebKitBrowserInspector, webkit_browser_inspector, G_TYPE_OBJECT) + +static guint signals[LAST_SIGNAL] = { 0, }; + +static void webkit_browser_inspector_class_init(WebKitBrowserInspectorClass* findClass) +{ + GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass); + + /** + * WebKitBrowserInspector::create-new-page: + * @inspector: the #WebKitBrowserInspector on which the signal is emitted + * + * Emitted when the inspector is requested to create a new page in the provided + * #WebKitWebContext. + * + * This signal is emitted when inspector receives 'Browser.createPage' command + * from its remote client. If the signla is not handled the command will fail. + * + * Returns: %WebKitWebView that contains created page. + */ + signals[CREATE_NEW_PAGE] = g_signal_new( + "create-new-page", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitBrowserInspectorClass, create_new_page), + nullptr, nullptr, + g_cclosure_marshal_generic, +#if PLATFORM(GTK) + GTK_TYPE_WIDGET, +#else + WEBKIT_TYPE_WEB_VIEW, +#endif + 1, + WEBKIT_TYPE_WEB_CONTEXT); +} + +WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext* context) +{ + WebKitWebView* newWebView; + g_signal_emit(webkit_browser_inspector_get_default(), signals[CREATE_NEW_PAGE], 0, context, &newWebView); + if (!newWebView) + return nullptr; + return &webkitWebViewGetPage(newWebView); +} + +static gpointer createWebKitBrowserInspector(gpointer) +{ + static GRefPtr browserInspector = adoptGRef(WEBKIT_BROWSER_INSPECTOR(g_object_new(WEBKIT_TYPE_BROWSER_INSPECTOR, nullptr))); + return browserInspector.get(); +} + +/** + * webkit_browser_inspector_get_default: + * + * Gets the default instance of the browser inspector. + * + * Returns: (transfer none): a #WebKitBrowserInspector + */ +WebKitBrowserInspector* webkit_browser_inspector_get_default(void) +{ + static GOnce onceInit = G_ONCE_INIT; + return WEBKIT_BROWSER_INSPECTOR(g_once(&onceInit, createWebKitBrowserInspector, 0)); +} + +/** + * webkit_browser_inspector_initialize_pipe: + * + * Creates browser inspector and configures pipe handler to communicate with + * the parent process. + */ +void webkit_browser_inspector_initialize_pipe(void) +{ +#if ENABLE(REMOTE_INSPECTOR) + WebKit::initializeBrowserInspectorPipe(makeUnique()); +#endif +} diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h new file mode 100644 index 0000000000000000000000000000000000000000..42310b02db6b6a2b9584aa478937f44a2af14c3f --- /dev/null +++ b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebKitBrowserInspector.h" +#include "WebPageProxy.h" + +WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext*); diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp index f769407fdc660c6f6fef77af90a43bd5dca9d544..ba010ed593bdedc0d70e4f4d3139e73d3c395463 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp @@ -91,6 +91,10 @@ private: { webkitWebViewRunJavaScriptPrompt(m_webView, message.utf8(), defaultValue.utf8(), WTFMove(completionHandler)); } + void handleJavaScriptDialog(WebPageProxy&, bool accept, const String& value) final + { + webkitWebViewHandleJavaScriptDialog(m_webView, accept, value); + } bool canRunBeforeUnloadConfirmPanel() const final { return true; } diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp index 33a9b7d5ad060f275dcf7156a8cff3f37644e736..406c6431bd84a9193f75a7689553fe79eb5d864b 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp @@ -385,6 +385,11 @@ static void webkitWebContextConstructed(GObject* object) if (!webkit_website_data_manager_is_ephemeral(priv->websiteDataManager.get())) WebKit::LegacyGlobalSettings::singleton().setHSTSStorageDirectory(FileSystem::stringFromFileSystemRepresentation(webkit_website_data_manager_get_hsts_cache_directory(priv->websiteDataManager.get()))); + const gchar *singleprocess = g_getenv("MINIBROWSER_SINGLEPROCESS"); + if (singleprocess && *singleprocess) { + // processModel is not set at this point, force single process. + configuration.setUsesSingleWebProcess(true); + } priv->processPool = WebProcessPool::create(configuration); priv->processPool->setPrimaryDataStore(webkitWebsiteDataManagerGetDataStore(priv->websiteDataManager.get())); priv->processPool->setUserMessageHandler([webContext](UserMessage&& message, CompletionHandler&& completionHandler) { diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp index 646e45adc2818287f47d00340567822c210a16ed..1caff042a6783addd52355527ea9797fb4e4c513 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp @@ -2385,6 +2385,15 @@ void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const webkit_script_dialog_unref(webView->priv->currentScriptDialog); } +void webkitWebViewHandleJavaScriptDialog(WebKitWebView* webView, bool accept, const String& value) { + if (!value.isNull()) + webkitWebViewSetCurrentScriptDialogUserInput(webView, value); + if (accept) + webkitWebViewAcceptCurrentScriptDialog(webView); + else + webkitWebViewDismissCurrentScriptDialog(webView); +} + bool webkitWebViewIsShowingScriptDialog(WebKitWebView* webView) { if (!webView->priv->currentScriptDialog) diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h index 811c35c49613f6fb6ff1ce24e525450ca4617723..b6eaa8315c0a12d0509d97a6608fd6d7c8e3289d 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h @@ -60,6 +60,7 @@ void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message, Fun void webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message, Function&& completionHandler); void webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText, Function&& completionHandler); void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView*, const CString& message, Function&& completionHandler); +void webkitWebViewHandleJavaScriptDialog(WebKitWebView*, bool accept, const String& value); bool webkitWebViewIsShowingScriptDialog(WebKitWebView*); bool webkitWebViewIsScriptDialogRunning(WebKitWebView*, WebKitScriptDialog*); String webkitWebViewGetCurrentScriptDialogMessage(WebKitWebView*); diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp index b1252daf7423bb66a177b5d028563e389b73802a..3edc383f6d7bbc1b43a7b4937eee03c473e65686 100644 --- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp +++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp @@ -224,6 +224,8 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool { if (wasEventHandled) return; + if (!event.nativeEvent()) + return; WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(m_viewWidget); webkitWebViewBaseForwardNextKeyEvent(webkitWebViewBase); diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h new file mode 100644 index 0000000000000000000000000000000000000000..f158ae5b8e3d4472cae87f4ebe034d33a7f11d80 --- /dev/null +++ b/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef WebKitBrowserInspector_h +#define WebKitBrowserInspector_h + +#include +#include +#include + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_BROWSER_INSPECTOR (webkit_browser_inspector_get_type()) +#define WEBKIT_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspector)) +#define WEBKIT_IS_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_BROWSER_INSPECTOR)) +#define WEBKIT_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass)) +#define WEBKIT_IS_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_BROWSER_INSPECTOR)) +#define WEBKIT_BROWSER_INSPECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass)) + +typedef struct _WebKitBrowserInspector WebKitBrowserInspector; +typedef struct _WebKitBrowserInspectorClass WebKitBrowserInspectorClass; +typedef struct _WebKitBrowserInspectorPrivate WebKitBrowserInspectorPrivate; + +struct _WebKitBrowserInspector { + GObject parent; + + WebKitBrowserInspectorPrivate *priv; +}; + +struct _WebKitBrowserInspectorClass { + GObjectClass parent_class; + + WebKitWebView *(* create_new_page) (WebKitBrowserInspector *browser_inspector, + WebKitWebContext *context); + + void (*_webkit_reserved0) (void); + void (*_webkit_reserved1) (void); + void (*_webkit_reserved2) (void); + void (*_webkit_reserved3) (void); +}; + +WEBKIT_API GType +webkit_browser_inspector_get_type (void); + +WEBKIT_API WebKitBrowserInspector * +webkit_browser_inspector_get_default (void); + +WEBKIT_API void +webkit_browser_inspector_initialize_pipe (void); + +G_END_DECLS + +#endif diff --git a/Source/WebKit/UIProcess/API/gtk/webkit2.h b/Source/WebKit/UIProcess/API/gtk/webkit2.h index 930b17b6629e04d0dfa2222bbc3217877c6e1812..395462e5f01c195231e9296d1204167cded99ad3 100644 --- a/Source/WebKit/UIProcess/API/gtk/webkit2.h +++ b/Source/WebKit/UIProcess/API/gtk/webkit2.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h new file mode 100644 index 0000000000000000000000000000000000000000..323ac896a7e5c70afc4a585a39ba06866535ac5f --- /dev/null +++ b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(__WEBKIT_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef WebKitBrowserInspector_h +#define WebKitBrowserInspector_h + +#include +#include +#include + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_BROWSER_INSPECTOR (webkit_browser_inspector_get_type()) +#define WEBKIT_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspector)) +#define WEBKIT_IS_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_BROWSER_INSPECTOR)) +#define WEBKIT_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass)) +#define WEBKIT_IS_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_BROWSER_INSPECTOR)) +#define WEBKIT_BROWSER_INSPECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass)) + +typedef struct _WebKitBrowserInspector WebKitBrowserInspector; +typedef struct _WebKitBrowserInspectorClass WebKitBrowserInspectorClass; +typedef struct _WebKitBrowserInspectorPrivate WebKitBrowserInspectorPrivate; + +struct _WebKitBrowserInspector { + GObject parent; + + WebKitBrowserInspectorPrivate *priv; +}; + +struct _WebKitBrowserInspectorClass { + GObjectClass parent_class; + + WebKitWebView *(* create_new_page) (WebKitBrowserInspector *browser_inspector, + WebKitWebContext *context); + + void (*_webkit_reserved0) (void); + void (*_webkit_reserved1) (void); + void (*_webkit_reserved2) (void); + void (*_webkit_reserved3) (void); +}; + +WEBKIT_API GType +webkit_browser_inspector_get_type (void); + +WEBKIT_API WebKitBrowserInspector * +webkit_browser_inspector_get_default (void); + +G_END_DECLS + +#endif diff --git a/Source/WebKit/UIProcess/API/wpe/webkit.h b/Source/WebKit/UIProcess/API/wpe/webkit.h index 15a4c1ff1c4aeee7d807856db0b3a74002e421dd..92212f1b5befe0f3b8c5222e81221a8a049b4818 100644 --- a/Source/WebKit/UIProcess/API/wpe/webkit.h +++ b/Source/WebKit/UIProcess/API/wpe/webkit.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/Source/WebKit/UIProcess/BrowserInspectorController.cpp b/Source/WebKit/UIProcess/BrowserInspectorController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59252db1b9ac816a7e19cf4568e3f7863fef683d --- /dev/null +++ b/Source/WebKit/UIProcess/BrowserInspectorController.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "BrowserInspectorController.h" + +#if ENABLE(REMOTE_INSPECTOR) + +#include "BrowserInspectorTargetAgent.h" +#include "InspectorBrowserAgent.h" +#include "InspectorBrowserAgentClient.h" +#include "WebPageInspectorController.h" +#include "WebPageProxy.h" +#include "WebProcessPool.h" +#include "WebProcessProxy.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace Inspector; + +namespace WebKit { + +static Vector allPages() +{ + ASSERT(isMainThread()); + Vector result; + for (WebProcessPool* pool : WebProcessPool::allProcessPools()) { + for (auto& process : pool->processes()) { + result.appendRange(process->pages().begin(), process->pages().end()); + } + } + return result; +} + +class BrowserInspectorController::PageProxyChannel : public FrontendChannel { + WTF_MAKE_FAST_ALLOCATED; +public: + PageProxyChannel(FrontendChannel& frontendChannel, String pageProxyID, WebPageProxy& page) + : m_pageProxyID(pageProxyID) + , m_frontendChannel(frontendChannel) + , m_page(page) + { + } + + ~PageProxyChannel() override = default; + + void dispatchMessageFromFrontend(const String& message) + { + m_page.inspectorController().dispatchMessageFromFrontend(message); + } + + void disconnect() + { + m_page.inspectorController().disconnectFrontend(*this); + } + +private: + ConnectionType connectionType() const override { return m_frontendChannel.connectionType(); } + void sendMessageToFrontend(const String& message) override + { + m_frontendChannel.sendMessageToFrontend(addTabIdToMessage(message)); + } + + String addTabIdToMessage(const String& message) { + RefPtr parsedMessage; + if (!JSON::Value::parseJSON(message, parsedMessage)) + return message; + + RefPtr messageObject; + if (!parsedMessage->asObject(messageObject)) + return message; + + messageObject->setString("pageProxyId"_s, m_pageProxyID); + return messageObject->toJSONString(); + } + + String m_pageProxyID; + FrontendChannel& m_frontendChannel; + WebPageProxy& m_page; +}; + +BrowserInspectorController::BrowserInspectorController(std::unique_ptr client) + : m_frontendChannel(nullptr) + , m_frontendRouter(FrontendRouter::create()) + , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef())) + , m_browserAgentClient(std::move(client)) +{ + auto browserAgent = makeUnique(m_frontendRouter, m_backendDispatcher, m_browserAgentClient.get()); + m_browserAgent = browserAgent.get(); + m_agents.append(WTFMove(browserAgent)); + + auto targetAgent = makeUnique(m_backendDispatcher); + m_browserTargetAgent = targetAgent.get(); + m_agents.append(WTFMove(targetAgent)); +} + +BrowserInspectorController::~BrowserInspectorController() +{ + if (m_frontendChannel) + disconnectFrontend(); +} + +void BrowserInspectorController::connectFrontend(FrontendChannel& frontendChannel) +{ + ASSERT(!m_frontendChannel); + m_frontendChannel = &frontendChannel; + WebPageInspectorController::setObserver(this); + + bool connectingFirstFrontend = !m_frontendRouter->hasFrontends(); + m_frontendRouter->connectFrontend(frontendChannel); + if (connectingFirstFrontend) + m_agents.didCreateFrontendAndBackend(&m_frontendRouter.get(), &m_backendDispatcher.get()); + + connectToAllPages(); +} + +void BrowserInspectorController::disconnectFrontend() +{ + ASSERT(m_frontendChannel); + disconnectFromAllPages(); + + m_frontendRouter->disconnectFrontend(*m_frontendChannel); + if (!m_frontendRouter->hasFrontends()) + m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectorDestroyed); + + WebPageInspectorController::setObserver(nullptr); + m_frontendChannel = nullptr; +} + +void BrowserInspectorController::dispatchMessageFromFrontend(const String& message) +{ + m_backendDispatcher->dispatch(message, BackendDispatcher::Mode::FailIfDomainIsMissing, [&](const RefPtr& messageObject) { + RefPtr pageProxyIDValue; + if (!messageObject->getValue("pageProxyId"_s, pageProxyIDValue)) + return BackendDispatcher::DispatchResult::Continue; + + String pageProxyID; + if (!pageProxyIDValue->asString(pageProxyID)) { + m_backendDispatcher->reportProtocolError(BackendDispatcher::InvalidRequest, "The type of 'pageProxyId' must be string"_s); + m_backendDispatcher->sendPendingErrors(); + return BackendDispatcher::DispatchResult::Finished; + } + + + if (auto pageProxyChannel = m_pageProxyChannels.get(pageProxyID)) { + pageProxyChannel->dispatchMessageFromFrontend(message); + return BackendDispatcher::DispatchResult::Finished; + } + + m_backendDispatcher->reportProtocolError(BackendDispatcher::InvalidRequest, "Cannot find page proxy with provided 'pageProxyId'"_s); + m_backendDispatcher->sendPendingErrors(); + return BackendDispatcher::DispatchResult::Finished; + }); +} + +void BrowserInspectorController::connectToAllPages() +{ + for (auto* page : allPages()) + connectToPage(*page); +} + +void BrowserInspectorController::disconnectFromAllPages() +{ + for (auto it = m_pageProxyChannels.begin(); it != m_pageProxyChannels.end(); ++it) + it->value->disconnect(); + m_pageProxyChannels.clear(); +} + +void BrowserInspectorController::connectToPage(WebPageProxy& page) +{ + String pageProxyID = InspectorBrowserAgent::toPageProxyIDProtocolString(page); + auto pageProxyChannel = makeUnique(*m_frontendChannel, pageProxyID, page); + page.inspectorController().connectFrontend(*pageProxyChannel); + m_pageProxyChannels.set(pageProxyID, WTFMove(pageProxyChannel)); +} + +void BrowserInspectorController::didCreateInspectorController(WebPageProxy& page) +{ + ASSERT(m_frontendChannel); + // Auto-connect to all new pages. + connectToPage(page); + m_browserAgent->didCreateWebPageProxy(page); +} + +void BrowserInspectorController::willDestroyInspectorController(WebPageProxy& page) +{ + m_browserAgent->willDestroyWebPageProxy(page); + + String pageProxyID = InspectorBrowserAgent::toPageProxyIDProtocolString(page); + auto it = m_pageProxyChannels.find(pageProxyID); + ASSERT(ti != m_pageProxyChannels.end()); + it->value->disconnect(); + m_pageProxyChannels.remove(it); +} + +void BrowserInspectorController::didCreateTarget(InspectorTarget& target) +{ + m_browserTargetAgent->didCreateTarget(target); +} + +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/BrowserInspectorController.h b/Source/WebKit/UIProcess/BrowserInspectorController.h new file mode 100644 index 0000000000000000000000000000000000000000..4b7d52c04b6a08de22e725c92fd8fd4804d00baa --- /dev/null +++ b/Source/WebKit/UIProcess/BrowserInspectorController.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +#include "WebPageInspectorController.h" +#include +#include +#include + +namespace Inspector { +class BackendDispatcher; +class FrontendChannel; +class FrontendRouter; +} + +namespace WebKit { + +class BrowserInspectorTargetAgent; +class InspectorBrowserAgent; +class InspectorBrowserAgentClient; + +class BrowserInspectorController : private WebPageInspectorControllerObserver { + WTF_MAKE_NONCOPYABLE(BrowserInspectorController); + WTF_MAKE_FAST_ALLOCATED; +public: + BrowserInspectorController(std::unique_ptr client); + ~BrowserInspectorController(); + + void connectFrontend(Inspector::FrontendChannel&); + void disconnectFrontend(); + void dispatchMessageFromFrontend(const String& message); + +private: + class TargetHandler; + class PageProxyChannel; + + // WebPageInspectorControllerObserver + void didCreateInspectorController(WebPageProxy&) override; + void willDestroyInspectorController(WebPageProxy&) override; + void didCreateTarget(Inspector::InspectorTarget&) override; + + void connectToAllPages(); + void disconnectFromAllPages(); + void connectToPage(WebPageProxy&); + + Inspector::FrontendChannel* m_frontendChannel { nullptr }; + Ref m_frontendRouter; + Ref m_backendDispatcher; + std::unique_ptr m_browserAgentClient; + Inspector::AgentRegistry m_agents; + InspectorBrowserAgent* m_browserAgent { nullptr }; + BrowserInspectorTargetAgent* m_browserTargetAgent { nullptr }; + HashMap> m_pageProxyChannels; +}; + +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44178b0f33cac1cdd51618e84ec73bfb5a590b4b --- /dev/null +++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "BrowserInspectorPipe.h" + +#if ENABLE(REMOTE_INSPECTOR) + +#include "BrowserInspectorController.h" +#include "RemoteInspectorPipe.h" +#include +#include "InspectorBrowserAgentClient.h" + +namespace WebKit { + +void initializeBrowserInspectorPipe(std::unique_ptr client) +{ + class BrowserInspectorPipe { + public: + BrowserInspectorPipe(std::unique_ptr client) + : m_browserInspectorController(std::move(client)) + , m_remoteInspectorPipe(m_browserInspectorController) + { + } + + BrowserInspectorController m_browserInspectorController; + RemoteInspectorPipe m_remoteInspectorPipe; + }; + + static NeverDestroyed pipe(std::move(client)); +} + +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/BrowserInspectorPipe.h b/Source/WebKit/UIProcess/BrowserInspectorPipe.h new file mode 100644 index 0000000000000000000000000000000000000000..c068a8f61e14dc8893fe4f7d1431aa8250799001 --- /dev/null +++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +namespace WebKit { + +class InspectorBrowserAgentClient; + +void initializeBrowserInspectorPipe(std::unique_ptr client); + +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/BrowserInspectorTargetAgent.cpp b/Source/WebKit/UIProcess/BrowserInspectorTargetAgent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0955a8a9fdb733184c5b34dbe486e0f1f3b66367 --- /dev/null +++ b/Source/WebKit/UIProcess/BrowserInspectorTargetAgent.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "BrowserInspectorTargetAgent.h" + +#include "WebPageInspectorController.h" +#include "WebPageProxy.h" +#include "WebProcessPool.h" +#include "WebProcessProxy.h" +#include +#include + +using namespace Inspector; + +namespace WebKit { + +namespace { + +InspectorTarget* targetForId(const String& targetId) +{ + ASSERT(isMainThread()); + for (auto* pool : WebProcessPool::allProcessPools()) { + for (auto& process : pool->processes()) { + for (auto* page : process->pages()) { + auto* result = page->inspectorController().findTarget(targetId); + if (result != nullptr) + return result; + } + } + } + return nullptr; +} + +} // namespace + +BrowserInspectorTargetAgent::BrowserInspectorTargetAgent(BackendDispatcher& backendDispatcher) + : InspectorAgentBase("Target"_s) + , m_backendDispatcher(TargetBackendDispatcher::create(backendDispatcher, this)) +{ +} + +BrowserInspectorTargetAgent::~BrowserInspectorTargetAgent() = default; + +void BrowserInspectorTargetAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) +{ +} + +void BrowserInspectorTargetAgent::willDestroyFrontendAndBackend(DisconnectReason) +{ + m_shouldPauseOnStart = false; +} + +void BrowserInspectorTargetAgent::setPauseOnStart(ErrorString&, bool pauseOnStart) +{ + m_shouldPauseOnStart = pauseOnStart; +} + +void BrowserInspectorTargetAgent::resume(ErrorString& errorString, const String& targetId) +{ + auto* target = targetForId(targetId); + if (!target) { + errorString = "Missing target for given targetId"_s; + return; + } + + if (!target->isPaused()) { + errorString = "Target for given targetId is not paused"_s; + return; + } + + target->resume(); +} + +void BrowserInspectorTargetAgent::sendMessageToTarget(ErrorString& error, const String& in_targetId, const String& in_message) +{ + auto* target = targetForId(in_targetId); + if (target == nullptr) { + error = "Cannot find target with provided id."; + return; + } + target->sendMessageToTargetBackend(in_message); +} + +void BrowserInspectorTargetAgent::activate(ErrorString& error, const String& targetId) +{ + auto* target = targetForId(targetId); + if (target == nullptr) { + error = "Cannot find target with provided id."; + return; + } + target->activate(error); +} + +void BrowserInspectorTargetAgent::close(ErrorString& error, const String& targetId, const bool* runBeforeUnload) +{ + auto* target = targetForId(targetId); + if (target == nullptr) { + error = "Cannot find target with provided id."; + return; + } + target->close(error, runBeforeUnload && *runBeforeUnload); +} + +void BrowserInspectorTargetAgent::didCreateTarget(InspectorTarget& target) +{ + if (m_shouldPauseOnStart) + target.pause(); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/BrowserInspectorTargetAgent.h b/Source/WebKit/UIProcess/BrowserInspectorTargetAgent.h new file mode 100644 index 0000000000000000000000000000000000000000..b238241a0cab0205d19115790bc6b7de37ecdb82 --- /dev/null +++ b/Source/WebKit/UIProcess/BrowserInspectorTargetAgent.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "config.h" + +#include +#include +#include +#include + +namespace Inspector { +class InspectorTarget; +} + +namespace WebKit { + +class BrowserInspectorTargetAgent final : public Inspector::InspectorAgentBase, public Inspector::TargetBackendDispatcherHandler { + WTF_MAKE_NONCOPYABLE(BrowserInspectorTargetAgent); + WTF_MAKE_FAST_ALLOCATED; +public: + explicit BrowserInspectorTargetAgent(Inspector::BackendDispatcher&); + ~BrowserInspectorTargetAgent() override; + + // InspectorAgentBase + void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; + void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; + + // TargetBackendDispatcherHandler + void sendMessageToTarget(Inspector::ErrorString&, const String& targetId, const String& message) final; + void activate(Inspector::ErrorString&, const String& targetId) override; + void close(Inspector::ErrorString&, const String& targetId, const bool* runBeforeUnload) override; + void setPauseOnStart(Inspector::ErrorString&, bool pauseOnStart) override; + void resume(Inspector::ErrorString&, const String& in_targetId) override; + + void didCreateTarget(Inspector::InspectorTarget&); + +private: + Ref m_backendDispatcher; + bool m_shouldPauseOnStart { false }; +}; + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h index 454c61ffdefecc476d1560c7c43f5b5d345f281d..6de7509037b7683ddd403ee247bdf2845ce4e87a 100644 --- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h +++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h @@ -27,6 +27,8 @@ #if HAVE(APP_SSO) +#include +#include #include "SOAuthorizationSession.h" #include @@ -39,6 +41,8 @@ class NavigationAction; namespace WebKit { +class WebPageProxy; + // FSM: Idle => Active => Completed class PopUpSOAuthorizationSession final : public SOAuthorizationSession { public: diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm index 0f18038de989e69a8432c85b71b6c04e931302b3..82a966779403346aed174dcfcd01a79691956d7b 100644 --- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm +++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm @@ -29,6 +29,7 @@ #if HAVE(APP_SSO) #import "APINavigationAction.h" +#import "WebPageProxy.h" #import "WKNavigationDelegatePrivate.h" #import "WKUIDelegate.h" #import "WKWebViewConfigurationPrivate.h" diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h index c9498f99107f5d416f349509a6bfb6c2310bd938..d9ab65cc0d3a2b319ce0675403875a17efa0d09c 100644 --- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h +++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h @@ -91,6 +91,7 @@ private: void runJavaScriptAlert(WebPageProxy&, const WTF::String&, WebFrameProxy*, WebCore::SecurityOriginData&&, Function&& completionHandler) final; void runJavaScriptConfirm(WebPageProxy&, const WTF::String&, WebFrameProxy*, WebCore::SecurityOriginData&&, Function&& completionHandler) final; void runJavaScriptPrompt(WebPageProxy&, const WTF::String&, const WTF::String&, WebFrameProxy*, WebCore::SecurityOriginData&&, Function&&) final; + void handleJavaScriptDialog(WebKit::WebPageProxy&, bool accept, const WTF::String&) final; void presentStorageAccessConfirmDialog(const WTF::String& requestingDomain, const WTF::String& currentDomain, CompletionHandler&&); void requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler&&) final; void decidePolicyForGeolocationPermissionRequest(WebPageProxy&, WebFrameProxy&, API::SecurityOrigin&, Function&) final; @@ -171,6 +172,7 @@ private: bool webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler : 1; bool webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler : 1; bool webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler : 1; + bool webViewHandleJavaScriptDialogValue : 1; bool webViewRequestStorageAccessPanelUnderFirstPartyCompletionHandler : 1; bool webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler : 1; bool webViewRequestGeolocationPermissionForFrameDecisionHandler : 1; diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm index ea9a9ca355836a25ca2d70c5bf67149f19d014ff..4d583a153929d6f554c0304c001725b3ecbbd796 100644 --- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm +++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm @@ -104,6 +104,7 @@ void UIDelegate::setDelegate(id delegate) m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)]; m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)]; m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)]; + m_delegateMethods.webViewHandleJavaScriptDialogValue = [delegate respondsToSelector:@selector(webView:handleJavaScriptDialog:value:)]; m_delegateMethods.webViewRequestStorageAccessPanelUnderFirstPartyCompletionHandler = [delegate respondsToSelector:@selector(_webView:requestStorageAccessPanelForDomain:underCurrentDomain:completionHandler:)]; m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:)]; m_delegateMethods.webViewRequestGeolocationPermissionForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestGeolocationPermissionForFrame:decisionHandler:)]; @@ -341,6 +342,15 @@ void UIDelegate::UIClient::runJavaScriptPrompt(WebPageProxy&, const WTF::String& }).get()]; } +void UIDelegate::UIClient::handleJavaScriptDialog(WebKit::WebPageProxy&, bool accept, const WTF::String& value) { + if (!m_uiDelegate.m_delegateMethods.webViewHandleJavaScriptDialogValue) + return; + auto delegate = m_uiDelegate.m_delegate.get(); + if (!delegate) + return; + [delegate webView:m_uiDelegate.m_webView handleJavaScriptDialog:accept value:value]; +} + void UIDelegate::UIClient::requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler&& completionHandler) { auto delegate = m_uiDelegate.m_delegate.get(); diff --git a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm index 0e6e5bdd8e5d2030511328517c32cfce72b682d8..33991ff5add2edd16fa8879840f4606aa18b81fb 100644 --- a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm +++ b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm @@ -125,6 +125,13 @@ static void registerUserDefaultsIfNeeded() [[NSUserDefaults standardUserDefaults] registerDefaults:registrationDictionary]; } +void WebProcessPool::setIgnoreTLSErrors(bool ignoreTLSErrors) +{ + m_ignoreTLSErrors = ignoreTLSErrors; + if (m_networkProcess) + m_networkProcess->send(Messages::NetworkProcess::SetIgnoreTLSErrors(m_ignoreTLSErrors), 0); +} + void WebProcessPool::updateProcessSuppressionState() { if (m_networkProcess) @@ -372,6 +379,7 @@ void WebProcessPool::platformInitializeNetworkProcess(NetworkProcessCreationPara } } + parameters.ignoreTLSErrors = m_ignoreTLSErrors; parameters.enableLegacyTLS = false; if (id value = [defaults objectForKey:@"WebKitEnableLegacyTLS"]) parameters.enableLegacyTLS = [value boolValue]; diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp index 9693809e34e40942c833164e19ac49eeb2c36f43..b45a4e7aa61c32f9143d29fcce410e9e647705ee 100644 --- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp +++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp @@ -37,6 +37,7 @@ #include "WebProcessProxy.h" #include #include +#include #if PLATFORM(GTK) #include @@ -133,6 +134,11 @@ void DrawingAreaProxyCoordinatedGraphics::deviceScaleFactorDidChange() backingStoreStateDidChange(RespondImmediately); } +void DrawingAreaProxyCoordinatedGraphics::waitForBackingStoreUpdate(Function&& callback) +{ + m_callbacks.set(m_currentBackingStoreStateID, WTFMove(callback)); +} + void DrawingAreaProxyCoordinatedGraphics::waitForBackingStoreUpdateOnNextPaint() { m_hasReceivedFirstUpdate = true; @@ -195,6 +201,16 @@ void DrawingAreaProxyCoordinatedGraphics::didUpdateBackingStoreState(uint64_t ba else m_hasReceivedFirstUpdate = true; + Vector notified; + for (auto& [key, value] : m_callbacks) { + if (backingStoreStateID > key) { + notified.append(key); + value(); + } + } + for (uint64_t id : notified) + m_callbacks.remove(id); + #if !PLATFORM(WPE) if (isInAcceleratedCompositingMode()) { ASSERT(!m_backingStore); diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h index d7695088e7cfc4f638f157338754f9f157489749..fd0e1db93b4b6fc094ff47565ca19e83c6104410 100644 --- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h +++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h @@ -30,6 +30,7 @@ #include "BackingStore.h" #include "DrawingAreaProxy.h" #include "LayerTreeContext.h" +#include #include namespace WebCore { @@ -49,6 +50,7 @@ public: bool isInAcceleratedCompositingMode() const { return !m_layerTreeContext.isEmpty(); } const LayerTreeContext& layerTreeContext() const { return m_layerTreeContext; } + void waitForBackingStoreUpdate(Function&&); private: // DrawingAreaProxy @@ -126,6 +128,9 @@ private: // For a new Drawing Area don't draw anything until the WebProcess has sent over the first content. bool m_hasReceivedFirstUpdate { false }; + using ResizeCallbackMap = HashMap, WTF::IntHash, WTF::UnsignedWithZeroKeyHashTraits>; + ResizeCallbackMap m_callbacks; + #if !PLATFORM(WPE) bool m_isBackingStoreDiscardable { true }; std::unique_ptr m_backingStore; diff --git a/Source/WebKit/UIProcess/InspectorBrowserAgent.cpp b/Source/WebKit/UIProcess/InspectorBrowserAgent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cafedaffaccb0dcc293681dcfa90f50203d35119 --- /dev/null +++ b/Source/WebKit/UIProcess/InspectorBrowserAgent.cpp @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "InspectorBrowserAgent.h" + +#if ENABLE(REMOTE_INSPECTOR) + +#include "InspectorBrowserAgentClient.h" +#include "InspectorTargetProxy.h" +#include "NetworkProcessMessages.h" +#include "NetworkProcessProxy.h" +#include "WebGeolocationManagerProxy.h" +#include "WebGeolocationPosition.h" +#include "WebPageInspectorTarget.h" +#include "WebPageProxy.h" +#include "WebProcessPool.h" +#include +#include +#include +#include +#include + + +using namespace Inspector; + +namespace WebKit { + +namespace { + +Inspector::Protocol::Browser::CookieSameSitePolicy cookieSameSitePolicy(WebCore::Cookie::SameSitePolicy policy) +{ + switch (policy) { + case WebCore::Cookie::SameSitePolicy::None: + return Inspector::Protocol::Browser::CookieSameSitePolicy::None; + case WebCore::Cookie::SameSitePolicy::Lax: + return Inspector::Protocol::Browser::CookieSameSitePolicy::Lax; + case WebCore::Cookie::SameSitePolicy::Strict: + return Inspector::Protocol::Browser::CookieSameSitePolicy::Strict; + } + ASSERT_NOT_REACHED(); + return Inspector::Protocol::Browser::CookieSameSitePolicy::None; +} + +Ref buildObjectForCookie(const WebCore::Cookie& cookie) +{ + return Inspector::Protocol::Browser::Cookie::create() + .setName(cookie.name) + .setValue(cookie.value) + .setDomain(cookie.domain) + .setPath(cookie.path) + .setExpires(cookie.expires) + .setHttpOnly(cookie.httpOnly) + .setSecure(cookie.secure) + .setSession(cookie.session) + .setSameSite(cookieSameSitePolicy(cookie.sameSite)) + .release(); +} + +Ref buildPageProxyInfo(const WebPageProxy& page) { + return Inspector::Protocol::Browser::PageProxyInfo::create() + .setPageProxyId(InspectorBrowserAgent::toPageProxyIDProtocolString(page)) + .setBrowserContextId(InspectorBrowserAgent::toBrowserContextIDProtocolString(page.sessionID())) + .release(); +} + +} // namespace + +InspectorBrowserAgent::InspectorBrowserAgent(Inspector::FrontendRouter& frontendRouter, Inspector::BackendDispatcher& backendDispatcher, InspectorBrowserAgentClient* client) + : InspectorAgentBase("Browser"_s) + , m_frontendDispatcher(makeUnique(frontendRouter)) + , m_backendDispatcher(BrowserBackendDispatcher::create(backendDispatcher, this)) + , m_client(client) +{ +} + +InspectorBrowserAgent::~InspectorBrowserAgent() = default; + +void InspectorBrowserAgent::didCreateWebPageProxy(const WebPageProxy& page) +{ + if (m_isConnected) + m_frontendDispatcher->pageProxyCreated(buildPageProxyInfo(page)); +} + +void InspectorBrowserAgent::willDestroyWebPageProxy(const WebPageProxy& page) +{ + if (m_isConnected) + m_frontendDispatcher->pageProxyDestroyed(toPageProxyIDProtocolString(page)); +} + +void InspectorBrowserAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) +{ + m_isConnected = true; +} + +void InspectorBrowserAgent::willDestroyFrontendAndBackend(DisconnectReason) +{ + m_isConnected = false; +} + +void InspectorBrowserAgent::close(ErrorString& errorString) +{ + if (m_client == nullptr) { + errorString = "no platform delegate to close browser"; + } else { + m_client->closeAllWindows(); + } +} + +void InspectorBrowserAgent::createContext(ErrorString& errorString, String* browserContextID) +{ + BrowserContext browserContext = m_client->createBrowserContext(errorString); + if (!errorString.isEmpty()) + return; + browserContext.processPool->setPrimaryDataStore(*browserContext.dataStore); + browserContext.processPool->ensureNetworkProcess(browserContext.dataStore.get()); + PAL::SessionID sessionID = browserContext.dataStore->sessionID(); + *browserContextID = toBrowserContextIDProtocolString(sessionID); + m_browserContexts.set(*browserContextID, browserContext); +} + +void InspectorBrowserAgent::deleteContext(ErrorString& errorString, const String& browserContextID) +{ + BrowserContext browserContext = lookupBrowserContext(errorString, &browserContextID); + if (!errorString.isEmpty()) + return; + + Vector pages; + for (auto& process : browserContext.processPool->processes()) { + for (auto* page : process->pages()) + pages.append(page); + } + + for (auto* page : pages) + page->closePage(); + + PAL::SessionID sessionID = browserContext.dataStore->sessionID(); + m_client->deleteBrowserContext(errorString, sessionID); + m_browserContexts.remove(browserContextID); +} + +void InspectorBrowserAgent::createPage(ErrorString& errorString, const String* browserContextID, String* targetID) +{ + BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID); + if (!errorString.isEmpty()) + return; + PAL::SessionID sessionID = browserContext.dataStore->sessionID(); + RefPtr page = m_client->createPage(errorString, sessionID); + if (page == nullptr) + return; + page->setPermissionsForAutomation(m_permissions.get(browserContextID ? *browserContextID : "")); + *targetID = WebPageInspectorTarget::toTargetID(page->webPageID()); +} + +void InspectorBrowserAgent::setIgnoreCertificateErrors(Inspector::ErrorString& errorString, const String* browserContextID, bool ignore) +{ + BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID); + if (!errorString.isEmpty()) + return; + browserContext.processPool->setIgnoreTLSErrors(ignore); +} + +void InspectorBrowserAgent::getAllCookies(const String* browserContextID, Ref&& callback) { + String errorString; + BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID); + if (!errorString.isEmpty()) { + callback->sendFailure(errorString); + return; + } + + PAL::SessionID sessionID = browserContext.dataStore->sessionID(); + NetworkProcessProxy* networkProcess = browserContext.processPool->networkProcess(); + networkProcess->sendWithAsyncReply(Messages::NetworkProcess::GetAllCookies(sessionID), + [callback = WTFMove(callback)](Vector allCookies) { + if (!callback->isActive()) + return; + auto cookies = JSON::ArrayOf::create(); + for (const auto& cookie : allCookies) + cookies->addItem(buildObjectForCookie(cookie)); + callback->sendSuccess(WTFMove(cookies)); + }, 0); +} + +void InspectorBrowserAgent::setCookies(const String* browserContextID, const JSON::Array& in_cookies, Ref&& callback) { + String errorString; + BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID); + if (!errorString.isEmpty()) { + callback->sendFailure(errorString); + return; + } + + NetworkProcessProxy* networkProcess = browserContext.processPool->networkProcess(); + PAL::SessionID sessionID = browserContext.dataStore->sessionID(); + + Vector cookies; + for (unsigned i = 0; i < in_cookies.length(); ++i) { + RefPtr item = in_cookies.get(i); + RefPtr obj; + if (!item->asObject(obj)) { + errorString = "Invalid cookie payload format"_s; + return; + } + + WebCore::Cookie cookie; + if (!obj->getString("name", cookie.name) || + !obj->getString("value", cookie.value) || + !obj->getString("domain", cookie.domain) || + !obj->getString("path", cookie.path)) { + errorString = "Invalid file payload format"_s; + return; + } + + obj->getDouble("expires", cookie.expires); + obj->getBoolean("httpOnly", cookie.httpOnly); + obj->getBoolean("secure", cookie.secure); + obj->getBoolean("session", cookie.session); + String sameSite; + if (obj->getString("sameSite", sameSite)) { + if (sameSite == "None") + cookie.sameSite = WebCore::Cookie::SameSitePolicy::None; + if (sameSite == "Lax") + cookie.sameSite = WebCore::Cookie::SameSitePolicy::Lax; + if (sameSite == "Strict") + cookie.sameSite = WebCore::Cookie::SameSitePolicy::Strict; + } + cookies.append(WTFMove(cookie)); + } + + networkProcess->sendWithAsyncReply(Messages::NetworkProcess::SetCookies(sessionID, WTFMove(cookies)), + [callback = WTFMove(callback)](bool success) { + if (!callback->isActive()) + return; + + if (success) + callback->sendSuccess(); + else + callback->sendFailure("Internal error: no network storage"_s); + callback->sendSuccess(); + }, 0); +} + +void InspectorBrowserAgent::deleteAllCookies(const String* browserContextID, Ref&& callback) { + String errorString; + BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID); + if (!errorString.isEmpty()) { + callback->sendFailure(errorString); + return; + } + + NetworkProcessProxy* networkProcess = browserContext.processPool->networkProcess(); + PAL::SessionID sessionID = browserContext.dataStore->sessionID(); + networkProcess->sendWithAsyncReply(Messages::NetworkProcess::DeleteAllCookies(sessionID), + [callback = WTFMove(callback)](bool success) { + if (!callback->isActive()) + return; + if (success) + callback->sendSuccess(); + else + callback->sendFailure("Internal error: no network storage"_s); + }, 0); +} + +void InspectorBrowserAgent::grantPermissions(Inspector::ErrorString& errorString, const String* browserContextID, const String& origin, const JSON::Array& values) +{ + BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID); + if (!errorString.isEmpty()) + return; + HashSet set; + for (const auto& value : values) { + String name; + if (!value->asString(name)) { + errorString = "Permission must be a string"_s; + return; + } + set.add(name); + } + String key = browserContextID ? *browserContextID : ""; + auto it = m_permissions.add(key, Permissions()).iterator; + it->value.set(origin, WTFMove(set)); + Vector pages; + for (auto& process : browserContext.processPool->processes()) { + for (auto* page : process->pages()) + page->setPermissionsForAutomation(it->value); + } +} + +void InspectorBrowserAgent::resetPermissions(Inspector::ErrorString& errorString, const String* browserContextID) +{ + BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID); + if (!errorString.isEmpty()) + return; + m_permissions.clear(); + for (auto& process : browserContext.processPool->processes()) { + for (auto* page : process->pages()) + page->setPermissionsForAutomation(HashMap>()); + } +} + +void InspectorBrowserAgent::setGeolocationOverride(Inspector::ErrorString& errorString, const String* browserContextID, const JSON::Object* geolocation) +{ + BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID); + if (!errorString.isEmpty()) + return; + auto* geoManager = browserContext.processPool->supplement(); + if (!geoManager) { + errorString = "Internal error: geolocation manager is not available."; + return; + } + if (geolocation) { + double timestamp; + double latitude; + double longitude; + double accuracy; + if (!geolocation->getDouble("timestamp", timestamp) || + !geolocation->getDouble("latitude", latitude) || + !geolocation->getDouble("longitude", longitude) || + !geolocation->getDouble("accuracy", accuracy)) { + errorString = "Invalid geolocation format"_s; + return; + } + auto position = WebGeolocationPosition::create(WebCore::GeolocationPositionData(timestamp, latitude, longitude, accuracy)); + geoManager->providerDidChangePosition(&position.get()); + } else { + geoManager->providerDidFailToDeterminePosition("Position unavailable"_s); + } +} + +String InspectorBrowserAgent::toBrowserContextIDProtocolString(const PAL::SessionID& sessionID) +{ + StringBuilder builder; + builder.append(hex(sessionID.toUInt64(), 16)); + return builder.toString(); +} + +String InspectorBrowserAgent::toPageProxyIDProtocolString(const WebPageProxy& page) +{ + return makeString("page-proxy-", page.identifier().toUInt64()); +} + +BrowserContext InspectorBrowserAgent::lookupBrowserContext(ErrorString& errorString, const String* browserContextID) +{ + if (!browserContextID) { + for (auto& pool : WebProcessPool::allProcessPools()) { + BrowserContext context; + context.processPool = pool; + context.dataStore = pool->websiteDataStore(); + return context; + } + errorString = "No default context"_s; + return BrowserContext(); + } + + BrowserContext browserContext = m_browserContexts.get(*browserContextID); + if (!browserContext.processPool) + errorString = "Could not find browser context for given id"_s; + return browserContext; +} + +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/InspectorBrowserAgent.h b/Source/WebKit/UIProcess/InspectorBrowserAgent.h new file mode 100644 index 0000000000000000000000000000000000000000..dee9b991757106fc33fd466d70f97ac922c60f42 --- /dev/null +++ b/Source/WebKit/UIProcess/InspectorBrowserAgent.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +#include "InspectorBrowserAgentClient.h" +#include +#include +#include +#include +#include +#include + +namespace Inspector { +class BackendDispatcher; +class BrowserFrontendDispatcher; +class FrontendChannel; +class FrontendRouter; +} + +namespace PAL { +class SessionID; +} + +namespace WebKit { + +class NetworkProcess; +class WebProcessPool; + +class InspectorBrowserAgent final : public Inspector::InspectorAgentBase, public Inspector::BrowserBackendDispatcherHandler { + WTF_MAKE_NONCOPYABLE(InspectorBrowserAgent); + WTF_MAKE_FAST_ALLOCATED; +public: + InspectorBrowserAgent(Inspector::FrontendRouter&, Inspector::BackendDispatcher&, InspectorBrowserAgentClient*); + ~InspectorBrowserAgent() override; + + void didCreateWebPageProxy(const WebPageProxy&); + void willDestroyWebPageProxy(const WebPageProxy&); + + // InspectorAgentBase + void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; + void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; + + // BrowserBackendDispatcherHandler + void close(Inspector::ErrorString&) override; + void createContext(Inspector::ErrorString&, String* browserContextID) override; + void deleteContext(Inspector::ErrorString&, const String& browserContextID) override; + void createPage(Inspector::ErrorString&, const String* browserContextID, String* targetId) override; + void setIgnoreCertificateErrors(Inspector::ErrorString&, const String* browserContextID, bool ignore) override; + + void getAllCookies(const String* browserContextID, Ref&&) override; + void setCookies(const String* browserContextID, const JSON::Array& in_cookies, Ref&&) override; + void deleteAllCookies(const String* browserContextID, Ref&&) override; + + void grantPermissions(Inspector::ErrorString&, const String* browserContextID, const String& origin, const JSON::Array& permissions) override; + void resetPermissions(Inspector::ErrorString&, const String* browserContextID) override; + void setGeolocationOverride(Inspector::ErrorString&, const String* browserContextID, const JSON::Object* geolocation) override; + + static String toBrowserContextIDProtocolString(const PAL::SessionID&); + static String toPageProxyIDProtocolString(const WebPageProxy&); + +private: + BrowserContext lookupBrowserContext(Inspector::ErrorString&, const String* browserContextID); + std::unique_ptr m_frontendDispatcher; + Ref m_backendDispatcher; + InspectorBrowserAgentClient* m_client; + using Permissions = HashMap>; + HashMap m_permissions; + HashMap m_browserContexts; + bool m_isConnected { false }; +}; + +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/InspectorBrowserAgentClient.h b/Source/WebKit/UIProcess/InspectorBrowserAgentClient.h new file mode 100644 index 0000000000000000000000000000000000000000..0af30b3904dc5c2ee3874c35334a44ad91b08a08 --- /dev/null +++ b/Source/WebKit/UIProcess/InspectorBrowserAgentClient.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +#include +#include + +namespace WebKit { + +class WebsiteDataStore; +class WebPageProxy; +class WebProcessPool; + +struct BrowserContext { + RefPtr dataStore; + RefPtr processPool; +}; + +class InspectorBrowserAgentClient { +public: + virtual ~InspectorBrowserAgentClient() = default; + virtual RefPtr createPage(WTF::String& error, PAL::SessionID) = 0; + virtual void closeAllWindows() = 0; + virtual BrowserContext createBrowserContext(WTF::String& error) = 0; + virtual void deleteBrowserContext(WTF::String& error, PAL::SessionID) = 0; +}; + +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/InspectorDialogAgent.cpp b/Source/WebKit/UIProcess/InspectorDialogAgent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b4e666e256c978b57510d82bab1a2b49680817c --- /dev/null +++ b/Source/WebKit/UIProcess/InspectorDialogAgent.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "InspectorDialogAgent.h" + +#include "APINavigation.h" +#include "APIUIClient.h" +#include "WebPageProxy.h" +#include + + +namespace WebKit { + +using namespace Inspector; + +InspectorDialogAgent::InspectorDialogAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page) + : InspectorAgentBase("Dialog"_s) + , m_frontendDispatcher(makeUnique(frontendRouter)) + , m_backendDispatcher(DialogBackendDispatcher::create(backendDispatcher, this)) + , m_page(page) +{ +} + +InspectorDialogAgent::~InspectorDialogAgent() +{ + Inspector::ErrorString err; + disable(err); +} + +void InspectorDialogAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) +{ +} + +void InspectorDialogAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason) +{ +} + +void InspectorDialogAgent::enable(Inspector::ErrorString& errorString) +{ + if (m_page.inspectorDialogAgent()) { + errorString = "Dialog domain is already enabled."_s; + return; + } + m_page.setInspectorDialogAgent(this); +} + +void InspectorDialogAgent::disable(Inspector::ErrorString&) +{ + if (m_page.inspectorDialogAgent() != this) + return; + m_page.setInspectorDialogAgent(nullptr); +} + +void InspectorDialogAgent::handleJavaScriptDialog(Inspector::ErrorString& errorString, bool accept, const String* value) +{ + m_page.uiClient().handleJavaScriptDialog(m_page, accept, value ? *value : String()); +} + +void InspectorDialogAgent::javascriptDialogOpening(const String& type, const String& message, const String* defaultValue) { + m_frontendDispatcher->javascriptDialogOpening(type, message, defaultValue); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/InspectorDialogAgent.h b/Source/WebKit/UIProcess/InspectorDialogAgent.h new file mode 100644 index 0000000000000000000000000000000000000000..227655daf8eba6c5852189fd929979d9ff8c334f --- /dev/null +++ b/Source/WebKit/UIProcess/InspectorDialogAgent.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebEvent.h" + +#include +#include +#include + +#include +#include + +namespace Inspector { +class FrontendChannel; +class FrontendRouter; +} + +namespace WebKit { + +class NativeWebKeyboardEvent; +class WebPageProxy; + +class InspectorDialogAgent : public Inspector::InspectorAgentBase, public Inspector::DialogBackendDispatcherHandler { + WTF_MAKE_NONCOPYABLE(InspectorDialogAgent); + WTF_MAKE_FAST_ALLOCATED; +public: + InspectorDialogAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page); + ~InspectorDialogAgent() override; + + void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; + void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; + + void enable(Inspector::ErrorString&) override; + void disable(Inspector::ErrorString&) override; + void handleJavaScriptDialog(Inspector::ErrorString& errorString, bool accept, const String* promptText) override; + + void javascriptDialogOpening(const String& type, const String& message, const String* defaultValue = nullptr); + +private: + void platformHandleJavaScriptDialog(bool accept, const String* promptText); + std::unique_ptr m_frontendDispatcher; + Ref m_backendDispatcher; + WebPageProxy& m_page; +}; + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/InspectorTargetProxy.cpp b/Source/WebKit/UIProcess/InspectorTargetProxy.cpp index 6928ca2fbfb6939062e3cd14bb7ba6f2fdc87f5f..a80eef613f485a84e523b4365ebab298104fe512 100644 --- a/Source/WebKit/UIProcess/InspectorTargetProxy.cpp +++ b/Source/WebKit/UIProcess/InspectorTargetProxy.cpp @@ -26,12 +26,15 @@ #include "config.h" #include "InspectorTargetProxy.h" +#include "APIPageConfiguration.h" #include "ProvisionalPageProxy.h" #include "WebFrameProxy.h" #include "WebPageInspectorTarget.h" #include "WebPageMessages.h" #include "WebPageProxy.h" #include "WebProcessProxy.h" +#include "ProvisionalPageProxy.h" + namespace WebKit { @@ -39,23 +42,29 @@ using namespace Inspector; std::unique_ptr InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type) { - return makeUnique(page, targetId, type); + return makeUnique(page, nullptr, targetId, type); } std::unique_ptr InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId, Inspector::InspectorTargetType type) { - auto target = InspectorTargetProxy::create(provisionalPage.page(), targetId, type); - target->m_provisionalPage = makeWeakPtr(provisionalPage); - return target; + return makeUnique(provisionalPage.page(), &provisionalPage, targetId, type); } -InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type) +InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, ProvisionalPageProxy* provisionalPage, const String& targetId, Inspector::InspectorTargetType type) : m_page(page) + , m_provisionalPage(makeWeakPtr(provisionalPage)) , m_identifier(targetId) , m_type(type) { } +String InspectorTargetProxy::url() const +{ + if (m_page.provisionalPageProxy()) + return m_page.provisionalPageProxy()->provisionalURL().string(); + return m_page.pageLoadState().activeURL(); +} + void InspectorTargetProxy::connect(Inspector::FrontendChannel::ConnectionType connectionType) { if (m_provisionalPage) { @@ -102,4 +111,19 @@ bool InspectorTargetProxy::isProvisional() const return !!m_provisionalPage; } +String InspectorTargetProxy::oldTargetID() const +{ + if (!m_provisionalPage) + return String(); + return WebPageInspectorTarget::toTargetID(m_page.webPageID()); +} + +String InspectorTargetProxy::openerID() const +{ + auto* opener = m_page.configuration().relatedPage(); + if (!opener) + return String(); + return WebPageInspectorTarget::toTargetID(opener->webPageID()); +} + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/InspectorTargetProxy.h b/Source/WebKit/UIProcess/InspectorTargetProxy.h index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..3985edf2081566b3dee85273b326e0fa81b16863 100644 --- a/Source/WebKit/UIProcess/InspectorTargetProxy.h +++ b/Source/WebKit/UIProcess/InspectorTargetProxy.h @@ -37,30 +37,35 @@ class WebPageProxy; // NOTE: This UIProcess side InspectorTarget doesn't care about the frontend channel, since // any target -> frontend messages will be routed to the WebPageProxy with a targetId. -class InspectorTargetProxy final : public Inspector::InspectorTarget { +class InspectorTargetProxy : public Inspector::InspectorTarget { WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(InspectorTargetProxy); public: static std::unique_ptr create(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType); static std::unique_ptr create(ProvisionalPageProxy&, const String& targetId, Inspector::InspectorTargetType); - InspectorTargetProxy(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType); + InspectorTargetProxy(WebPageProxy&, ProvisionalPageProxy*, const String& targetId, Inspector::InspectorTargetType); ~InspectorTargetProxy() = default; Inspector::InspectorTargetType type() const final { return m_type; } String identifier() const final { return m_identifier; } + String url() const final; void didCommitProvisionalTarget(); bool isProvisional() const override; + String oldTargetID() const override; + String openerID() const override; void connect(Inspector::FrontendChannel::ConnectionType) override; void disconnect() override; void sendMessageToTargetBackend(const String&) override; -private: +protected: WebPageProxy& m_page; + +private: + WeakPtr m_provisionalPage; String m_identifier; Inspector::InspectorTargetType m_type; - WeakPtr m_provisionalPage; }; } // namespace WebKit diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f6549694ac2956e97480eab87ccc25fb5220d79 --- /dev/null +++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "RemoteInspectorPipe.h" + +#if ENABLE(REMOTE_INSPECTOR) + +#include "BrowserInspectorController.h" +#include +#include +#include +#include +#include +#include + +#if OS(UNIX) +#include +#include +#endif + +namespace WebKit { + +static const int readFD = 3; +static const int writeFD = 4; + +class RemoteInspectorPipe::RemoteFrontendChannel : public Inspector::FrontendChannel { + WTF_MAKE_FAST_ALLOCATED; +public: + RemoteFrontendChannel() + : m_senderQueue(WorkQueue::create("Inspector pipe writer")) + { + } + + ~RemoteFrontendChannel() override = default; + + ConnectionType connectionType() const override + { + return ConnectionType::Remote; + } + + void sendMessageToFrontend(const String& message) override + { + m_senderQueue->dispatch([message = message.isolatedCopy()]() { + dprintf(writeFD, "%s%c", message.ascii().data(), '\0'); + }); + } + +private: + Ref m_senderQueue; +}; + +RemoteInspectorPipe::RemoteInspectorPipe(BrowserInspectorController& browserInspectorController) + : m_remoteFrontendChannel(makeUnique()) + , m_browserInspectorController(browserInspectorController) +{ + start(); +} + +RemoteInspectorPipe::~RemoteInspectorPipe() +{ + stop(); +} + +bool RemoteInspectorPipe::start() +{ + if (m_receiverThread) + return true; + + m_browserInspectorController.connectFrontend(*m_remoteFrontendChannel); + m_terminated = false; + m_receiverThread = Thread::create("Inspector pipe reader", [this] { + workerRun(); + }); + return true; +} + +void RemoteInspectorPipe::stop() +{ + if (!m_receiverThread) + return; + + m_browserInspectorController.disconnectFrontend(); + + m_terminated = true; + m_receiverThread->waitForCompletion(); + m_receiverThread = nullptr; +} + +void RemoteInspectorPipe::workerRun() +{ + const size_t bufSize = 256 * 1024; + auto buffer = makeUniqueArray(bufSize); + Vector line; + while (!m_terminated) { + ssize_t size = read(readFD, buffer.get(), bufSize); + if (size == 0) { + break; + } + if (size < 0) { + break; + } + size_t start = 0; + size_t end = line.size(); + line.append(buffer.get(), size); + while (true) { + for (; end < line.size(); ++end) { + if (line[end] == '\0') + break; + } + if (end == line.size()) + break; + + if (end > start) { + String message = String::fromUTF8(line.data() + start, end - start); + RunLoop::main().dispatch([this, message] { + if (!m_terminated) + m_browserInspectorController.dispatchMessageFromFrontend(message); + }); + } + ++end; + start = end; + } + if (start != 0 && start < line.size()) + memmove(line.data(), line.data() + start, line.size() - start); + line.shrink(line.size() - start); + } +} + +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.h b/Source/WebKit/UIProcess/RemoteInspectorPipe.h new file mode 100644 index 0000000000000000000000000000000000000000..a7f444318fddd2d0936e9a3c72b7bbd2144bb034 --- /dev/null +++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +#include +#include +#include + +namespace Inspector { +class FrontendChannel; +} + +namespace WebKit { + +class BrowserInspectorController; + +class RemoteInspectorPipe { + WTF_MAKE_NONCOPYABLE(RemoteInspectorPipe); + WTF_MAKE_FAST_ALLOCATED; +public: + explicit RemoteInspectorPipe(BrowserInspectorController&); + ~RemoteInspectorPipe(); + +private: + class RemoteFrontendChannel; + + bool start(); + void stop(); + + void workerRun(); + + RefPtr m_receiverThread; + std::atomic m_terminated { false }; + std::unique_ptr m_remoteFrontendChannel; + BrowserInspectorController& m_browserInspectorController; +}; + +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp b/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp index 6faede547644ab7d8f96e890d838a1bb13bc089c..b98b1c7831249d7a693884ea2f4c2d3be0272bbe 100644 --- a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp +++ b/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp @@ -35,6 +35,7 @@ #include "NfcService.h" #include "WebPageProxy.h" #include "WebPreferencesKeys.h" +#include "WebProcessProxy.h" #include #include #include diff --git a/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp b/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp index 846a5aa27dfab3d274cffa4873861f2587d17fd8..cf0dc99f5601636c48abff09cd47ace49d127a08 100644 --- a/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp +++ b/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp @@ -118,7 +118,8 @@ void WebGeolocationManagerProxy::startUpdating(IPC::Connection& connection) if (!wasUpdating) { m_provider->setEnableHighAccuracy(*this, isHighAccuracyEnabled()); m_provider->startUpdating(*this); - } else if (m_lastPosition) + } + if (m_lastPosition) connection.send(Messages::WebGeolocationManager::DidChangePosition(m_lastPosition.value()), 0); } diff --git a/Source/WebKit/UIProcess/WebPageInspectorController.cpp b/Source/WebKit/UIProcess/WebPageInspectorController.cpp index 1ee28bf716374371433215148aa20a51927a8a33..d33dae4a49f477eed3e4706bbeabfee631fe739b 100644 --- a/Source/WebKit/UIProcess/WebPageInspectorController.cpp +++ b/Source/WebKit/UIProcess/WebPageInspectorController.cpp @@ -26,10 +26,13 @@ #include "config.h" #include "WebPageInspectorController.h" +#include "InspectorBrowserAgent.h" #include "ProvisionalPageProxy.h" #include "WebFrameProxy.h" #include "WebPageInspectorTarget.h" +#include "WebPageInspectorTargetProxy.h" #include "WebPageProxy.h" +#include "WebPreferences.h" #include #include #include @@ -46,12 +49,23 @@ static String getTargetID(const ProvisionalPageProxy& provisionalPage) return WebPageInspectorTarget::toTargetID(provisionalPage.webPageID()); } +WebPageInspectorControllerObserver* WebPageInspectorController::s_observer = nullptr; + +void WebPageInspectorController::setObserver(WebPageInspectorControllerObserver* observer) +{ + s_observer = observer; +} + WebPageInspectorController::WebPageInspectorController(WebPageProxy& page) : m_page(page) , m_frontendRouter(FrontendRouter::create()) , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef())) { - auto targetAgent = makeUnique(m_frontendRouter.get(), m_backendDispatcher.get()); + String browserContextID; +#if ENABLE(REMOTE_INSPECTOR) + browserContextID = InspectorBrowserAgent::toBrowserContextIDProtocolString(page.sessionID()); +#endif + auto targetAgent = makeUnique(m_frontendRouter.get(), m_backendDispatcher.get(), browserContextID); m_targetAgent = targetAgent.get(); @@ -60,15 +74,51 @@ WebPageInspectorController::WebPageInspectorController(WebPageProxy& page) void WebPageInspectorController::init() { + if (s_observer) + s_observer->didCreateInspectorController(m_page); + + // window.open will create page with already running process. + if (!m_page.hasRunningProcess()) + return; String pageTargetId = WebPageInspectorTarget::toTargetID(m_page.webPageID()); createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page); } +void WebPageInspectorController::didFinishAttachingToWebProcess() +{ + String pageTargetID = WebPageInspectorTarget::toTargetID(m_page.webPageID()); + // Create target only after attaching to a Web Process first time. Before that + // we cannot event establish frontend connection. + if (m_targets.contains(pageTargetID)) + return; + createInspectorTarget(pageTargetID, Inspector::InspectorTargetType::Page); +} + void WebPageInspectorController::pageClosed() { + String pageTargetId = WebPageInspectorTarget::toTargetID(m_page.webPageID()); + destroyInspectorTarget(pageTargetId); + disconnectAllFrontends(); m_agents.discardValues(); + + if (s_observer) + s_observer->willDestroyInspectorController(m_page); +} + +bool WebPageInspectorController::pageCrashed(ProcessTerminationReason reason) +{ + if (reason != ProcessTerminationReason::Crash) + return false; + String targetId = WebPageInspectorTarget::toTargetID(m_page.webPageID()); + auto it = m_targets.find(targetId); + if (it == m_targets.end()) + return false; + m_targetAgent->targetCrashed(*it->value); + m_targets.remove(it); + + return m_targetAgent->isConnected(); } bool WebPageInspectorController::hasLocalFrontend() const @@ -80,6 +130,9 @@ void WebPageInspectorController::connectFrontend(Inspector::FrontendChannel& fro { bool connectingFirstFrontend = !m_frontendRouter->hasFrontends(); + if (connectingFirstFrontend) + adjustPageSettings(); + m_frontendRouter->connectFrontend(frontendChannel); if (connectingFirstFrontend) @@ -134,6 +187,16 @@ void WebPageInspectorController::dispatchMessageFromFrontend(const String& messa m_backendDispatcher->dispatch(message); } +bool WebPageInspectorController::dispatchMessageToTargetBackend(const String& message) +{ + return m_backendDispatcher->dispatch(message, BackendDispatcher::Mode::ContinueIfDomainIsMissing) == BackendDispatcher::DispatchResult::Finished; +} + +Inspector::InspectorTarget* WebPageInspectorController::findTarget(const String& targetId) +{ + return m_targets.get(targetId); +} + #if ENABLE(REMOTE_INSPECTOR) void WebPageInspectorController::setIndicating(bool indicating) { @@ -150,7 +213,12 @@ void WebPageInspectorController::setIndicating(bool indicating) void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type) { - addTarget(InspectorTargetProxy::create(m_page, targetId, type)); + std::unique_ptr target; + if (type == Inspector::InspectorTargetType::Page) + target = WebPageInspectorTargetProxy::create(m_page, *m_targetAgent, targetId); + else + target = InspectorTargetProxy::create(m_page, targetId, type); + addTarget(WTFMove(target)); } void WebPageInspectorController::destroyInspectorTarget(const String& targetId) @@ -186,7 +254,7 @@ void WebPageInspectorController::setContinueLoadingCallback(const ProvisionalPag void WebPageInspectorController::didCreateProvisionalPage(ProvisionalPageProxy& provisionalPage) { - addTarget(InspectorTargetProxy::create(provisionalPage, getTargetID(provisionalPage), Inspector::InspectorTargetType::Page)); + addTarget(WebPageInspectorTargetProxy::create(provisionalPage, *m_targetAgent, getTargetID(provisionalPage))); } void WebPageInspectorController::willDestroyProvisionalPage(const ProvisionalPageProxy& provisionalPage) @@ -214,8 +282,22 @@ void WebPageInspectorController::didCommitProvisionalPage(WebCore::PageIdentifie void WebPageInspectorController::addTarget(std::unique_ptr&& target) { + if (s_observer) + s_observer->didCreateTarget(*target); m_targetAgent->targetCreated(*target); m_targets.set(target->identifier(), WTFMove(target)); } +void WebPageInspectorController::adjustPageSettings() +{ + // Set this to true as otherwise updating any preferences will override its + // value in the Web Process to false (and InspectorController sets it locally + // to true when frontend is connected). + m_page.preferences().setDeveloperExtrasEnabled(true); + + // Navigation to cached pages doesn't fire some of the events (e.g. execution context created) + // that inspector depends on. So we disable the cache when front-end connects. + m_page.preferences().setUsesBackForwardCache(false); +} + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorController.h b/Source/WebKit/UIProcess/WebPageInspectorController.h index 78caedf0c0ce83675569502d150fcc44e5f9868c..ae6b43a49986380a521dcfbe8d5dc9e388121694 100644 --- a/Source/WebKit/UIProcess/WebPageInspectorController.h +++ b/Source/WebKit/UIProcess/WebPageInspectorController.h @@ -26,6 +26,7 @@ #pragma once #include "InspectorTargetProxy.h" +#include "ProcessTerminationReason.h" #include #include #include @@ -37,10 +38,23 @@ namespace Inspector { class BackendDispatcher; class FrontendChannel; class FrontendRouter; +class InspectorTarget; } namespace WebKit { +class WebPageInspectorController; + +class WebPageInspectorControllerObserver { +public: + virtual void didCreateInspectorController(WebPageProxy&) = 0; + virtual void willDestroyInspectorController(WebPageProxy&) = 0; + virtual void didCreateTarget(Inspector::InspectorTarget&) = 0; + +protected: + virtual ~WebPageInspectorControllerObserver() = default; +}; + class WebPageInspectorController { WTF_MAKE_NONCOPYABLE(WebPageInspectorController); WTF_MAKE_FAST_ALLOCATED; @@ -48,7 +62,13 @@ public: WebPageInspectorController(WebPageProxy&); void init(); + void didFinishAttachingToWebProcess(); + + static void setObserver(WebPageInspectorControllerObserver*); + void pageClosed(); + bool pageCrashed(ProcessTerminationReason); + void didProcessAllPendingKeyboardEvents(); bool hasLocalFrontend() const; @@ -57,6 +77,8 @@ public: void disconnectAllFrontends(); void dispatchMessageFromFrontend(const String& message); + Inspector::InspectorTarget* findTarget(const String& targetId); + bool dispatchMessageToTargetBackend(const String&); #if ENABLE(REMOTE_INSPECTOR) void setIndicating(bool); @@ -75,6 +97,7 @@ public: private: void addTarget(std::unique_ptr&&); + void adjustPageSettings(); WebPageProxy& m_page; Ref m_frontendRouter; @@ -82,6 +105,8 @@ private: Inspector::AgentRegistry m_agents; Inspector::InspectorTargetAgent* m_targetAgent; HashMap> m_targets; + + static WebPageInspectorControllerObserver* s_observer; }; } // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd9dc8dfea2d482e41fc82c619062fac832222e7 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebPageInspectorEmulationAgent.h" + +#include "WebPageProxy.h" +#include "WebPreferences.h" +#include +#include + + +namespace WebKit { + +using namespace Inspector; + +WebPageInspectorEmulationAgent::WebPageInspectorEmulationAgent(BackendDispatcher& backendDispatcher, WebPageProxy& page) + : InspectorAgentBase("Emulation"_s) + , m_backendDispatcher(EmulationBackendDispatcher::create(backendDispatcher, this)) + , m_page(page) +{ +} + +WebPageInspectorEmulationAgent::~WebPageInspectorEmulationAgent() +{ +} + +void WebPageInspectorEmulationAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) +{ +} + +void WebPageInspectorEmulationAgent::willDestroyFrontendAndBackend(DisconnectReason) +{ +} + +void WebPageInspectorEmulationAgent::setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref&& callback) +{ + m_page.setCustomDeviceScaleFactor(deviceScaleFactor); + m_page.setUseFixedLayout(fixedlayout); + platformSetSize(width, height, [callback = WTFMove(callback)](const String& error) { + if (error.isEmpty()) + callback->sendSuccess(); + else + callback->sendFailure(error); + }); +} + +void WebPageInspectorEmulationAgent::setJavaScriptEnabled(ErrorString&, bool enabled) +{ + auto copy = m_page.preferences().copy(); + copy->setJavaScriptEnabled(enabled); + m_page.setPreferences(copy); +} + +void WebPageInspectorEmulationAgent::setAuthCredentials(Inspector::ErrorString&, const String* username, const String* password) +{ + if (username && password) + m_page.setAuthCredentialsForAutomation(WebCore::Credential(*username, *password, CredentialPersistencePermanent)); + else + m_page.setAuthCredentialsForAutomation(Optional()); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h new file mode 100644 index 0000000000000000000000000000000000000000..6f76e5a958dcd55a151608efafbb7ebe86155021 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include + +#include +#include +#include + +namespace Inspector { +class BackendDispatcher; +class FrontendChannel; +class FrontendRouter; +} + +namespace WebKit { + +class WebPageProxy; + +class WebPageInspectorEmulationAgent : public Inspector::InspectorAgentBase, public Inspector::EmulationBackendDispatcherHandler { + WTF_MAKE_NONCOPYABLE(WebPageInspectorEmulationAgent); + WTF_MAKE_FAST_ALLOCATED; +public: + WebPageInspectorEmulationAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page); + ~WebPageInspectorEmulationAgent() override; + + void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; + void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; + + void setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref&&) override; + void setJavaScriptEnabled(Inspector::ErrorString&, bool enabled) override; + void setAuthCredentials(Inspector::ErrorString&, const String*, const String*) override; + +private: + void platformSetSize(int width, int height, Function&&); + + Ref m_backendDispatcher; + WebPageProxy& m_page; +}; + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96fb400438c5e9944317b947964de7cb412591ac --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebPageInspectorInputAgent.h" + +#include "APINavigation.h" +#include "NativeWebKeyboardEvent.h" +#include "NativeWebMouseEvent.h" +#include "WebPageProxy.h" +#include + + +namespace WebKit { + +using namespace Inspector; + +namespace { + +template +class CallbackList { + WTF_MAKE_FAST_ALLOCATED; +public: + ~CallbackList() + { + for (const auto& callback : m_callbacks) + callback->sendFailure("Page closed"); + } + + void append(Ref&& callback) + { + m_callbacks.append(WTFMove(callback)); + } + + void sendSuccess() + { + for (const auto& callback : m_callbacks) + callback->sendSuccess(); + m_callbacks.clear(); + } + +private: + Vector> m_callbacks; +}; + +} // namespace + +class WebPageInspectorInputAgent::InspectorInputObserver : public WebPageProxy::InputProcessingObserver { + WTF_MAKE_FAST_ALLOCATED; +public: + using KeyboardCallback = Inspector::InputBackendDispatcherHandler::DispatchKeyEventCallback; + using MouseCallback = Inspector::InputBackendDispatcherHandler::DispatchMouseEventCallback; + + ~InspectorInputObserver() override = default; + + void didProcessAllPendingKeyboardEvents() override + { + m_keyboardCallbacks.sendSuccess(); + } + + void didProcessAllPendingMouseEvents() override + { + m_mouseCallbacks.sendSuccess(); + } + + void addMouseCallback(Ref&& callback) + { + m_mouseCallbacks.append(WTFMove(callback)); + } + + void addKeyboardCallback(Ref&& callback) + { + m_keyboardCallbacks.append(WTFMove(callback)); + } + +private: + CallbackList m_keyboardCallbacks; + CallbackList m_mouseCallbacks; +}; + +WebPageInspectorInputAgent::WebPageInspectorInputAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page) + : InspectorAgentBase("Input"_s) + , m_backendDispatcher(InputBackendDispatcher::create(backendDispatcher, this)) + , m_page(page) + , m_inputObserver(makeUnique()) +{ + m_page.setObserber(m_inputObserver.get()); +} + +WebPageInspectorInputAgent::~WebPageInspectorInputAgent() +{ + m_page.setObserber(nullptr); +} + +void WebPageInspectorInputAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) +{ +} + +void WebPageInspectorInputAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason) +{ +} + +void WebPageInspectorInputAgent::dispatchKeyEvent(const String& in_type, const int* opt_in_modifiers, const String* opt_in_text, const String* opt_in_unmodifiedText, const String* opt_in_code, const String* opt_in_key, const int* opt_in_windowsVirtualKeyCode, const int* opt_in_nativeVirtualKeyCode, const bool* opt_in_autoRepeat, const bool* opt_in_isKeypad, const bool* opt_in_isSystemKey, const JSON::Array* opt_in_mac_commands, Ref&& callback) +{ + WebKit::WebEvent::Type type; + if (in_type == "keyDown") { + type = WebKit::WebEvent::KeyDown; + } else if (in_type == "keyUp") { + type = WebKit::WebEvent::KeyUp; + } else { + callback->sendFailure("Unsupported event type."); + return; + } + OptionSet modifiers; + if (opt_in_modifiers) + modifiers = modifiers.fromRaw(*opt_in_modifiers); + String text; + if (opt_in_text) + text = *opt_in_text; + String unmodifiedText; + if (opt_in_unmodifiedText) + unmodifiedText = *opt_in_unmodifiedText; + String code; + if (opt_in_code) + code = *opt_in_code; + String key; + if (opt_in_key) + key = *opt_in_key; + int windowsVirtualKeyCode = 0; + if (opt_in_windowsVirtualKeyCode) + windowsVirtualKeyCode = *opt_in_windowsVirtualKeyCode; + int nativeVirtualKeyCode = 0; + if (opt_in_nativeVirtualKeyCode) + nativeVirtualKeyCode = *opt_in_nativeVirtualKeyCode; + Vector commands; + if (opt_in_mac_commands) { + for (const auto& value : *opt_in_mac_commands) { + String command; + if (!value->asString(command)) { + callback->sendFailure("Command must be string"); + return; + } + commands.append(command); + } + } + + bool isAutoRepeat = false; + if (opt_in_autoRepeat) + isAutoRepeat = *opt_in_autoRepeat; + bool isKeypad = false; + if (opt_in_isKeypad) + isKeypad = *opt_in_isKeypad; + bool isSystemKey = false; + if (opt_in_isSystemKey) + isSystemKey = *opt_in_isSystemKey; + WallTime timestamp = WallTime::now(); + + m_inputObserver->addKeyboardCallback(WTFMove(callback)); + platformDispatchKeyEvent( + type, + text, + unmodifiedText, + key, + code, + windowsVirtualKeyCode, + nativeVirtualKeyCode, + isAutoRepeat, + isKeypad, + isSystemKey, + modifiers, + commands, + timestamp); +} + +void WebPageInspectorInputAgent::dispatchMouseEvent(const String& in_type, int in_x, int in_y, const int* opt_in_modifiers, const String* opt_in_button, const int* opt_in_buttons, const int* opt_in_clickCount, const int* opt_in_deltaX, const int* opt_in_deltaY, Ref&& callback) +{ + WebEvent::Type type = WebEvent::NoType; + if (in_type == "down") + type = WebEvent::MouseDown; + else if (in_type == "up") + type = WebEvent::MouseUp; + else if (in_type == "move") + type = WebEvent::MouseMove; + else { + callback->sendFailure("Unsupported event type"); + return; + } + + OptionSet modifiers; + if (opt_in_modifiers) + modifiers = modifiers.fromRaw(*opt_in_modifiers); + + WebMouseEvent::Button button = WebMouseEvent::NoButton; + if (opt_in_button) { + if (*opt_in_button == "left") + button = WebMouseEvent::LeftButton; + else if (*opt_in_button == "middle") + button = WebMouseEvent::MiddleButton; + else if (*opt_in_button == "right") + button = WebMouseEvent::RightButton; + else if (*opt_in_button == "none") + button = WebMouseEvent::NoButton; + else { + callback->sendFailure("Unsupported button"); + return; + } + } + + unsigned short buttons = 0; + if (opt_in_buttons) + buttons = *opt_in_buttons; + + int clickCount = 0; + if (opt_in_clickCount) + clickCount = *opt_in_clickCount; + int deltaX = 0; + if (opt_in_deltaX) + deltaX = *opt_in_deltaX; + int deltaY = 0; + if (opt_in_deltaY) + deltaY = *opt_in_deltaY; + m_inputObserver->addMouseCallback(WTFMove(callback)); +#if PLATFORM(WPE) + platformDispatchMouseEvent(type, in_x, in_y, button, modifiers); +#elif PLATFORM(MAC) + platformDispatchMouseEvent(in_type, in_x, in_y, opt_in_modifiers, opt_in_button, opt_in_clickCount); +#elif PLATFORM(GTK) + WallTime timestamp = WallTime::now(); + NativeWebMouseEvent event( + type, + button, + buttons, + {in_x, in_y}, + WebCore::IntPoint(), + deltaX, + deltaY, + 0, + clickCount, + modifiers, + timestamp); + m_page.handleMouseEvent(event); +#endif +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h new file mode 100644 index 0000000000000000000000000000000000000000..1e2737943a9b8443367181ec9542051839319322 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebEvent.h" + +#include +#include + +#include +#include + +namespace Inspector { +class BackendDispatcher; +class FrontendChannel; +class FrontendRouter; +} + +namespace WebKit { + +class NativeWebKeyboardEvent; +class WebPageProxy; + +class WebPageInspectorInputAgent : public Inspector::InspectorAgentBase, public Inspector::InputBackendDispatcherHandler { + WTF_MAKE_NONCOPYABLE(WebPageInspectorInputAgent); + WTF_MAKE_FAST_ALLOCATED; +public: + WebPageInspectorInputAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page); + ~WebPageInspectorInputAgent() override; + + void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; + void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; + + void dispatchKeyEvent(const String& in_type, const int* opt_in_modifiers, const String* opt_in_text, const String* opt_in_unmodifiedText, const String* opt_in_code, const String* opt_in_key, const int* opt_in_windowsVirtualKeyCode, const int* opt_in_nativeVirtualKeyCode, const bool* opt_in_autoRepeat, const bool* opt_in_isKeypad, const bool* opt_in_isSystemKey, const JSON::Array*, Ref&& callback) override; + void dispatchMouseEvent(const String& in_type, int in_x, int in_y, const int* opt_in_modifiers, const String* opt_in_button, const int* opt_in_buttons, const int* opt_in_clickCount, const int* opt_in_deltaX, const int* opt_in_deltaY, Ref&& callback) override; + +private: + void platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, Vector& commands, WallTime timestamp); +#if PLATFORM(WPE) + void platformDispatchMouseEvent(WebMouseEvent::Type type, int x, int y, WebMouseEvent::Button button, OptionSet modifiers); +#endif +#if PLATFORM(MAC) + void platformDispatchMouseEvent(const String& type, int x, int y, const int* modifier, const String* button, const int* clickCount); +#endif + + Ref m_backendDispatcher; + WebPageProxy& m_page; + // Keep track of currently active modifiers across multiple keystrokes. + // Most platforms do not track current modifiers from synthesized events. + unsigned m_currentModifiers { 0 }; + class InspectorInputObserver; + std::unique_ptr m_inputObserver; +}; + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorTargetProxy.cpp b/Source/WebKit/UIProcess/WebPageInspectorTargetProxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0baff14219c3cdd8948d97db780d549d65c9f172 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorTargetProxy.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebPageInspectorTargetProxy.h" + +#include "InspectorDialogAgent.h" +#include "ProvisionalPageProxy.h" +#include "WebPageInspectorController.h" +#include "WebPageInspectorEmulationAgent.h" +#include "WebPageInspectorInputAgent.h" +#include "WebPageMessages.h" +#include "WebPageProxy.h" +#include "WebProcessProxy.h" +#include +#include +#include +#include + +namespace WebKit { + +using namespace Inspector; + +namespace { + +class TargetFrontendChannel final : public FrontendChannel { + WTF_MAKE_NONCOPYABLE(TargetFrontendChannel); +public: + TargetFrontendChannel(InspectorTargetAgent& targetAgent, const String& targetId, FrontendChannel::ConnectionType type) + : m_targetAgent(targetAgent) + , m_targetId(targetId) + , m_connectionType(type) + { + } + ~TargetFrontendChannel() override = default; + + ConnectionType connectionType() const override { return m_connectionType; } + void sendMessageToFrontend(const String& message) override + { + m_targetAgent.sendMessageFromTargetToFrontend(m_targetId, message); + } + +private: + InspectorTargetAgent& m_targetAgent; + String m_targetId; + FrontendChannel::ConnectionType m_connectionType; +}; + +} // namespace + +std::unique_ptr WebPageInspectorTargetProxy::create(WebPageProxy& page, Inspector::InspectorTargetAgent& targetAgent, const String& targetId) +{ + return makeUnique(page, nullptr, targetAgent, targetId); +} + +std::unique_ptr WebPageInspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, Inspector::InspectorTargetAgent& targetAgent, const String& targetId) +{ + return makeUnique(provisionalPage.page(), &provisionalPage, targetAgent, targetId); +} + +WebPageInspectorTargetProxy::WebPageInspectorTargetProxy(WebPageProxy& page, ProvisionalPageProxy* provisionalPage, Inspector::InspectorTargetAgent& targetAgent, const String& targetId) + : InspectorTargetProxy(page, provisionalPage, targetId, Inspector::InspectorTargetType::Page) + , m_frontendRouter(FrontendRouter::create()) + , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef())) + , m_targetAgent(targetAgent) +{ + m_agents.append(std::make_unique(m_backendDispatcher.get(), page)); + m_agents.append(std::make_unique(m_backendDispatcher.get(), page)); + m_agents.append(std::make_unique(m_backendDispatcher.get(), m_frontendRouter.get(), page)); +} + +void WebPageInspectorTargetProxy::connect(Inspector::FrontendChannel::ConnectionType connectionType) +{ + InspectorTargetProxy::connect(connectionType); + ASSERT(!m_frontendChannel); + if (m_frontendChannel) + return; + m_frontendChannel = std::make_unique(m_targetAgent, identifier(), connectionType); + m_frontendRouter->connectFrontend(*m_frontendChannel); +} + +void WebPageInspectorTargetProxy::disconnect() +{ + ASSERT(m_frontendChannel); + m_frontendRouter->disconnectAllFrontends(); + m_frontendChannel.reset(); + InspectorTargetProxy::disconnect(); +} + +void WebPageInspectorTargetProxy::sendMessageToTargetBackend(const String& message) +{ + if (m_backendDispatcher->dispatch(message, BackendDispatcher::Mode::ContinueIfDomainIsMissing) == BackendDispatcher::DispatchResult::Finished) + return; + if (m_page.inspectorController().dispatchMessageToTargetBackend(message)) + return; + InspectorTargetProxy::sendMessageToTargetBackend(message); +} + +void WebPageInspectorTargetProxy::activate(String& error) +{ + platformActivate(error); +} + +void WebPageInspectorTargetProxy::close(String& error, bool runBeforeUnload) +{ + if (runBeforeUnload) + m_page.tryClose(); + else + m_page.closePage(); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorTargetProxy.h b/Source/WebKit/UIProcess/WebPageInspectorTargetProxy.h new file mode 100644 index 0000000000000000000000000000000000000000..4c721597c5ec9a9f41a0e2926b085dd7e2a3d066 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorTargetProxy.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "InspectorTargetProxy.h" +#include +#include +#include + +namespace Inspector { +class BackendDispatcher; +class InspectorTargetAgent; +} + +namespace WebKit { + +class WebPageProxy; + +class WebPageInspectorTargetProxy final : public InspectorTargetProxy { + WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(WebPageInspectorTargetProxy); +public: + static std::unique_ptr create(WebPageProxy&, Inspector::InspectorTargetAgent&, const String& targetId); + static std::unique_ptr create(ProvisionalPageProxy&, Inspector::InspectorTargetAgent&, const String& targetId); + WebPageInspectorTargetProxy(WebPageProxy&, ProvisionalPageProxy*, Inspector::InspectorTargetAgent&, const String& targetId); + ~WebPageInspectorTargetProxy() = default; + + void connect(Inspector::FrontendChannel::ConnectionType) override; + void disconnect() override; + void sendMessageToTargetBackend(const String&) override; + void activate(String& error) override; + void close(String& error, bool runBeforeUnload) override; + +private: + void platformActivate(String& error) const; + + Ref m_frontendRouter; + Ref m_backendDispatcher; + Inspector::InspectorTargetAgent& m_targetAgent; + Inspector::AgentRegistry m_agents; + std::unique_ptr m_frontendChannel; +}; + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp index 4ff9dddf30a92ba6a0f7f324c0bf187077b2e8f0..5a260380ecca1ac5c0979694a328d3120faa5be4 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit/UIProcess/WebPageProxy.cpp @@ -889,6 +889,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason) m_pageLoadState.didSwapWebProcesses(); if (reason != ProcessLaunchReason::InitialProcess) m_drawingArea->waitForBackingStoreUpdateOnNextPaint(); + m_inspectorController->didFinishAttachingToWebProcess(); } void WebPageProxy::didAttachToRunningProcess() @@ -1660,6 +1661,19 @@ void WebPageProxy::setControlledByAutomation(bool controlled) m_process->processPool().sendToNetworkingProcess(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation)); } +void WebPageProxy::setObserber(InputProcessingObserver* observer) +{ + m_inputProcessingObserver = observer; +} + +void WebPageProxy::setAuthCredentialsForAutomation(Optional&& credentials) { + m_credentialsForAutomation = WTFMove(credentials); +} + +void WebPageProxy::setPermissionsForAutomation(const HashMap>& permissions) { + m_permissionsForAutomation = permissions; +} + void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type) { m_inspectorController->createInspectorTarget(targetId, type); @@ -2716,7 +2730,7 @@ static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b) void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent) { -#if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA) +#if ENABLE(ASYNC_SCROLLING) && PLATFORM(IOS_FAMILY) const EventNames& names = eventNames(); for (auto& touchPoint : touchStartEvent.touchPoints()) { IntPoint location = touchPoint.location(); @@ -2749,7 +2763,7 @@ void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent m_touchAndPointerEventTracking.touchStartTracking = TrackingType::Synchronous; m_touchAndPointerEventTracking.touchMoveTracking = TrackingType::Synchronous; m_touchAndPointerEventTracking.touchEndTracking = TrackingType::Synchronous; -#endif // ENABLE(ASYNC_SCROLLING) +#endif // ENABLE(ASYNC_SCROLLING) && PLATFORM(IOS_FAMILY) } TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const @@ -5404,6 +5418,8 @@ void WebPageProxy::runJavaScriptAlert(FrameIdentifier frameID, SecurityOriginDat if (auto* automationSession = process().processPool().automationSession()) automationSession->willShowJavaScriptDialog(*this); } + if (m_inspectorDialogAgent) + m_inspectorDialogAgent->javascriptDialogOpening("alert"_s, message); m_uiClient->runJavaScriptAlert(*this, message, frame, WTFMove(securityOrigin), WTFMove(reply)); } @@ -5423,6 +5439,8 @@ void WebPageProxy::runJavaScriptConfirm(FrameIdentifier frameID, SecurityOriginD if (auto* automationSession = process().processPool().automationSession()) automationSession->willShowJavaScriptDialog(*this); } + if (m_inspectorDialogAgent) + m_inspectorDialogAgent->javascriptDialogOpening("confirm"_s, message); m_uiClient->runJavaScriptConfirm(*this, message, frame, WTFMove(securityOrigin), WTFMove(reply)); } @@ -5442,6 +5460,8 @@ void WebPageProxy::runJavaScriptPrompt(FrameIdentifier frameID, SecurityOriginDa if (auto* automationSession = process().processPool().automationSession()) automationSession->willShowJavaScriptDialog(*this); } + if (m_inspectorDialogAgent) + m_inspectorDialogAgent->javascriptDialogOpening("prompt"_s, message, &defaultValue); m_uiClient->runJavaScriptPrompt(*this, message, defaultValue, frame, WTFMove(securityOrigin), WTFMove(reply)); } @@ -5601,6 +5621,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(FrameIdentifier frameID, Security return; } } + if (m_inspectorDialogAgent) + m_inspectorDialogAgent->javascriptDialogOpening("beforeunload"_s, message); // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer. m_process->responsivenessTimer().stop(); @@ -6625,6 +6647,8 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) if (auto* automationSession = process().processPool().automationSession()) automationSession->mouseEventsFlushedForPage(*this); pageClient().didFinishProcessingAllPendingMouseEvents(); + if (m_inputProcessingObserver) + m_inputProcessingObserver->didProcessAllPendingMouseEvents(); } break; @@ -6651,7 +6675,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) case WebEvent::RawKeyDown: case WebEvent::Char: { LOG(KeyHandling, "WebPageProxy::didReceiveEvent: %s (queue empty %d)", webKeyboardEventTypeString(type), m_keyEventQueue.isEmpty()); - MESSAGE_CHECK(m_process, !m_keyEventQueue.isEmpty()); NativeWebKeyboardEvent event = m_keyEventQueue.takeFirst(); @@ -6671,7 +6694,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) // The call to doneWithKeyEvent may close this WebPage. // Protect against this being destroyed. Ref protect(*this); - pageClient().doneWithKeyEvent(event, handled); if (!handled) m_uiClient->didNotHandleKeyEvent(this, event); @@ -6680,6 +6702,8 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) if (!canProcessMoreKeyEvents) { if (auto* automationSession = process().processPool().automationSession()) automationSession->keyboardEventsFlushedForPage(*this); + if (m_inputProcessingObserver) + m_inputProcessingObserver->didProcessAllPendingKeyboardEvents(); } break; } @@ -7148,8 +7172,10 @@ static bool shouldReloadAfterProcessTermination(ProcessTerminationReason reason) void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason) { RELEASE_LOG_IF_ALLOWED(Loading, "dispatchProcessDidTerminate: reason = %d", reason); + bool handledByClient = m_inspectorController->pageCrashed(reason); + if (handledByClient) + return; - bool handledByClient = false; if (m_loaderClient) handledByClient = reason != ProcessTerminationReason::RequestedByClient && m_loaderClient->processDidCrash(*this); else @@ -7596,6 +7622,14 @@ void WebPageProxy::gamepadActivity(const Vector& gamepadDatas, bool void WebPageProxy::didReceiveAuthenticationChallengeProxy(Ref&& authenticationChallenge) { + if (m_credentialsForAutomation.hasValue()) { + if (m_credentialsForAutomation->isEmpty() || authenticationChallenge->core().previousFailureCount()) { + authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::PerformDefaultHandling); + return; + } + authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::UseCredential, *m_credentialsForAutomation); + return; + } m_navigationClient->didReceiveAuthenticationChallenge(*this, authenticationChallenge.get()); } @@ -7657,7 +7691,8 @@ void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID, MESSAGE_CHECK(m_process, frame); // FIXME: Geolocation should probably be using toString() as its string representation instead of databaseIdentifier(). - auto origin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(originIdentifier)->securityOrigin()); + auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(originIdentifier)->securityOrigin(); + auto origin = API::SecurityOrigin::create(securityOrigin); auto request = m_geolocationPermissionRequestManager.createRequest(geolocationID); Function completionHandler = [request = WTFMove(request)](bool allowed) { if (allowed) @@ -7665,6 +7700,11 @@ void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID, else request->deny(); }; + auto permissions = m_permissionsForAutomation.find(securityOrigin->toString()); + if (permissions != m_permissionsForAutomation.end()) { + completionHandler(permissions->value.contains("geolocation")); + return; + } // FIXME: Once iOS migrates to the new WKUIDelegate SPI, clean this up // and make it one UIClient call that calls the completionHandler with false diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h index 2c87b48e73c2fd361a2a0da8c8e766cd2c57e325..a9c5882682abbc55f7d7d017b19b035f4d16271e 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.h +++ b/Source/WebKit/UIProcess/WebPageProxy.h @@ -35,6 +35,7 @@ #include "FocusedElementInformation.h" #include "GeolocationPermissionRequestManagerProxy.h" #include "HiddenPageThrottlingAutoIncreasesCounter.h" +#include "InspectorDialogAgent.h" #include "LayerTreeContext.h" #include "MessageSender.h" #include "NotificationPermissionRequestManagerProxy.h" @@ -473,6 +474,8 @@ public: void setControlledByAutomation(bool); WebPageInspectorController& inspectorController() { return *m_inspectorController; } + InspectorDialogAgent* inspectorDialogAgent() { return m_inspectorDialogAgent; } + void setInspectorDialogAgent(InspectorDialogAgent * dialogAgent) { m_inspectorDialogAgent = dialogAgent; } #if PLATFORM(IOS_FAMILY) void showInspectorIndication(); @@ -538,6 +541,16 @@ public: void setPageLoadStateObserver(std::unique_ptr&&); + class InputProcessingObserver { + public: + virtual ~InputProcessingObserver() = default; + virtual void didProcessAllPendingKeyboardEvents() = 0; + virtual void didProcessAllPendingMouseEvents() = 0; + }; + void setObserber(InputProcessingObserver*); + void setAuthCredentialsForAutomation(Optional&&); + void setPermissionsForAutomation(const HashMap>&); + void initializeWebPage(); void setDrawingArea(std::unique_ptr&&); @@ -2248,6 +2261,7 @@ private: bool m_treatsSHA1CertificatesAsInsecure { true }; RefPtr m_inspector; + InspectorDialogAgent* m_inspectorDialogAgent { nullptr }; #if ENABLE(FULLSCREEN_API) std::unique_ptr m_fullScreenManager; @@ -2599,6 +2613,7 @@ private: #if ENABLE(REMOTE_INSPECTOR) std::unique_ptr m_inspectorDebuggable; #endif + InputProcessingObserver* m_inputProcessingObserver { nullptr }; Optional m_spellDocumentTag; @@ -2649,6 +2664,8 @@ private: bool m_isLayerTreeFrozenDueToSwipeAnimation { false }; String m_overriddenMediaType; + Optional m_credentialsForAutomation; + HashMap> m_permissionsForAutomation; #if PLATFORM(IOS_FAMILY) && ENABLE(DEVICE_ORIENTATION) std::unique_ptr m_webDeviceOrientationUpdateProviderProxy; diff --git a/Source/WebKit/UIProcess/WebProcessPool.h b/Source/WebKit/UIProcess/WebProcessPool.h index b7c955a5f3ebe5805ad7095bc06878e128d11568..ab65f14db987e4e03e0474c9127efad669585355 100644 --- a/Source/WebKit/UIProcess/WebProcessPool.h +++ b/Source/WebKit/UIProcess/WebProcessPool.h @@ -415,7 +415,7 @@ public: void windowServerConnectionStateChanged(); -#if USE(SOUP) +#if USE(SOUP) || PLATFORM(COCOA) void setIgnoreTLSErrors(bool); bool ignoreTLSErrors() const { return m_ignoreTLSErrors; } #endif @@ -710,7 +710,7 @@ private: HashMap> m_dictionaryCallbacks; HashMap> m_statisticsRequests; -#if USE(SOUP) +#if USE(SOUP) || PLATFORM(COCOA) bool m_ignoreTLSErrors { true }; #endif diff --git a/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.cpp b/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8e1d948cb786752b3cb506b9d01fb96d872fd76 --- /dev/null +++ b/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "InspectorBrowserAgentClientGLib.h" + +#if ENABLE(REMOTE_INSPECTOR) + +#include "InspectorBrowserAgent.h" +#include "WebKitBrowserInspectorPrivate.h" +#include "WebKitWebContextPrivate.h" +#include "WebKitWebsiteDataManagerPrivate.h" +#include "WebKitWebViewPrivate.h" +#include "WebPageProxy.h" +#include +#include +#include +#include + +namespace WebKit { + +static Vector collectPages(Optional sessionID) +{ + Vector result; + for (WebProcessPool* pool : WebProcessPool::allProcessPools()) { + for (auto& process : pool->processes()) { + for (auto* page : process->pages()) { + if (!sessionID || page->sessionID() == sessionID) + result.append(page); + } + } + } + return result; +} + +static void closeAllPages(Optional sessionID) +{ + Vector pages = collectPages(sessionID); + for (auto* page : pages) + page->closePage(); +} + +InspectorBrowserAgentClientGlib::InspectorBrowserAgentClientGlib() +{ +} + +RefPtr InspectorBrowserAgentClientGlib::createPage(WTF::String& error, PAL::SessionID sessionID) +{ + WebKitWebContext* context; + if (!sessionID || webkitWebContextGetProcessPool(webkit_web_context_get_default()).websiteDataStore()->sessionID() == sessionID) + context = webkit_web_context_get_default(); + else + context = m_idToContext.get(sessionID); + + if (context == nullptr) { + error = "Context with provided id not found"; + return nullptr; + } + + RefPtr page = webkitBrowserInspectorCreateNewPageInContext(context); + if (page == nullptr) + error = "Failed to create new page in the context"; + return page; +} + +void InspectorBrowserAgentClientGlib::closeAllWindows() +{ + closeAllPages(Optional()); + m_idToContext.clear(); + // FIXME(yurys): call g_main_loop_quit() ? +} + +static PAL::SessionID sessionIDFromContext(WebKitWebContext* context) +{ + WebKitWebsiteDataManager* data_manager = webkit_web_context_get_website_data_manager(context); + WebsiteDataStore& websiteDataStore = webkitWebsiteDataManagerGetDataStore(data_manager); + return websiteDataStore.sessionID(); +} + +BrowserContext InspectorBrowserAgentClientGlib::createBrowserContext(WTF::String& error) +{ + BrowserContext browserContext; + GRefPtr data_manager = adoptGRef(webkit_website_data_manager_new_ephemeral()); + GRefPtr context = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", data_manager.get(), "process-swap-on-cross-site-navigation-enabled", true, nullptr))); + if (!context) { + error = "Failed to create GLib ephemeral context"; + return browserContext; + } + browserContext.processPool = &webkitWebContextGetProcessPool(context.get()); + browserContext.dataStore = &webkitWebsiteDataManagerGetDataStore(data_manager.get()); + PAL::SessionID sessionID = sessionIDFromContext(context.get()); + m_idToContext.set(sessionID, WTFMove(context)); + return browserContext; +} + +void InspectorBrowserAgentClientGlib::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID) +{ + m_idToContext.remove(sessionID); +} + +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.h b/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.h new file mode 100644 index 0000000000000000000000000000000000000000..39a646bc4bca4c052d8dc57a8cd1b51cd55bf2f1 --- /dev/null +++ b/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +#include "InspectorBrowserAgentClient.h" +#include "WebKitWebContext.h" +#include +#include +#include +#include + +namespace WebKit { + +class InspectorBrowserAgentClientGlib : public InspectorBrowserAgentClient { + WTF_MAKE_FAST_ALLOCATED; +public: + InspectorBrowserAgentClientGlib(); + ~InspectorBrowserAgentClientGlib() override = default; + + RefPtr createPage(WTF::String& error, PAL::SessionID) override; + void closeAllWindows() override; + BrowserContext createBrowserContext(WTF::String& error) override; + void deleteBrowserContext(WTF::String& error, PAL::SessionID) override; + +private: + WebKitWebContext* findContext(WTF::String& error, PAL::SessionID); + + HashMap> m_idToContext; +}; + +} // namespace API + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp new file mode 100644 index 0000000000000000000000000000000000000000..898b0c7acd270a6362281cb69a297ddecae9b614 --- /dev/null +++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DrawingAreaProxyCoordinatedGraphics.h" +#include "WebPageInspectorEmulationAgent.h" +#include "WebPageProxy.h" +#include +#include + +namespace WebKit { +void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function&& callback) +{ + GtkWidget* viewWidget = m_page.viewWidget(); + GtkWidget* window = gtk_widget_get_toplevel(viewWidget); + if (!window) { + callback("Cannot find parent window"_s); + return; + } + if (!GTK_IS_WINDOW(window)) { + callback("Toplevel is not a window"_s); + return; + } + GtkAllocation viewAllocation; + gtk_widget_get_allocation(viewWidget, &viewAllocation); + if (viewAllocation.width == width && viewAllocation.height == height) { + callback(String()); + return; + } + + GtkAllocation windowAllocation; + gtk_widget_get_allocation(window, &windowAllocation); + + width += windowAllocation.width - viewAllocation.width; + height += windowAllocation.height - viewAllocation.height; + + if (auto* drawingArea = static_cast(m_page.drawingArea())) { + drawingArea->waitForBackingStoreUpdate([callback = WTFMove(callback)]() { + callback(String()); + }); + } else { + callback("No backing store for window"_s); + } + gtk_window_resize(GTK_WINDOW(window), width, height); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e80487b377cef06e309d18b89698c2dd989c8d8d --- /dev/null +++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebPageInspectorInputAgent.h" + +#include "KeyBindingTranslator.h" +#include "NativeWebKeyboardEvent.h" +#include "WebPageProxy.h" +#include + +namespace WebKit { + +static Vector commandsForKeyEvent(GdkEventType type, unsigned keyVal, unsigned state) +{ + ASSERT(type == GDK_KEY_PRESS || type == GDK_KEY_RELEASE); + + GUniquePtr event(gdk_event_new(type)); + event->key.keyval = keyVal; + event->key.time = GDK_CURRENT_TIME; + event->key.state = state; + // When synthesizing an event, an invalid hardware_keycode value can cause it to be badly processed by GTK+. + GUniqueOutPtr keys; + int keysCount; + if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyVal, &keys.outPtr(), &keysCount) && keysCount) + event->key.hardware_keycode = keys.get()[0].keycode; + return KeyBindingTranslator().commandsForKeyEvent(&event->key); +} + +static unsigned modifiersToEventState(OptionSet modifiers) +{ + unsigned state = 0; + if (modifiers.contains(WebEvent::Modifier::ControlKey)) + state |= GDK_CONTROL_MASK; + if (modifiers.contains(WebEvent::Modifier::ShiftKey)) + state |= GDK_SHIFT_MASK; + if (modifiers.contains(WebEvent::Modifier::AltKey)) + state |= GDK_META_MASK; + if (modifiers.contains(WebEvent::Modifier::CapsLockKey)) + state |= GDK_LOCK_MASK; + return state; +} + +void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, Vector& macCommands, WallTime timestamp) +{ + Vector commands; + const guint keyVal = WebCore::PlatformKeyboardEvent::gdkKeyCodeForWindowsKeyCode(windowsVirtualKeyCode); + String keyIdentifier; + if (keyVal) { + GdkEventType event = GDK_NOTHING; + switch (type) + { + case WebKeyboardEvent::KeyDown: + event = GDK_KEY_PRESS; + break; + case WebKeyboardEvent::KeyUp: + event = GDK_KEY_RELEASE; + break; + default: + fprintf(stderr, "Unsupported event type = %d\n", type); + break; + } + unsigned state = modifiersToEventState(modifiers); + commands = commandsForKeyEvent(event, keyVal, state); + keyIdentifier = WebCore::PlatformKeyboardEvent::keyIdentifierForGdkKeyCode(keyVal); + } + NativeWebKeyboardEvent event( + type, + text, + unmodifiedText, + key, + code, + keyIdentifier, + windowsVirtualKeyCode, + nativeVirtualKeyCode, + isAutoRepeat, + isKeypad, + isSystemKey, + modifiers, + timestamp, + WTFMove(commands)); + m_page.handleKeyboardEvent(event); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorTargetProxyGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorTargetProxyGtk.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16579e02ad439d79ecdffa3e3971f7d99aef7da5 --- /dev/null +++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorTargetProxyGtk.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebPageInspectorTargetProxy.h" + +#include "WebPageProxy.h" +#include +#include + +namespace WebKit { + +void WebPageInspectorTargetProxy::platformActivate(String& error) const +{ + GtkWidget* parent = gtk_widget_get_toplevel(m_page.viewWidget()); + if (WebCore::widgetIsOnscreenToplevelWindow(parent)) + gtk_window_present(GTK_WINDOW(parent)); + else + error = "The view is not on screen"; +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm index dbfb34900ad983a8f2267a29ccca9adbb89de2d6..bcf76c1f8df1bb307074393a62fa8b2eb72c9b74 100644 --- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm +++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm @@ -416,6 +416,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled) { + if (!event.nativeEvent()) + return; [m_contentView _didHandleKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled]; } diff --git a/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.h b/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.h new file mode 100644 index 0000000000000000000000000000000000000000..fb2737f4c7088afce0641255251accbe4bf6b995 --- /dev/null +++ b/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "InspectorBrowserAgentClient.h" +#include + +OBJC_PROTOCOL(_WKBrowserInspectorDelegate); + +namespace WebKit { + +class InspectorBrowserAgentClientMac : public InspectorBrowserAgentClient { + WTF_MAKE_FAST_ALLOCATED; +public: + InspectorBrowserAgentClientMac(_WKBrowserInspectorDelegate* delegate); + ~InspectorBrowserAgentClientMac() override = default; + + RefPtr createPage(WTF::String& error, PAL::SessionID) override; + void closeAllWindows() override; + BrowserContext createBrowserContext(WTF::String& error) override; + void deleteBrowserContext(WTF::String& error, PAL::SessionID) override; + private: + + _WKBrowserInspectorDelegate* delegate_; +}; + + +} // namespace API diff --git a/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.mm b/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.mm new file mode 100644 index 0000000000000000000000000000000000000000..b6229aa222ab716a23ae2a8de6646df9b6f9044f --- /dev/null +++ b/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.mm @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "config.h" +#import "InspectorBrowserAgentClientMac.h" + +#import +#import +#import "WebPageProxy.h" +#import "WebProcessPool.h" +#import "WebsiteDataStore.h" +#import "_WKBrowserInspector.h" +#import "WKProcessPoolInternal.h" +#import "WKWebsiteDataStoreInternal.h" +#import "WKWebView.h" +#import "WKWebViewInternal.h" + +namespace WebKit { + +InspectorBrowserAgentClientMac::InspectorBrowserAgentClientMac(_WKBrowserInspectorDelegate* delegate) + : delegate_(delegate) +{ +} + +RefPtr InspectorBrowserAgentClientMac::createPage(WTF::String& error, PAL::SessionID sessionID) +{ + WKWebView *webView = [delegate_ createNewPage:sessionID.toUInt64()]; + if (!webView) { + error = "Internal error: can't create page in given context"_s; + return nil; + } + return [webView _page]; +} + +void InspectorBrowserAgentClientMac::closeAllWindows() +{ + [delegate_ quit]; +} + +BrowserContext InspectorBrowserAgentClientMac::createBrowserContext(WTF::String& error) +{ + _WKBrowserContext* wkBrowserContext = [[delegate_ createBrowserContext] autorelease]; + BrowserContext browserContext; + browserContext.processPool = &static_cast([[wkBrowserContext processPool] _apiObject]); + browserContext.dataStore = &static_cast([[wkBrowserContext dataStore] _apiObject]); + return browserContext; +} + +void InspectorBrowserAgentClientMac::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID) +{ + [delegate_ deleteBrowserContext:sessionID.toUInt64()]; +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.h b/Source/WebKit/UIProcess/mac/PageClientImplMac.h index 8016b56c160acc7b4269600f07f737b3793767bb..651a86c41af3305e215d7baf7f149cc7f401c470 100644 --- a/Source/WebKit/UIProcess/mac/PageClientImplMac.h +++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.h @@ -53,6 +53,8 @@ class PageClientImpl final : public PageClientImplCocoa #endif { public: + static void setHeadless(bool headless); + PageClientImpl(NSView *, WKWebView *); virtual ~PageClientImpl(); @@ -206,6 +208,10 @@ private: void beganExitFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame) override; #endif +#if ENABLE(TOUCH_EVENTS) + void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled) override; +#endif + void navigationGestureDidBegin() override; void navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem&) override; void navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem&) override; diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm index bf7dc132b1ef9e081275cbecb562dd1bfd3a2a0e..63eb41bc3e52c97b933e6bd8288f6824f71ca675 100644 --- a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm +++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm @@ -78,6 +78,7 @@ #import #import #import +#import #import #import #import @@ -105,6 +106,13 @@ static NSString * const kAXLoadCompleteNotification = @"AXLoadComplete"; namespace WebKit { using namespace WebCore; +static bool _headless = false; + +// static +void PageClientImpl::setHeadless(bool headless) { + _headless = true; +} + PageClientImpl::PageClientImpl(NSView* view, WKWebView *webView) : PageClientImplCocoa(webView) , m_view(view) @@ -163,6 +171,9 @@ NSWindow *PageClientImpl::activeWindow() const bool PageClientImpl::isViewWindowActive() { + if (_headless) + return true; + ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer)); NSWindow *activeViewWindow = activeWindow(); return activeViewWindow.isKeyWindow || [NSApp keyWindow] == activeViewWindow; @@ -170,6 +181,9 @@ bool PageClientImpl::isViewWindowActive() bool PageClientImpl::isViewFocused() { + if (_headless) + return true; + // FIXME: This is called from the WebPageProxy constructor before we have a WebViewImpl. // Once WebViewImpl and PageClient merge, this won't be a problem. if (!m_impl) @@ -193,6 +207,9 @@ void PageClientImpl::makeFirstResponder() bool PageClientImpl::isViewVisible() { + if (_headless) + return true; + NSView *activeView = this->activeView(); NSWindow *activeViewWindow = activeWindow(); @@ -456,6 +473,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled) { + if (!event.nativeEvent()) + return; m_impl->doneWithKeyEvent(event.nativeEvent(), eventWasHandled); } @@ -760,6 +779,13 @@ void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntR #endif // ENABLE(FULLSCREEN_API) +#if ENABLE(TOUCH_EVENTS) +void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled) +{ + notImplemented(); +} +#endif // ENABLE(TOUCH_EVENTS) + void PageClientImpl::navigationGestureDidBegin() { m_impl->dismissContentRelativeChildWindowsWithAnimation(true); @@ -931,6 +957,9 @@ void PageClientImpl::didRestoreScrollPosition() bool PageClientImpl::windowIsFrontWindowUnderMouse(const NativeWebMouseEvent& event) { + // Simulated event. + if (!event.nativeEvent()) + return false; return m_impl->windowIsFrontWindowUnderMouse(event.nativeEvent()); } diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm new file mode 100644 index 0000000000000000000000000000000000000000..4a8c59ffde6143da898f33452459dd14989a03da --- /dev/null +++ b/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "config.h" +#import "WebPageInspectorEmulationAgent.h" + +#import "WebPageProxy.h" + +namespace WebKit { + +void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function&& callback) +{ + NSWindow* window = m_page.platformWindow(); + NSRect windowRect = [window frame]; + NSRect viewRect = window.contentLayoutRect; + windowRect.size.width += width - viewRect.size.width; + windowRect.size.height += height - viewRect.size.height; + [window setFrame:windowRect display:YES animate:NO]; + callback(String()); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm new file mode 100644 index 0000000000000000000000000000000000000000..e762d503caa4329f83082e3e33b01fab7793b259 --- /dev/null +++ b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "config.h" +#import "NativeWebMouseEvent.h" +#import "WebPageInspectorInputAgent.h" +#import "WebPageProxy.h" +#import +#import +#import "NativeWebKeyboardEvent.h" +#import + +namespace WebKit { + +using namespace WebCore; + +void WebPageInspectorInputAgent::platformDispatchMouseEvent(const String& type, int x, int y, const int* optionalModifiers, const String* button, const int* optionalClickCount) { + IntPoint locationInWindow(x, y); + + NSEventModifierFlags modifiers = optionalModifiers ? *optionalModifiers : 0; + int clickCount = optionalClickCount ? *optionalClickCount : 0; + + NSTimeInterval timestamp = [NSDate timeIntervalSinceReferenceDate]; + NSWindow *window = m_page.platformWindow(); + NSInteger windowNumber = window.windowNumber; + + NSEventType downEventType = (NSEventType)0; + NSEventType dragEventType = (NSEventType)0; + NSEventType upEventType = (NSEventType)0; + + if (!button || *button == "none") { + downEventType = NSEventTypeMouseMoved; + dragEventType = NSEventTypeMouseMoved; + upEventType = NSEventTypeMouseMoved; + } else if (*button == "left") { + downEventType = NSEventTypeLeftMouseDown; + dragEventType = NSEventTypeLeftMouseDragged; + upEventType = NSEventTypeLeftMouseUp; + } else if (*button == "middle") { + downEventType = NSEventTypeOtherMouseDown; + dragEventType = NSEventTypeLeftMouseDragged; + upEventType = NSEventTypeOtherMouseUp; + } else if (*button == "right") { + downEventType = NSEventTypeRightMouseDown; + upEventType = NSEventTypeRightMouseUp; + } + + NSInteger eventNumber = 0; + + NSEvent* event = nil; + if (type == "move") { + event = [NSEvent mouseEventWithType:dragEventType location:locationInWindow modifierFlags:modifiers timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:eventNumber clickCount:clickCount pressure:0.0f]; + } else if (type == "down") { + event = [NSEvent mouseEventWithType:downEventType location:locationInWindow modifierFlags:modifiers timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:eventNumber clickCount:clickCount pressure:WebCore::ForceAtClick]; + } else if (type == "up") { + event = [NSEvent mouseEventWithType:upEventType location:locationInWindow modifierFlags:modifiers timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:eventNumber clickCount:clickCount pressure:0.0f]; + } + + if (event) { + NativeWebMouseEvent nativeEvent(event, nil, [window contentView]); + m_page.handleMouseEvent(nativeEvent); + } +} + +void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, Vector& commands, WallTime timestamp) +{ + String keyIdentifier = key.length() == 1 ? makeString("U+", hex(toASCIIUpper(key.characterAt(0)), 4)) : key; + Vector macCommands; + for (const String& command : commands) + macCommands.append(WebCore::KeypressCommand(command.utf8().data())); + if (text.length() > 0 && macCommands.size() == 0) + macCommands.append(WebCore::KeypressCommand("insertText:", text)); + NativeWebKeyboardEvent event( + type, + text, + unmodifiedText, + key, + code, + keyIdentifier, + windowsVirtualKeyCode, + nativeVirtualKeyCode, + isAutoRepeat, + isKeypad, + isSystemKey, + modifiers, + timestamp, + WTFMove(macCommands)); + m_page.handleKeyboardEvent(event); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorTargetProxyMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorTargetProxyMac.mm new file mode 100644 index 0000000000000000000000000000000000000000..6168521bb1279268a41629a68cf7feccd605c7a6 --- /dev/null +++ b/Source/WebKit/UIProcess/mac/WebPageInspectorTargetProxyMac.mm @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "config.h" +#import "WebPageInspectorTargetProxy.h" +#import "WebPageProxy.h" + +#if PLATFORM(MAC) + +namespace WebKit { + +void WebPageInspectorTargetProxy::platformActivate(String& error) const +{ + NSWindow* window = m_page.platformWindow(); + [window makeKeyAndOrderFront:nil]; +} + +} // namespace WebKit + +#endif diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a8860eb55c79bbf37df30d38e79ad13096b1d6f --- /dev/null +++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebPageInspectorEmulationAgent.h" + +#include "WebPageProxy.h" +#include + +namespace WebKit { + +void WebPageInspectorEmulationAgent::platformSetSize(String& error, int width, int height) +{ + struct wpe_view_backend* backend = m_page.viewBackend(); + wpe_view_backend_dispatch_set_size(backend, width, height); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp new file mode 100644 index 0000000000000000000000000000000000000000..28dc33bddca844dd03de845a9ffa427d80fb0867 --- /dev/null +++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebPageInspectorInputAgent.h" + +#include "NativeWebKeyboardEvent.h" +#include "WebPageProxy.h" +#include +#include + +namespace WebKit { + +void WebPageInspectorInputAgent::platformDispatchKeyEvent(String& error, const String& type, const String& keyRef) +{ +} + +static unsigned toWPEButton(WebMouseEvent::Button button) +{ + switch (button) { + case WebMouseEvent::NoButton: + case WebMouseEvent::LeftButton: + return 1; + case WebMouseEvent::MiddleButton: + return 3; + case WebMouseEvent::RightButton: + return 2; + } + return 1; +} + +static unsigned toWPEModifiers(OptionSet modifiers) +{ + unsigned result = 0; + if (modifiers.contains(WebEvent::Modifier::ControlKey)) + result |= wpe_input_keyboard_modifier_control; + if (modifiers.contains(WebEvent::Modifier::ShiftKey)) + result |= wpe_input_keyboard_modifier_shift; + if (modifiers.contains(WebEvent::Modifier::AltKey)) + result |= wpe_input_keyboard_modifier_alt; + if (modifiers.contains(WebEvent::Modifier::CapsLockKey)) + fprintf(stderr, "Unsupported modifier CapsLock will be ignored.\n"); + return result; +} + +void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, Vector& macCommands, WallTime timestamp) +{ + unsigned keyCode = WebCore::PlatformKeyboardEvent::WPEKeyCodeForWindowsKeyCode(windowsVirtualKeyCode); + struct wpe_input_xkb_keymap_entry* entries; + uint32_t entriesCount; + fprintf(stderr, "platformDispatchKeyEvent %s => %d\n", key.ascii().data(), keyCode); + wpe_input_xkb_context_get_entries_for_key_code(wpe_input_xkb_context_get_default(), keyCode, &entries, &entriesCount); + bool pressed = type == WebKeyboardEvent::KeyDown; + struct wpe_input_keyboard_event event = { 0, keyCode, entriesCount ? entries[0].hardware_key_code : 0, pressed, toWPEModifiers(modifiers) }; + // event.time = timestamp.secondsSinceEpoch().milliseconds(); + wpe_view_backend_dispatch_keyboard_event(m_page.viewBackend(), &event); + free(entries); +} + +void WebPageInspectorInputAgent::platformDispatchMouseEvent(WebMouseEvent::Type type, int x, int y, WebMouseEvent::Button button, OptionSet modifiers) +{ + wpe_input_pointer_event_type eventType = wpe_input_pointer_event_type_null; + uint32_t eventButton = 0; + uint32_t state = 0; + if (type == WebEvent::MouseDown || type == WebEvent::MouseUp) { + eventType = wpe_input_pointer_event_type_button; + state = (type == WebEvent::MouseDown); + eventButton = toWPEButton(button); + } else if (type == WebEvent::MouseMove) { + eventType = wpe_input_pointer_event_type_motion; + } + struct wpe_input_pointer_event event { eventType, 0, x, y, eventButton, state, toWPEModifiers(modifiers) }; + wpe_view_backend_dispatch_pointer_event(m_page.viewBackend(), &event); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorTargetProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorTargetProxyWPE.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a69c02f6b5786c7ed2179fea6b29de80262ec9e --- /dev/null +++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorTargetProxyWPE.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebPageInspectorTargetProxy.h" + +#include "WebPageProxy.h" +#include + +namespace WebKit { + +void WebPageInspectorTargetProxy::platformActivate(String& error) const +{ + struct wpe_view_backend* backend = m_page.viewBackend(); + wpe_view_backend_add_activity_state(backend, wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window); +} + +} // namespace WebKit diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj index 6897af5ec1990cd0d563aa55fd4889528460f05f..b9f9c0ac8586a222916d45890ddcd67a33191f7e 100644 --- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj +++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj @@ -1720,6 +1720,20 @@ CEE4AE2B1A5DCF430002F49B /* UIKitSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE4AE2A1A5DCF430002F49B /* UIKitSPI.h */; }; D3B9484711FF4B6500032B39 /* WebPopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = D3B9484311FF4B6500032B39 /* WebPopupMenu.h */; }; D3B9484911FF4B6500032B39 /* WebSearchPopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */; }; + D71A94322370E025002C4D9E /* InspectorBrowserAgentClientMac.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94302370E025002C4D9E /* InspectorBrowserAgentClientMac.h */; }; + D71A94342370E07A002C4D9E /* InspectorBrowserAgentClient.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94332370E07A002C4D9E /* InspectorBrowserAgentClient.h */; }; + D71A94382370F032002C4D9E /* BrowserInspectorController.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94372370F032002C4D9E /* BrowserInspectorController.h */; }; + D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */; }; + D71A94412371F67E002C4D9E /* WebPageInspectorTargetProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A943E2371F67E002C4D9E /* WebPageInspectorTargetProxy.h */; }; + D71A94422371F67E002C4D9E /* WebPageInspectorEmulationAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */; }; + D71A94432371F67E002C4D9E /* WebPageInspectorInputAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */; }; + D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94492372290B002C4D9E /* _WKBrowserInspector.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */; }; + D76D6888238DBD81008D314B /* InspectorDialogAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D76D6887238DBD80008D314B /* InspectorDialogAgent.h */; }; + D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */; }; + D79902B2236E9404005D6F7E /* WebPageInspectorTargetProxyMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AF236E9404005D6F7E /* WebPageInspectorTargetProxyMac.mm */; }; + D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */; }; + D7EB04E72372A73B00F744CE /* InspectorBrowserAgentClientMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D7EB04E62372A73B00F744CE /* InspectorBrowserAgentClientMac.mm */; }; E105FE5418D7B9DE008F57A8 /* EditingRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E105FE5318D7B9DE008F57A8 /* EditingRange.h */; }; E11D35AE16B63D1B006D23D7 /* com.apple.WebProcess.sb in Resources */ = {isa = PBXBuildFile; fileRef = E1967E37150AB5E200C73169 /* com.apple.WebProcess.sb */; }; E14A954A16E016A40068DE82 /* NetworkProcessPlatformStrategies.h in Headers */ = {isa = PBXBuildFile; fileRef = E14A954816E016A40068DE82 /* NetworkProcessPlatformStrategies.h */; }; @@ -4905,6 +4919,21 @@ D3B9484311FF4B6500032B39 /* WebPopupMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPopupMenu.h; sourceTree = ""; }; D3B9484411FF4B6500032B39 /* WebSearchPopupMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSearchPopupMenu.cpp; sourceTree = ""; }; D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSearchPopupMenu.h; sourceTree = ""; }; + D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBrowserInspector.h; sourceTree = ""; }; + D71A94302370E025002C4D9E /* InspectorBrowserAgentClientMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorBrowserAgentClientMac.h; sourceTree = ""; }; + D71A94332370E07A002C4D9E /* InspectorBrowserAgentClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorBrowserAgentClient.h; sourceTree = ""; }; + D71A94372370F032002C4D9E /* BrowserInspectorController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrowserInspectorController.h; sourceTree = ""; }; + D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteInspectorPipe.h; sourceTree = ""; }; + D71A943E2371F67E002C4D9E /* WebPageInspectorTargetProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorTargetProxy.h; sourceTree = ""; }; + D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorEmulationAgent.h; sourceTree = ""; }; + D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorInputAgent.h; sourceTree = ""; }; + D71A94492372290B002C4D9E /* _WKBrowserInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKBrowserInspector.h; sourceTree = ""; }; + D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrowserInspectorPipe.h; sourceTree = ""; }; + D76D6887238DBD80008D314B /* InspectorDialogAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDialogAgent.h; sourceTree = ""; }; + D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorEmulationAgentMac.mm; sourceTree = ""; }; + D79902AF236E9404005D6F7E /* WebPageInspectorTargetProxyMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorTargetProxyMac.mm; sourceTree = ""; }; + D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorInputAgentMac.mm; sourceTree = ""; }; + D7EB04E62372A73B00F744CE /* InspectorBrowserAgentClientMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorBrowserAgentClientMac.mm; sourceTree = ""; }; DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebWheelEvent.h; sourceTree = ""; }; DF58C6351371ACA000F9A37C /* NativeWebWheelEventMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NativeWebWheelEventMac.mm; sourceTree = ""; }; E105FE5318D7B9DE008F57A8 /* EditingRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingRange.h; sourceTree = ""; }; @@ -6702,6 +6731,7 @@ 37C4C08318149C2A003688B9 /* Cocoa */ = { isa = PBXGroup; children = ( + D71A94492372290B002C4D9E /* _WKBrowserInspector.h */, 1A43E826188F38E2009E4D30 /* Deprecated */, 37A5E01218BBF937000A081E /* _WKActivatedElementInfo.h */, 37A5E01118BBF937000A081E /* _WKActivatedElementInfo.mm */, @@ -8219,6 +8249,14 @@ BC032DC310F438260058C15A /* UIProcess */ = { isa = PBXGroup; children = ( + D76D6887238DBD80008D314B /* InspectorDialogAgent.h */, + D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */, + D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */, + D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */, + D71A943E2371F67E002C4D9E /* WebPageInspectorTargetProxy.h */, + D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */, + D71A94372370F032002C4D9E /* BrowserInspectorController.h */, + D71A94332370E07A002C4D9E /* InspectorBrowserAgentClient.h */, BC032DC410F4387C0058C15A /* API */, 512F588D12A8836F00629530 /* Authentication */, 9955A6E81C79809000EB6A93 /* Automation */, @@ -8502,6 +8540,7 @@ BC0C376610F807660076D7CB /* C */ = { isa = PBXGroup; children = ( + D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */, 5123CF18133D25E60056F800 /* cg */, 6EE849C41368D9040038D481 /* mac */, BCB63477116BF10600603215 /* WebKit2_C.h */, @@ -9101,6 +9140,11 @@ BCCF085C113F3B7500C650C5 /* mac */ = { isa = PBXGroup; children = ( + D7EB04E62372A73B00F744CE /* InspectorBrowserAgentClientMac.mm */, + D71A94302370E025002C4D9E /* InspectorBrowserAgentClientMac.h */, + D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */, + D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */, + D79902AF236E9404005D6F7E /* WebPageInspectorTargetProxyMac.mm */, B878B613133428DC006888E9 /* CorrectionPanel.h */, B878B614133428DC006888E9 /* CorrectionPanel.mm */, C1817362205844A900DFDA65 /* DisplayLink.cpp */, @@ -9798,6 +9842,7 @@ 5CAFDE452130846300B1F7E1 /* _WKInspector.h in Headers */, 991F492F23A812C60054642B /* _WKInspectorDebuggableInfo.h in Headers */, 99036AE223A949CF0000B06A /* _WKInspectorDebuggableInfoInternal.h in Headers */, + D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */, 5CAFDE472130846A00B1F7E1 /* _WKInspectorInternal.h in Headers */, 9979CA58237F49F10039EC05 /* _WKInspectorPrivate.h in Headers */, A5C0F0AB2000658200536536 /* _WKInspectorWindow.h in Headers */, @@ -9916,6 +9961,7 @@ 7C89D2981A6753B2003A5FDE /* APIPageConfiguration.h in Headers */, 1AC1336C18565C7A00F3EC05 /* APIPageHandle.h in Headers */, 1AFDD3151891B54000153970 /* APIPolicyClient.h in Headers */, + D71A94382370F032002C4D9E /* BrowserInspectorController.h in Headers */, 7CE4D2201A4914CA00C7F152 /* APIProcessPoolConfiguration.h in Headers */, 49BCA19223A177660028A836 /* APIResourceLoadStatisticsFirstParty.h in Headers */, 49BCA19723A1930D0028A836 /* APIResourceLoadStatisticsThirdParty.h in Headers */, @@ -10039,6 +10085,7 @@ BC06F43A12DBCCFB002D78DE /* GeolocationPermissionRequestProxy.h in Headers */, 2DA944A41884E4F000ED86DB /* GestureTypes.h in Headers */, 2DA049B8180CCD0A00AAFA9E /* GraphicsLayerCARemote.h in Headers */, + D71A94342370E07A002C4D9E /* InspectorBrowserAgentClient.h in Headers */, C0CE72AD1247E78D00BC0EC4 /* HandleMessage.h in Headers */, 1AC75A1B1B3368270056745B /* HangDetectionDisabler.h in Headers */, 57AC8F50217FEED90055438C /* HidConnection.h in Headers */, @@ -10162,8 +10209,10 @@ 41DC45961E3D6E2200B11F51 /* NetworkRTCProvider.h in Headers */, 413075AB1DE85F330039EC69 /* NetworkRTCSocket.h in Headers */, 5C20CBA01BB1ECD800895BB1 /* NetworkSession.h in Headers */, + D71A94422371F67E002C4D9E /* WebPageInspectorEmulationAgent.h in Headers */, 532159551DBAE7290054AA3C /* NetworkSessionCocoa.h in Headers */, 417915B92257046F00D6F97E /* NetworkSocketChannel.h in Headers */, + D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */, 570DAAC22303730300E8FC04 /* NfcConnection.h in Headers */, 570DAAAE23026F5C00E8FC04 /* NfcService.h in Headers */, 31A2EC5614899C0900810D71 /* NotificationPermissionRequest.h in Headers */, @@ -10245,6 +10294,7 @@ CD2865EE2255562000606AC7 /* ProcessTaskStateObserver.h in Headers */, 463FD4821EB94EC000A2982C /* ProcessTerminationReason.h in Headers */, 86E67A251910B9D100004AB7 /* ProcessThrottler.h in Headers */, + D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */, 83048AE61ACA45DC0082C832 /* ProcessThrottlerClient.h in Headers */, A1E688701F6E2BAB007006A6 /* QuarantineSPI.h in Headers */, 57FD318222B3515E008D0E8B /* RedirectSOAuthorizationSession.h in Headers */, @@ -10418,6 +10468,7 @@ F430E94422473DFF005FE053 /* WebContentMode.h in Headers */, 31A505FA1680025500A930EB /* WebContextClient.h in Headers */, BC09B8F9147460F7005F5625 /* WebContextConnectionClient.h in Headers */, + D71A94412371F67E002C4D9E /* WebPageInspectorTargetProxy.h in Headers */, BCDE059B11CDA8AE00E41AF1 /* WebContextInjectedBundleClient.h in Headers */, 51871B5C127CB89D00F76232 /* WebContextMenu.h in Headers */, BC032D7710F4378D0058C15A /* WebContextMenuClient.h in Headers */, @@ -10656,6 +10707,7 @@ BCD25F1711D6BDE100169B0E /* WKBundleFrame.h in Headers */, BCF049E611FE20F600F86A58 /* WKBundleFramePrivate.h in Headers */, BC49862F124D18C100D834E1 /* WKBundleHitTestResult.h in Headers */, + D71A94432371F67E002C4D9E /* WebPageInspectorInputAgent.h in Headers */, BC204EF211C83EC8008F3375 /* WKBundleInitialize.h in Headers */, 65B86F1E12F11DE300B7DD8A /* WKBundleInspector.h in Headers */, 1A8B66B41BC45B010082DF77 /* WKBundleMac.h in Headers */, @@ -10704,6 +10756,7 @@ 5C795D71229F3757003FF1C4 /* WKContextMenuElementInfoPrivate.h in Headers */, 51A555F6128C6C47009ABCEC /* WKContextMenuItem.h in Headers */, 51A55601128C6D92009ABCEC /* WKContextMenuItemTypes.h in Headers */, + D76D6888238DBD81008D314B /* InspectorDialogAgent.h in Headers */, A1EA02381DABFF7E0096021F /* WKContextMenuListener.h in Headers */, BCC938E11180DE440085E5FE /* WKContextPrivate.h in Headers */, 9FB5F395169E6A80002C25BF /* WKContextPrivateMac.h in Headers */, @@ -10853,6 +10906,7 @@ 1AB8A1F818400BB800E9AE69 /* WKPageContextMenuClient.h in Headers */, 8372DB251A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h in Headers */, 1AB8A1F418400B8F00E9AE69 /* WKPageFindClient.h in Headers */, + D71A94322370E025002C4D9E /* InspectorBrowserAgentClientMac.h in Headers */, 1AB8A1F618400B9D00E9AE69 /* WKPageFindMatchesClient.h in Headers */, 1AB8A1F018400B0000E9AE69 /* WKPageFormClient.h in Headers */, BC7B633712A45ABA00D174A4 /* WKPageGroup.h in Headers */, @@ -11887,6 +11941,7 @@ 2D92A781212B6A7100F493FD /* MessageReceiverMap.cpp in Sources */, 2D92A782212B6A7100F493FD /* MessageSender.cpp in Sources */, 2D92A77A212B6A6100F493FD /* Module.cpp in Sources */, + D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */, 57B826452304F14000B72EB0 /* NearFieldSoftLink.mm in Sources */, 2D913443212CF9F000128AFD /* NetscapeBrowserFuncs.cpp in Sources */, 2D913444212CF9F000128AFD /* NetscapePlugin.cpp in Sources */, @@ -11911,6 +11966,7 @@ 1A2D8439127F65D5001EB962 /* NPObjectMessageReceiverMessageReceiver.cpp in Sources */, 2D92A792212B6AD400F493FD /* NPObjectProxy.cpp in Sources */, 2D92A793212B6AD400F493FD /* NPRemoteObjectMap.cpp in Sources */, + D7EB04E72372A73B00F744CE /* InspectorBrowserAgentClientMac.mm in Sources */, 2D913447212CF9F000128AFD /* NPRuntimeObjectMap.cpp in Sources */, 2D913448212CF9F000128AFD /* NPRuntimeUtilities.cpp in Sources */, 2D92A794212B6AD400F493FD /* NPVariantData.cpp in Sources */, @@ -11961,11 +12017,13 @@ A1ADAFB62368E6A8009CB776 /* SharedMemory.cpp in Sources */, 2DE6943D18BD2A68005C15E5 /* SmartMagnificationControllerMessageReceiver.cpp in Sources */, 1A334DED16DE8F88006A8E38 /* StorageAreaMapMessageReceiver.cpp in Sources */, + D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */, 9368EEDE2303A90200BDB11A /* StorageManagerSetMessageReceiver.cpp in Sources */, 2D92A783212B6A7100F493FD /* StringReference.cpp in Sources */, 2D11B7512126A282006F8878 /* UnifiedSource1-mm.mm in Sources */, 2D11B7522126A282006F8878 /* UnifiedSource1.cpp in Sources */, 2D11B7542126A282006F8878 /* UnifiedSource2.cpp in Sources */, + D79902B2236E9404005D6F7E /* WebPageInspectorTargetProxyMac.mm in Sources */, 2D11B7532126A282006F8878 /* UnifiedSource2-mm.mm in Sources */, 2D11B7562126A282006F8878 /* UnifiedSource3.cpp in Sources */, 2D11B7552126A282006F8878 /* UnifiedSource3-mm.mm in Sources */, diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp index b7303e828456f51ba2c7fa4bc5b8860b4afaff52..e96cd89e0265ac877e0e9276b5d5af824efa850f 100644 --- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp +++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -227,8 +228,22 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou } #endif + if (m_emulateOfflineState) { + scheduleInternallyFailedLoad(resourceLoader); + return; + } + if (!tryLoadingUsingURLSchemeHandler(resourceLoader, trackingParameters)) { WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be scheduled with the NetworkProcess"); + + RefPtr coreLoader = &resourceLoader; + if (InspectorInstrumentationWebKit::interceptRequest(resourceLoader, [this, coreLoader, trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, resource](bool handled) mutable { + if (!handled) + scheduleLoadFromNetworkProcess(*coreLoader, coreLoader->request(), trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime(resource)); + })) { + return; + } + scheduleLoadFromNetworkProcess(resourceLoader, resourceLoader.request(), trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime(resource)); return; } @@ -718,7 +733,7 @@ void WebLoaderStrategy::didFinishPreconnection(uint64_t preconnectionIdentifier, bool WebLoaderStrategy::isOnLine() const { - return m_isOnLine; + return m_emulateOfflineState ? false : m_isOnLine; } void WebLoaderStrategy::addOnlineStateChangeListener(Function&& listener) @@ -729,6 +744,11 @@ void WebLoaderStrategy::addOnlineStateChangeListener(Function&& list void WebLoaderStrategy::setOnLineState(bool isOnLine) { + if (m_emulateOfflineState) { + m_isOnLine = isOnLine; + return; + } + if (m_isOnLine == isOnLine) return; @@ -737,6 +757,12 @@ void WebLoaderStrategy::setOnLineState(bool isOnLine) listener(isOnLine); } +void WebLoaderStrategy::setEmulateOfflineState(bool offline) { + m_emulateOfflineState = offline; + for (auto& listener : m_onlineStateChangeListeners) + listener(offline ? false : m_isOnLine); +} + void WebLoaderStrategy::setCaptureExtraNetworkLoadMetricsEnabled(bool enabled) { WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCaptureExtraNetworkLoadMetricsEnabled(enabled), 0); diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h index 9a78a5fe24da78b34ebefa785a07b5049ba473ba..17f4f626641629cb6c97d36b7361305a1f5d8258 100644 --- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h +++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h @@ -87,6 +87,7 @@ public: bool isOnLine() const final; void addOnlineStateChangeListener(Function&&) final; void setOnLineState(bool); + void setEmulateOfflineState(bool) final; private: void scheduleLoad(WebCore::ResourceLoader&, WebCore::CachedResource*, bool shouldClearReferrerOnHTTPSToHTTPRedirect); @@ -125,6 +126,7 @@ private: HashMap m_preconnectCompletionHandlers; Vector> m_onlineStateChangeListeners; bool m_isOnLine { true }; + bool m_emulateOfflineState { false }; HashSet m_loadersWithUploads; }; diff --git a/Source/WebKit/WebProcess/WebPage/WebPageInspectorTarget.cpp b/Source/WebKit/WebProcess/WebPage/WebPageInspectorTarget.cpp index a70f6fd52096a5dca901ea70a3755f14d6b4a0fd..f02e5c774a49d3e67860adb3b011531313eaf8d1 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPageInspectorTarget.cpp +++ b/Source/WebKit/WebProcess/WebPage/WebPageInspectorTarget.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "WebPageInspectorTarget.h" +#include "FrameInfoData.h" +#include "WebFrame.h" #include "WebPage.h" #include "WebPageInspectorTargetFrontendChannel.h" #include @@ -45,6 +47,11 @@ String WebPageInspectorTarget::identifier() const return toTargetID(m_page.identifier()); } +String WebPageInspectorTarget::url() const +{ + return m_page.mainWebFrame()->info().request.url().string(); +} + void WebPageInspectorTarget::connect(Inspector::FrontendChannel::ConnectionType connectionType) { if (m_channel) diff --git a/Source/WebKit/WebProcess/WebPage/WebPageInspectorTarget.h b/Source/WebKit/WebProcess/WebPage/WebPageInspectorTarget.h index 6cbd7fad5ff91afd858da346adbfeed6424b0b2b..176c46f186bc925fd28492d14d8d9e11bd8def26 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPageInspectorTarget.h +++ b/Source/WebKit/WebProcess/WebPage/WebPageInspectorTarget.h @@ -44,6 +44,7 @@ public: Inspector::InspectorTargetType type() const final { return Inspector::InspectorTargetType::Page; } String identifier() const final; + String url() const final; void connect(Inspector::FrontendChannel::ConnectionType) override; void disconnect() override; diff --git a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm index 0ff9e315b063c1fff273946018b60f5a02b72875..18dc8a4e40194d596db1ff7fb0cdbca363024706 100644 --- a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm +++ b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm @@ -4243,7 +4243,7 @@ static BOOL currentScrollIsBlit(NSView *clipView) _private->handlingMouseDownEvent = NO; } -#if ENABLE(TOUCH_EVENTS) +#if ENABLE(IOS_TOUCH_EVENTS) - (void)touch:(WebEvent *)event { diff --git a/Source/WebKitLegacy/mac/WebView/WebView.mm b/Source/WebKitLegacy/mac/WebView/WebView.mm index 4c41864d89f40567ed81ed2efefb501f6753db84..b9cab7c400c0c129ea4a9851dc397682a6ffc7e5 100644 --- a/Source/WebKitLegacy/mac/WebView/WebView.mm +++ b/Source/WebKitLegacy/mac/WebView/WebView.mm @@ -4336,7 +4336,7 @@ IGNORE_WARNINGS_END } #endif // PLATFORM(IOS_FAMILY) -#if ENABLE(TOUCH_EVENTS) +#if ENABLE(IOS_TOUCH_EVENTS) - (NSArray *)_touchEventRegions { auto* frame = [self _mainCoreFrame]; @@ -4382,7 +4382,7 @@ IGNORE_WARNINGS_END return eventRegionArray; } -#endif // ENABLE(TOUCH_EVENTS) +#endif // ENABLE(IOS_TOUCH_EVENTS) // For backwards compatibility with the WebBackForwardList API, we honor both // a per-WebView and a per-preferences setting for whether to use the back/forward cache. diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.h b/Tools/MiniBrowser/gtk/BrowserWindow.h index 1570d65effb5d601ee3c44a2a7461436f4691c2c..456f96cf589320efa70a76f76e230b6795886b5a 100644 --- a/Tools/MiniBrowser/gtk/BrowserWindow.h +++ b/Tools/MiniBrowser/gtk/BrowserWindow.h @@ -37,7 +37,7 @@ G_BEGIN_DECLS #define BROWSER_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), BROWSER_TYPE_WINDOW)) #define BROWSER_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), BROWSER_TYPE_WINDOW)) #define BROWSER_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), BROWSER_TYPE_WINDOW, BrowserWindowClass)) -#define BROWSER_DEFAULT_URL "http://www.webkitgtk.org/" +#define BROWSER_DEFAULT_URL "about:blank" #define BROWSER_ABOUT_SCHEME "minibrowser-about" typedef struct _BrowserWindow BrowserWindow; diff --git a/Tools/MiniBrowser/gtk/main.c b/Tools/MiniBrowser/gtk/main.c index 4c5147dcd38a53e2feaeaae0fce38f92dc60eba6..bc895f379e5dcca90464b63ebebcc756c479c47e 100644 --- a/Tools/MiniBrowser/gtk/main.c +++ b/Tools/MiniBrowser/gtk/main.c @@ -53,6 +53,7 @@ static const char *cookiesFile; static const char *cookiesPolicy; static const char *proxy; static gboolean darkMode; +static gboolean inspectorPipe; static gboolean printVersion; typedef enum { @@ -121,6 +122,7 @@ static const GOptionEntry commandLineOptions[] = { "ignore-tls-errors", 0, 0, G_OPTION_ARG_NONE, &ignoreTLSErrors, "Ignore TLS errors", NULL }, { "content-filter", 0, 0, G_OPTION_ARG_FILENAME, &contentFilter, "JSON with content filtering rules", "FILE" }, { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WebKitGTK version", NULL }, + { "inspector-pipe", 0, 0, G_OPTION_ARG_NONE, &inspectorPipe, "Open pipe connection to the remote inspector", NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL…]" }, { 0, 0, 0, 0, 0, 0, 0 } }; @@ -498,6 +500,29 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul g_main_loop_quit(data->mainLoop); } +static WebKitWebView *createNewPage(WebKitBrowserInspector *browser_inspector, WebKitWebContext *context) +{ + WebKitWebView *newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, + "web-context", context, + "is-ephemeral", webkit_web_context_is_ephemeral(context), + "is-controlled-by-automation", TRUE, + NULL)); + GtkWidget *newWindow = browser_window_new(NULL, context); + browser_window_append_view(BROWSER_WINDOW(newWindow), newWebView); + gtk_widget_grab_focus(GTK_WIDGET(newWebView)); + gtk_widget_show(GTK_WIDGET(newWindow)); + webkit_web_view_load_uri(newWebView, "about:blank"); + return newWebView; +} + +static void configureBrowserInspectorPipe() +{ + WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default(); + g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL); + + webkit_browser_inspector_initialize_pipe(); +} + int main(int argc, char *argv[]) { #if ENABLE_DEVELOPER_MODE @@ -541,10 +566,22 @@ int main(int argc, char *argv[]) return 0; } - WebKitWebsiteDataManager *manager = (privateMode || automationMode) ? webkit_website_data_manager_new_ephemeral() : webkit_website_data_manager_new(NULL); + WebKitWebsiteDataManager *manager; + if (inspectorPipe) { + manager = webkit_web_context_get_website_data_manager(webkit_web_context_get_default()); + g_object_ref(manager); + } else if (privateMode || automationMode) { + manager = webkit_website_data_manager_new_ephemeral(); + } else { + manager = webkit_website_data_manager_new(NULL); + } + WebKitWebContext *webContext = g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, "process-swap-on-cross-site-navigation-enabled", TRUE, NULL); g_object_unref(manager); + if (inspectorPipe) + configureBrowserInspectorPipe(); + if (cookiesPolicy) { WebKitCookieManager *cookieManager = webkit_web_context_get_cookie_manager(webContext); GEnumClass *enumClass = g_type_class_ref(WEBKIT_TYPE_COOKIE_ACCEPT_POLICY); diff --git a/Tools/MiniBrowser/mac/AppDelegate.h b/Tools/MiniBrowser/mac/AppDelegate.h index ca98036e51491695bc976fedcd10c9e63d386144..06c41ff9d246d06fb41e16e1dd46daca7ba71807 100644 --- a/Tools/MiniBrowser/mac/AppDelegate.h +++ b/Tools/MiniBrowser/mac/AppDelegate.h @@ -23,12 +23,25 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +#import + @class ExtensionManagerWindowController; @class SettingsController; -@interface BrowserAppDelegate : NSObject { +WK_CLASS_AVAILABLE(macos(10.14.0)) +@interface WebViewDialog : NSObject +@property (nonatomic, strong) WKWebView *webView; +@property (nonatomic, copy) void (^completionHandler)(BOOL accept, NSString* value); +@end + +@interface BrowserAppDelegate : NSObject { NSMutableSet *_browserWindowControllers; SettingsController *_settingsController; + NSMutableSet *_headlessWindows; + NSMutableSet *_browserContexts; + bool _headless; + NSMutableSet *_dialogs; + NSString* _initialURL; ExtensionManagerWindowController *_extensionManagerWindowController; IBOutlet NSMenu *_settingsMenu; diff --git a/Tools/MiniBrowser/mac/AppDelegate.m b/Tools/MiniBrowser/mac/AppDelegate.m index 2b79519691b5d55be16bf8b47c3a755f2ddefc72..69549058b067505fa3fe20a8c6271a935be1695b 100644 --- a/Tools/MiniBrowser/mac/AppDelegate.m +++ b/Tools/MiniBrowser/mac/AppDelegate.m @@ -33,7 +33,9 @@ #import #import #import +#import #import +#import #import #import #import @@ -64,16 +66,53 @@ @interface NSApplication (TouchBar) @end +@implementation WebViewDialog +@end + +enum { + _NSBackingStoreUnbuffered = 3 +}; + +NSString* const ActivityReason = @"Batch headless process"; +const NSActivityOptions ActivityOptions = + (NSActivityUserInitiatedAllowingIdleSystemSleep | + NSActivityLatencyCritical) & + ~(NSActivitySuddenTerminationDisabled | + NSActivityAutomaticTerminationDisabled); + @implementation BrowserAppDelegate - (id)init { self = [super init]; - if (self) { - _browserWindowControllers = [[NSMutableSet alloc] init]; - _extensionManagerWindowController = [[ExtensionManagerWindowController alloc] init]; + if (!self) + return nil; + + _initialURL = nil; + NSArray *arguments = [[NSProcessInfo processInfo] arguments]; + NSRange subargs = NSMakeRange(1, [arguments count] - 1); + NSArray *subArray = [arguments subarrayWithRange:subargs]; + + for (NSString *argument in subArray) { + if (![argument hasPrefix:@"--"]) + _initialURL = argument; } + _headless = [arguments containsObject: @"--headless"]; + _browserContexts = [[NSMutableSet alloc] init]; + + if (_headless) { + _headlessWindows = [[NSMutableSet alloc] init]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory]; + [[NSProcessInfo processInfo] beginActivityWithOptions:ActivityOptions + reason:ActivityReason]; + _dialogs = [[NSMutableSet alloc] init]; + } else { + _extensionManagerWindowController = [[ExtensionManagerWindowController alloc] init]; + _browserWindowControllers = [[NSMutableSet alloc] init]; + } + if ([arguments containsObject: @"--inspector-pipe"]) + [_WKBrowserInspector initializeRemoteInspectorPipe:self headless:_headless]; return self; } @@ -99,7 +138,7 @@ - (void)awakeFromNib configuration.networkCacheSpeculativeValidationEnabled = YES; dataStore = [[WKWebsiteDataStore alloc] _initWithConfiguration:configuration]; } - + return dataStore; } @@ -114,13 +153,18 @@ - (WKWebViewConfiguration *)defaultConfiguration configuration.preferences._developerExtrasEnabled = YES; configuration.preferences._mediaDevicesEnabled = YES; configuration.preferences._mockCaptureDevicesEnabled = YES; + configuration.preferences._hiddenPageDOMTimerThrottlingEnabled = NO; + configuration.preferences._hiddenPageDOMTimerThrottlingAutoIncreases = NO; + configuration.preferences._pageVisibilityBasedProcessSuppressionEnabled = NO; + configuration.preferences._domTimersThrottlingEnabled = NO; + configuration.preferences._requestAnimationFrameEnabled = YES; _WKProcessPoolConfiguration *processConfiguration = [[[_WKProcessPoolConfiguration alloc] init] autorelease]; if (_settingsController.perWindowWebProcessesDisabled) processConfiguration.usesSingleWebProcess = YES; if (_settingsController.processSwapOnWindowOpenWithOpenerEnabled) processConfiguration.processSwapsOnWindowOpenWithOpener = true; - + configuration.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration] autorelease]; NSArray<_WKExperimentalFeature *> *experimentalFeatures = [WKPreferences _experimentalFeatures]; @@ -156,6 +200,9 @@ - (WKPreferences *)defaultPreferences - (BrowserWindowController *)createBrowserWindowController:(id)sender { + if (_headless) + return nil; + BrowserWindowController *controller = nil; BOOL useWebKit2 = NO; BOOL makeEditable = NO; @@ -169,9 +216,9 @@ - (BrowserWindowController *)createBrowserWindowController:(id)sender } if (!useWebKit2) - controller = [[WK1BrowserWindowController alloc] initWithWindowNibName:@"BrowserWindow"]; + controller = [[[WK1BrowserWindowController alloc] initWithWindowNibName:@"BrowserWindow"] autorelease]; else - controller = [[WK2BrowserWindowController alloc] initWithConfiguration:[self defaultConfiguration]]; + controller = [[[WK2BrowserWindowController alloc] initWithConfiguration:[self defaultConfiguration]] autorelease]; if (makeEditable) controller.editable = YES; @@ -196,6 +243,9 @@ - (IBAction)newWindow:(id)sender - (IBAction)newPrivateWindow:(id)sender { + if (_headless) + return; + WKWebViewConfiguration *privateConfiguraton = [self.defaultConfiguration copy]; privateConfiguraton.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore]; @@ -225,16 +275,19 @@ - (void)browserWindowWillClose:(NSWindow *)window - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + if (_headless) { + [self createNewPage:0]; + return; + } + WebHistory *webHistory = [[WebHistory alloc] init]; [WebHistory setOptionalSharedHistory:webHistory]; [webHistory release]; [self _updateNewWindowKeyEquivalents]; - - if (_settingsController.createEditorByDefault) - [self newEditorWindow:self]; - else + if (!_initialURL) [self newWindow:self]; + _initialURL = nil; } - (BrowserWindowController *)frontmostBrowserWindowController @@ -260,12 +313,15 @@ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filenam return NO; [controller.window makeKeyAndOrderFront:self]; - [controller loadURLString:[NSURL fileURLWithPath:filename].absoluteString]; + [controller loadURLString:_initialURL ? _initialURL : [NSURL fileURLWithPath:filename].absoluteString]; return YES; } - (IBAction)openDocument:(id)sender { + if (_headless) + return; + BrowserWindowController *browserWindowController = [self frontmostBrowserWindowController]; if (browserWindowController) { @@ -295,6 +351,9 @@ - (IBAction)openDocument:(id)sender - (void)didChangeSettings { + if (_headless) + return; + [self _updateNewWindowKeyEquivalents]; // Let all of the BrowserWindowControllers know that a setting changed, so they can attempt to dynamically update. @@ -323,6 +382,8 @@ - (void)_updateNewWindowKeyEquivalents - (IBAction)showExtensionsManager:(id)sender { + if (_headless) + return; [_extensionManagerWindowController showWindow:sender]; } @@ -356,4 +417,159 @@ - (IBAction)clearDefaultStoreWebsiteData:(id)sender }]; } +#pragma mark WKBrowserInspectorDelegate + +- (WKWebViewConfiguration *) sessionConfiguration:(uint64_t)sessionID +{ + for (_WKBrowserContext *browserContext in _browserContexts) { + if ([[browserContext dataStore] sessionID] != sessionID) + continue; + WKWebViewConfiguration *configuration = [[[self defaultConfiguration] copy] autorelease]; + configuration.websiteDataStore = [browserContext dataStore]; + configuration.processPool = [browserContext processPool]; + return configuration; + } + return [self defaultConfiguration]; +} + +- (WKWebView *)createNewPage:(uint64_t)sessionID +{ + if (_headless) + return [self createHeadlessPage:sessionID]; + + WKWebViewConfiguration *configuration = [self sessionConfiguration:sessionID]; + WK2BrowserWindowController *controller = [[[WK2BrowserWindowController alloc] initWithConfiguration:configuration] autorelease]; + if (!controller) + return nil; + [[controller window] makeKeyAndOrderFront:nil]; + [_browserWindowControllers addObject:controller]; + [controller loadURLString:_settingsController.defaultURL]; + return [controller webView]; +} + +- (WKWebView *)createHeadlessWebView:(WKWebViewConfiguration *)configuration +{ + NSRect rect = NSMakeRect(0, 0, 1024, 768); + NSScreen *firstScreen = [[NSScreen screens] objectAtIndex:0]; + NSRect windowRect = NSOffsetRect(rect, -10000, [firstScreen frame].size.height - rect.size.height + 10000); + NSWindow* window = [[NSWindow alloc] initWithContentRect:windowRect styleMask:NSWindowStyleMaskBorderless backing:(NSBackingStoreType)_NSBackingStoreUnbuffered defer:YES]; + + WKWebView* webView = [[WKWebView alloc] initWithFrame:[window.contentView bounds] configuration:configuration]; + webView._windowOcclusionDetectionEnabled = NO; + if (!webView) + return nil; + + webView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; + [window.contentView addSubview:webView]; + NSURL *url = [NSURL _webkit_URLWithUserTypedString:_initialURL ? _initialURL : @"about:blank"]; + _initialURL = nil; + [webView loadRequest:[NSURLRequest requestWithURL:url]]; + [_headlessWindows addObject:window]; + webView.UIDelegate = self; + return [webView autorelease]; +} + +- (WKWebView *)createHeadlessPage:(uint64_t)sessionID +{ + WKWebViewConfiguration *configuration = [self sessionConfiguration:sessionID]; + return [self createHeadlessWebView:configuration]; +} + +- (_WKBrowserContext *)createBrowserContext +{ + _WKBrowserContext *browserContext = [[_WKBrowserContext alloc] init]; + _WKProcessPoolConfiguration *processConfiguration = [[[_WKProcessPoolConfiguration alloc] init] autorelease]; + browserContext.dataStore = [WKWebsiteDataStore nonPersistentDataStore]; + browserContext.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration] autorelease]; + [_browserContexts addObject:browserContext]; + return browserContext; +} + +- (void)deleteBrowserContext:(uint64_t)sessionID +{ + for (_WKBrowserContext *browserContext in _browserContexts) { + if ([[browserContext dataStore] sessionID] != sessionID) + continue; + [_browserContexts removeObject:browserContext]; + return; + } +} + +- (void)quit +{ + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; +} + +#pragma mark WKUIDelegate + +- (void)webViewDidClose:(WKWebView *)webView { + for (NSWindow *window in _headlessWindows) { + if (webView.window != window) + continue; + [webView removeFromSuperview]; + [window close]; + [_headlessWindows removeObject:window]; + break; + } +} + +- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler +{ + WebViewDialog* dialog = [[WebViewDialog alloc] autorelease]; + dialog.webView = webView; + dialog.completionHandler = ^void (BOOL accept, NSString* value) { + completionHandler(); + [_dialogs removeObject:dialog]; + }; + [_dialogs addObject:dialog]; +} + +- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler +{ + WebViewDialog* dialog = [[WebViewDialog alloc] autorelease]; + dialog.webView = webView; + dialog.completionHandler = ^void (BOOL accept, NSString* value) { + completionHandler(accept); + [_dialogs removeObject:dialog]; + }; + [_dialogs addObject:dialog]; +} + +- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *result))completionHandler +{ + WebViewDialog* dialog = [[WebViewDialog alloc] autorelease]; + dialog.webView = webView; + dialog.completionHandler = ^void (BOOL accept, NSString* value) { + completionHandler(accept && value ? value : nil); + [_dialogs removeObject:dialog]; + }; + [_dialogs addObject:dialog]; +} + +- (void)_webView:(WKWebView *)webView runBeforeUnloadConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler +{ + WebViewDialog* dialog = [[WebViewDialog alloc] autorelease]; + dialog.webView = webView; + dialog.completionHandler = ^void (BOOL accept, NSString* value) { + completionHandler(accept); + [_dialogs removeObject:dialog]; + }; + [_dialogs addObject:dialog]; +} + +- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(NSString *)value +{ + for (WebViewDialog *dialog in _dialogs) { + if (dialog.webView != webView) + continue; + dialog.completionHandler(accept, value); + break; + } +} + +- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures +{ + return [self createHeadlessWebView:configuration]; +} + @end diff --git a/Tools/MiniBrowser/mac/SettingsController.m b/Tools/MiniBrowser/mac/SettingsController.m index d68c854ad582702c6a6ea638708f1d3f8e4e1b18..3a078cbc6c5b081de013497fe8254bedb8e034d4 100644 --- a/Tools/MiniBrowser/mac/SettingsController.m +++ b/Tools/MiniBrowser/mac/SettingsController.m @@ -33,7 +33,7 @@ NSString * const kUserAgentChangedNotificationName = @"UserAgentChangedNotification"; -static NSString * const defaultURL = @"http://www.webkit.org/"; +static NSString * const defaultURL = @"about:blank"; static NSString * const DefaultURLPreferenceKey = @"DefaultURL"; static NSString * const CustomUserAgentPreferenceKey = @"CustomUserAgentIdentifier"; diff --git a/Tools/MiniBrowser/mac/WK2BrowserWindowController.h b/Tools/MiniBrowser/mac/WK2BrowserWindowController.h index 6f0949b0f4ad0ec86b8a6f27c6a53ce9ad691500..e774433031a66b2ae606d74deb2417fa510e59e3 100644 --- a/Tools/MiniBrowser/mac/WK2BrowserWindowController.h +++ b/Tools/MiniBrowser/mac/WK2BrowserWindowController.h @@ -25,8 +25,11 @@ #import "BrowserWindowController.h" +@class WKWebView; + @interface WK2BrowserWindowController : BrowserWindowController - (instancetype)initWithConfiguration:(WKWebViewConfiguration *)configuration; +- (WKWebView *)webView; @end diff --git a/Tools/MiniBrowser/mac/WK2BrowserWindowController.m b/Tools/MiniBrowser/mac/WK2BrowserWindowController.m index 031edd533ae1b791bc6862c631b909ae99dac886..0eee1f2071e5e6800f4889a561e94951f41ea811 100644 --- a/Tools/MiniBrowser/mac/WK2BrowserWindowController.m +++ b/Tools/MiniBrowser/mac/WK2BrowserWindowController.m @@ -73,6 +73,7 @@ @implementation WK2BrowserWindowController { WKWebView *_webView; BOOL _zoomTextOnly; BOOL _isPrivateBrowsingWindow; + NSAlert* _alert; BOOL _useShrinkToFit; @@ -83,7 +84,10 @@ @implementation WK2BrowserWindowController { - (void)awakeFromNib { + self.window.styleMask &= ~NSWindowStyleMaskFullSizeContentView; + _webView = [[WKWebView alloc] initWithFrame:[containerView bounds] configuration:_configuration]; + _webView._windowOcclusionDetectionEnabled = NO; [self didChangeSettings]; _webView.allowsMagnification = YES; @@ -107,7 +111,7 @@ - (void)awakeFromNib // telling WebKit to load every icon referenced by the page. if (settingsController.loadsAllSiteIcons) _webView._iconLoadingDelegate = self; - + _webView._observedRenderingProgressEvents = _WKRenderingProgressEventFirstLayout | _WKRenderingProgressEventFirstVisuallyNonEmptyLayout | _WKRenderingProgressEventFirstPaintWithSignificantArea @@ -147,14 +151,11 @@ - (instancetype)initWithConfiguration:(WKWebViewConfiguration *)configuration - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [_webView removeObserver:self forKeyPath:@"title"]; - [_webView removeObserver:self forKeyPath:@"URL"]; [progressIndicator unbind:NSHiddenBinding]; [progressIndicator unbind:NSValueBinding]; [_textFinder release]; - [_webView release]; [_configuration release]; @@ -387,9 +388,15 @@ - (BOOL)windowShouldClose:(id)sender - (void)windowWillClose:(NSNotification *)notification { [[[NSApplication sharedApplication] browserAppDelegate] browserWindowWillClose:self.window]; + [_webView removeObserver:self forKeyPath:@"title"]; + [_webView removeObserver:self forKeyPath:@"URL"]; [self autorelease]; } +- (void)webViewDidClose:(WKWebView *)webView { + [self.window close]; +} + #define DefaultMinimumZoomFactor (.5) #define DefaultMaximumZoomFactor (3.0) #define DefaultZoomFactorRatio (1.2) @@ -527,9 +534,11 @@ - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSStrin [alert setInformativeText:message]; [alert addButtonWithTitle:@"OK"]; + _alert = alert; [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) { completionHandler(); [alert release]; + _alert = nil; }]; } @@ -543,9 +552,11 @@ - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSStr [alert addButtonWithTitle:@"OK"]; [alert addButtonWithTitle:@"Cancel"]; + _alert = alert; [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) { completionHandler(response == NSAlertFirstButtonReturn); [alert release]; + _alert = nil; }]; } @@ -563,13 +574,25 @@ - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSSt [input setStringValue:defaultText]; [alert setAccessoryView:input]; + _alert = alert; [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) { [input validateEditing]; completionHandler(response == NSAlertFirstButtonReturn ? [input stringValue] : nil); [alert release]; + _alert = nil; }]; } +- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(NSString *)value +{ + if (!_alert) + return; + NSTextField* input = (NSTextField*)_alert.accessoryView; + if (accept && input && value) + [input setStringValue:value]; + [self.window endSheet:_alert.window returnCode: accept ? NSAlertFirstButtonReturn : NSModalResponseCancel]; +} + #if __has_feature(objc_generics) - (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray * URLs))completionHandler #else @@ -863,4 +886,9 @@ - (IBAction)saveAsWebArchive:(id)sender }]; } +- (WKWebView *)webView +{ + return _webView; +} + @end diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp index 2d183d394123bd84545dc51f53eb9be796fb8873..d94d4f06fc5be9ab9cd732ceb612a1676089ab82 100644 --- a/Tools/MiniBrowser/wpe/main.cpp +++ b/Tools/MiniBrowser/wpe/main.cpp @@ -172,6 +172,41 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi return newWebView; } +static WebKitWebView *createNewPage(WebKitBrowserInspector*, WebKitWebContext *context) +{ + auto backend = createViewBackend(1280, 720); + struct wpe_view_backend* wpeBackend = backend->backend(); + if (!wpeBackend) + return nullptr; + + auto* viewBackend = webkit_web_view_backend_new(wpeBackend, + [](gpointer data) { + delete static_cast(data); + }, backend.release()); + + auto* newWebView = webkit_web_view_new_with_context(viewBackend, context); + + g_signal_connect(newWebView, "close", G_CALLBACK(webViewClose), nullptr); + + webkit_web_view_load_uri(newWebView, "about:blank"); + + return newWebView; + +} + +static void closeAll(WebKitBrowserInspector*, GMainLoop* mainLoop) +{ + g_main_loop_quit(mainLoop); +} + +static void configureBrowserInspector(GMainLoop* mainLoop, WebKitWebView *firstWebView) +{ + WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default(); + g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL); + // FIXME: This signal is received only when closeAll is called. We should not rely on that. + g_signal_connect(firstWebView, "close", G_CALLBACK(closeAll), mainLoop); +} + int main(int argc, char *argv[]) { #if ENABLE_DEVELOPER_MODE @@ -301,6 +336,8 @@ int main(int argc, char *argv[]) g_signal_connect(webView, "permission-request", G_CALLBACK(decidePermissionRequest), nullptr); g_signal_connect(webView, "create", G_CALLBACK(createWebView), nullptr); + configureBrowserInspector(loop, webView); + if (ignoreTLSErrors) webkit_web_context_set_tls_errors_policy(webContext, WEBKIT_TLS_ERRORS_POLICY_IGNORE);