playwright/browser_patches/webkit/patches/bootstrap.diff
Joel Einbinder d4fb159154
browser(webkit): fix webcontent startup crash on macos 11 (#4370)
reverts #4357 and provides the real fix. Apple accidentally landed some code that will crash the web process if it is not signed by them. I'm sure they will figure it out once they get test bots for macos 11. But until then, we can just revert.

https://bugs.webkit.org/show_bug.cgi?id=218342
2020-11-06 11:11:19 -08:00

17441 lines
776 KiB
Diff

diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index 1d1dca6779f08fb82c85fb62c4c3fc9e821638a0..ddc5d0051d57c1d4f0934f2847773a2335d94c3b 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -1179,22 +1179,27 @@ set(JavaScriptCore_INSPECTOR_DOMAINS
${JAVASCRIPTCORE_DIR}/inspector/protocol/CSS.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Canvas.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Console.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Dialog.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/DOM.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMDebugger.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMStorage.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Database.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Debugger.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Emulation.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/GenericTypes.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Heap.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/IndexedDB.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Input.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Inspector.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/LayerTree.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Memory.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Network.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Page.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Playwright.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Recording.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Runtime.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/ScriptProfiler.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Screencast.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Security.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/ServiceWorker.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Target.json
diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make
index 275a1c1b676e7974d2a8bcce5bba28fc805f8ce3..d5d70175f5df5f1a12fd199136ff9638bceeb3d8 100644
--- a/Source/JavaScriptCore/DerivedSources.make
+++ b/Source/JavaScriptCore/DerivedSources.make
@@ -267,22 +267,27 @@ INSPECTOR_DOMAINS := \
$(JavaScriptCore)/inspector/protocol/CSS.json \
$(JavaScriptCore)/inspector/protocol/Canvas.json \
$(JavaScriptCore)/inspector/protocol/Console.json \
+ $(JavaScriptCore)/inspector/protocol/Dialog.json \
$(JavaScriptCore)/inspector/protocol/DOM.json \
$(JavaScriptCore)/inspector/protocol/DOMDebugger.json \
$(JavaScriptCore)/inspector/protocol/DOMStorage.json \
$(JavaScriptCore)/inspector/protocol/Database.json \
$(JavaScriptCore)/inspector/protocol/Debugger.json \
+ $(JavaScriptCore)/inspector/protocol/Emulation.json \
$(JavaScriptCore)/inspector/protocol/GenericTypes.json \
$(JavaScriptCore)/inspector/protocol/Heap.json \
$(JavaScriptCore)/inspector/protocol/IndexedDB.json \
+ $(JavaScriptCore)/inspector/protocol/Input.json \
$(JavaScriptCore)/inspector/protocol/Inspector.json \
$(JavaScriptCore)/inspector/protocol/LayerTree.json \
$(JavaScriptCore)/inspector/protocol/Memory.json \
$(JavaScriptCore)/inspector/protocol/Network.json \
$(JavaScriptCore)/inspector/protocol/Page.json \
+ $(JavaScriptCore)/inspector/protocol/Playwright.json \
$(JavaScriptCore)/inspector/protocol/Recording.json \
$(JavaScriptCore)/inspector/protocol/Runtime.json \
$(JavaScriptCore)/inspector/protocol/ScriptProfiler.json \
+ $(JavaScriptCore)/inspector/protocol/Screencast.json \
$(JavaScriptCore)/inspector/protocol/Security.json \
$(JavaScriptCore)/inspector/protocol/ServiceWorker.json \
$(JavaScriptCore)/inspector/protocol/Target.json \
diff --git a/Source/JavaScriptCore/bindings/ScriptValue.cpp b/Source/JavaScriptCore/bindings/ScriptValue.cpp
index 7968b90a73b282df5982256a6edcb2d6e574396e..6cc034017ae9b2f35c9c526633052586db920ee4 100644
--- a/Source/JavaScriptCore/bindings/ScriptValue.cpp
+++ b/Source/JavaScriptCore/bindings/ScriptValue.cpp
@@ -79,7 +79,10 @@ static RefPtr<JSON::Value> jsToInspectorValue(JSGlobalObject* globalObject, JSVa
PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
object.methodTable(vm)->getOwnPropertyNames(&object, globalObject, propertyNames, 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(), inspectorValue.releaseNonNull());
diff --git a/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp b/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp
index 95cd87b01b15cb8667e57bc5bb51a71f06bc3760..0481fa93227f297be9d9cf000c5a72235956a390 100644
--- a/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp
+++ b/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp
@@ -30,14 +30,21 @@
namespace Inspector {
namespace {
+static uint64_t s_processID = 0;
static long s_lastUsedIdentifier = 0;
}
static String addPrefixToIdentifier(const String& identifier)
{
- return makeString("0.", identifier);
+ return makeString(s_processID, ".", identifier);
}
+void IdentifiersFactory::initializeWithProcessID(uint64_t processID) {
+ ASSERT(!s_processID);
+ s_processID = processID;
+}
+
+
String IdentifiersFactory::createIdentifier()
{
return addPrefixToIdentifier(String::number(++s_lastUsedIdentifier));
diff --git a/Source/JavaScriptCore/inspector/IdentifiersFactory.h b/Source/JavaScriptCore/inspector/IdentifiersFactory.h
index eb25aedee4cd9ebe007e06c2515b37ee095b06f4..badf6559595c8377db1089ca3c25008e1be2c8f1 100644
--- a/Source/JavaScriptCore/inspector/IdentifiersFactory.h
+++ b/Source/JavaScriptCore/inspector/IdentifiersFactory.h
@@ -31,6 +31,7 @@ namespace Inspector {
class JS_EXPORT_PRIVATE IdentifiersFactory {
public:
+ static void initializeWithProcessID(uint64_t);
static String createIdentifier();
static String requestId(unsigned long identifier);
};
diff --git a/Source/JavaScriptCore/inspector/InjectedScript.cpp b/Source/JavaScriptCore/inspector/InjectedScript.cpp
index 65f8d6bf17af27b559d5bef3089757ffa85c54de..d624b031ac0564a2525b923acfb69cee9afbcbfb 100644
--- a/Source/JavaScriptCore/inspector/InjectedScript.cpp
+++ b/Source/JavaScriptCore/inspector/InjectedScript.cpp
@@ -289,6 +289,10 @@ RefPtr<Protocol::Runtime::RemoteObject> InjectedScript::wrapObject(JSC::JSValue
auto callResult = callFunctionWithEvalEnabled(wrapFunction);
if (!callResult)
return nullptr;
+ auto callResultValue = callResult.value();
+ // callResultValue could be missing if the execution was terminated
+ if (!callResultValue)
+ return nullptr;
auto resultValue = toInspectorValue(globalObject(), callResult.value());
if (!resultValue)
diff --git a/Source/JavaScriptCore/inspector/InjectedScriptSource.js b/Source/JavaScriptCore/inspector/InjectedScriptSource.js
index 48baed6a1b7ffad453379a2f1eb71b8c4925f6c4..aadd4ae30513a87f36355fa4ffcb6ba7b15dd4fc 100644
--- a/Source/JavaScriptCore/inspector/InjectedScriptSource.js
+++ b/Source/JavaScriptCore/inspector/InjectedScriptSource.js
@@ -136,7 +136,7 @@ let InjectedScript = class InjectedScript
return;
}
- if (!(promiseObject instanceof Promise)) {
+ if (InjectedScriptHost.internalConstructorName(promiseObject) !== 'Promise') {
callback("Object with given id is not a Promise");
return;
}
diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
index 033a1b4713352777ee0de5ed53e64f8391f9d74f..fc356dec4b1518547a4217def6a7b5f1d97330fb 100644
--- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
+++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
@@ -101,7 +101,7 @@ void BackendDispatcher::registerDispatcherForDomain(const String& domain, Supple
m_dispatchers.set(domain, dispatcher);
}
-void BackendDispatcher::dispatch(const String& message)
+void BackendDispatcher::dispatch(const String& message, Interceptor&& interceptor)
{
Ref<BackendDispatcher> protect(*this);
@@ -146,6 +146,9 @@ void BackendDispatcher::dispatch(const String& message)
requestId = *requestIdInt;
}
+ if (interceptor && interceptor(messageObject) == InterceptionResult::Intercepted)
+ return;
+
{
// We could be called re-entrantly from a nested run loop, so restore the previous id.
SetForScope<Optional<long>> scopedRequestId(m_currentRequestId, requestId);
diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
index 8a5efb316e9d09337ada2323dc6f926056a9c2f9..f3dcc8fcc087f474abc88cea837d11ff3e5faeff 100644
--- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
+++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
@@ -84,7 +84,10 @@ public:
};
void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*);
- void dispatch(const String& message);
+
+ enum class InterceptionResult { Intercepted, Continue };
+ using Interceptor = WTF::Function<InterceptionResult(const RefPtr<JSON::Object>&)>;
+ void dispatch(const String& message, Interceptor&& interceptor = Interceptor());
// Note that 'unused' is a workaround so the compiler can pick the right sendResponse based on arity.
// When <http://webkit.org/b/179847> is fixed or this class is renamed for the JSON::Object case,
diff --git a/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp b/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp
index d408d364f1986983161f9d44efbc8bc6f6898676..1375ce9990f0c63d7e6f33ee62930051d6cd44cb 100644
--- a/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp
+++ b/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp
@@ -49,7 +49,7 @@ void FrontendRouter::connectFrontend(FrontendChannel& connection)
void FrontendRouter::disconnectFrontend(FrontendChannel& connection)
{
if (!m_connections.contains(&connection)) {
- ASSERT_NOT_REACHED();
+ ASSERT(m_connections.isEmpty());
return;
}
diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.cpp b/Source/JavaScriptCore/inspector/InspectorTarget.cpp
index 0cc2127c9c12c2d82dea9550bad73f4ffb99ba24..8ca65cc042d435cbc0e05dcc5c5dfc958eb24f5a 100644
--- a/Source/JavaScriptCore/inspector/InspectorTarget.cpp
+++ b/Source/JavaScriptCore/inspector/InspectorTarget.cpp
@@ -44,6 +44,8 @@ void InspectorTarget::resume()
ASSERT(m_isPaused);
m_isPaused = false;
+ willResume();
+
if (m_resumeCallback) {
m_resumeCallback();
m_resumeCallback = nullptr;
@@ -52,7 +54,6 @@ void InspectorTarget::resume()
void InspectorTarget::setResumeCallback(WTF::Function<void()>&& callback)
{
- ASSERT(!m_resumeCallback);
m_resumeCallback = WTFMove(callback);
}
diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.h b/Source/JavaScriptCore/inspector/InspectorTarget.h
index 4b95964db4d902b4b7f4b0b4c40afea51654ff2f..966a5927702b65edb343369decafda7fc83eaec7 100644
--- a/Source/JavaScriptCore/inspector/InspectorTarget.h
+++ b/Source/JavaScriptCore/inspector/InspectorTarget.h
@@ -56,8 +56,12 @@ public:
virtual void connect(FrontendChannel::ConnectionType) = 0;
virtual void disconnect() = 0;
virtual void sendMessageToTargetBackend(const String&) = 0;
+ virtual void activate(String& error) { error = "Target cannot be activated"; }
+ virtual void close(String& error, bool /* runBeforeUnload */) { error = "Target cannot be closed"; }
private:
+ virtual void willResume() { }
+
WTF::Function<void()> m_resumeCallback;
bool m_isPaused { false };
};
diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
index 508eb02ec95c52408384a1e2b77648afd426dd9d..05f483dced4b62ffdd60b0a0447504802e1f5711 100644
--- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
+++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
@@ -87,6 +87,34 @@ Protocol::ErrorStringOr<void> InspectorTargetAgent::sendMessageToTarget(const St
return { };
}
+Protocol::ErrorStringOr<void> InspectorTargetAgent::activate(const String& targetId)
+{
+ InspectorTarget* target = m_targets.get(targetId);
+ if (!target)
+ return makeUnexpected("Missing target for given targetId"_s);
+
+ String errorString;
+ target->activate(errorString);
+ if (!errorString.isEmpty())
+ return makeUnexpected(errorString);
+
+ return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorTargetAgent::close(const String& targetId, Optional<bool>&& runBeforeUnload)
+{
+ InspectorTarget* target = m_targets.get(targetId);
+ if (!target)
+ return makeUnexpected("Missing target for given targetId"_s);
+
+ String errorString;
+ target->close(errorString, runBeforeUnload && *runBeforeUnload);
+ if (!errorString.isEmpty())
+ return makeUnexpected(errorString);
+
+ return { };
+}
+
void InspectorTargetAgent::sendMessageFromTargetToFrontend(const String& targetId, const String& message)
{
ASSERT_WITH_MESSAGE(m_targets.get(targetId), "Sending a message from an untracked target to the frontend.");
@@ -144,7 +172,17 @@ void InspectorTargetAgent::targetDestroyed(InspectorTarget& target)
if (!m_isConnected)
return;
- m_frontendDispatcher->targetDestroyed(target.identifier());
+ m_frontendDispatcher->targetDestroyed(target.identifier(), false);
+}
+
+void InspectorTargetAgent::targetCrashed(InspectorTarget& target)
+{
+ m_targets.remove(target.identifier());
+
+ if (!m_isConnected)
+ return;
+
+ m_frontendDispatcher->targetDestroyed(target.identifier(), true);
}
void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID)
@@ -159,6 +197,18 @@ void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID,
m_frontendDispatcher->didCommitProvisionalTarget(oldTargetID, committedTargetID);
}
+void InspectorTargetAgent::ensureConnected(const String& targetID)
+{
+ if (!m_isConnected)
+ return;
+
+ auto* target = m_targets.get(targetID);
+ if (!target)
+ return;
+
+ target->connect(connectionType());
+}
+
FrontendChannel::ConnectionType InspectorTargetAgent::connectionType() const
{
return m_router.hasLocalFrontend() ? Inspector::FrontendChannel::ConnectionType::Local : Inspector::FrontendChannel::ConnectionType::Remote;
diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h
index edcd489b76e080827e0741f14bab09f9ea9303d4..25a20c38575604ca1702a23ccf55c2024a07d993 100644
--- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h
+++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h
@@ -43,22 +43,28 @@ public:
~InspectorTargetAgent();
// InspectorAgentBase
- void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*);
- void willDestroyFrontendAndBackend(DisconnectReason);
+ void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(DisconnectReason) override;
// TargetBackendDispatcherHandler
- Protocol::ErrorStringOr<void> setPauseOnStart(bool);
- Protocol::ErrorStringOr<void> resume(const String& targetId);
- Protocol::ErrorStringOr<void> sendMessageToTarget(const String& targetId, const String& message);
+ Protocol::ErrorStringOr<void> setPauseOnStart(bool) override;
+ Protocol::ErrorStringOr<void> resume(const String& targetId) override;
+ Protocol::ErrorStringOr<void> sendMessageToTarget(const String& targetId, const String& message) override;
+ Protocol::ErrorStringOr<void> activate(const String& targetId) override;
+ Protocol::ErrorStringOr<void> close(const String& targetId, Optional<bool>&& runBeforeUnload) override;
// Target lifecycle.
void targetCreated(InspectorTarget&);
void targetDestroyed(InspectorTarget&);
+ void targetCrashed(InspectorTarget&);
void didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID);
+ void ensureConnected(const String& targetID);
// Target messages.
void sendMessageFromTargetToFrontend(const String& targetId, const String& message);
+ bool isConnected() { return m_isConnected; }
+
private:
// FrontendChannel
FrontendChannel::ConnectionType connectionType() const;
diff --git a/Source/JavaScriptCore/inspector/protocol/DOM.json b/Source/JavaScriptCore/inspector/protocol/DOM.json
index 998bc4afe68ec70502a009b7bf5ed1de9758ab31..e50d833cee34a9d0a8349b193ced87dc10d93381 100644
--- a/Source/JavaScriptCore/inspector/protocol/DOM.json
+++ b/Source/JavaScriptCore/inspector/protocol/DOM.json
@@ -79,6 +79,16 @@
{ "name": "value", "type": "string", "description": "The value that is resolved to with this data binding relationship." }
]
},
+ {
+ "id": "Rect",
+ "type": "object",
+ "properties": [
+ { "name": "x", "type": "integer", "description": "X coordinate" },
+ { "name": "y", "type": "integer", "description": "Y coordinate" },
+ { "name": "width", "type": "integer", "description": "Rectangle width" },
+ { "name": "height", "type": "integer", "description": "Rectangle height" }
+ ]
+ },
{
"id": "EventListener",
"type": "object",
@@ -167,6 +177,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": [
@@ -509,7 +529,9 @@
"description": "Resolves JavaScript node object for given node id.",
"targetTypes": ["page"],
"parameters": [
- { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to resolve." },
+ { "name": "nodeId", "$ref": "NodeId", "optional": true, "description": "Id of the node to resolve." },
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "Source element handle." },
+ { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Specifies in which execution context to adopt to." },
{ "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }
],
"returns": [
@@ -576,6 +598,45 @@
"parameters": [
{ "name": "allow", "type": "boolean" }
]
+ },
+ {
+ "name": "describeNode",
+ "description": "Returns node description.",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." }
+ ],
+ "returns": [
+ { "name": "contentFrameId", "$ref": "Network.FrameId", "optional": true, "description": "Frame ID for frame owner elements." },
+ { "name": "ownerFrameId", "$ref": "Network.FrameId", "optional": true, "description": "ID of the owning frame element." }
+ ]
+ },
+ {
+ "name": "scrollIntoViewIfNeeded",
+ "description": "Scrolls the given rect into view if not already in the viewport.",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." },
+ { "name": "rect", "$ref": "Rect", "optional": true, "description": "Rect relative to the node's border box, in CSS pixels." }
+ ]
+ },
+ {
+ "name": "getContentQuads",
+ "description": "Returns quads that describe node position on the page. This method\nmight return multiple quads for inline nodes.",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." }
+ ],
+ "returns": [
+ {
+ "name": "quads", "type": "array", "items": { "$ref": "Quad" }, "description": "Quads that describe node layout relative to viewport."
+ }
+ ]
+ },
+ {
+ "name": "setInputFiles",
+ "description": "Sets input files for given <input type=file>",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Input element handle." },
+ { "name": "files", "type": "array", "items": { "$ref": "FilePayload" }, "description": "Files to set" }
+ ]
}
],
"events": [
diff --git a/Source/JavaScriptCore/inspector/protocol/Dialog.json b/Source/JavaScriptCore/inspector/protocol/Dialog.json
new file mode 100644
index 0000000000000000000000000000000000000000..79edea03fed4e9be5da96e1275e182a479cb7a0a
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Dialog.json
@@ -0,0 +1,36 @@
+{
+ "domain": "Dialog",
+ "description": "Actions and events related to alert boxes.",
+ "availability": ["web"],
+ "types": [
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables dialog domain notifications."
+ },
+ {
+ "name": "disable",
+ "description": "Disables dialog domain notifications."
+ },
+ {
+ "name": "handleJavaScriptDialog",
+ "description": "Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).",
+ "parameters": [
+ { "name": "accept", "type": "boolean", "description": "Whether to accept or dismiss the dialog."},
+ { "name": "promptText", "optional": true, "type": "string", "description": "The text to enter into the dialog prompt before accepting. Used only if this is a prompt dialog."}
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "javascriptDialogOpening",
+ "description": "Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) is about to open.",
+ "parameters": [
+ { "name": "type", "type": "string", "description": "Dialog type."},
+ { "name": "message", "type": "string", "description": "Message that will be displayed by the dialog."},
+ { "name": "defaultPrompt", "optional": true, "type": "string", "description": "Default dialog prompt."}
+ ]
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/Emulation.json b/Source/JavaScriptCore/inspector/protocol/Emulation.json
new file mode 100644
index 0000000000000000000000000000000000000000..3f28f8e41b39c517369c8ca69415486a75657489
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Emulation.json
@@ -0,0 +1,51 @@
+{
+ "domain": "Emulation",
+ "availability": ["web"],
+ "commands": [
+ {
+ "name": "setDeviceMetricsOverride",
+ "description": "Overrides device metrics with provided values.",
+ "async": true,
+ "parameters": [
+ { "name": "width", "type": "integer" },
+ { "name": "height", "type": "integer" },
+ { "name": "deviceScaleFactor", "type": "number" },
+ { "name": "fixedLayout", "type": "boolean" }
+ ]
+ },
+ {
+ "name": "setJavaScriptEnabled",
+ "description": "Allows to disable script execution for the page.",
+ "parameters": [
+ { "name": "enabled", "type": "boolean" }
+ ]
+ },
+ {
+ "name": "setAuthCredentials",
+ "description": "Credentials to use during HTTP authentication.",
+ "parameters": [
+ { "name": "username", "type": "string", "optional": true },
+ { "name": "password", "type": "string", "optional": true }
+ ]
+ },
+ {
+ "name": "setActiveAndFocused",
+ "description": "Makes page focused for test.",
+ "parameters": [
+ { "name": "active", "type": "boolean", "optional": true }
+ ]
+ },
+ {
+ "name": "grantPermissions",
+ "parameters": [
+ { "name": "origin", "type": "string" },
+ { "name": "permissions", "type": "array", "items": { "type": "string" } }
+ ],
+ "description": "Overrides the permissions."
+ },
+ {
+ "name": "resetPermissions",
+ "description": "Clears permission overrides."
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/Input.json b/Source/JavaScriptCore/inspector/protocol/Input.json
new file mode 100644
index 0000000000000000000000000000000000000000..587287d52fde2735cbae34a27a0f673b7e38e1a7
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Input.json
@@ -0,0 +1,188 @@
+{
+ "domain": "Input",
+ "availability": ["web"],
+ "types": [
+ {
+ "id": "TimeSinceEpoch",
+ "description": "UTC time in seconds, counted from January 1, 1970.",
+ "type": "number"
+ }
+ ],
+ "commands": [
+ {
+ "name": "dispatchKeyEvent",
+ "description": "Dispatches a key event to the page.",
+ "async": true,
+ "parameters": [
+ {
+ "name": "type",
+ "description": "Type of the key event.",
+ "type": "string",
+ "enum": [
+ "keyDown",
+ "keyUp"
+ ]
+ },
+ {
+ "name": "modifiers",
+ "description": "Bit field representing pressed modifier keys. (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "text",
+ "description": "Text as generated by processing a virtual key code with a keyboard layout. Not needed for\nfor `keyUp` and `rawKeyDown` events (default: \"\")",
+ "optional": true,
+ "type": "string"
+ },
+ {
+ "name": "unmodifiedText",
+ "description": "Text that would have been generated by the keyboard if no modifiers were pressed (except for\nshift). Useful for shortcut (accelerator) key handling (default: \"\").",
+ "optional": true,
+ "type": "string"
+ },
+ {
+ "name": "code",
+ "description": "Unique DOM defined string value for each physical key (e.g., 'KeyA') (default: \"\").",
+ "optional": true,
+ "type": "string"
+ },
+ {
+ "name": "key",
+ "description": "Unique DOM defined string value describing the meaning of the key in the context of active\nmodifiers, keyboard layout, etc (e.g., 'AltGr') (default: \"\").",
+ "optional": true,
+ "type": "string"
+ },
+ {
+ "name": "windowsVirtualKeyCode",
+ "description": "Windows virtual key code (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "nativeVirtualKeyCode",
+ "description": "Native virtual key code (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "autoRepeat",
+ "description": "Whether the event was generated from auto repeat (default: false).",
+ "optional": true,
+ "type": "boolean"
+ },
+ {
+ "name": "isKeypad",
+ "description": "Whether the event was generated from the keypad (default: false).",
+ "optional": true,
+ "type": "boolean"
+ },
+ {
+ "name": "isSystemKey",
+ "description": "Whether the event was a system key event (default: false).",
+ "optional": true,
+ "type": "boolean"
+ },
+ {
+ "name": "macCommands",
+ "description": "Mac editing commands associated with this key",
+ "type": "array",
+ "optional": true,
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ {
+ "name": "dispatchMouseEvent",
+ "description": "Dispatches a mouse event to the page.",
+ "async": true,
+ "parameters": [
+ {
+ "name": "type",
+ "description": "Type of the mouse event.",
+ "type": "string",
+ "enum": [ "move", "down", "up", "wheel"]
+ },
+ {
+ "name": "x",
+ "description": "X coordinate of the event relative to the main frame's viewport in CSS pixels.",
+ "type": "integer"
+ },
+ {
+ "name": "y",
+ "description": "Y coordinate of the event relative to the main frame's viewport in CSS pixels. 0 refers to\nthe top of the viewport and Y increases as it proceeds towards the bottom of the viewport.",
+ "type": "integer"
+ },
+ {
+ "name": "modifiers",
+ "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8\n(default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "button",
+ "description": "Mouse button (default: \"none\").",
+ "optional": true,
+ "type": "string",
+ "enum": [
+ "none",
+ "left",
+ "middle",
+ "right",
+ "back",
+ "forward"
+ ]
+ },
+ {
+ "name": "buttons",
+ "description": "A number indicating which buttons are pressed on the mouse when a mouse event is triggered.\nLeft=1, Right=2, Middle=4, Back=8, Forward=16, None=0.",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "clickCount",
+ "description": "Number of times the mouse button was clicked (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "deltaX",
+ "description": "X delta in CSS pixels for mouse wheel event (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "deltaY",
+ "description": "Y delta in CSS pixels for mouse wheel event (default: 0).",
+ "optional": true,
+ "type": "integer"
+ }
+ ]
+ },
+ {
+ "name": "dispatchTapEvent",
+ "description": "Dispatches a tap event to the page.",
+ "async": true,
+ "parameters": [
+ {
+ "name": "x",
+ "description": "X coordinate of the event relative to the main frame's viewport in CSS pixels.",
+ "type": "integer"
+ },
+ {
+ "name": "y",
+ "description": "Y coordinate of the event relative to the main frame's viewport in CSS pixels. 0 refers to\nthe top of the viewport and Y increases as it proceeds towards the bottom of the viewport.",
+ "type": "integer"
+ },
+ {
+ "name": "modifiers",
+ "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8\n(default: 0).",
+ "optional": true,
+ "type": "integer"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/Network.json b/Source/JavaScriptCore/inspector/protocol/Network.json
index 65ab2092b0ffd0ead3da1ddccd398d4f4179f51a..2d9ef40a20df819193c9a5867fbf6f8f8bf46b48 100644
--- a/Source/JavaScriptCore/inspector/protocol/Network.json
+++ b/Source/JavaScriptCore/inspector/protocol/Network.json
@@ -321,6 +321,13 @@
{ "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network request to fail." },
{ "name": "errorType", "$ref": "ResourceErrorType", "description": "Deliver error reason for the request failure." }
]
+ },
+ {
+ "name": "setEmulateOfflineState",
+ "description": "Emulate offline state overriding the actual state.",
+ "parameters": [
+ { "name": "offline", "type": "boolean", "description": "True to emulate offline." }
+ ]
}
],
"events": [
diff --git a/Source/JavaScriptCore/inspector/protocol/Page.json b/Source/JavaScriptCore/inspector/protocol/Page.json
index 8252792649549f708a9e88f8c64506e34839de15..ca26340290bcdf0fa2eef5920e9e3158204b4ccb 100644
--- a/Source/JavaScriptCore/inspector/protocol/Page.json
+++ b/Source/JavaScriptCore/inspector/protocol/Page.json
@@ -27,7 +27,7 @@
{
"id": "ResourceType",
"type": "string",
- "enum": ["Document", "StyleSheet", "Image", "Font", "Script", "XHR", "Fetch", "Ping", "Beacon", "WebSocket", "Other"],
+ "enum": ["Document", "StyleSheet", "Image", "Font", "Script", "XHR", "Fetch", "Ping", "Beacon", "WebSocket", "EventSource", "Other"],
"description": "Resource type as it was perceived by the rendering engine."
},
{
@@ -112,6 +112,41 @@
{ "name": "secure", "type": "boolean", "description": "True if cookie is secure." },
{ "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." }
]
+ },
+ {
+ "id": "AXNode",
+ "type": "object",
+ "description": "Accessibility Node",
+ "properties": [
+ { "name": "role", "type": "string", "description": "The role."},
+ { "name": "name", "type": "string","optional": true, "description": "A human readable name for the node."},
+ { "name": "value", "type": "any", "optional": true, "description": "The current value of the node."},
+ { "name": "description", "type": "string", "optional": true, "description": "An additional human readable description of the node."},
+ { "name": "keyshortcuts", "type": "string", "optional": true, "description": "Keyboard shortcuts associated with this node."},
+ { "name": "roledescription", "type": "string", "optional": true, "description": "A human readable alternative to the role."},
+ { "name": "valuetext", "type": "string", "optional": true, "description": "A description of the current value."},
+ { "name": "disabled", "type": "boolean", "optional": true, "description": "Whether the node is disabled."},
+ { "name": "expanded", "type": "boolean", "optional": true, "description": "Whether the node is expanded or collapsed."},
+ { "name": "focused", "type": "boolean", "optional": true, "description": "Whether the node is focused."},
+ { "name": "modal", "type": "boolean", "optional": true, "description": "Whether the node is modal."},
+ { "name": "multiline", "type": "boolean", "optional": true, "description": "Whether the node text input supports multiline."},
+ { "name": "multiselectable", "type": "boolean", "optional": true, "description": "Whether more than one child can be selected."},
+ { "name": "readonly", "type": "boolean", "optional": true, "description": "Whether the node is read only."},
+ { "name": "required", "type": "boolean", "optional": true, "description": "Whether the node is required."},
+ { "name": "selected", "type": "boolean", "optional": true, "description": "Whether the node is selected in its parent node."},
+ { "name": "checked", "type": "string", "optional": true, "enum": ["true", "false", "mixed"], "description": "Whether the checkbox is checked, or \"mixed\"."},
+ { "name": "pressed", "type": "string", "optional": true, "enum": ["true", "false", "mixed"], "description": "Whether the toggle button is checked, or \"mixed\"."},
+ { "name": "level", "type": "integer", "optional": true, "description": "The level of a heading."},
+ { "name": "valuemin", "type": "number", "optional": true, "description": "The minimum value in a node."},
+ { "name": "valuemax", "type": "number", "optional": true, "description": "The maximum value in a node."},
+ { "name": "autocomplete", "type": "string", "optional": true, "description": "What kind of autocomplete is supported by a control."},
+ { "name": "haspopup", "type": "string", "optional": true, "description": "What kind of popup is currently being shown for a node."},
+ { "name": "invalid", "type": "string", "optional": true, "enum": ["true", "false", "grammar", "spelling"], "description": "Whether and in what way this node's value is invalid."},
+ { "name": "orientation", "type": "string", "optional": true, "description": "Whether the node is oriented horizontally or vertically."},
+ { "name": "focusable", "type": "boolean", "optional": true, "description": "Whether the node is focusable."},
+ { "name": "children", "type": "array", "optional": true, "items": { "$ref": "AXNode"}, "description": "Child AXNodes of this node, if any."},
+ { "name": "found", "type": "boolean", "optional": true, "description": "True if this AXNode corresponds with the ObjectId passed into acessibilitySnapshot."}
+ ]
}
],
"commands": [
@@ -131,6 +166,14 @@
{ "name": "revalidateAllResources", "type": "boolean", "optional": true, "description": "If true, all cached subresources will be revalidated when the main resource loads. Otherwise, only expired cached subresources will be revalidated (the default behavior for most WebKit clients)." }
]
},
+ {
+ "name": "goBack",
+ "description": "Goes back in the history."
+ },
+ {
+ "name": "goForward",
+ "description": "Goes forward in the history."
+ },
{
"name": "navigate",
"description": "Navigates current page to the given URL.",
@@ -270,6 +313,20 @@
{ "name": "appearance", "$ref": "Appearance", "optional": true }
]
},
+ {
+ "name": "setTimeZone",
+ "description": "Enables time zone emulation.",
+ "parameters": [
+ { "name": "timeZone", "type": "string", "optional": true }
+ ]
+ },
+ {
+ "name": "setTouchEmulationEnabled",
+ "description": "Enables touch events on platforms that lack them.",
+ "parameters": [
+ {"name": "enabled", "type": "boolean", "description": "Whether touch should be enabled."}
+ ]
+ },
{
"name": "snapshotNode",
"description": "Capture a snapshot of the specified node that does not include unrelated layers.",
@@ -308,12 +365,67 @@
{
"name": "setScreenSizeOverride",
"description": "Overrides screen size exposed to DOM and used in media queries for testing with provided values.",
- "condition": "!(defined(WTF_PLATFORM_COCOA) && WTF_PLATFORM_COCOA)",
"targetTypes": ["page"],
"parameters": [
{ "name": "width", "type": "integer", "description": "Screen width", "optional": true },
{ "name": "height", "type": "integer", "description": "Screen height", "optional": true }
]
+ },
+ {
+ "name": "insertText",
+ "description": "Insert text into the current selection of the page.",
+ "parameters": [
+ { "name": "text", "type": "string", "description": "Text to insert." }
+ ]
+ },
+ {
+ "name": "accessibilitySnapshot",
+ "description": "Serializes and returns all of the accessibility nodes of the page.",
+ "parameters": [
+ { "name": "objectId", "type": "string", "optional": true, "description": "Object Id of a node to find in the accessibility tree."}
+ ],
+ "returns": [
+ { "name": "axNode", "$ref": "AXNode", "description": "The root AXNode."}
+ ]
+ },
+ {
+ "name": "setInterceptFileChooserDialog",
+ "description": "Intercepts file chooser dialog",
+ "parameters": [
+ { "name": "enabled", "type": "boolean", "description": "True to enable." }
+ ]
+ },
+ {
+ "name": "setDefaultBackgroundColorOverride",
+ "description": "Sets or clears an override of the default background color of the frame. This override is used if the content does not specify one.",
+ "parameters": [
+ { "name": "color", "$ref": "DOM.RGBAColor", "optional": true, "description": "RGBA of the default background color. If not specified, any existing override will be cleared." }
+ ]
+ },
+ {
+ "name": "createUserWorld",
+ "description": "Creates an user world for every loaded frame.",
+ "parameters": [
+ { "name": "name", "type": "string", "description": "Isolated world name, will be used as an execution context name." }
+ ]
+ },
+ {
+ "name": "setBypassCSP",
+ "description": "Enable page Content Security Policy by-passing.",
+ "parameters": [
+ { "name": "enabled", "type": "boolean", "description": "Whether to bypass page CSP." }
+ ]
+ },
+ {
+ "name": "crash",
+ "description": "Crashes the page process"
+ },
+ {
+ "name": "setOrientationOverride",
+ "description": "Overrides window.orientation with provided value.",
+ "parameters": [
+ { "name": "angle", "type": "integer", "optional": true }
+ ]
}
],
"events": [
@@ -321,14 +433,16 @@
"name": "domContentEventFired",
"targetTypes": ["page"],
"parameters": [
- { "name": "timestamp", "type": "number" }
+ { "name": "timestamp", "type": "number" },
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired DOMContentLoaded event." }
]
},
{
"name": "loadEventFired",
"targetTypes": ["page"],
"parameters": [
- { "name": "timestamp", "type": "number" }
+ { "name": "timestamp", "type": "number" },
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired load event." }
]
},
{
@@ -338,6 +452,14 @@
{ "name": "frame", "$ref": "Frame", "description": "Frame object." }
]
},
+ {
+ "name": "frameAttached",
+ "description": "Fired when frame has been attached to its parent.",
+ "parameters": [
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has been detached." },
+ { "name": "parentFrameId", "$ref": "Network.FrameId", "optional": true, "description": "Parent frame id if non-root." }
+ ]
+ },
{
"name": "frameDetached",
"description": "Fired when frame has been detached from its parent.",
@@ -377,6 +499,22 @@
{ "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has cleared its scheduled navigation." }
]
},
+ {
+ "name": "navigatedWithinDocument",
+ "description": "Fired when same-document navigation happens, e.g. due to history API usage or anchor navigation.",
+ "parameters": [
+ {
+ "name": "frameId",
+ "description": "Id of the frame.",
+ "$ref": "Network.FrameId"
+ },
+ {
+ "name": "url",
+ "description": "Frame's new url.",
+ "type": "string"
+ }
+ ]
+ },
{
"name": "defaultAppearanceDidChange",
"description": "Fired when page's default appearance changes, even if there is a forced appearance.",
@@ -385,6 +523,28 @@
"parameters": [
{ "name": "appearance", "$ref": "Appearance", "description": "Name of the appearance that is active (not considering any forced appearance.)" }
]
+ },
+ {
+ "name": "willRequestOpenWindow",
+ "description": "Fired when page tries to open a new window.",
+ "parameters": [
+ { "name": "url", "type": "string" }
+ ]
+ },
+ {
+ "name": "didRequestOpenWindow",
+ "description": "Fired after page did try to open a new window.",
+ "parameters": [
+ { "name": "opened", "type": "boolean" }
+ ]
+ },
+ {
+ "name": "fileChooserOpened",
+ "description": "Fired when the page shows file chooser for it's <input type=file>.",
+ "parameters": [
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Frame where file chooser is opened." },
+ { "name": "element", "$ref": "Runtime.RemoteObject", "description": "Input element." }
+ ]
}
]
}
diff --git a/Source/JavaScriptCore/inspector/protocol/Playwright.json b/Source/JavaScriptCore/inspector/protocol/Playwright.json
new file mode 100644
index 0000000000000000000000000000000000000000..ce69bc6a10b49460c73110e54b2936afe5dd4ebf
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Playwright.json
@@ -0,0 +1,244 @@
+{
+ "domain": "Playwright",
+ "availability": ["web"],
+ "types": [
+ {
+ "id": "ContextID",
+ "type": "string",
+ "description": "Id of Browser context."
+ },
+ {
+ "id": "PageProxyID",
+ "type": "string",
+ "description": "Id of WebPageProxy."
+ },
+ {
+ "id": "CookieSameSitePolicy",
+ "type": "string",
+ "enum": ["None", "Lax", "Strict"],
+ "description": "Same-Site policy of a cookie."
+ },
+ {
+ "id": "Cookie",
+ "type": "object",
+ "description": "Cookie object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Cookie name." },
+ { "name": "value", "type": "string", "description": "Cookie value." },
+ { "name": "domain", "type": "string", "description": "Cookie domain." },
+ { "name": "path", "type": "string", "description": "Cookie path." },
+ { "name": "expires", "type": "number", "description": "Cookie expires." },
+ { "name": "httpOnly", "type": "boolean", "description": "True if cookie is http-only." },
+ { "name": "secure", "type": "boolean", "description": "True if cookie is secure." },
+ { "name": "session", "type": "boolean", "description": "True if cookie is session cookie." },
+ { "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." }
+ ]
+ },
+ {
+ "id": "SetCookieParam",
+ "type": "object",
+ "description": "Cookie object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Cookie name." },
+ { "name": "value", "type": "string", "description": "Cookie value." },
+ { "name": "domain", "type": "string", "description": "Cookie domain." },
+ { "name": "path", "type": "string", "description": "Cookie path." },
+ { "name": "expires", "type": "number", "optional": true, "description": "Cookie expires." },
+ { "name": "httpOnly", "type": "boolean", "optional": true, "description": "True if cookie is http-only." },
+ { "name": "secure", "type": "boolean", "optional": true, "description": "True if cookie is secure." },
+ { "name": "session", "type": "boolean", "optional": true, "description": "True if cookie is session cookie." },
+ { "name": "sameSite", "$ref": "CookieSameSitePolicy", "optional": true, "description": "Cookie Same-Site policy." }
+ ]
+ },
+ {
+ "id": "Geolocation",
+ "type": "object",
+ "description": "Geolocation",
+ "properties": [
+ { "name": "timestamp", "type": "number", "description": "Mock latitude" },
+ { "name": "latitude", "type": "number", "description": "Mock latitude" },
+ { "name": "longitude", "type": "number", "description": "Mock longitude" },
+ { "name": "accuracy", "type": "number", "description": "Mock accuracy" }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable"
+ },
+ {
+ "name": "disable"
+ },
+ {
+ "name": "close",
+ "async": true,
+ "description": "Close browser."
+ },
+ {
+ "name": "createContext",
+ "description": "Creates new ephemeral browser context.",
+ "parameters": [
+ { "name": "proxyServer", "type": "string", "optional": true, "description": "Proxy server, similar to the one passed to --proxy-server" },
+ { "name": "proxyBypassList", "type": "string", "optional": true, "description": "Proxy bypass list, similar to the one passed to --proxy-bypass-list" }
+ ],
+ "returns": [
+ { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." }
+ ]
+ },
+ {
+ "name": "deleteContext",
+ "async": true,
+ "description": "Deletes browser context previously created with createContect. The command will automatically close all pages that use the context.",
+ "parameters": [
+ { "name": "browserContextId", "$ref": "ContextID", "description": "Identifier of the context to delete." }
+ ]
+ },
+ {
+ "name": "createPage",
+ "parameters": [
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "JSON Inspector Protocol message (command) to be dispatched on the backend." }
+ ],
+ "returns": [
+ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." }
+ ]
+ },
+ {
+ "name": "navigate",
+ "async": true,
+ "description": "Navigates current page to the given URL.",
+ "parameters": [
+ { "name": "url", "type": "string", "description": "URL to navigate the page to." },
+ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." },
+ { "name": "frameId", "$ref": "Network.FrameId", "optional": true, "description": "Id of the frame to navigate."},
+ { "name": "referrer", "type": "string", "optional": true, "description": "Referrer URL." }
+ ],
+ "returns": [
+ { "name": "loaderId", "$ref": "Network.LoaderId", "optional": true, "description": "Identifier of the loader associated with the navigation." }
+ ]
+ },
+ {
+ "name": "setIgnoreCertificateErrors",
+ "description": "Change whether all certificate errors should be ignored.",
+ "parameters": [
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." },
+ { "name": "ignore", "type": "boolean" }
+ ]
+ },
+ {
+ "name": "getAllCookies",
+ "description": "Returns all cookies in the given browser context.",
+ "async": true,
+ "parameters": [
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
+ ],
+ "returns": [
+ { "name": "cookies", "type": "array", "items": { "$ref": "Cookie" }, "description": "Cookies." }
+ ]
+ },
+ {
+ "name": "setCookies",
+ "description": "Sets cookies in the given browser context.",
+ "async": true,
+ "parameters": [
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." },
+ { "name": "cookies", "type": "array", "items": { "$ref": "SetCookieParam" }, "description": "Cookies." }
+ ]
+ },
+ {
+ "name": "deleteAllCookies",
+ "description": "Deletes cookies in the given browser context.",
+ "async": true,
+ "parameters": [
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
+ ]
+ },
+ {
+ "name": "setGeolocationOverride",
+ "parameters": [
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." },
+ { "name": "geolocation", "$ref": "Geolocation", "optional": true, "description": "Geolocation to set, if missing emulates position unavailable." }
+ ],
+ "description": "Overrides the geolocation position or error."
+ },
+ {
+ "name": "setLanguages",
+ "description": "Allows to set locale language for context.",
+ "parameters": [
+ { "name": "languages", "type": "array", "items": { "type": "string" } },
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
+ ]
+ },
+ {
+ "name": "setDownloadBehavior",
+ "description": "Allows to override download behavior.",
+ "parameters": [
+ { "name": "behavior", "optional": true, "type": "string", "enum": ["allow", "deny"] },
+ { "name": "downloadPath", "optional": true, "type": "string" },
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "pageProxyCreated",
+ "parameters": [
+ { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." },
+ { "name": "pageProxyId", "$ref": "PageProxyID" },
+ { "name": "openerId", "$ref": "PageProxyID", "optional": true, "description": "Unique identifier of the opening page. Only set for pages created by window.open()." }
+ ]
+ },
+ {
+ "name": "pageProxyDestroyed",
+ "parameters": [
+ { "name": "pageProxyId", "$ref": "PageProxyID" }
+ ]
+ },
+ {
+ "name": "provisionalLoadFailed",
+ "description": "Fired when provisional load fails.",
+ "parameters": [
+ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." },
+ { "name": "loaderId", "$ref": "Network.LoaderId", "description": "Identifier of the loader associated with the navigation." },
+ { "name": "error", "type": "string", "description": "Localized error string." }
+ ]
+ },
+ {
+ "name": "windowOpen",
+ "description": "Fired when page opens a new window.",
+ "parameters": [
+ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." },
+ { "name": "url", "type": "string" },
+ { "name": "windowFeatures", "type": "array", "items": { "type": "string" } }
+ ]
+ },
+ {
+ "name": "downloadCreated",
+ "parameters": [
+ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." },
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Unique identifier of the originating frame." },
+ { "name": "uuid", "type": "string" },
+ { "name": "url", "type": "string" }
+ ]
+ },
+ {
+ "name": "downloadFilenameSuggested",
+ "parameters": [
+ { "name": "uuid", "type": "string" },
+ { "name": "suggestedFilename", "type": "string" }
+ ]
+ },
+ {
+ "name": "downloadFinished",
+ "parameters": [
+ { "name": "uuid", "type": "string" },
+ { "name": "error", "type": "string" }
+ ]
+ },
+ {
+ "name": "screencastFinished",
+ "parameters": [
+ { "name": "screencastId", "$ref": "Screencast.ScreencastId", "description": "Unique identifier of the screencast." }
+ ]
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/Screencast.json b/Source/JavaScriptCore/inspector/protocol/Screencast.json
new file mode 100644
index 0000000000000000000000000000000000000000..a51b42b2a2b575927509e11dc7241ab6f203c104
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Screencast.json
@@ -0,0 +1,31 @@
+{
+ "domain": "Screencast",
+ "availability": ["web"],
+ "types": [
+ {
+ "id": "ScreencastId",
+ "type": "string",
+ "description": "Unique identifier of the screencast."
+ }
+ ],
+ "commands": [
+ {
+ "name": "start",
+ "description": "Starts recoring video to speified file.",
+ "parameters": [
+ { "name": "file", "type": "string", "description": "Output file location." },
+ { "name": "width", "type": "integer" },
+ { "name": "height", "type": "integer" },
+ { "name": "scale", "type": "number", "optional": true }
+ ],
+ "returns": [
+ { "name": "screencastId", "$ref": "ScreencastId", "description": "Unique identifier of the screencast." }
+ ]
+ },
+ {
+ "name": "stop",
+ "async": true,
+ "description": "Stops recoding video. Returns after the file has been closed."
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/Target.json b/Source/JavaScriptCore/inspector/protocol/Target.json
index 52920cded24a9c6b0ef6fb4e518664955db4f9fa..bbbabc4e7259088b9404e8cc07eecd6f45077da0 100644
--- a/Source/JavaScriptCore/inspector/protocol/Target.json
+++ b/Source/JavaScriptCore/inspector/protocol/Target.json
@@ -10,7 +10,7 @@
"properties": [
{ "name": "targetId", "type": "string", "description": "Unique identifier for the target." },
{ "name": "type", "type": "string", "enum": ["page", "service-worker", "worker"] },
- { "name": "isProvisional", "type": "boolean", "optional": true, "description": "Whether this is a provisional page target." },
+ { "name": "isProvisional", "type": "boolean", "optional": true, "description": "True value indicates that this is a provisional page target i.e. Such target may be created when current page starts cross-origin navigation. Eventually each provisional target is either committed and swaps with the current target or gets destroyed, e.g. in case of load request failure." },
{ "name": "isPaused", "type": "boolean", "optional": true, "description": "Whether the target is paused on start and has to be explicitely resumed by inspector." }
]
}
@@ -37,6 +37,21 @@
{ "name": "targetId", "type": "string" },
{ "name": "message", "type": "string", "description": "JSON Inspector Protocol message (command) to be dispatched on the backend." }
]
+ },
+ {
+ "name": "activate",
+ "description": "Reveals the target on screen.",
+ "parameters": [
+ { "name": "targetId", "type": "string" }
+ ]
+ },
+ {
+ "name": "close",
+ "description": "Closes the target.",
+ "parameters": [
+ { "name": "targetId", "type": "string" },
+ { "name": "runBeforeUnload", "type": "boolean", "optional": true }
+ ]
}
],
"events": [
@@ -49,7 +64,8 @@
{
"name": "targetDestroyed",
"parameters": [
- { "name": "targetId", "type": "string" }
+ { "name": "targetId", "type": "string" },
+ { "name": "crashed", "type": "boolean" }
]
},
{
diff --git a/Source/JavaScriptCore/inspector/protocol/Worker.json b/Source/JavaScriptCore/inspector/protocol/Worker.json
index 638612413466efc87b737e8a81042ed07ca12703..6f9e518ff0bfa2a6228675d25b6b785f1ed3022a 100644
--- a/Source/JavaScriptCore/inspector/protocol/Worker.json
+++ b/Source/JavaScriptCore/inspector/protocol/Worker.json
@@ -16,7 +16,7 @@
"description": "Sent after the frontend has sent all initialization messages and can resume this worker. This command is required to allow execution in the worker.",
"parameters": [
{ "name": "workerId", "type": "string" }
- ]
+ ]
},
{
"name": "sendMessageToWorker",
@@ -33,7 +33,8 @@
"parameters": [
{ "name": "workerId", "type": "string" },
{ "name": "url", "type": "string" },
- { "name": "name", "type": "string" }
+ { "name": "name", "type": "string" },
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame this worker belongs to." }
]
},
{
diff --git a/Source/JavaScriptCore/runtime/DateConversion.cpp b/Source/JavaScriptCore/runtime/DateConversion.cpp
index 955756ba405f400970610f9a68c7ed42a67cb015..1520c0a1475a90de2795e4ccd8919c1bb1384066 100644
--- a/Source/JavaScriptCore/runtime/DateConversion.cpp
+++ b/Source/JavaScriptCore/runtime/DateConversion.cpp
@@ -100,17 +100,23 @@ String formatDateTime(const GregorianDateTime& t, DateTimeFormat format, bool as
appendNumber<2>(builder, offset / 60);
appendNumber<2>(builder, offset % 60);
-#if OS(WINDOWS)
- TIME_ZONE_INFORMATION timeZoneInformation;
- GetTimeZoneInformation(&timeZoneInformation);
- const WCHAR* winTimeZoneName = t.isDST() ? timeZoneInformation.DaylightName : timeZoneInformation.StandardName;
- String timeZoneName(winTimeZoneName);
+ String timeZoneName;
+ if (!WTF::timeZoneDisplayNameForAutomation().isEmpty()) {
+ timeZoneName = WTF::timeZoneDisplayNameForAutomation();
+ } else {
+ #if OS(WINDOWS)
+ TIME_ZONE_INFORMATION timeZoneInformation;
+ GetTimeZoneInformation(&timeZoneInformation);
+ const WCHAR* winTimeZoneName = t.isDST() ? timeZoneInformation.DaylightName : timeZoneInformation.StandardName;
+ timeZoneName = String(winTimeZoneName);
#else
- struct tm gtm = t;
- char timeZoneName[70];
- strftime(timeZoneName, sizeof(timeZoneName), "%Z", &gtm);
+ struct tm gtm = t;
+ char tzName[70];
+ strftime(tzName, sizeof(tzName), "%Z", &gtm);
+ timeZoneName = String(tzName);
#endif
- if (timeZoneName[0]) {
+ }
+ if (!timeZoneName.isEmpty()) {
builder.appendLiteral(" (");
builder.append(timeZoneName);
builder.append(')');
diff --git a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
index f51cb02ee88d86c997a2332c5cc0d01b4641be1c..342ad6b5402afaa7883e3656d15641667ff45edd 100644
--- a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
+++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
@@ -34,6 +34,7 @@
#include "ObjectConstructor.h"
#include <unicode/ucal.h>
#include <unicode/uenum.h>
+#include <wtf/DateMath.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/unicode/icu/ICUHelpers.h>
@@ -93,6 +94,10 @@ static ALWAYS_INLINE bool isUTCEquivalent(StringView timeZone)
// https://tc39.es/ecma402/#sec-defaulttimezone
static String defaultTimeZone()
{
+ String tz = WTF::timeZoneForAutomation();
+ if (!tz.isEmpty())
+ return tz;
+
String canonical;
Vector<UChar, 32> buffer;
diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp
index 509aed3b93418c5edecbc7fcdad2b972382f692d..f8c267b01b50e0274703434b7b84098a376a667c 100644
--- a/Source/JavaScriptCore/runtime/JSDateMath.cpp
+++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp
@@ -75,6 +75,7 @@
#include "ExceptionHelpers.h"
#include "VM.h"
#include <limits>
+#include <wtf/DateMath.h>
// icu::TimeZone and icu::BasicTimeZone features are only available in ICU C++ APIs.
// We use these C++ APIs as an exception.
@@ -195,7 +196,9 @@ void DateCache::timeZoneCacheSlow()
{
// Do not use icu::TimeZone::createDefault. ICU internally has a cache for timezone and createDefault returns this cached value.
ASSERT(!m_timeZoneCache);
- m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(bitwise_cast<OpaqueICUTimeZone*>(icu::TimeZone::detectHostTimeZone()));
+ String override = WTF::timeZoneForAutomation();
+ auto* timezone = override.isEmpty() ? icu::TimeZone::detectHostTimeZone() : icu::TimeZone::createTimeZone(override.utf8().data());
+ m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(bitwise_cast<OpaqueICUTimeZone*>(timezone));
}
void DateCache::reset()
diff --git a/Source/ThirdParty/libwebrtc/CMakeLists.txt b/Source/ThirdParty/libwebrtc/CMakeLists.txt
index 5d216b16f31c0f7bd095f9e9f6e0eac0ead90d2f..61a48cd9a06dffd8e3397570c32fb1e18157f385 100644
--- a/Source/ThirdParty/libwebrtc/CMakeLists.txt
+++ b/Source/ThirdParty/libwebrtc/CMakeLists.txt
@@ -291,6 +291,11 @@ set(webrtc_SOURCES
Source/third_party/jsoncpp/source/src/lib_json/json_reader.cpp
Source/third_party/jsoncpp/source/src/lib_json/json_value.cpp
Source/third_party/jsoncpp/source/src/lib_json/json_writer.cpp
+# Playwright begin
+ Source/third_party/libwebm/mkvmuxer/mkvmuxer.cc
+ Source/third_party/libwebm/mkvmuxer/mkvmuxerutil.cc
+ Source/third_party/libwebm/mkvmuxer/mkvwriter.cc
+# Playwright end
Source/third_party/libyuv/source/compare.cc
Source/third_party/libyuv/source/compare_common.cc
Source/third_party/libyuv/source/compare_gcc.cc
@@ -1466,6 +1471,9 @@ target_include_directories(webrtc PRIVATE
Source/third_party/libsrtp/config
Source/third_party/libsrtp/crypto/include
Source/third_party/libsrtp/include
+# Playwright begin
+ Source/third_party/libwebm
+# Playwright end
Source/third_party/libyuv/include
Source/third_party/opus/src/celt
Source/third_party/opus/src/include
diff --git a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp
index 00099ab2f4beb853a8498636badbaad2856e494a..ac3cf7638035dd30c8695a7fb6a096af173276b0 100644
--- a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp
+++ b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp
@@ -328,3 +328,23 @@ __ZN10vp9_parser15Vp9HeaderParser23ParseUncompressedHeaderEPKhm
__ZN6webrtc14ParseCandidateERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEPN7cricket9CandidateEPNS_13SdpParseErrorEb
__ZN7cricket27ICE_CANDIDATE_COMPONENT_RTPE
__ZNK3rtc13SocketAddress5IsNilEv
+__ZN8mkvmuxer11SegmentInfo15set_writing_appEPKc
+__ZN8mkvmuxer11SegmentInfo4InitEv
+__ZN8mkvmuxer7Segment10OutputCuesEb
+__ZN8mkvmuxer7Segment13AddVideoTrackEiii
+__ZN8mkvmuxer7Segment4InitEPNS_10IMkvWriterE
+__ZN8mkvmuxer7Segment8AddFrameEPKhyyyb
+__ZN8mkvmuxer7Segment8FinalizeEv
+__ZN8mkvmuxer7SegmentC1Ev
+__ZN8mkvmuxer7SegmentD1Ev
+__ZN8mkvmuxer9MkvWriterC1EP7__sFILE
+_ARGBToI420
+_vpx_codec_enc_config_default
+_vpx_codec_enc_init_ver
+_vpx_codec_encode
+_vpx_codec_err_to_string
+_vpx_codec_error
+_vpx_codec_get_cx_data
+_vpx_codec_iface_name
+_vpx_codec_version_str
+_vpx_codec_vp8_cx
diff --git a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.xcconfig b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.xcconfig
index c5d73fc6a0759fc65ae9cf56531d271a27e42bee..e58a216891bc8bec31f5bf80c25989619e6c4e04 100644
--- a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.xcconfig
+++ b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.xcconfig
@@ -18,7 +18,7 @@ DYLIB_INSTALL_NAME_BASE_WK_RELOCATABLE_FRAMEWORKS_ = $(DYLIB_INSTALL_NAME_BASE);
DYLIB_INSTALL_NAME_BASE_WK_RELOCATABLE_FRAMEWORKS_YES = @loader_path/../../../;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
-HEADER_SEARCH_PATHS = Source Source/third_party/jsoncpp/source/include Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include Source/third_party/boringssl/src/include Source/third_party/libyuv/include Source/third_party/usrsctp Source/third_party/usrsctp/usrsctplib Source/third_party/usrsctp/usrsctplib/usrsctplib Source/webrtc/sdk/objc/Framework/Headers Source/webrtc/common_audio/signal_processing/include Source/webrtc/modules/audio_coding/codecs/isac/main/include Source/third_party/opus/src/celt Source/third_party/opus/src/include Source/third_party/opus/src/src Source/webrtc/modules/audio_device/mac Source/third_party/usrsctp/usrsctplib/usrsctplib/netinet Source/webrtc/modules/audio_device/ios Source/webrtc Source/webrtc/sdk/objc Source/webrtc/sdk/objc/base Source/webrtc/sdk/objc/Framework/Classes Source/third_party/libsrtp/config Source/webrtc/sdk/objc/Framework/Classes/Common Source/webrtc/sdk/objc/Framework/Classes/Video Source/webrtc/sdk/objc/Framework/Classes/PeerConnection Source/third_party/abseil-cpp Source/third_party/libvpx/source/libvpx Source/third_party/libwebm/webm_parser/include;
+HEADER_SEARCH_PATHS = Source Source/third_party/jsoncpp/source/include Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include Source/third_party/boringssl/src/include Source/third_party/libyuv/include Source/third_party/usrsctp Source/third_party/usrsctp/usrsctplib Source/third_party/usrsctp/usrsctplib/usrsctplib Source/webrtc/sdk/objc/Framework/Headers Source/webrtc/common_audio/signal_processing/include Source/webrtc/modules/audio_coding/codecs/isac/main/include Source/third_party/opus/src/celt Source/third_party/opus/src/include Source/third_party/opus/src/src Source/webrtc/modules/audio_device/mac Source/third_party/usrsctp/usrsctplib/usrsctplib/netinet Source/webrtc/modules/audio_device/ios Source/webrtc Source/webrtc/sdk/objc Source/webrtc/sdk/objc/base Source/webrtc/sdk/objc/Framework/Classes Source/third_party/libsrtp/config Source/webrtc/sdk/objc/Framework/Classes/Common Source/webrtc/sdk/objc/Framework/Classes/Video Source/webrtc/sdk/objc/Framework/Classes/PeerConnection Source/third_party/abseil-cpp Source/third_party/libvpx/source/libvpx Source/third_party/libwebm/webm_parser/include Source/third_party/libvpx/source/libvpx/third_party/libwebm;
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/libwebrtc;
USE_HEADERMAP = NO;
diff --git a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj
index 1b697b71f6a99c382d28d57851ac34e056b1177b..da63db342b0da4cc66fc319a614e5b958448a168 100644
--- a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj
+++ b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj
@@ -3891,6 +3891,9 @@
CDFD2FCD24C4DAF70048DAC3 /* status.h in Copy webm headers */ = {isa = PBXBuildFile; fileRef = CDEBB40624C0191A00ADBD44 /* status.h */; };
CDFD2FCE24C4DAF70048DAC3 /* webm_parser.h in Copy webm headers */ = {isa = PBXBuildFile; fileRef = CDEBB40824C0191A00ADBD44 /* webm_parser.h */; };
CDFD2FD024C4DB2F0048DAC3 /* vp9_header_parser.h in Copy common headers */ = {isa = PBXBuildFile; fileRef = CDFD2F9624C4B2F90048DAC3 /* vp9_header_parser.h */; };
+ F3B7819924C7CC5200FCB122 /* mkvmuxerutil.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */; };
+ F3B7819A24C7CC5200FCB122 /* mkvmuxer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */; };
+ F3B7819B24C7CC5200FCB122 /* mkvwriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3B7819824C7CC5200FCB122 /* mkvwriter.cc */; };
/* End PBXBuildFile section */
/* Begin PBXBuildRule section */
@@ -8409,6 +8412,9 @@
CDEBB49D24C0191A00ADBD44 /* master_parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = master_parser.h; sourceTree = "<group>"; };
CDFD2F9624C4B2F90048DAC3 /* vp9_header_parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vp9_header_parser.h; sourceTree = "<group>"; };
CDFD2F9A24C4B2F90048DAC3 /* vp9_header_parser.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = vp9_header_parser.cc; sourceTree = "<group>"; };
+ F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvmuxerutil.cc; path = mkvmuxer/mkvmuxerutil.cc; sourceTree = "<group>"; };
+ F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvmuxer.cc; path = mkvmuxer/mkvmuxer.cc; sourceTree = "<group>"; };
+ F3B7819824C7CC5200FCB122 /* mkvwriter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvwriter.cc; path = mkvmuxer/mkvwriter.cc; sourceTree = "<group>"; };
FB39D0D11200F0E300088E69 /* libwebrtc.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libwebrtc.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
@@ -15296,6 +15302,7 @@
isa = PBXGroup;
children = (
CDFD2F9224C4B2F90048DAC3 /* common */,
+ F3B7819524C7CC1300FCB122 /* mkvmuxer */,
CDEBB19224C0191800ADBD44 /* webm_parser */,
);
path = libwebm;
@@ -15430,6 +15437,16 @@
path = common;
sourceTree = "<group>";
};
+ F3B7819524C7CC1300FCB122 /* mkvmuxer */ = {
+ isa = PBXGroup;
+ children = (
+ F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */,
+ F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */,
+ F3B7819824C7CC5200FCB122 /* mkvwriter.cc */,
+ );
+ name = mkvmuxer;
+ sourceTree = "<group>";
+ };
FB39D06E1200ED9200088E69 = {
isa = PBXGroup;
children = (
@@ -17543,7 +17560,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "PRIVATE_HEADERS_FOLDER_PATH=usr/local/include\n\nif [[ \"${DEPLOYMENT_LOCATION}\" == \"NO\" ]]; then\n PRIVATE_HEADERS_PATH=\"${TARGET_BUILD_DIR%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nelse\n PRIVATE_HEADERS_PATH=\"${DSTROOT}${INSTALL_PATH_PREFIX%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nfi;\n\nmkdir -p \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/webrtc\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/abseil-cpp/absl\" \"${PRIVATE_HEADERS_PATH}\"\n";
+ shellScript = "PRIVATE_HEADERS_FOLDER_PATH=usr/local/include\n\nif [[ \"${DEPLOYMENT_LOCATION}\" == \"NO\" ]]; then\n PRIVATE_HEADERS_PATH=\"${TARGET_BUILD_DIR%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nelse\n PRIVATE_HEADERS_PATH=\"${DSTROOT}${INSTALL_PATH_PREFIX%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nfi;\n\nmkdir -p \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/webrtc\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/abseil-cpp/absl\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/libyuv/include/\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --exclude \"src\" --exclude \"internal\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/libvpx/source/libvpx/vpx\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/libwebm/\" \"${PRIVATE_HEADERS_PATH}\"\n";
};
5CD286461E6E154E0094FDC8 /* Check for Weak VTables and Externals */ = {
isa = PBXShellScriptBuildPhase;
@@ -18691,6 +18708,7 @@
419C82F51FE20EB50040C30F /* audio_encoder_opus.cc in Sources */,
419C82F31FE20EB50040C30F /* audio_encoder_opus_config.cc in Sources */,
4140B8201E4E3383007409E6 /* audio_encoder_pcm.cc in Sources */,
+ F3B7819A24C7CC5200FCB122 /* mkvmuxer.cc in Sources */,
5CDD8FFE1E43CE3A00621E92 /* audio_encoder_pcm16b.cc in Sources */,
5CD285461E6A61D20094FDC8 /* audio_format.cc in Sources */,
41DDB26F212679D200296D47 /* audio_format_to_string.cc in Sources */,
@@ -18813,6 +18831,7 @@
4131C1C0234B8A4A0028A615 /* connection.cc in Sources */,
4131C1D2234B8A4B0028A615 /* connection_info.cc in Sources */,
5CDD8A931E43C00F00621E92 /* constant_pcm_packet_source.cc in Sources */,
+ F3B7819B24C7CC5200FCB122 /* mkvwriter.cc in Sources */,
5CDD8B891E43C2B500621E92 /* constants.c in Sources */,
4131C291234B8CC40028A615 /* constants.cc in Sources */,
41FCBB3921B1F8FC00A5DF27 /* control_handler.cc in Sources */,
@@ -19377,6 +19396,7 @@
4131C53B234C8B190028A615 /* rtc_event_rtp_packet_outgoing.cc in Sources */,
4131C552234C8B190028A615 /* rtc_event_video_receive_stream_config.cc in Sources */,
4131C554234C8B190028A615 /* rtc_event_video_send_stream_config.cc in Sources */,
+ F3B7819924C7CC5200FCB122 /* mkvmuxerutil.cc in Sources */,
4131C3CF234B98420028A615 /* rtc_stats.cc in Sources */,
4131BF2D234B88200028A615 /* rtc_stats_collector.cc in Sources */,
4131C3CE234B98420028A615 /* rtc_stats_report.cc in Sources */,
diff --git a/Source/WTF/Scripts/Preferences/WebPreferences.yaml b/Source/WTF/Scripts/Preferences/WebPreferences.yaml
index 3c07437744b1d5aa2b549546431c3b5f8b0fd7b7..c8334bcc3f7dfa64cbbcc3431bf88b5e64f17b81 100644
--- a/Source/WTF/Scripts/Preferences/WebPreferences.yaml
+++ b/Source/WTF/Scripts/Preferences/WebPreferences.yaml
@@ -937,7 +937,7 @@ InspectorStartsAttached:
exposed: [ WebKit ]
defaultValue:
WebKit:
- default: true
+ default: false
InspectorWindowFrame:
type: String
diff --git a/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml b/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml
index 260f11060fba717a32871c9944b2a0cbe6bf7c93..5d119439366e6763ad4174a9652b636a0ca1824b 100644
--- a/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml
+++ b/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml
@@ -532,7 +532,7 @@ MaskWebGLStringsEnabled:
WebKitLegacy:
default: true
WebKit:
- default: true
+ default: false
# FIXME: This is on by default in WebKit2. Perhaps we should consider turning it on for WebKitLegacy as well.
MediaCapabilitiesExtensionsEnabled:
diff --git a/Source/WTF/wtf/DateMath.cpp b/Source/WTF/wtf/DateMath.cpp
index af92f674770349cc8e7be9a53b1cee6e7840e781..f0a960db046292a3505d339a333f03098f3d8418 100644
--- a/Source/WTF/wtf/DateMath.cpp
+++ b/Source/WTF/wtf/DateMath.cpp
@@ -76,9 +76,14 @@
#include <limits>
#include <stdint.h>
#include <time.h>
+#include <unicode/ucal.h>
#include <wtf/Assertions.h>
#include <wtf/ASCIICType.h>
+#include <wtf/Language.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/ThreadSpecific.h>
#include <wtf/text/StringBuilder.h>
+#include <wtf/unicode/UTF8Conversion.h>
#if OS(WINDOWS)
#include <windows.h>
@@ -92,6 +97,18 @@ template<unsigned length> inline bool startsWithLettersIgnoringASCIICase(const c
return equalLettersIgnoringASCIICase(string, lowercaseLetters, length - 1);
}
+struct TimeZoneForAutomation {
+ UCalendar* cal;
+ String id;
+ String displayName;
+};
+
+static TimeZoneForAutomation& innerTimeZoneForAutomation()
+{
+ static NeverDestroyed<WTF::ThreadSpecific<TimeZoneForAutomation>> timeZoneForAutomation;
+ return *timeZoneForAutomation.get();
+}
+
/* Constants */
const char* const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
@@ -318,6 +335,14 @@ static double calculateDSTOffset(time_t localTime, double utcOffset)
// Returns combined offset in millisecond (UTC + DST).
LocalTimeOffset calculateLocalTimeOffset(double ms, TimeType inputTimeType)
{
+ TimeZoneForAutomation& tz = innerTimeZoneForAutomation();
+ if (tz.cal) {
+ UErrorCode status = U_ZERO_ERROR;
+ ucal_setMillis(tz.cal, ms, &status);
+ int32_t offset = ucal_get(tz.cal, UCAL_ZONE_OFFSET, &status);
+ int32_t dstOffset = ucal_get(tz.cal, UCAL_DST_OFFSET, &status);
+ return LocalTimeOffset(dstOffset, offset + dstOffset);
+ }
#if HAVE(TM_GMTOFF)
double localToUTCTimeOffset = inputTimeType == LocalTime ? calculateUTCOffset() : 0;
#else
@@ -1019,4 +1044,65 @@ String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, u
return stringBuilder.toString();
}
+bool setTimeZoneForAutomation(const String& timeZone)
+{
+ innerTimeZoneForAutomation().displayName = String();
+ if (innerTimeZoneForAutomation().cal) {
+ ucal_close(innerTimeZoneForAutomation().cal);
+ innerTimeZoneForAutomation().cal = nullptr;
+ }
+ if (timeZone.isEmpty()) {
+ innerTimeZoneForAutomation().id = String();
+ return true;
+ }
+
+ // Timezone is ascii.
+ Vector<UChar> buffer(timeZone.length());
+ UChar* bufferStart = buffer.data();
+ CString ctz = timeZone.utf8();
+ if (!Unicode::convertUTF8ToUTF16(ctz.data(), ctz.data() + ctz.length(), &bufferStart, bufferStart + timeZone.length()))
+ return false;
+
+ Vector<UChar, 32> canonicalBuffer(32);
+ UErrorCode status = U_ZERO_ERROR;
+ auto canonicalLength = ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalBuffer.size(), nullptr, &status);
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ status = U_ZERO_ERROR;
+ canonicalBuffer.grow(canonicalLength);
+ ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalLength, nullptr, &status);
+ }
+ if (!U_SUCCESS(status))
+ return false;
+
+ UCalendar* cal = ucal_open(canonicalBuffer.data(), canonicalLength, nullptr, UCAL_TRADITIONAL, &status);
+ if (!U_SUCCESS(status))
+ return false;
+
+ Vector<UChar, 32> displayNameBuffer(32);
+ auto displayNameLength = ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameBuffer.size(), &status);
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ status = U_ZERO_ERROR;
+ displayNameBuffer.grow(displayNameLength);
+ ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameLength, &status);
+ }
+ if (!U_SUCCESS(status))
+ return false;
+
+ TimeZoneForAutomation& tzfa = innerTimeZoneForAutomation();
+ tzfa.cal = cal;
+ tzfa.id = String(canonicalBuffer.data(), canonicalLength);
+ tzfa.displayName = String(displayNameBuffer.data(), displayNameLength);
+ return true;
+}
+
+String timeZoneForAutomation()
+{
+ return innerTimeZoneForAutomation().id;
+}
+
+String timeZoneDisplayNameForAutomation()
+{
+ return innerTimeZoneForAutomation().displayName;
+}
+
} // namespace WTF
diff --git a/Source/WTF/wtf/DateMath.h b/Source/WTF/wtf/DateMath.h
index 246ba67c764b629042a7927d24fe89b049d82a0b..68d536878d1f0ba832d1c1d3e36e10b8227bbfac 100644
--- a/Source/WTF/wtf/DateMath.h
+++ b/Source/WTF/wtf/DateMath.h
@@ -389,6 +389,10 @@ inline int dayInMonthFromDayInYear(int dayInYear, bool leapYear)
return d - step;
}
+WTF_EXPORT_PRIVATE bool setTimeZoneForAutomation(const String& timeZone);
+WTF_EXPORT_PRIVATE String timeZoneForAutomation();
+WTF_EXPORT_PRIVATE String timeZoneDisplayNameForAutomation();
+
// Returns combined offset in millisecond (UTC + DST).
WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds, TimeType = UTCTime);
diff --git a/Source/WTF/wtf/PlatformEnable.h b/Source/WTF/wtf/PlatformEnable.h
index 0d66641786ebe9467ae0596d5077a160597e807a..5e5809e8b4d9999c32b40b78481b9597bd469215 100644
--- a/Source/WTF/wtf/PlatformEnable.h
+++ b/Source/WTF/wtf/PlatformEnable.h
@@ -401,7 +401,7 @@
#endif
#if !defined(ENABLE_ORIENTATION_EVENTS)
-#define ENABLE_ORIENTATION_EVENTS 0
+#define ENABLE_ORIENTATION_EVENTS 1
#endif
#if OS(WINDOWS)
@@ -470,7 +470,7 @@
#endif
#if !defined(ENABLE_TOUCH_EVENTS)
-#define ENABLE_TOUCH_EVENTS 0
+#define ENABLE_TOUCH_EVENTS 1
#endif
#if !defined(ENABLE_TOUCH_ACTION_REGIONS)
diff --git a/Source/WTF/wtf/PlatformHave.h b/Source/WTF/wtf/PlatformHave.h
index b9ce2042ff73fb427897e3d2d9cbf816d0e16bb8..2076f889cd553d207bacff2f1ff4daf8bdb577cc 100644
--- a/Source/WTF/wtf/PlatformHave.h
+++ b/Source/WTF/wtf/PlatformHave.h
@@ -335,7 +335,7 @@
#define HAVE_NSHTTPCOOKIESTORAGE__INITWITHIDENTIFIER_WITH_INACCURATE_NULLABILITY 1
#endif
-#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST)
+#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)
#define HAVE_OS_DARK_MODE_SUPPORT 1
#endif
diff --git a/Source/WebCore/DerivedSources.make b/Source/WebCore/DerivedSources.make
index 4cfce5b3bff69b658e049f9b3686840f2b3c2258..2e757cb8de7bf7c741cf23a3059a591a94225067 100644
--- a/Source/WebCore/DerivedSources.make
+++ b/Source/WebCore/DerivedSources.make
@@ -760,6 +760,10 @@ JS_BINDING_IDLS := \
$(WebCore)/dom/Slotable.idl \
$(WebCore)/dom/StaticRange.idl \
$(WebCore)/dom/StringCallback.idl \
+ $(WebCore)/dom/Document+Touch.idl \
+ $(WebCore)/dom/Touch.idl \
+ $(WebCore)/dom/TouchEvent.idl \
+ $(WebCore)/dom/TouchList.idl \
$(WebCore)/dom/Text.idl \
$(WebCore)/dom/TextDecoder.idl \
$(WebCore)/dom/TextDecoderStream.idl \
@@ -1283,9 +1287,6 @@ JS_BINDING_IDLS := \
ADDITIONAL_BINDING_IDLS = \
DocumentTouch.idl \
GestureEvent.idl \
- Touch.idl \
- TouchEvent.idl \
- TouchList.idl \
#
vpath %.in $(WEBKITADDITIONS_HEADER_SEARCH_PATHS)
diff --git a/Source/WebCore/Modules/geolocation/Geolocation.cpp b/Source/WebCore/Modules/geolocation/Geolocation.cpp
index 6d5be9a591a272cd67d6e9d097b30505bdf8ae5e..8f67ba28c380e844c8e4191ee704466559d88f97 100644
--- a/Source/WebCore/Modules/geolocation/Geolocation.cpp
+++ b/Source/WebCore/Modules/geolocation/Geolocation.cpp
@@ -356,8 +356,9 @@ bool Geolocation::shouldBlockGeolocationRequests()
bool isSecure = SecurityOrigin::isSecure(document()->url());
bool hasMixedContent = !document()->foundMixedContent().isEmpty();
bool isLocalOrigin = securityOrigin()->isLocal();
+ bool isPotentiallyTrustworthy = securityOrigin()->isPotentiallyTrustworthy();
if (securityOrigin()->canRequestGeolocation()) {
- if (isLocalOrigin || (isSecure && !hasMixedContent) || isRequestFromIBooks())
+ if (isLocalOrigin || isPotentiallyTrustworthy || (isSecure && !hasMixedContent) || isRequestFromIBooks())
return false;
}
diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt
index 2ad33a955192d9076eb3d8c162cfe38622dfb18c..3350bf01f5e7cb1e6ee82a61b85aae688b39dad2 100644
--- a/Source/WebCore/SourcesCocoa.txt
+++ b/Source/WebCore/SourcesCocoa.txt
@@ -601,3 +601,9 @@ platform/graphics/angle/TemporaryANGLESetting.cpp @no-unify
// Derived Sources
WHLSLStandardLibraryFunctionMap.cpp
+
+// Playwright begin
+JSTouch.cpp
+JSTouchEvent.cpp
+JSTouchList.cpp
+// Playwright end
diff --git a/Source/WebCore/WebCore.order b/Source/WebCore/WebCore.order
index ef168b76819216d984b7a2d0f760005fb9d24de8..2d6cf51f3b45191ad84106429d4f108f85679123 100644
--- a/Source/WebCore/WebCore.order
+++ b/Source/WebCore/WebCore.order
@@ -3093,7 +3093,6 @@ __ZN7WebCore14DocumentLoader23stopLoadingSubresourcesEv
__ZN7WebCore14DocumentLoader18stopLoadingPlugInsEv
__ZN7WebCore14DocumentLoader15detachFromFrameEv
__ZN7WebCore20ApplicationCacheHost22setDOMApplicationCacheEPNS_19DOMApplicationCacheE
-__ZN7WebCore24InspectorInstrumentation27loaderDetachedFromFrameImplEPNS_19InstrumentingAgentsEPNS_14DocumentLoaderE
__ZN7WebCore14DocumentLoaderD0Ev
__ZN7WebCore14DocumentLoaderD2Ev
__ZN7WebCore14DocumentLoader17clearMainResourceEv
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 704ff178ad226d6362b4c97dec10547ae8b24762..fc334f6fc45f01c7afda1b20e54ffa5ac4fa8fd4 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -5154,6 +5154,14 @@
EDE3A5000C7A430600956A37 /* ColorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = EDE3A4FF0C7A430600956A37 /* ColorMac.h */; settings = {ATTRIBUTES = (Private, ); }; };
EDEC98030AED7E170059137F /* WebCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EDEC98020AED7E170059137F /* WebCorePrefix.h */; };
EFCC6C8F20FE914400A2321B /* CanvasActivityRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16923AD660C0011CE47 /* Touch.cpp */; };
+ F050E16D23AD66630011CE47 /* TouchList.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16B23AD66620011CE47 /* TouchList.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E16E23AD66630011CE47 /* TouchList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16C23AD66630011CE47 /* TouchList.cpp */; };
+ F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16F23AD669E0011CE47 /* TouchEvent.cpp */; };
+ F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17023AD669F0011CE47 /* TouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E17423AD6A800011CE47 /* DocumentTouch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E17323AD6A800011CE47 /* DocumentTouch.cpp */; };
+ F050E17823AD70C50011CE47 /* PlatformTouchPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
F12171F616A8CF0B000053CA /* WebVTTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = F12171F416A8BC63000053CA /* WebVTTElement.h */; };
F32BDCD92363AACA0073B6AE /* UserGestureEmulationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = F32BDCD72363AACA0073B6AE /* UserGestureEmulationScope.h */; };
F344C7141125B82C00F26EEE /* InspectorFrontendClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F344C7121125B82C00F26EEE /* InspectorFrontendClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -16301,6 +16309,14 @@
EDEC98020AED7E170059137F /* WebCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCorePrefix.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
EFB7287B2124C73D005C2558 /* CanvasActivityRecord.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CanvasActivityRecord.cpp; sourceTree = "<group>"; };
EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanvasActivityRecord.h; sourceTree = "<group>"; };
+ F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchEvent.h; sourceTree = "<group>"; };
+ F050E16923AD660C0011CE47 /* Touch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Touch.cpp; path = dom/Touch.cpp; sourceTree = SOURCE_ROOT; };
+ F050E16B23AD66620011CE47 /* TouchList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TouchList.h; path = dom/TouchList.h; sourceTree = SOURCE_ROOT; };
+ F050E16C23AD66630011CE47 /* TouchList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TouchList.cpp; path = dom/TouchList.cpp; sourceTree = SOURCE_ROOT; };
+ F050E16F23AD669E0011CE47 /* TouchEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TouchEvent.cpp; path = dom/TouchEvent.cpp; sourceTree = SOURCE_ROOT; };
+ F050E17023AD669F0011CE47 /* TouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TouchEvent.h; path = dom/TouchEvent.h; sourceTree = SOURCE_ROOT; };
+ F050E17323AD6A800011CE47 /* DocumentTouch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentTouch.cpp; sourceTree = "<group>"; };
+ F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchPoint.h; sourceTree = "<group>"; };
F12171F316A8BC63000053CA /* WebVTTElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebVTTElement.cpp; sourceTree = "<group>"; };
F12171F416A8BC63000053CA /* WebVTTElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebVTTElement.h; sourceTree = "<group>"; };
F32BDCD52363AAC90073B6AE /* UserGestureEmulationScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserGestureEmulationScope.cpp; sourceTree = "<group>"; };
@@ -21720,7 +21736,12 @@
81F65FF513788FAA00FF6F2D /* DragState.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 */,
@@ -27140,7 +27161,9 @@
B2C3D9EC0D006C1D00EF6F26 /* text */,
E1EE8B6B2412B2A700E794D6 /* xr */,
DFDB912CF8E88A6DA1AD264F /* AbortableTaskQueue.h */,
+ F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */,
49AE2D94134EE5F90072920A /* CalculationValue.cpp */,
+ F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */,
49AE2D95134EE5F90072920A /* CalculationValue.h */,
C330A22113EC196B0000B45B /* ColorChooser.h */,
C37CDEBC149EF2030042090D /* ColorChooserClient.h */,
@@ -29634,6 +29657,7 @@
BCCFBAE70B5152ED0001F1D7 /* DocumentParser.h */,
AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */,
AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */,
+ F050E17323AD6A800011CE47 /* DocumentTouch.cpp */,
6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */,
6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */,
86D982F6125C154000AD9E3D /* DocumentTiming.h */,
@@ -30655,6 +30679,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 */,
@@ -32605,6 +32630,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 */,
@@ -34562,9 +34588,11 @@
B2C3DA3A0D006C1D00EF6F26 /* TextCodec.h in Headers */,
26E98A10130A9FCA008EB7B2 /* TextCodecASCIIFastPath.h in Headers */,
DF95B14A24FDAFD300B1F4D7 /* TextCodecCJK.h in Headers */,
+ F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */,
B2C3DA3C0D006C1D00EF6F26 /* TextCodecICU.h in Headers */,
B2C3DA3E0D006C1D00EF6F26 /* TextCodecLatin1.h in Headers */,
57EF5E601D20C83900171E60 /* TextCodecReplacement.h in Headers */,
+ F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */,
B2C3DA400D006C1D00EF6F26 /* TextCodecUserDefined.h in Headers */,
B2C3DA420D006C1D00EF6F26 /* TextCodecUTF16.h in Headers */,
9343CB8212F25E510033C5EE /* TextCodecUTF8.h in Headers */,
@@ -35551,6 +35579,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 */,
@@ -35582,6 +35611,7 @@
6E72F54F229DCD1300B3E151 /* TemporaryANGLESetting.cpp in Sources */,
CE88EE262414467B007F29C2 /* TextAlternativeWithRange.mm in Sources */,
51DF6D800B92A18E00C2DC85 /* ThreadCheck.mm in Sources */,
+ F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */,
538EC8031F96AF81004D22A8 /* UnifiedSource1-mm.mm in Sources */,
538EC8021F96AF81004D22A8 /* UnifiedSource1.cpp in Sources */,
538EC8051F96AF81004D22A8 /* UnifiedSource2-mm.mm in Sources */,
@@ -35630,6 +35660,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 */,
@@ -36162,6 +36193,7 @@
2D8B92F1203D13E1009C868F /* UnifiedSource516.cpp in Sources */,
2D8B92F2203D13E1009C868F /* UnifiedSource517.cpp in Sources */,
2D8B92F3203D13E1009C868F /* UnifiedSource518.cpp in Sources */,
+ F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */,
2D8B92F4203D13E1009C868F /* UnifiedSource519.cpp in Sources */,
2D8B92F5203D13E1009C868F /* UnifiedSource520.cpp in Sources */,
2D8B92F6203D13E1009C868F /* UnifiedSource521.cpp in Sources */,
diff --git a/Source/WebCore/accessibility/AccessibilityObject.cpp b/Source/WebCore/accessibility/AccessibilityObject.cpp
index dc856667a52b96b9201f266e01aae199feab39b7..ee2d99e10e3db27f620fec0809fe008d38aae48a 100644
--- a/Source/WebCore/accessibility/AccessibilityObject.cpp
+++ b/Source/WebCore/accessibility/AccessibilityObject.cpp
@@ -58,6 +58,7 @@
#include "HTMLParserIdioms.h"
#include "HTMLTextAreaElement.h"
#include "HitTestResult.h"
+#include "InspectorInstrumentation.h"
#include "LocalizedStrings.h"
#include "MathMLNames.h"
#include "NodeList.h"
@@ -3241,10 +3242,15 @@ AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const
if (useParentData ? m_isIgnoredFromParentData.isPresentationalChildOfAriaRole : isPresentationalChildOfAriaRole())
return AccessibilityObjectInclusion::IgnoreObject;
-
- return accessibilityPlatformIncludesObject();
+
+ AccessibilityObjectInclusion platformBehavior = accessibilityPlatformIncludesObject();
+ if (platformBehavior != AccessibilityObjectInclusion::DefaultBehavior) {
+ if (auto* page = this->page())
+ InspectorInstrumentation::maybeOverrideDefaultObjectInclusion(*page, platformBehavior);
+ }
+ return platformBehavior;
}
-
+
bool AccessibilityObject::accessibilityIsIgnored() const
{
AXComputedObjectAttributeCache* attributeCache = nullptr;
diff --git a/Source/WebCore/dom/PointerEvent.cpp b/Source/WebCore/dom/PointerEvent.cpp
index 3cc7f016fb8414d7385c1189a7595940d1972a4b..5a7fc02255900a9f9705567e79ee43718436cf2d 100644
--- a/Source/WebCore/dom/PointerEvent.cpp
+++ b/Source/WebCore/dom/PointerEvent.cpp
@@ -129,4 +129,61 @@ EventInterface PointerEvent::eventInterface() const
return PointerEventInterfaceType;
}
+#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS_FAMILY)
+
+static const AtomString& pointerEventType(PlatformTouchPoint::State state)
+{
+ switch (state) {
+ case PlatformTouchPoint::State::TouchPressed:
+ return eventNames().pointerdownEvent;
+ case PlatformTouchPoint::State::TouchMoved:
+ return eventNames().pointermoveEvent;
+ case PlatformTouchPoint::State::TouchStationary:
+ return eventNames().pointermoveEvent;
+ case PlatformTouchPoint::State::TouchReleased:
+ return eventNames().pointerupEvent;
+ case PlatformTouchPoint::State::TouchCancelled:
+ return eventNames().pointercancelEvent;
+ case PlatformTouchPoint::State::TouchStateEnd:
+ break;
+ }
+ ASSERT_NOT_REACHED();
+ return nullAtom();
+}
+
+static short buttonForType(const AtomString& type)
+{
+ return type == eventNames().pointermoveEvent ? -1 : 0;
+}
+
+static unsigned short buttonsForType(const AtomString& type)
+{
+ // We have contact with the touch surface for most events except when we've released the touch or canceled it.
+ return (type == eventNames().pointerupEvent || type == eventNames().pointeroutEvent || type == eventNames().pointerleaveEvent || type == eventNames().pointercancelEvent) ? 0 : 1;
+}
+
+Ref<PointerEvent> PointerEvent::create(const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref<WindowProxy>&& view)
+{
+ const auto& type = pointerEventType(event.touchPoints().at(index).state());
+ return adoptRef(*new PointerEvent(type, event, typeIsCancelable(type), index, isPrimary, WTFMove(view)));
+}
+
+Ref<PointerEvent> PointerEvent::create(const String& type, const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref<WindowProxy>&& view)
+{
+ return adoptRef(*new PointerEvent(type, event, typeIsCancelable(type), index, isPrimary, WTFMove(view)));
+}
+
+PointerEvent::PointerEvent(const AtomString& type, const PlatformTouchEvent& event, IsCancelable isCancelable, unsigned index, bool isPrimary, Ref<WindowProxy>&& view)
+ : MouseEvent(type, typeCanBubble(type), isCancelable, typeIsComposed(type), event.timestamp().approximateMonotonicTime(), WTFMove(view), 0, event.touchPoints().at(index).pos(), event.touchPoints().at(index).pos(), { }, event.modifiers(), buttonForType(type), buttonsForType(type), nullptr, 0, 0, IsSimulated::No, IsTrusted::Yes)
+ , m_pointerId(2)
+ , m_width(2 * event.touchPoints().at(index).radiusX())
+ , m_height(2 * event.touchPoints().at(index).radiusY())
+ , m_pressure(event.touchPoints().at(index).force())
+ , m_pointerType(PointerEvent::touchPointerType())
+ , m_isPrimary(isPrimary)
+{
+}
+
+#endif // ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS_FAMILY)
+
} // namespace WebCore
diff --git a/Source/WebCore/dom/PointerEvent.h b/Source/WebCore/dom/PointerEvent.h
index 4310f235a12ca941c613794ac3ab572b68a2b4f8..7a8e56455777174c46cb3ea6359025dc5409b8c6 100644
--- a/Source/WebCore/dom/PointerEvent.h
+++ b/Source/WebCore/dom/PointerEvent.h
@@ -33,6 +33,8 @@
#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
#include "PlatformTouchEventIOS.h"
+#else
+#include "PlatformTouchEvent.h"
#endif
namespace WebCore {
@@ -79,7 +81,7 @@ public:
static Ref<PointerEvent> create(const String& type, short button, const MouseEvent&);
static Ref<PointerEvent> create(const String& type, PointerID, const String& pointerType, IsPrimary = IsPrimary::No);
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
+#if ENABLE(TOUCH_EVENTS)
static Ref<PointerEvent> create(const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref<WindowProxy>&&);
static Ref<PointerEvent> create(const String& type, const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref<WindowProxy>&&);
#endif
@@ -123,7 +125,7 @@ private:
PointerEvent(const AtomString&, Init&&);
PointerEvent(const AtomString& type, short button, const MouseEvent&);
PointerEvent(const AtomString& type, PointerID, const String& pointerType, IsPrimary);
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
+#if ENABLE(TOUCH_EVENTS)
PointerEvent(const AtomString& type, const PlatformTouchEvent&, IsCancelable isCancelable, unsigned touchIndex, bool isPrimary, Ref<WindowProxy>&&);
#endif
diff --git a/Source/WebCore/dom/UserGestureIndicator.cpp b/Source/WebCore/dom/UserGestureIndicator.cpp
index 76399ab574d94d73c5abc08f8df7901979e58273..8df80e34cda19470e305d5696bf108bd8de5fa8c 100644
--- a/Source/WebCore/dom/UserGestureIndicator.cpp
+++ b/Source/WebCore/dom/UserGestureIndicator.cpp
@@ -67,8 +67,7 @@ UserGestureIndicator::UserGestureIndicator(Optional<ProcessingUserGestureState>
if (state)
currentToken() = UserGestureToken::create(state.value(), gestureType);
-
- if (document && currentToken()->processingUserGesture() && state) {
+ if (document && state && currentToken()->processingUserGesture()) {
document->updateLastHandledUserGestureTimestamp(currentToken()->startTime());
if (processInteractionStyle == ProcessInteractionStyle::Immediate)
ResourceLoadObserver::shared().logUserInteractionWithReducedTimeResolution(document->topDocument());
diff --git a/Source/WebCore/html/FileInputType.cpp b/Source/WebCore/html/FileInputType.cpp
index de06188e522381e034914f539af45166907767c9..900c152116b75e14e990a2810402afc49eaca78d 100644
--- a/Source/WebCore/html/FileInputType.cpp
+++ b/Source/WebCore/html/FileInputType.cpp
@@ -36,6 +36,7 @@
#include "HTMLNames.h"
#include "Icon.h"
#include "InputTypeNames.h"
+#include "InspectorInstrumentation.h"
#include "LocalizedStrings.h"
#include "MIMETypeRegistry.h"
#include "RenderFileUploadControl.h"
@@ -211,6 +212,11 @@ void FileInputType::handleDOMActivateEvent(Event& event)
if (input.isDisabledFormControl())
return;
+ bool intercept = false;
+ InspectorInstrumentation::runOpenPanel(input.document().frame(), element(), &intercept);
+ if (intercept)
+ return;
+
if (!UserGestureIndicator::processingUserGesture())
return;
diff --git a/Source/WebCore/inspector/InspectorController.cpp b/Source/WebCore/inspector/InspectorController.cpp
index 734e8b7854fd031873428ace885049dde661732b..706d983925ff25cb69dab28ffa67bce6fd0d92fd 100644
--- a/Source/WebCore/inspector/InspectorController.cpp
+++ b/Source/WebCore/inspector/InspectorController.cpp
@@ -371,8 +371,8 @@ void InspectorController::inspect(Node* node)
if (!enabled())
return;
- if (!hasRemoteFrontend())
- show();
+ // HACK: Always attempt to show inspector even if there is a remote connection.
+ show();
ensureDOMAgent().inspect(node);
}
@@ -513,4 +513,24 @@ void InspectorController::didComposite(Frame& frame)
InspectorInstrumentation::didComposite(frame);
}
+void InspectorController::pauseWhenShown()
+{
+ m_pauseWhenShown = true;
+}
+
+void InspectorController::resumeIfPausedInNewWindow()
+{
+ m_pauseWhenShown = false;
+}
+
+void InspectorController::didShowNewWindow()
+{
+ if (!m_pauseWhenShown)
+ return;
+ while (m_pauseWhenShown) {
+ if (RunLoop::cycle() == RunLoop::CycleResult::Stop)
+ break;
+ }
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorController.h b/Source/WebCore/inspector/InspectorController.h
index 1cbd452fff3fc386050db8a0ead33b50116d81f5..a9c17a561d268835af189f08edd5428e0e288bc7 100644
--- a/Source/WebCore/inspector/InspectorController.h
+++ b/Source/WebCore/inspector/InspectorController.h
@@ -101,6 +101,10 @@ public:
WEBCORE_EXPORT void willComposite(Frame&);
WEBCORE_EXPORT void didComposite(Frame&);
+ WEBCORE_EXPORT void pauseWhenShown();
+ WEBCORE_EXPORT void resumeIfPausedInNewWindow();
+ WEBCORE_EXPORT void didShowNewWindow();
+
bool isUnderTest() const { return m_isUnderTest; }
void setIsUnderTest(bool isUnderTest) { m_isUnderTest = isUnderTest; }
WEBCORE_EXPORT void evaluateForTestInFrontend(const String& script);
@@ -150,6 +154,7 @@ private:
bool m_isAutomaticInspection { false };
bool m_pauseAfterInitialization = { false };
bool m_didCreateLazyAgents { false };
+ bool m_pauseWhenShown { false };
};
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp
index 437b3f336c517bec661728e71309eefafa20c892..10689d78a3b2406e4ba97683cbf5711c244d900e 100644
--- a/Source/WebCore/inspector/InspectorInstrumentation.cpp
+++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp
@@ -627,6 +627,12 @@ void InspectorInstrumentation::didFailLoadingImpl(InstrumentingAgents& instrumen
consoleAgent->didFailLoading(identifier, error); // This should come AFTER resource notification, front-end relies on this.
}
+void InspectorInstrumentation::didReceiveMainResourceErrorImpl(InstrumentingAgents& instrumentingAgents, Frame& frame, const ResourceError&)
+{
+ if (auto* pageRuntimeAgent = instrumentingAgents.enabledPageRuntimeAgent())
+ pageRuntimeAgent->didReceiveMainResourceError(frame);
+}
+
void InspectorInstrumentation::willLoadXHRSynchronouslyImpl(InstrumentingAgents& instrumentingAgents)
{
if (auto* networkAgent = instrumentingAgents.enabledNetworkAgent())
@@ -659,20 +665,17 @@ void InspectorInstrumentation::didReceiveScriptResponseImpl(InstrumentingAgents&
void InspectorInstrumentation::domContentLoadedEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
{
- if (!frame.isMainFrame())
- return;
-
if (auto* pageAgent = instrumentingAgents.enabledPageAgent())
- pageAgent->domContentEventFired();
+ pageAgent->domContentEventFired(frame);
}
void InspectorInstrumentation::loadEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame* frame)
{
- if (!frame || !frame->isMainFrame())
+ if (!frame)
return;
if (auto* pageAgent = instrumentingAgents.enabledPageAgent())
- pageAgent->loadEventFired();
+ pageAgent->loadEventFired(*frame);
}
void InspectorInstrumentation::frameDetachedFromParentImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
@@ -753,12 +756,6 @@ void InspectorInstrumentation::frameDocumentUpdatedImpl(InstrumentingAgents& ins
pageDOMDebuggerAgent->frameDocumentUpdated(frame);
}
-void InspectorInstrumentation::loaderDetachedFromFrameImpl(InstrumentingAgents& instrumentingAgents, DocumentLoader& loader)
-{
- if (auto* inspectorPageAgent = instrumentingAgents.enabledPageAgent())
- inspectorPageAgent->loaderDetachedFromFrame(loader);
-}
-
void InspectorInstrumentation::frameStartedLoadingImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
{
if (frame.isMainFrame()) {
@@ -795,6 +792,12 @@ void InspectorInstrumentation::frameClearedScheduledNavigationImpl(Instrumenting
inspectorPageAgent->frameClearedScheduledNavigation(frame);
}
+void InspectorInstrumentation::didNavigateWithinPageImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
+{
+ if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.enabledPageAgent())
+ inspectorPageAgent->didNavigateWithinPage(frame);
+}
+
#if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
void InspectorInstrumentation::defaultAppearanceDidChangeImpl(InstrumentingAgents& instrumentingAgents, bool useDarkAppearance)
{
@@ -1320,6 +1323,36 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents& ins
layerTreeAgent->renderLayerDestroyed(renderLayer);
}
+void InspectorInstrumentation::runOpenPanelImpl(InstrumentingAgents& instrumentingAgents, HTMLInputElement* element, bool* intercept)
+{
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent())
+ pageAgent->runOpenPanel(element, intercept);
+}
+
+void InspectorInstrumentation::frameAttachedImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) {
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent())
+ pageAgent->frameAttached(frame);
+}
+
+bool InspectorInstrumentation::shouldBypassCSPImpl(InstrumentingAgents& instrumentingAgents)
+{
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent())
+ return pageAgent->shouldBypassCSP();
+ return false;
+}
+
+void InspectorInstrumentation::willCheckNewWindowPolicyImpl(InstrumentingAgents& instrumentingAgents, const URL& url)
+{
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent())
+ pageAgent->willCheckNewWindowPolicy(url);
+}
+
+void InspectorInstrumentation::didCheckNewWindowPolicyImpl(InstrumentingAgents& instrumentingAgents, bool allowed)
+{
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent())
+ pageAgent->didCheckNewWindowPolicy(allowed);
+}
+
InstrumentingAgents& InspectorInstrumentation::instrumentingAgents(WorkerOrWorkletGlobalScope& globalScope)
{
return globalScope.inspectorController().m_instrumentingAgents;
@@ -1331,6 +1364,13 @@ InstrumentingAgents& InspectorInstrumentation::instrumentingAgents(Page& page)
return page.inspectorController().m_instrumentingAgents.get();
}
+void InspectorInstrumentation::maybeOverrideDefaultObjectInclusion(Page& page, AccessibilityObjectInclusion& inclusion) {
+ if (InspectorPageAgent* pageAgent = instrumentingAgents(page).enabledPageAgent()) {
+ if (pageAgent->doingAccessibilitySnapshot())
+ inclusion = AccessibilityObjectInclusion::DefaultBehavior;
+ }
+}
+
InstrumentingAgents* InspectorInstrumentation::instrumentingAgents(ScriptExecutionContext& context)
{
if (is<Document>(context))
diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h
index 3b00f3125085a72ca2884d2c0389380a4b882bcd..c05decbf1086c0407c9bc6490d9061a9246a96fd 100644
--- a/Source/WebCore/inspector/InspectorInstrumentation.h
+++ b/Source/WebCore/inspector/InspectorInstrumentation.h
@@ -31,6 +31,7 @@
#pragma once
+#include "AccessibilityObjectInterface.h"
#include "CSSSelector.h"
#include "CallTracerTypes.h"
#include "CanvasBase.h"
@@ -80,6 +81,7 @@ class DOMWrapperWorld;
class Document;
class DocumentLoader;
class EventListener;
+class HTMLInputElement;
class HTTPHeaderMap;
class InspectorTimelineAgent;
class InstrumentingAgents;
@@ -200,6 +202,7 @@ public:
static void didReceiveData(Frame*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
static void didFinishLoading(Frame*, DocumentLoader*, unsigned long identifier, const NetworkLoadMetrics&, ResourceLoader*);
static void didFailLoading(Frame*, DocumentLoader*, unsigned long identifier, const ResourceError&);
+ static void didReceiveMainResourceError(Frame&, const ResourceError&);
static void willSendRequest(WorkerOrWorkletGlobalScope&, unsigned long identifier, ResourceRequest&);
static void didReceiveResourceResponse(WorkerOrWorkletGlobalScope&, unsigned long identifier, const ResourceResponse&);
@@ -226,11 +229,11 @@ public:
static void frameDetachedFromParent(Frame&);
static void didCommitLoad(Frame&, DocumentLoader*);
static void frameDocumentUpdated(Frame&);
- static void loaderDetachedFromFrame(Frame&, DocumentLoader&);
static void frameStartedLoading(Frame&);
static void frameStoppedLoading(Frame&);
static void frameScheduledNavigation(Frame&, Seconds delay);
static void frameClearedScheduledNavigation(Frame&);
+ static void didNavigateWithinPage(Frame&);
#if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
static void defaultAppearanceDidChange(Page&, bool useDarkAppearance);
#endif
@@ -325,6 +328,12 @@ public:
static void layerTreeDidChange(Page*);
static void renderLayerDestroyed(Page*, const RenderLayer&);
+ static void runOpenPanel(Frame*, HTMLInputElement*, bool*);
+ static void frameAttached(Frame*);
+ static bool shouldBypassCSP(ScriptExecutionContext*);
+ static void willCheckNewWindowPolicy(Frame&, const URL&);
+ static void didCheckNewWindowPolicy(Frame&, bool allowed);
+
static void frontendCreated();
static void frontendDeleted();
static bool hasFrontends() { return InspectorInstrumentationPublic::hasFrontends(); }
@@ -340,6 +349,8 @@ public:
static void registerInstrumentingAgents(InstrumentingAgents&);
static void unregisterInstrumentingAgents(InstrumentingAgents&);
+ static void maybeOverrideDefaultObjectInclusion(Page&, AccessibilityObjectInclusion&);
+
private:
static void didClearWindowObjectInWorldImpl(InstrumentingAgents&, Frame&, DOMWrapperWorld&);
static bool isDebuggerPausedImpl(InstrumentingAgents&);
@@ -426,6 +437,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);
@@ -436,11 +448,11 @@ private:
static void frameDetachedFromParentImpl(InstrumentingAgents&, Frame&);
static void didCommitLoadImpl(InstrumentingAgents&, Frame&, DocumentLoader*);
static void frameDocumentUpdatedImpl(InstrumentingAgents&, Frame&);
- static void loaderDetachedFromFrameImpl(InstrumentingAgents&, DocumentLoader&);
static void frameStartedLoadingImpl(InstrumentingAgents&, Frame&);
static void frameStoppedLoadingImpl(InstrumentingAgents&, Frame&);
static void frameScheduledNavigationImpl(InstrumentingAgents&, Frame&, Seconds delay);
static void frameClearedScheduledNavigationImpl(InstrumentingAgents&, Frame&);
+ static void didNavigateWithinPageImpl(InstrumentingAgents&, Frame&);
#if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
static void defaultAppearanceDidChangeImpl(InstrumentingAgents&, bool useDarkAppearance);
#endif
@@ -531,6 +543,12 @@ private:
static void layerTreeDidChangeImpl(InstrumentingAgents&);
static void renderLayerDestroyedImpl(InstrumentingAgents&, const RenderLayer&);
+ static void runOpenPanelImpl(InstrumentingAgents&, HTMLInputElement*, bool*);
+ static void frameAttachedImpl(InstrumentingAgents&, Frame&);
+ static bool shouldBypassCSPImpl(InstrumentingAgents&);
+ static void willCheckNewWindowPolicyImpl(InstrumentingAgents&, const URL&);
+ static void didCheckNewWindowPolicyImpl(InstrumentingAgents&, bool allowed);
+
static InstrumentingAgents& instrumentingAgents(Page&);
static InstrumentingAgents& instrumentingAgents(WorkerOrWorkletGlobalScope&);
@@ -1119,6 +1137,13 @@ inline void InspectorInstrumentation::didFailLoading(Frame* frame, DocumentLoade
didFailLoadingImpl(*agents, identifier, loader, error);
}
+inline void InspectorInstrumentation::didReceiveMainResourceError(Frame& frame, const ResourceError& error)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (auto* agents = instrumentingAgents(frame))
+ didReceiveMainResourceErrorImpl(*agents, frame, error);
+}
+
inline void InspectorInstrumentation::didFailLoading(WorkerOrWorkletGlobalScope& globalScope, unsigned long identifier, const ResourceError& error)
{
didFailLoadingImpl(instrumentingAgents(globalScope), identifier, nullptr, error);
@@ -1214,13 +1239,6 @@ inline void InspectorInstrumentation::frameDocumentUpdated(Frame& frame)
frameDocumentUpdatedImpl(*agents, frame);
}
-inline void InspectorInstrumentation::loaderDetachedFromFrame(Frame& frame, DocumentLoader& loader)
-{
- FAST_RETURN_IF_NO_FRONTENDS(void());
- if (auto* agents = instrumentingAgents(frame))
- loaderDetachedFromFrameImpl(*agents, loader);
-}
-
inline void InspectorInstrumentation::frameStartedLoading(Frame& frame)
{
FAST_RETURN_IF_NO_FRONTENDS(void());
@@ -1249,6 +1267,13 @@ inline void InspectorInstrumentation::frameClearedScheduledNavigation(Frame& fra
frameClearedScheduledNavigationImpl(*agents, frame);
}
+inline void InspectorInstrumentation::didNavigateWithinPage(Frame& frame)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (auto* agents = instrumentingAgents(frame))
+ didNavigateWithinPageImpl(*agents, frame);
+}
+
#if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
inline void InspectorInstrumentation::defaultAppearanceDidChange(Page& page, bool useDarkAppearance)
{
@@ -1723,6 +1748,42 @@ inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const Ren
renderLayerDestroyedImpl(*agents, renderLayer);
}
+inline void InspectorInstrumentation::runOpenPanel(Frame* frame, HTMLInputElement* element, bool* intercept)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (auto* agents = instrumentingAgents(*frame))
+ runOpenPanelImpl(*agents, element, intercept);
+}
+
+inline void InspectorInstrumentation::frameAttached(Frame* frame)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (auto* agents = instrumentingAgents(frame))
+ frameAttachedImpl(*agents, *frame);
+}
+
+inline bool InspectorInstrumentation::shouldBypassCSP(ScriptExecutionContext* context)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(false);
+ if (auto* agents = instrumentingAgents(context))
+ return shouldBypassCSPImpl(*agents);
+ return false;
+}
+
+inline void InspectorInstrumentation::willCheckNewWindowPolicy(Frame& frame, const URL& url)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (auto* agents = instrumentingAgents(frame))
+ willCheckNewWindowPolicyImpl(*agents, url);
+}
+
+inline void InspectorInstrumentation::didCheckNewWindowPolicy(Frame& frame, bool allowed)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (auto* agents = instrumentingAgents(frame))
+ didCheckNewWindowPolicyImpl(*agents, allowed);
+}
+
inline InstrumentingAgents* InspectorInstrumentation::instrumentingAgents(ScriptExecutionContext* context)
{
return context ? instrumentingAgents(*context) : nullptr;
diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp
index 57f4ec4440c8b54a48ca456327c33e4c521685d9..21d25cbb18489691e3c3c57ab84b40410c9c428a 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"
@@ -92,11 +96,14 @@
#include "Page.h"
#include "Pasteboard.h"
#include "PseudoElement.h"
+#include "RenderLayer.h"
+#include "RenderObject.h"
#include "RenderStyle.h"
#include "RenderStyleConstants.h"
#include "ScriptState.h"
#include "SelectorChecker.h"
#include "ShadowRoot.h"
+#include "SharedBuffer.h"
#include "StaticNodeList.h"
#include "StyleProperties.h"
#include "StyleResolver.h"
@@ -128,7 +135,8 @@ using namespace HTMLNames;
static const size_t maxTextSize = 10000;
static const UChar ellipsisUChar[] = { 0x2026, 0 };
-static Color parseColor(RefPtr<JSON::Object>&& colorObject)
+// static
+Color InspectorDOMAgent::parseColor(RefPtr<JSON::Object>&& colorObject)
{
if (!colorObject)
return Color::transparentBlack;
@@ -147,7 +155,7 @@ static Color parseColor(RefPtr<JSON::Object>&& colorObject)
static Color parseConfigColor(const String& fieldName, JSON::Object& configObject)
{
- return parseColor(configObject.getObject(fieldName));
+ return InspectorDOMAgent::parseColor(configObject.getObject(fieldName));
}
static bool parseQuad(Ref<JSON::Array>&& quadArray, FloatQuad* quad)
@@ -430,6 +438,20 @@ Node* InspectorDOMAgent::assertNode(Protocol::ErrorString& errorString, Protocol
return node;
}
+Node* InspectorDOMAgent::assertNode(Protocol::ErrorString& errorString, Optional<Protocol::DOM::NodeId>&& nodeId, const String& objectId)
+{
+ Node* node = nullptr;
+ if (nodeId) {
+ node = assertNode(errorString, *nodeId);
+ } else if (!!objectId) {
+ node = nodeForObjectId(objectId);
+ if (!node)
+ errorString = "Missing node for given objectId"_s;
+ } else
+ errorString = "Either nodeId or objectId must be specified"_s;
+ return node;
+}
+
Document* InspectorDOMAgent::assertDocument(Protocol::ErrorString& errorString, Protocol::DOM::NodeId nodeId)
{
Node* node = assertNode(errorString, nodeId);
@@ -1389,16 +1411,7 @@ Protocol::ErrorStringOr<void> InspectorDOMAgent::highlightSelector(Ref<JSON::Obj
Protocol::ErrorStringOr<void> InspectorDOMAgent::highlightNode(Ref<JSON::Object>&& highlightInspectorObject, Optional<Protocol::DOM::NodeId>&& nodeId, const Protocol::Runtime::RemoteObjectId& objectId)
{
Protocol::ErrorString errorString;
-
- Node* node = nullptr;
- if (nodeId)
- node = assertNode(errorString, *nodeId);
- else if (!!objectId) {
- node = nodeForObjectId(objectId);
- errorString = "Missing node for given objectId"_s;
- } else
- errorString = "Either nodeId or objectId must be specified"_s;
-
+ Node* node = assertNode(errorString, WTFMove(nodeId), objectId);
if (!node)
return makeUnexpected(errorString);
@@ -1560,15 +1573,137 @@ Protocol::ErrorStringOr<void> InspectorDOMAgent::setInspectedNode(Protocol::DOM:
return { };
}
-Protocol::ErrorStringOr<Ref<Protocol::Runtime::RemoteObject>> InspectorDOMAgent::resolveNode(Protocol::DOM::NodeId nodeId, const String& objectGroup)
+static FloatPoint contentsToRootView(FrameView& containingView, const FloatPoint& point)
{
- Protocol::ErrorString errorString;
+ return containingView.convertToRootView(point - toFloatSize(containingView.documentScrollPositionRelativeToViewOrigin()));
+}
- Node* node = assertNode(errorString, nodeId);
+static void frameQuadToViewport(FrameView& containingView, FloatQuad& quad, float pageScaleFactor)
+{
+ // Return css (not dip) coordinates by scaling back.
+ quad.setP1(contentsToRootView(containingView, quad.p1()).scaled(1 / pageScaleFactor));
+ quad.setP2(contentsToRootView(containingView, quad.p2()).scaled(1 / pageScaleFactor));
+ quad.setP3(contentsToRootView(containingView, quad.p3()).scaled(1 / pageScaleFactor));
+ quad.setP4(contentsToRootView(containingView, quad.p4()).scaled(1 / pageScaleFactor));
+}
+
+static Ref<Inspector::Protocol::DOM::Quad> buildObjectForQuad(const FloatQuad& quad)
+{
+ auto result = Inspector::Protocol::DOM::Quad::create();
+ result->addItem(quad.p1().x());
+ result->addItem(quad.p1().y());
+ result->addItem(quad.p2().x());
+ result->addItem(quad.p2().y());
+ result->addItem(quad.p3().x());
+ result->addItem(quad.p3().y());
+ result->addItem(quad.p4().x());
+ result->addItem(quad.p4().y());
+ return result;
+}
+
+static Ref<JSON::ArrayOf<Inspector::Protocol::DOM::Quad>> buildArrayOfQuads(const Vector<FloatQuad>& quads)
+{
+ auto result = JSON::ArrayOf<Inspector::Protocol::DOM::Quad>::create();
+ for (const auto& quad : quads)
+ result->addItem(buildObjectForQuad(quad));
+ return result;
+}
+
+Inspector::Protocol::ErrorStringOr<std::tuple<String /* contentFrameId */, String /* ownerFrameId */>> InspectorDOMAgent::describeNode(const String& objectId)
+{
+ Node* node = nodeForObjectId(objectId);
+ if (!node)
+ return makeUnexpected("Node not found"_s);
+
+ auto* pageAgent = m_instrumentingAgents.enabledPageAgent();
+ if (!pageAgent)
+ return makeUnexpected("Page agent must be enabled"_s);
+
+ String ownerFrameId;
+ String frameId = pageAgent->frameId(node->document().frame());
+ if (!frameId.isEmpty())
+ ownerFrameId = frameId;
+
+ String contentFrameId;
+ if (is<HTMLFrameOwnerElement>(*node)) {
+ const auto& frameOwner = downcast<HTMLFrameOwnerElement>(*node);
+ String frameId = pageAgent->frameId(frameOwner.contentFrame());
+ if (!frameId.isEmpty())
+ contentFrameId = frameId;
+ }
+
+ return { { contentFrameId, ownerFrameId } };
+}
+
+Protocol::ErrorStringOr<void> InspectorDOMAgent::scrollIntoViewIfNeeded(const String& objectId, RefPtr<JSON::Object>&& rect)
+{
+ Node* node = nodeForObjectId(objectId);
+ if (!node)
+ return makeUnexpected("Node not found"_s);
+
+ m_inspectedPage.isolatedUpdateRendering();
+ if (!node->isConnected())
+ return makeUnexpected("Node is detached from document"_s);
+
+ RenderObject* renderer = node->renderer();
+ if (!renderer)
+ return makeUnexpected("Node does not have a layout object"_s);
+
+ bool insideFixed;
+ LayoutRect absoluteBounds = renderer->absoluteBoundingBoxRect(true, &insideFixed);
+ if (rect) {
+ Optional<double> x = rect->getDouble("x");
+ Optional<double> y = rect->getDouble("y");
+ Optional<double> width = rect->getDouble("width");
+ Optional<double> height = rect->getDouble("height");
+ if (!x || !y || !width || !height)
+ return makeUnexpected("Malformed rect"_s);
+
+ absoluteBounds.setX(absoluteBounds.x() + LayoutUnit(*x));
+ absoluteBounds.setY(absoluteBounds.y() + LayoutUnit(*y));
+ absoluteBounds.setWidth(LayoutUnit(std::max(*width, 1.0)));
+ absoluteBounds.setHeight(LayoutUnit(std::max(*height, 1.0)));
+ }
+ // Note: we should use ScrollAlignment::alignCenterIfNotVisible, but
+ // RenderLayer insists on no horizontal scroll if enough of the rect is visible.
+ ScrollAlignment alignment = ScrollAlignment::alignCenterAlways;
+ renderer->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, alignment, alignment, ShouldAllowCrossOriginScrolling::Yes });
+ return { };
+}
+
+Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Protocol::DOM::Quad>>> InspectorDOMAgent::getContentQuads(const String& objectId)
+{
+ Node* node = nodeForObjectId(objectId);
+ if (!node)
+ return makeUnexpected("Node not found"_s);
+
+ RenderObject* renderer = node->renderer();
+ if (!renderer)
+ return makeUnexpected("Node doesn't have renderer"_s);
+
+ // Ensure quads are up to date.
+ m_inspectedPage.isolatedUpdateRendering();
+
+ Frame* containingFrame = renderer->document().frame();
+ FrameView* containingView = containingFrame ? containingFrame->view() : nullptr;
+ if (!containingView)
+ return makeUnexpected("Internal error: no containing view"_s);
+
+ Vector<FloatQuad> quads;
+ renderer->absoluteQuads(quads);
+ for (auto& quad : quads)
+ frameQuadToViewport(*containingView, quad, m_inspectedPage.pageScaleFactor());
+ return buildArrayOfQuads(quads);
+}
+
+Protocol::ErrorStringOr<Ref<Protocol::Runtime::RemoteObject>> InspectorDOMAgent::resolveNode(Optional<Inspector::Protocol::DOM::NodeId>&& nodeId, const String& objectId, Optional<int>&& contextId, const String& objectGroup)
+{
+ Protocol::ErrorString errorString;
+ Node* node = assertNode(errorString, WTFMove(nodeId), objectId);
if (!node)
return makeUnexpected(errorString);
- auto object = resolveNode(node, objectGroup);
+ auto object = resolveNode(node, objectGroup, WTFMove(contextId));
if (!object)
return makeUnexpected("Missing injected script for given nodeId"_s);
@@ -2759,7 +2894,7 @@ Protocol::ErrorStringOr<Protocol::DOM::NodeId> InspectorDOMAgent::pushNodeByPath
return makeUnexpected("Missing node for given path"_s);
}
-RefPtr<Protocol::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
+RefPtr<Inspector::Protocol::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup, Optional<int>&& contextId)
{
Document* document = &node->document();
if (auto* templateHost = document->templateDocumentHost())
@@ -2768,12 +2903,16 @@ RefPtr<Protocol::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* nod
if (!frame)
return nullptr;
- auto& state = *mainWorldExecState(frame);
- auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state);
+ InjectedScript injectedScript;
+ if (contextId) {
+ injectedScript = m_injectedScriptManager.injectedScriptForId(*contextId);
+ } else {
+ injectedScript = m_injectedScriptManager.injectedScriptFor(mainWorldExecState(frame));
+ }
if (injectedScript.hasNoValue())
return nullptr;
- return injectedScript.wrapObject(nodeAsScriptValue(state, node), objectGroup);
+ return injectedScript.wrapObject(nodeAsScriptValue(*injectedScript.globalObject(), node), objectGroup);
}
Node* InspectorDOMAgent::scriptValueAsNode(JSC::JSValue value)
@@ -2796,4 +2935,42 @@ Protocol::ErrorStringOr<void> InspectorDOMAgent::setAllowEditingUserAgentShadowT
return { };
}
+Protocol::ErrorStringOr<void> InspectorDOMAgent::setInputFiles(const String& objectId, Ref<JSON::Array>&& files) {
+ InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
+ if (injectedScript.hasNoValue())
+ return makeUnexpected("Can not find element's context for given id"_s);
+
+ Node* node = scriptValueAsNode(injectedScript.findObjectById(objectId));
+ if (!node)
+ return makeUnexpected("Can not find element for given id"_s);
+
+ if (node->nodeType() != Node::ELEMENT_NODE || node->nodeName() != "INPUT")
+ return makeUnexpected("Not an input node"_s);
+
+ HTMLInputElement* element = static_cast<HTMLInputElement*>(node);
+ Vector<Ref<File>> fileObjects;
+ for (unsigned i = 0; i < files->length(); ++i) {
+ RefPtr<JSON::Value> item = files->get(i);
+ RefPtr<JSON::Object> obj = item->asObject();
+ if (!obj)
+ return makeUnexpected("Invalid file payload format"_s);
+
+ String name;
+ String type;
+ String data;
+ if (!obj->getString("name", name) || !obj->getString("type", type) || !obj->getString("data", data))
+ return makeUnexpected("Invalid file payload format"_s);
+
+ Vector<uint8_t> buffer;
+ if (!base64Decode(data, buffer))
+ return makeUnexpected("Unable to decode given content"_s);
+
+ ScriptExecutionContext* context = element->scriptExecutionContext();
+ fileObjects.append(File::create(context, Blob::create(context, SharedBuffer::create(WTFMove(buffer)), type), name));
+ }
+ RefPtr<FileList> fileList = FileList::create(WTFMove(fileObjects));
+ element->setFiles(WTFMove(fileList));
+ return { };
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.h b/Source/WebCore/inspector/agents/InspectorDOMAgent.h
index 87d6b91ac953d2b9af4b2cbd4270df4932647af3..57a90c4c09ca104b68a3052452747c3dfd15b31c 100644
--- a/Source/WebCore/inspector/agents/InspectorDOMAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.h
@@ -56,6 +56,7 @@ namespace WebCore {
class AXCoreObject;
class CharacterData;
+class Color;
class DOMEditor;
class Document;
class Element;
@@ -85,6 +86,7 @@ public:
static String toErrorString(Exception&&);
static String documentURLString(Document*);
+ static Color parseColor(RefPtr<JSON::Object>&&);
// We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently.
// We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics.
@@ -128,7 +130,7 @@ public:
Inspector::Protocol::ErrorStringOr<std::tuple<String /* searchId */, int /* resultCount */>> performSearch(const String& query, RefPtr<JSON::Array>&& nodeIds, Optional<bool>&& caseSensitive);
Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Inspector::Protocol::DOM::NodeId>>> getSearchResults(const String& searchId, int fromIndex, int toIndex);
Inspector::Protocol::ErrorStringOr<void> discardSearchResults(const String& searchId);
- Inspector::Protocol::ErrorStringOr<Ref<Inspector::Protocol::Runtime::RemoteObject>> resolveNode(Inspector::Protocol::DOM::NodeId, const String& objectGroup);
+ Inspector::Protocol::ErrorStringOr<Ref<Inspector::Protocol::Runtime::RemoteObject>> resolveNode(Optional<Inspector::Protocol::DOM::NodeId>&& nodeId, const String& objectId, Optional<int>&& contextId, const String& objectGroup);
Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<String>>> getAttributes(Inspector::Protocol::DOM::NodeId);
#if PLATFORM(IOS_FAMILY)
Inspector::Protocol::ErrorStringOr<void> setInspectModeEnabled(bool, RefPtr<JSON::Object>&& highlightConfig);
@@ -151,6 +153,10 @@ public:
Inspector::Protocol::ErrorStringOr<void> focus(Inspector::Protocol::DOM::NodeId);
Inspector::Protocol::ErrorStringOr<void> setInspectedNode(Inspector::Protocol::DOM::NodeId);
Inspector::Protocol::ErrorStringOr<void> setAllowEditingUserAgentShadowTrees(bool);
+ Inspector::Protocol::ErrorStringOr<std::tuple<String /* contentFrameId */, String /* ownerFrameId */>> describeNode(const String& objectId);
+ Inspector::Protocol::ErrorStringOr<void> scrollIntoViewIfNeeded(const String& objectId, RefPtr<JSON::Object>&& rect);
+ Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Inspector::Protocol::DOM::Quad>>> getContentQuads(const String& objectId);
+ Inspector::Protocol::ErrorStringOr<void> setInputFiles(const String& objectId, Ref<JSON::Array>&& files);
// InspectorInstrumentation
Inspector::Protocol::DOM::NodeId identifierForNode(Node&);
@@ -188,7 +194,7 @@ public:
Node* nodeForId(Inspector::Protocol::DOM::NodeId);
Inspector::Protocol::DOM::NodeId boundNodeId(const Node*);
- RefPtr<Inspector::Protocol::Runtime::RemoteObject> resolveNode(Node*, const String& objectGroup);
+ RefPtr<Inspector::Protocol::Runtime::RemoteObject> resolveNode(Node*, const String& objectGroup, Optional<int>&& contextId);
bool handleMousePress();
void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags);
void inspect(Node*);
@@ -199,12 +205,15 @@ public:
void reset();
Node* assertNode(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId);
+ Node* assertNode(Inspector::Protocol::ErrorString&, Optional<Inspector::Protocol::DOM::NodeId>&& nodeId, const String& objectId);
Element* assertElement(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId);
Document* assertDocument(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId);
RefPtr<JSC::Breakpoint> breakpointForEventListener(EventTarget&, const AtomString& eventType, EventListener&, bool capture);
Inspector::Protocol::DOM::EventListenerId idForEventListener(EventTarget&, const AtomString& eventType, EventListener&, bool capture);
+ Node* nodeForObjectId(const Inspector::Protocol::Runtime::RemoteObjectId&);
+
private:
#if ENABLE(VIDEO)
void mediaMetricsTimerFired();
@@ -233,7 +242,6 @@ private:
void processAccessibilityChildren(AXCoreObject&, JSON::ArrayOf<Inspector::Protocol::DOM::NodeId>&);
Node* nodeForPath(const String& path);
- Node* nodeForObjectId(const Inspector::Protocol::Runtime::RemoteObjectId&);
void discardBindings();
diff --git a/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h b/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h
index 3386cb879f1178c1b9635775c9a0e864f5b94c52..d2350182f5f061855e8ca172779ad60ee73b39fb 100644
--- a/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h
@@ -40,6 +40,7 @@ class DOMStorageFrontendDispatcher;
namespace WebCore {
+class Color;
class Frame;
class Page;
class SecurityOrigin;
diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp
index 575382e4390dd31dbf404fc72662b2206071c7e8..d6ec8d26d165b110872dea47fa09a9dfa751f37b 100644
--- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp
@@ -45,6 +45,7 @@
#include "DocumentThreadableLoader.h"
#include "FormData.h"
#include "Frame.h"
+#include "FormData.h"
#include "FrameLoader.h"
#include "HTTPHeaderMap.h"
#include "HTTPHeaderNames.h"
@@ -57,6 +58,7 @@
#include "MIMETypeRegistry.h"
#include "MemoryCache.h"
#include "NetworkResourcesData.h"
+#include "NetworkStateNotifier.h"
#include "Page.h"
#include "PlatformStrategies.h"
#include "ProgressTracker.h"
@@ -355,6 +357,8 @@ RefPtr<Protocol::Network::Response> InspectorNetworkAgent::buildObjectForResourc
.setSource(responseSource(response.source()))
.release();
+ responseObject->setRequestHeaders(buildObjectForHeaders(response.m_httpRequestHeaderFields));
+
if (resourceLoader)
responseObject->setTiming(buildObjectForTiming(response.deprecatedNetworkLoadMetricsOrNull(), *resourceLoader));
@@ -490,8 +494,14 @@ static InspectorPageAgent::ResourceType resourceTypeForLoadType(InspectorInstrum
void InspectorNetworkAgent::willSendRequest(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse)
{
- auto* cachedResource = loader ? InspectorPageAgent::cachedResource(loader->frame(), request.url()) : nullptr;
- willSendRequest(identifier, loader, request, redirectResponse, resourceTypeForCachedResource(cachedResource));
+ InspectorPageAgent::ResourceType resourceType;
+ if (request.initiatorIdentifier() == initiatorIdentifierForEventSource()) {
+ resourceType = InspectorPageAgent::EventSource;
+ } else {
+ auto* cachedResource = loader ? InspectorPageAgent::cachedResource(loader->frame(), request.url()) : nullptr;
+ resourceType = resourceTypeForCachedResource(cachedResource);
+ }
+ willSendRequest(identifier, loader, request, redirectResponse, resourceType);
}
void InspectorNetworkAgent::willSendRequestOfType(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, InspectorInstrumentation::LoadType loadType)
@@ -1105,8 +1115,7 @@ bool InspectorNetworkAgent::willIntercept(const ResourceRequest& request)
if (!m_interceptionEnabled)
return false;
- return shouldIntercept(request.url(), Protocol::Network::NetworkStage::Request)
- || shouldIntercept(request.url(), Protocol::Network::NetworkStage::Response);
+ return shouldIntercept(request.url(), Protocol::Network::NetworkStage::Response);
}
bool InspectorNetworkAgent::shouldInterceptRequest(const ResourceRequest& request)
@@ -1189,6 +1198,9 @@ Protocol::ErrorStringOr<void> InspectorNetworkAgent::interceptWithRequest(const
return makeUnexpected("Missing pending intercept request for given requestId"_s);
auto& loader = *pendingRequest->m_loader;
+ if (loader.reachedTerminalState())
+ return makeUnexpected("Unable to intercept request, it has already been processed"_s);
+
ResourceRequest request = loader.request();
if (!!url)
request.setURL(URL({ }, url));
@@ -1292,6 +1304,8 @@ Protocol::ErrorStringOr<void> InspectorNetworkAgent::interceptRequestWithRespons
response.setHTTPHeaderFields(WTFMove(explicitHeaders));
response.setHTTPHeaderField(HTTPHeaderName::ContentType, response.mimeType());
loader->didReceiveResponse(response, [loader, buffer = data.releaseNonNull()]() mutable {
+ if (loader->reachedTerminalState())
+ return;
if (buffer->size())
loader->didReceiveBuffer(WTFMove(buffer), buffer->size(), DataPayloadWholeResource);
loader->didFinishLoading(NetworkLoadMetrics());
@@ -1332,6 +1346,12 @@ Protocol::ErrorStringOr<void> InspectorNetworkAgent::interceptRequestWithError(c
return { };
}
+Inspector::Protocol::ErrorStringOr<void> InspectorNetworkAgent::setEmulateOfflineState(bool offline)
+{
+ platformStrategies()->loaderStrategy()->setEmulateOfflineState(offline);
+ return { };
+}
+
bool InspectorNetworkAgent::shouldTreatAsText(const String& mimeType)
{
return startsWithLettersIgnoringASCIICase(mimeType, "text/")
@@ -1373,6 +1393,12 @@ Optional<String> InspectorNetworkAgent::textContentForCachedResource(CachedResou
return WTF::nullopt;
}
+// static
+String InspectorNetworkAgent::initiatorIdentifierForEventSource()
+{
+ return "InspectorNetworkAgent: eventSource"_s;
+}
+
bool InspectorNetworkAgent::cachedResourceContent(CachedResource& resource, String* result, bool* base64Encoded)
{
ASSERT(result);
diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
index 933601761667417ebe5de301586869ccc64fc3da..f63a95c3c45980d5606971b83881e8245df11403 100644
--- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
@@ -71,6 +71,7 @@ public:
static Ref<TextResourceDecoder> createTextDecoder(const String& mimeType, const String& textEncodingName);
static Optional<String> textContentForCachedResource(CachedResource&);
static bool cachedResourceContent(CachedResource&, String* result, bool* base64Encoded);
+ static String initiatorIdentifierForEventSource();
// InspectorAgentBase
void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) final;
@@ -93,6 +94,7 @@ public:
Inspector::Protocol::ErrorStringOr<void> interceptWithResponse(const Inspector::Protocol::Network::RequestId&, const String& content, bool base64Encoded, const String& mimeType, Optional<int>&& status, const String& statusText, RefPtr<JSON::Object>&& headers) final;
Inspector::Protocol::ErrorStringOr<void> interceptRequestWithResponse(const Inspector::Protocol::Network::RequestId&, const String& content, bool base64Encoded, const String& mimeType, int status, const String& statusText, Ref<JSON::Object>&& headers) final;
Inspector::Protocol::ErrorStringOr<void> interceptRequestWithError(const Inspector::Protocol::Network::RequestId&, Inspector::Protocol::Network::ResourceErrorType) final;
+ Inspector::Protocol::ErrorStringOr<void> setEmulateOfflineState(bool offline) final;
// InspectorInstrumentation
void willRecalculateStyle();
diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
index 6f13bd503d9858fd603a7954d16376da1cc1eb42..601ed22c19fd0fd8115ea9ee9ab7fdfe194283b6 100644
--- a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
@@ -32,19 +32,25 @@
#include "config.h"
#include "InspectorPageAgent.h"
+#include "AXObjectCache.h"
+#include "BackForwardController.h"
#include "CachedResource.h"
#include "CachedResourceLoader.h"
#include "Cookie.h"
#include "CookieJar.h"
+#include "CustomHeaderFields.h"
#include "DOMWrapperWorld.h"
#include "Document.h"
#include "DocumentLoader.h"
+#include "FocusController.h"
#include "Frame.h"
#include "FrameLoadRequest.h"
#include "FrameLoader.h"
+#include "FrameLoaderClient.h"
#include "FrameSnapshotting.h"
#include "FrameView.h"
#include "HTMLFrameOwnerElement.h"
+#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "ImageBuffer.h"
#include "InspectorClient.h"
@@ -55,19 +61,28 @@
#include "MIMETypeRegistry.h"
#include "MemoryCache.h"
#include "Page.h"
+#include "PageRuntimeAgent.h"
#include "RenderObject.h"
#include "RenderTheme.h"
+#include "RuntimeEnabledFeatures.h"
#include "ScriptController.h"
#include "ScriptSourceCode.h"
+#include "ScriptState.h"
#include "SecurityOrigin.h"
#include "Settings.h"
#include "StyleScope.h"
#include "TextEncoding.h"
+#include "TypingCommand.h"
#include "UserGestureIndicator.h"
#include <JavaScriptCore/ContentSearchUtilities.h>
#include <JavaScriptCore/IdentifiersFactory.h>
+#include <JavaScriptCore/InjectedScriptManager.h>
#include <JavaScriptCore/RegularExpression.h>
+#include <wtf/DateMath.h>
#include <wtf/ListHashSet.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/Ref.h>
+#include <wtf/RefPtr.h>
#include <wtf/Stopwatch.h>
#include <wtf/text/Base64.h>
#include <wtf/text/StringBuilder.h>
@@ -80,11 +95,15 @@
#include "LegacyWebArchive.h"
#endif
-
namespace WebCore {
using namespace Inspector;
+static HashMap<String, Ref<DOMWrapperWorld>>& createdUserWorlds() {
+ static NeverDestroyed<HashMap<String, Ref<DOMWrapperWorld>>> nameToWorld;
+ return nameToWorld;
+}
+
static bool decodeBuffer(const char* buffer, unsigned size, const String& textEncodingName, String* result)
{
if (buffer) {
@@ -234,6 +253,8 @@ Protocol::Page::ResourceType InspectorPageAgent::resourceTypeJSON(InspectorPageA
return Protocol::Page::ResourceType::Beacon;
case WebSocketResource:
return Protocol::Page::ResourceType::WebSocket;
+ case EventSource:
+ return Protocol::Page::ResourceType::EventSource;
case OtherResource:
return Protocol::Page::ResourceType::Other;
#if ENABLE(APPLICATION_MANIFEST)
@@ -321,6 +342,7 @@ InspectorPageAgent::InspectorPageAgent(PageAgentContext& context, InspectorClien
, m_frontendDispatcher(makeUnique<Inspector::PageFrontendDispatcher>(context.frontendRouter))
, m_backendDispatcher(Inspector::PageBackendDispatcher::create(context.backendDispatcher, this))
, m_inspectedPage(context.inspectedPage)
+ , m_injectedScriptManager(context.injectedScriptManager)
, m_client(client)
, m_overlay(overlay)
{
@@ -352,12 +374,20 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::enable()
defaultAppearanceDidChange(m_inspectedPage.defaultUseDarkAppearance());
#endif
+ if (!createdUserWorlds().isEmpty()) {
+ Vector<DOMWrapperWorld*> worlds;
+ for (const auto& world : createdUserWorlds().values())
+ worlds.append(world.ptr());
+ ensureUserWorldsExistInAllFrames(worlds);
+ }
return { };
}
Protocol::ErrorStringOr<void> InspectorPageAgent::disable()
{
m_instrumentingAgents.setEnabledPageAgent(nullptr);
+ m_interceptFileChooserDialog = false;
+ m_bypassCSP = false;
setShowPaintRects(false);
#if !PLATFORM(IOS_FAMILY)
@@ -406,6 +436,22 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::reload(Optional<bool>&& ignore
return { };
}
+Protocol::ErrorStringOr<void> InspectorPageAgent::goBack()
+{
+ if (!m_inspectedPage.backForward().goBack())
+ return makeUnexpected("Failed to go back"_s);
+
+ return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::goForward()
+{
+ if (!m_inspectedPage.backForward().goForward())
+ return makeUnexpected("Failed to go forward"_s);
+
+ return { };
+}
+
Protocol::ErrorStringOr<void> InspectorPageAgent::navigate(const String& url)
{
UserGestureIndicator indicator { ProcessingUserGesture };
@@ -801,15 +847,16 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::setShowPaintRects(bool show)
return { };
}
-void InspectorPageAgent::domContentEventFired()
+void InspectorPageAgent::domContentEventFired(Frame& frame)
{
- m_isFirstLayoutAfterOnLoad = true;
- m_frontendDispatcher->domContentEventFired(timestamp());
+ if (frame.isMainFrame())
+ m_isFirstLayoutAfterOnLoad = true;
+ m_frontendDispatcher->domContentEventFired(timestamp(), frameId(&frame));
}
-void InspectorPageAgent::loadEventFired()
+void InspectorPageAgent::loadEventFired(Frame& frame)
{
- m_frontendDispatcher->loadEventFired(timestamp());
+ m_frontendDispatcher->loadEventFired(timestamp(), frameId(&frame));
}
void InspectorPageAgent::frameNavigated(Frame& frame)
@@ -817,13 +864,23 @@ void InspectorPageAgent::frameNavigated(Frame& frame)
m_frontendDispatcher->frameNavigated(buildObjectForFrame(&frame));
}
+String InspectorPageAgent::makeFrameID(ProcessIdentifier processID, FrameIdentifier frameID)
+{
+ return makeString(processID.toUInt64(), ".", frameID.toUInt64());
+}
+
+static String globalIDForFrame(Frame& frame)
+{
+ return InspectorPageAgent::makeFrameID(Process::identifier(), *frame.loader().client().frameID());
+}
+
void InspectorPageAgent::frameDetached(Frame& frame)
{
- auto identifier = m_frameToIdentifier.take(&frame);
- if (identifier.isNull())
+ String identifier = globalIDForFrame(frame);
+ if (!m_identifierToFrame.take(identifier))
return;
+
m_frontendDispatcher->frameDetached(identifier);
- m_identifierToFrame.remove(identifier);
}
Frame* InspectorPageAgent::frameForId(const Protocol::Network::FrameId& frameId)
@@ -835,20 +892,18 @@ String InspectorPageAgent::frameId(Frame* frame)
{
if (!frame)
return emptyString();
- return m_frameToIdentifier.ensure(frame, [this, frame] {
- auto identifier = IdentifiersFactory::createIdentifier();
- m_identifierToFrame.set(identifier, frame);
- return identifier;
- }).iterator->value;
+
+ String identifier = globalIDForFrame(*frame);
+ m_identifierToFrame.set(identifier, frame);
+ return identifier;
}
String InspectorPageAgent::loaderId(DocumentLoader* loader)
{
if (!loader)
return emptyString();
- return m_loaderToIdentifier.ensure(loader, [] {
- return IdentifiersFactory::createIdentifier();
- }).iterator->value;
+
+ return String::number(loader->loaderIDForInspector());
}
Frame* InspectorPageAgent::assertFrame(Protocol::ErrorString& errorString, const Protocol::Network::FrameId& frameId)
@@ -859,11 +914,6 @@ Frame* InspectorPageAgent::assertFrame(Protocol::ErrorString& errorString, const
return frame;
}
-void InspectorPageAgent::loaderDetachedFromFrame(DocumentLoader& loader)
-{
- m_loaderToIdentifier.remove(&loader);
-}
-
void InspectorPageAgent::frameStartedLoading(Frame& frame)
{
m_frontendDispatcher->frameStartedLoading(frameId(&frame));
@@ -884,6 +934,12 @@ void InspectorPageAgent::frameClearedScheduledNavigation(Frame& frame)
m_frontendDispatcher->frameClearedScheduledNavigation(frameId(&frame));
}
+void InspectorPageAgent::didNavigateWithinPage(Frame& frame)
+{
+ String url = frame.document()->url().string();
+ m_frontendDispatcher->navigatedWithinDocument(frameId(&frame), url);
+}
+
#if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
void InspectorPageAgent::defaultAppearanceDidChange(bool useDarkAppearance)
{
@@ -943,6 +999,52 @@ void InspectorPageAgent::didRecalculateStyle()
m_overlay->update();
}
+void InspectorPageAgent::runOpenPanel(HTMLInputElement* element, bool* intercept)
+{
+ if (m_interceptFileChooserDialog) {
+ *intercept = true;
+ } else {
+ return;
+ }
+ Document& document = element->document();
+ auto* frame = document.frame();
+ if (!frame)
+ return;
+
+ auto& state = *mainWorldExecState(frame);
+ auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state);
+ if (injectedScript.hasNoValue())
+ return;
+
+ auto object = injectedScript.wrapObject(InspectorDOMAgent::nodeAsScriptValue(state, element), WTF::String());
+ if (!object)
+ return;
+
+ m_frontendDispatcher->fileChooserOpened(frameId(frame), object.releaseNonNull());
+}
+
+void InspectorPageAgent::frameAttached(Frame& frame)
+{
+ Frame* parent = frame.tree().parent();
+ String parentFrameId = frameId(parent);
+ m_frontendDispatcher->frameAttached(frameId(&frame), parentFrameId);
+}
+
+bool InspectorPageAgent::shouldBypassCSP()
+{
+ return m_bypassCSP;
+}
+
+void InspectorPageAgent::willCheckNewWindowPolicy(const URL& url)
+{
+ m_frontendDispatcher->willRequestOpenWindow(url.string());
+}
+
+void InspectorPageAgent::didCheckNewWindowPolicy(bool allowed)
+{
+ m_frontendDispatcher->didRequestOpenWindow(allowed);
+}
+
Ref<Protocol::Page::Frame> InspectorPageAgent::buildObjectForFrame(Frame* frame)
{
ASSERT_ARG(frame, frame);
@@ -1094,6 +1196,27 @@ Protocol::ErrorStringOr<String> InspectorPageAgent::snapshotRect(int x, int y, i
return snapshot->toDataURL("image/png"_s, WTF::nullopt, PreserveResolution::Yes);
}
+Protocol::ErrorStringOr<void> InspectorPageAgent::setTimeZone(const String& timeZone)
+{
+ bool success = WTF::setTimeZoneForAutomation(timeZone);
+ if (!success)
+ return makeUnexpected("Invalid time zone " + timeZone);
+
+ return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setTouchEmulationEnabled(bool enabled)
+{
+#if ENABLE(TOUCH_EVENTS)
+ RuntimeEnabledFeatures::sharedFeatures().setTouchEventsEnabled(enabled);
+ return { };
+#else
+ UNUSED_PARAM(enabled);
+ return makeUnexpected("Not supported"_s);
+#endif
+}
+
+
#if ENABLE(WEB_ARCHIVE) && USE(CF)
Protocol::ErrorStringOr<String> InspectorPageAgent::archive()
{
@@ -1106,7 +1229,6 @@ Protocol::ErrorStringOr<String> InspectorPageAgent::archive()
}
#endif
-#if !PLATFORM(COCOA)
Protocol::ErrorStringOr<void> InspectorPageAgent::setScreenSizeOverride(Optional<int>&& width, Optional<int>&& height)
{
if (width.hasValue() != height.hasValue())
@@ -1121,6 +1243,533 @@ Protocol::ErrorStringOr<void> InspectorPageAgent::setScreenSizeOverride(Optional
m_inspectedPage.mainFrame().setOverrideScreenSize(FloatSize(width.valueOr(0), height.valueOr(0)));
return { };
}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::insertText(const String& text)
+{
+ UserGestureIndicator indicator { ProcessingUserGesture };
+ Document* focusedDocument = m_inspectedPage.focusController().focusedOrMainFrame().document();
+ TypingCommand::insertText(*focusedDocument, text, 0);
+ return { };
+}
+
+static String roleFromObject(RefPtr<AXCoreObject> axObject)
+{
+ String computedRoleString = axObject->computedRoleString();
+ if (!computedRoleString.isEmpty())
+ return computedRoleString;
+ AccessibilityRole role = axObject->roleValue();
+ switch(role) {
+ case AccessibilityRole::Annotation:
+ return "Annotation";
+ case AccessibilityRole::Application:
+ return "Application";
+ case AccessibilityRole::ApplicationAlert:
+ return "ApplicationAlert";
+ case AccessibilityRole::ApplicationAlertDialog:
+ return "ApplicationAlertDialog";
+ case AccessibilityRole::ApplicationDialog:
+ return "ApplicationDialog";
+ case AccessibilityRole::ApplicationGroup:
+ return "ApplicationGroup";
+ case AccessibilityRole::ApplicationLog:
+ return "ApplicationLog";
+ case AccessibilityRole::ApplicationMarquee:
+ return "ApplicationMarquee";
+ case AccessibilityRole::ApplicationStatus:
+ return "ApplicationStatus";
+ case AccessibilityRole::ApplicationTextGroup:
+ return "ApplicationTextGroup";
+ case AccessibilityRole::ApplicationTimer:
+ return "ApplicationTimer";
+ case AccessibilityRole::Audio:
+ return "Audio";
+ case AccessibilityRole::Blockquote:
+ return "Blockquote";
+ case AccessibilityRole::Browser:
+ return "Browser";
+ case AccessibilityRole::BusyIndicator:
+ return "BusyIndicator";
+ case AccessibilityRole::Button:
+ return "Button";
+ case AccessibilityRole::Canvas:
+ return "Canvas";
+ case AccessibilityRole::Caption:
+ return "Caption";
+ case AccessibilityRole::Cell:
+ return "Cell";
+ case AccessibilityRole::CheckBox:
+ return "CheckBox";
+ case AccessibilityRole::ColorWell:
+ return "ColorWell";
+ case AccessibilityRole::Column:
+ return "Column";
+ case AccessibilityRole::ColumnHeader:
+ return "ColumnHeader";
+ case AccessibilityRole::ComboBox:
+ return "ComboBox";
+ case AccessibilityRole::Definition:
+ return "Definition";
+ case AccessibilityRole::Deletion:
+ return "Deletion";
+ case AccessibilityRole::DescriptionList:
+ return "DescriptionList";
+ case AccessibilityRole::DescriptionListTerm:
+ return "DescriptionListTerm";
+ case AccessibilityRole::DescriptionListDetail:
+ return "DescriptionListDetail";
+ case AccessibilityRole::Details:
+ return "Details";
+ case AccessibilityRole::Directory:
+ return "Directory";
+ case AccessibilityRole::DisclosureTriangle:
+ return "DisclosureTriangle";
+ case AccessibilityRole::Div:
+ return "Div";
+ case AccessibilityRole::Document:
+ return "Document";
+ case AccessibilityRole::DocumentArticle:
+ return "DocumentArticle";
+ case AccessibilityRole::DocumentMath:
+ return "DocumentMath";
+ case AccessibilityRole::DocumentNote:
+ return "DocumentNote";
+ case AccessibilityRole::Drawer:
+ return "Drawer";
+ case AccessibilityRole::EditableText:
+ return "EditableText";
+ case AccessibilityRole::Feed:
+ return "Feed";
+ case AccessibilityRole::Figure:
+ return "Figure";
+ case AccessibilityRole::Footer:
+ return "Footer";
+ case AccessibilityRole::Footnote:
+ return "Footnote";
+ case AccessibilityRole::Form:
+ return "Form";
+ case AccessibilityRole::GraphicsDocument:
+ return "GraphicsDocument";
+ case AccessibilityRole::GraphicsObject:
+ return "GraphicsObject";
+ case AccessibilityRole::GraphicsSymbol:
+ return "GraphicsSymbol";
+ case AccessibilityRole::Grid:
+ return "Grid";
+ case AccessibilityRole::GridCell:
+ return "GridCell";
+ case AccessibilityRole::Group:
+ return "Group";
+ case AccessibilityRole::GrowArea:
+ return "GrowArea";
+ case AccessibilityRole::Heading:
+ return "Heading";
+ case AccessibilityRole::HelpTag:
+ return "HelpTag";
+ case AccessibilityRole::HorizontalRule:
+ return "HorizontalRule";
+ case AccessibilityRole::Ignored:
+ return "Ignored";
+ case AccessibilityRole::Inline:
+ return "Inline";
+ case AccessibilityRole::Image:
+ return "Image";
+ case AccessibilityRole::ImageMap:
+ return "ImageMap";
+ case AccessibilityRole::ImageMapLink:
+ return "ImageMapLink";
+ case AccessibilityRole::Incrementor:
+ return "Incrementor";
+ case AccessibilityRole::Insertion:
+ return "Insertion";
+ case AccessibilityRole::Label:
+ return "Label";
+ case AccessibilityRole::LandmarkBanner:
+ return "LandmarkBanner";
+ case AccessibilityRole::LandmarkComplementary:
+ return "LandmarkComplementary";
+ case AccessibilityRole::LandmarkContentInfo:
+ return "LandmarkContentInfo";
+ case AccessibilityRole::LandmarkDocRegion:
+ return "LandmarkDocRegion";
+ case AccessibilityRole::LandmarkMain:
+ return "LandmarkMain";
+ case AccessibilityRole::LandmarkNavigation:
+ return "LandmarkNavigation";
+ case AccessibilityRole::LandmarkRegion:
+ return "LandmarkRegion";
+ case AccessibilityRole::LandmarkSearch:
+ return "LandmarkSearch";
+ case AccessibilityRole::Legend:
+ return "Legend";
+ case AccessibilityRole::Link:
+ return "Link";
+ case AccessibilityRole::List:
+ return "List";
+ case AccessibilityRole::ListBox:
+ return "ListBox";
+ case AccessibilityRole::ListBoxOption:
+ return "ListBoxOption";
+ case AccessibilityRole::ListItem:
+ return "ListItem";
+ case AccessibilityRole::ListMarker:
+ return "ListMarker";
+ case AccessibilityRole::Mark:
+ return "Mark";
+ case AccessibilityRole::MathElement:
+ return "MathElement";
+ case AccessibilityRole::Matte:
+ return "Matte";
+ case AccessibilityRole::Menu:
+ return "Menu";
+ case AccessibilityRole::MenuBar:
+ return "MenuBar";
+ case AccessibilityRole::MenuButton:
+ return "MenuButton";
+ case AccessibilityRole::MenuItem:
+ return "MenuItem";
+ case AccessibilityRole::MenuItemCheckbox:
+ return "MenuItemCheckbox";
+ case AccessibilityRole::MenuItemRadio:
+ return "MenuItemRadio";
+ case AccessibilityRole::MenuListPopup:
+ return "MenuListPopup";
+ case AccessibilityRole::MenuListOption:
+ return "MenuListOption";
+ case AccessibilityRole::Meter:
+ return "Meter";
+ case AccessibilityRole::Outline:
+ return "Outline";
+ case AccessibilityRole::Paragraph:
+ return "Paragraph";
+ case AccessibilityRole::PopUpButton:
+ return "PopUpButton";
+ case AccessibilityRole::Pre:
+ return "Pre";
+ case AccessibilityRole::Presentational:
+ return "Presentational";
+ case AccessibilityRole::ProgressIndicator:
+ return "ProgressIndicator";
+ case AccessibilityRole::RadioButton:
+ return "RadioButton";
+ case AccessibilityRole::RadioGroup:
+ return "RadioGroup";
+ case AccessibilityRole::RowHeader:
+ return "RowHeader";
+ case AccessibilityRole::Row:
+ return "Row";
+ case AccessibilityRole::RowGroup:
+ return "RowGroup";
+ case AccessibilityRole::RubyBase:
+ return "RubyBase";
+ case AccessibilityRole::RubyBlock:
+ return "RubyBlock";
+ case AccessibilityRole::RubyInline:
+ return "RubyInline";
+ case AccessibilityRole::RubyRun:
+ return "RubyRun";
+ case AccessibilityRole::RubyText:
+ return "RubyText";
+ case AccessibilityRole::Ruler:
+ return "Ruler";
+ case AccessibilityRole::RulerMarker:
+ return "RulerMarker";
+ case AccessibilityRole::ScrollArea:
+ return "ScrollArea";
+ case AccessibilityRole::ScrollBar:
+ return "ScrollBar";
+ case AccessibilityRole::SearchField:
+ return "SearchField";
+ case AccessibilityRole::Sheet:
+ return "Sheet";
+ case AccessibilityRole::Slider:
+ return "Slider";
+ case AccessibilityRole::SliderThumb:
+ return "SliderThumb";
+ case AccessibilityRole::SpinButton:
+ return "SpinButton";
+ case AccessibilityRole::SpinButtonPart:
+ return "SpinButtonPart";
+ case AccessibilityRole::SplitGroup:
+ return "SplitGroup";
+ case AccessibilityRole::Splitter:
+ return "Splitter";
+ case AccessibilityRole::StaticText:
+ return "StaticText";
+ case AccessibilityRole::Subscript:
+ return "Subscript";
+ case AccessibilityRole::Summary:
+ return "Summary";
+ case AccessibilityRole::Superscript:
+ return "Superscript";
+ case AccessibilityRole::Switch:
+ return "Switch";
+ case AccessibilityRole::SystemWide:
+ return "SystemWide";
+ case AccessibilityRole::SVGRoot:
+ return "SVGRoot";
+ case AccessibilityRole::SVGText:
+ return "SVGText";
+ case AccessibilityRole::SVGTSpan:
+ return "SVGTSpan";
+ case AccessibilityRole::SVGTextPath:
+ return "SVGTextPath";
+ case AccessibilityRole::TabGroup:
+ return "TabGroup";
+ case AccessibilityRole::TabList:
+ return "TabList";
+ case AccessibilityRole::TabPanel:
+ return "TabPanel";
+ case AccessibilityRole::Tab:
+ return "Tab";
+ case AccessibilityRole::Table:
+ return "Table";
+ case AccessibilityRole::TableHeaderContainer:
+ return "TableHeaderContainer";
+ case AccessibilityRole::TextArea:
+ return "TextArea";
+ case AccessibilityRole::TextGroup:
+ return "TextGroup";
+ case AccessibilityRole::Term:
+ return "Term";
+ case AccessibilityRole::Time:
+ return "Time";
+ case AccessibilityRole::Tree:
+ return "Tree";
+ case AccessibilityRole::TreeGrid:
+ return "TreeGrid";
+ case AccessibilityRole::TreeItem:
+ return "TreeItem";
+ case AccessibilityRole::TextField:
+ return "TextField";
+ case AccessibilityRole::ToggleButton:
+ return "ToggleButton";
+ case AccessibilityRole::Toolbar:
+ return "Toolbar";
+ case AccessibilityRole::Unknown:
+ return "Unknown";
+ case AccessibilityRole::UserInterfaceTooltip:
+ return "UserInterfaceTooltip";
+ case AccessibilityRole::ValueIndicator:
+ return "ValueIndicator";
+ case AccessibilityRole::Video:
+ return "Video";
+ case AccessibilityRole::WebApplication:
+ return "WebApplication";
+ case AccessibilityRole::WebArea:
+ return "WebArea";
+ case AccessibilityRole::WebCoreLink:
+ return "WebCoreLink";
+ case AccessibilityRole::Window:
+ return "Window";
+ };
+ return "Unknown";
+}
+
+static Ref<Inspector::Protocol::Page::AXNode> snapshotForAXObject(RefPtr<AXCoreObject> axObject, Node* nodeToFind)
+{
+ auto axNode = Inspector::Protocol::Page::AXNode::create()
+ .setRole(roleFromObject(axObject))
+ .release();
+
+ if (!axObject->computedLabel().isEmpty())
+ axNode->setName(axObject->computedLabel());
+ if (!axObject->stringValue().isEmpty())
+ axNode->setValue(JSON::Value::create(axObject->stringValue()));
+ if (!axObject->accessibilityDescription().isEmpty())
+ axNode->setDescription(axObject->accessibilityDescription());
+ if (!axObject->keyShortcutsValue().isEmpty())
+ axNode->setKeyshortcuts(axObject->keyShortcutsValue());
+ if (!axObject->valueDescription().isEmpty())
+ axNode->setValuetext(axObject->valueDescription());
+ if (!axObject->roleDescription().isEmpty())
+ axNode->setRoledescription(axObject->roleDescription());
+ if (!axObject->isEnabled())
+ axNode->setDisabled(!axObject->isEnabled());
+ if (axObject->supportsExpanded())
+ axNode->setExpanded(axObject->isExpanded());
+ if (axObject->isFocused())
+ axNode->setFocused(axObject->isFocused());
+ if (axObject->isModalNode())
+ axNode->setModal(axObject->isModalNode());
+ bool multiline = axObject->ariaIsMultiline() || axObject->roleValue() == AccessibilityRole::TextArea;
+ if (multiline)
+ axNode->setMultiline(multiline);
+ if (axObject->isMultiSelectable())
+ axNode->setMultiselectable(axObject->isMultiSelectable());
+ if (axObject->supportsReadOnly() && !axObject->canSetValueAttribute() && axObject->isEnabled())
+ axNode->setReadonly(true);
+ if (axObject->supportsRequiredAttribute())
+ axNode->setRequired(axObject->isRequired());
+ if (axObject->isSelected())
+ axNode->setSelected(axObject->isSelected());
+ if (axObject->supportsChecked()) {
+ AccessibilityButtonState checkedState = axObject->checkboxOrRadioValue();
+ switch (checkedState) {
+ case AccessibilityButtonState::On:
+ axNode->setChecked(Inspector::Protocol::Page::AXNode::Checked::True);
+ break;
+ case AccessibilityButtonState::Off:
+ axNode->setChecked(Inspector::Protocol::Page::AXNode::Checked::False);
+ break;
+ case AccessibilityButtonState::Mixed:
+ axNode->setChecked(Inspector::Protocol::Page::AXNode::Checked::Mixed);
+ break;
+ }
+ }
+ if (axObject->supportsPressed()) {
+ AccessibilityButtonState checkedState = axObject->checkboxOrRadioValue();
+ switch (checkedState) {
+ case AccessibilityButtonState::On:
+ axNode->setPressed(Inspector::Protocol::Page::AXNode::Pressed::True);
+ break;
+ case AccessibilityButtonState::Off:
+ axNode->setPressed(Inspector::Protocol::Page::AXNode::Pressed::False);
+ break;
+ case AccessibilityButtonState::Mixed:
+ axNode->setPressed(Inspector::Protocol::Page::AXNode::Pressed::Mixed);
+ break;
+ }
+ }
+ unsigned level = axObject->hierarchicalLevel() ? axObject->hierarchicalLevel() : axObject->headingLevel();
+ if (level)
+ axNode->setLevel(level);
+ if (axObject->minValueForRange() != 0)
+ axNode->setValuemin(axObject->minValueForRange());
+ if (axObject->maxValueForRange() != 0)
+ axNode->setValuemax(axObject->maxValueForRange());
+ if (axObject->supportsAutoComplete())
+ axNode->setAutocomplete(axObject->autoCompleteValue());
+ if (axObject->hasPopup())
+ axNode->setHaspopup(axObject->popupValue());
+
+ String invalidValue = axObject->invalidStatus();
+ if (invalidValue != "false") {
+ if (invalidValue == "grammar")
+ axNode->setInvalid(Inspector::Protocol::Page::AXNode::Invalid::Grammar);
+ else if (invalidValue == "spelling")
+ axNode->setInvalid(Inspector::Protocol::Page::AXNode::Invalid::Spelling);
+ else // Future versions of ARIA may allow additional truthy values. Ex. format, order, or size.
+ axNode->setInvalid(Inspector::Protocol::Page::AXNode::Invalid::True);
+ }
+ switch (axObject->orientation()) {
+ case AccessibilityOrientation::Undefined:
+ break;
+ case AccessibilityOrientation::Vertical:
+ axNode->setOrientation("vertical"_s);
+ break;
+ case AccessibilityOrientation::Horizontal:
+ axNode->setOrientation("horizontal"_s);
+ break;
+ }
+
+ if (axObject->isKeyboardFocusable())
+ axNode->setFocusable(axObject->isKeyboardFocusable());
+
+ if (nodeToFind && axObject->node() == nodeToFind)
+ axNode->setFound(true);
+
+ if (axObject->hasChildren()) {
+ Ref<JSON::ArrayOf<Inspector::Protocol::Page::AXNode>> children = JSON::ArrayOf<Inspector::Protocol::Page::AXNode>::create();
+ for (auto& childObject : axObject->children())
+ children->addItem(snapshotForAXObject(childObject, nodeToFind));
+ axNode->setChildren(WTFMove(children));
+ }
+ return axNode;
+}
+
+
+Protocol::ErrorStringOr<Ref<Protocol::Page::AXNode>> InspectorPageAgent::accessibilitySnapshot(const String& objectId)
+{
+ if (!WebCore::AXObjectCache::accessibilityEnabled())
+ WebCore::AXObjectCache::enableAccessibility();
+ auto document = makeRefPtr(m_inspectedPage.mainFrame().document());
+ if (!document)
+ return makeUnexpected("No document for main frame"_s);
+
+ AXObjectCache* axObjectCache = document->axObjectCache();
+ if (!axObjectCache)
+ return makeUnexpected("No AXObjectCache for main document"_s);
+
+ AXCoreObject* axObject = axObjectCache->rootObject();
+ if (!axObject)
+ return makeUnexpected("No AXObject for main document"_s);
+
+ Node* node = nullptr;
+ if (!objectId.isEmpty()) {
+ InspectorDOMAgent* domAgent = m_instrumentingAgents.persistentDOMAgent();
+ ASSERT(domAgent);
+ node = domAgent->nodeForObjectId(objectId);
+ if (!node)
+ return makeUnexpected("No Node for objectId"_s);
+ }
+
+ m_doingAccessibilitySnapshot = true;
+ Ref<Inspector::Protocol::Page::AXNode> axNode = snapshotForAXObject(makeRefPtr(axObject), node);
+ m_doingAccessibilitySnapshot = false;
+ return axNode;
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setInterceptFileChooserDialog(bool enabled)
+{
+ m_interceptFileChooserDialog = enabled;
+ return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setDefaultBackgroundColorOverride(RefPtr<JSON::Object>&& color)
+{
+ FrameView* view = m_inspectedPage.mainFrame().view();
+ if (!view)
+ return makeUnexpected("Internal error: No frame view to set color two"_s);
+
+ if (!color) {
+ view->updateBackgroundRecursively(Optional<Color>());
+ return { };
+ }
+
+ view->updateBackgroundRecursively(InspectorDOMAgent::parseColor(WTFMove(color)));
+ return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::createUserWorld(const String& name)
+{
+ if (createdUserWorlds().contains(name))
+ return makeUnexpected("World with the given name already exists"_s);
+
+ Ref<DOMWrapperWorld> world = ScriptController::createWorld(name, ScriptController::WorldType::User);
+ ensureUserWorldsExistInAllFrames({world.ptr()});
+ createdUserWorlds().set(name, WTFMove(world));
+ return { };
+}
+
+void InspectorPageAgent::ensureUserWorldsExistInAllFrames(const Vector<DOMWrapperWorld*>& worlds)
+{
+ for (Frame* frame = &m_inspectedPage.mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ for (auto* world : worlds)
+ frame->windowProxy().jsWindowProxy(*world)->window();
+ }
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setBypassCSP(bool enabled)
+{
+ m_bypassCSP = enabled;
+ return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::crash()
+{
+ CRASH();
+ return { };
+}
+
+Protocol::ErrorStringOr<void> InspectorPageAgent::setOrientationOverride(Optional<int>&& angle)
+{
+#if ENABLE(ORIENTATION_EVENTS)
+ m_inspectedPage.setOverrideOrientation(WTFMove(angle));
+ return { };
+#else
+ UNUSED_PARAM(angle);
+ return makeUnexpected("Orientation events are disabled in this build");
#endif
+}
} // namespace WebCore
diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.h b/Source/WebCore/inspector/agents/InspectorPageAgent.h
index bf88345253bb7295ce5ccda0356355d123d27be0..6cecbc95e6fb4ad88888c3027adcfd1d518313e8 100644
--- a/Source/WebCore/inspector/agents/InspectorPageAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorPageAgent.h
@@ -34,17 +34,23 @@
#include "CachedResource.h"
#include "InspectorWebAgentBase.h"
#include "LayoutRect.h"
+#include "ProcessIdentifier.h"
#include <JavaScriptCore/InspectorBackendDispatchers.h>
#include <JavaScriptCore/InspectorFrontendDispatchers.h>
#include <wtf/HashMap.h>
#include <wtf/Seconds.h>
#include <wtf/text/WTFString.h>
+namespace Inspector {
+class InjectedScriptManager;
+}
+
namespace WebCore {
class DOMWrapperWorld;
class DocumentLoader;
class Frame;
+class HTMLInputElement;
class InspectorClient;
class InspectorOverlay;
class Page;
@@ -69,12 +75,14 @@ public:
PingResource,
BeaconResource,
WebSocketResource,
+ EventSource,
#if ENABLE(APPLICATION_MANIFEST)
ApplicationManifestResource,
#endif
OtherResource,
};
+ WEBCORE_EXPORT static String makeFrameID(ProcessIdentifier processID, FrameIdentifier frameID);
static bool sharedBufferContent(RefPtr<SharedBuffer>&&, const String& textEncodingName, bool withBase64Encode, String* result);
static Vector<CachedResource*> cachedResourcesForFrame(Frame*);
static void resourceContent(Inspector::Protocol::ErrorString&, Frame*, const URL&, String* result, bool* base64Encoded);
@@ -95,6 +103,8 @@ public:
Inspector::Protocol::ErrorStringOr<void> enable();
Inspector::Protocol::ErrorStringOr<void> disable();
Inspector::Protocol::ErrorStringOr<void> reload(Optional<bool>&& ignoreCache, Optional<bool>&& revalidateAllResources);
+ Inspector::Protocol::ErrorStringOr<void> goBack();
+ Inspector::Protocol::ErrorStringOr<void> goForward();
Inspector::Protocol::ErrorStringOr<void> navigate(const String& url);
Inspector::Protocol::ErrorStringOr<void> overrideUserAgent(const String&);
Inspector::Protocol::ErrorStringOr<void> overrideSetting(Inspector::Protocol::Page::Setting, Optional<bool>&& value);
@@ -114,25 +124,35 @@ public:
#if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
Inspector::Protocol::ErrorStringOr<void> setForcedAppearance(Optional<Inspector::Protocol::Page::Appearance>&&);
#endif
+ Inspector::Protocol::ErrorStringOr<void> setTimeZone(const String&);
+ Inspector::Protocol::ErrorStringOr<void> setTouchEmulationEnabled(bool);
Inspector::Protocol::ErrorStringOr<String> snapshotNode(Inspector::Protocol::DOM::NodeId);
Inspector::Protocol::ErrorStringOr<String> snapshotRect(int x, int y, int width, int height, Inspector::Protocol::Page::CoordinateSystem);
#if ENABLE(WEB_ARCHIVE) && USE(CF)
Inspector::Protocol::ErrorStringOr<String> archive();
#endif
-#if !PLATFORM(COCOA)
Inspector::Protocol::ErrorStringOr<void> setScreenSizeOverride(Optional<int>&& width, Optional<int>&& height);
-#endif
+
+ Inspector::Protocol::ErrorStringOr<void> insertText(const String& text);
+ Inspector::Protocol::ErrorStringOr<Ref<Inspector::Protocol::Page::AXNode>> accessibilitySnapshot(const String& objectId);
+ Inspector::Protocol::ErrorStringOr<void> setInterceptFileChooserDialog(bool enabled);
+ Inspector::Protocol::ErrorStringOr<void> setDefaultBackgroundColorOverride(RefPtr<JSON::Object>&&);
+ Inspector::Protocol::ErrorStringOr<void> createUserWorld(const String&);
+ Inspector::Protocol::ErrorStringOr<void> setBypassCSP(bool);
+ Inspector::Protocol::ErrorStringOr<void> crash();
+ Inspector::Protocol::ErrorStringOr<void> setScreenSizeOverride(int width, int height);
+ Inspector::Protocol::ErrorStringOr<void> setOrientationOverride(Optional<int>&& angle);
// InspectorInstrumentation
- void domContentEventFired();
- void loadEventFired();
+ void domContentEventFired(Frame&);
+ void loadEventFired(Frame&);
void frameNavigated(Frame&);
void frameDetached(Frame&);
- void loaderDetachedFromFrame(DocumentLoader&);
void frameStartedLoading(Frame&);
void frameStoppedLoading(Frame&);
void frameScheduledNavigation(Frame&, Seconds delay);
void frameClearedScheduledNavigation(Frame&);
+ void didNavigateWithinPage(Frame&);
#if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
void defaultAppearanceDidChange(bool useDarkAppearance);
#endif
@@ -143,6 +163,12 @@ public:
void didLayout();
void didScroll();
void didRecalculateStyle();
+ void runOpenPanel(HTMLInputElement* element, bool* intercept);
+ void frameAttached(Frame&);
+ bool shouldBypassCSP();
+ void willCheckNewWindowPolicy(const URL&);
+ void didCheckNewWindowPolicy(bool allowed);
+ bool doingAccessibilitySnapshot() const { return m_doingAccessibilitySnapshot; };
Frame* frameForId(const Inspector::Protocol::Network::FrameId&);
WEBCORE_EXPORT String frameId(Frame*);
@@ -151,6 +177,7 @@ public:
private:
double timestamp();
+ void ensureUserWorldsExistInAllFrames(const Vector<DOMWrapperWorld*>&);
static bool mainResourceContent(Frame*, bool withBase64Encode, String* result);
static bool dataContent(const char* data, unsigned size, const String& textEncodingName, bool withBase64Encode, String* result);
@@ -162,17 +189,19 @@ private:
RefPtr<Inspector::PageBackendDispatcher> m_backendDispatcher;
Page& m_inspectedPage;
+ Inspector::InjectedScriptManager& m_injectedScriptManager;
InspectorClient* m_client { nullptr };
InspectorOverlay* m_overlay { nullptr };
- HashMap<Frame*, String> m_frameToIdentifier;
HashMap<String, Frame*> m_identifierToFrame;
- HashMap<DocumentLoader*, String> m_loaderToIdentifier;
String m_userAgentOverride;
String m_emulatedMedia;
String m_bootstrapScript;
bool m_isFirstLayoutAfterOnLoad { false };
bool m_showPaintRects { false };
+ bool m_interceptFileChooserDialog { false };
+ bool m_bypassCSP { false };
+ bool m_doingAccessibilitySnapshot { false };
};
} // namespace WebCore
diff --git a/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp b/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp
index 33caa0aa2079ad4081cc29605a53537c24d66bef..4b74d397d4de9a7eba3d5530538443d8907726aa 100644
--- a/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp
@@ -161,7 +161,11 @@ void InspectorWorkerAgent::connectToWorkerInspectorProxy(WorkerInspectorProxy& p
m_connectedProxies.set(proxy.identifier(), &proxy);
- m_frontendDispatcher->workerCreated(proxy.identifier(), proxy.url().string(), proxy.name());
+ ASSERT(is<Document>(proxy.scriptExecutionContext()));
+ Document& document = downcast<Document>(*proxy.scriptExecutionContext());
+ auto* pageAgent = m_instrumentingAgents.enabledPageAgent();
+ m_frontendDispatcher->workerCreated(proxy.identifier(), proxy.url().string(), proxy.name(),
+ pageAgent ? pageAgent->frameId(document.frame()) : emptyString());
}
void InspectorWorkerAgent::disconnectFromWorkerInspectorProxy(WorkerInspectorProxy& proxy)
diff --git a/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp b/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp
index 69f97fb2b9a959f1ae4a9ae59928b8350df3f875..a8e72eba9aaa24435ccdc8c0b3df44026cb7d6a2 100644
--- a/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp
+++ b/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp
@@ -38,6 +38,7 @@
#include "Frame.h"
#include "InspectorPageAgent.h"
#include "InstrumentingAgents.h"
+#include "JSDOMWindowBase.h"
#include "Page.h"
#include "PageConsoleClient.h"
#include "PageDebugger.h"
@@ -70,7 +71,11 @@ bool PageDebuggerAgent::enabled() const
Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, Optional<bool> /* wasThrown */, Optional<int> /* savedResultIndex */>> PageDebuggerAgent::evaluateOnCallFrame(const Protocol::Debugger::CallFrameId& callFrameId, const String& expression, const String& objectGroup, Optional<bool>&& includeCommandLineAPI, Optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, Optional<bool>&& returnByValue, Optional<bool>&& generatePreview, Optional<bool>&& saveResult, Optional<bool>&& emulateUserGesture)
{
- UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture);
+ InjectedScript injectedScript = injectedScriptManager().injectedScriptForObjectId(callFrameId);
+ JSC::JSGlobalObject* globalObject = injectedScript.globalObject();
+ Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr;
+ auto shouldEmulateUserGesture = emulateUserGesture && *emulateUserGesture;
+ UserGestureEmulationScope userGestureScope(m_inspectedPage, shouldEmulateUserGesture, document);
return WebDebuggerAgent::evaluateOnCallFrame(callFrameId, expression, objectGroup, WTFMove(includeCommandLineAPI), WTFMove(doNotPauseOnExceptionsAndMuteConsole), WTFMove(returnByValue), WTFMove(generatePreview), WTFMove(saveResult), WTFMove(emulateUserGesture));
}
diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
index 00e69f1aa2e3f8ea2f445e8dd446dd16ea6363df..92d45059ca6d87ddf7b6cc12033267a4c108a73c 100644
--- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
+++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
@@ -35,12 +35,14 @@
#include "DOMWrapperWorld.h"
#include "Document.h"
#include "Frame.h"
+#include "FrameLoader.h"
#include "InspectorPageAgent.h"
#include "InstrumentingAgents.h"
#include "JSDOMWindowBase.h"
#include "Page.h"
#include "PageConsoleClient.h"
#include "ScriptController.h"
+#include "ScriptSourceCode.h"
#include "ScriptState.h"
#include "SecurityOrigin.h"
#include "UserGestureEmulationScope.h"
@@ -103,6 +105,15 @@ void PageRuntimeAgent::didClearWindowObjectInWorld(Frame& frame, DOMWrapperWorld
notifyContextCreated(pageAgent->frameId(&frame), frame.script().globalObject(world), world);
}
+void PageRuntimeAgent::didReceiveMainResourceError(Frame& frame)
+{
+ if (frame.loader().stateMachine().isDisplayingInitialEmptyDocument()) {
+ // Ensure execution context is created for the empty docment to make
+ // it usable in case loading failed.
+ mainWorldExecState(&frame);
+ }
+}
+
InjectedScript PageRuntimeAgent::injectedScriptForEval(Protocol::ErrorString& errorString, Optional<Protocol::Runtime::ExecutionContextId>&& executionContextId)
{
if (!executionContextId) {
@@ -191,13 +202,23 @@ void PageRuntimeAgent::notifyContextCreated(const Protocol::Network::FrameId& fr
Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, Optional<bool> /* wasThrown */, Optional<int> /* savedResultIndex */>> PageRuntimeAgent::evaluate(const String& expression, const String& objectGroup, Optional<bool>&& includeCommandLineAPI, Optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, Optional<Protocol::Runtime::ExecutionContextId>&& executionContextId, Optional<bool>&& returnByValue, Optional<bool>&& generatePreview, Optional<bool>&& saveResult, Optional<bool>&& emulateUserGesture)
{
- UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture);
+ String errorString;
+ InjectedScript injectedScript = injectedScriptForEval(errorString, Optional(executionContextId));
+ if (!errorString.isEmpty())
+ return makeUnexpected(errorString);
+
+ JSC::JSGlobalObject* globalObject = injectedScript.globalObject();
+ Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr;
+ UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture, document);
return InspectorRuntimeAgent::evaluate(expression, objectGroup, WTFMove(includeCommandLineAPI), WTFMove(doNotPauseOnExceptionsAndMuteConsole), WTFMove(executionContextId), WTFMove(returnByValue), WTFMove(generatePreview), WTFMove(saveResult), WTFMove(emulateUserGesture));
}
Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, Optional<bool> /* wasThrown */>> PageRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& expression, RefPtr<JSON::Array>&& optionalArguments, Optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, Optional<bool>&& returnByValue, Optional<bool>&& generatePreview, Optional<bool>&& emulateUserGesture)
{
- UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture);
+ InjectedScript injectedScript = injectedScriptManager().injectedScriptForObjectId(objectId);
+ JSC::JSGlobalObject* globalObject = injectedScript.globalObject();
+ Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr;
+ UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture, document);
return InspectorRuntimeAgent::callFunctionOn(objectId, expression, WTFMove(optionalArguments), WTFMove(doNotPauseOnExceptionsAndMuteConsole), WTFMove(returnByValue), WTFMove(generatePreview), WTFMove(emulateUserGesture));
}
diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
index 298465c52b42464c2733659e07f3f760174a95eb..3b7ac5a5e6fba11bfbc3d641e5a312db5f1391a8 100644
--- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
+++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
@@ -62,6 +62,7 @@ public:
// InspectorInstrumentation
void frameNavigated(Frame&);
void didClearWindowObjectInWorld(Frame&, DOMWrapperWorld&);
+ void didReceiveMainResourceError(Frame&);
private:
Inspector::InjectedScript injectedScriptForEval(Inspector::Protocol::ErrorString&, Optional<Inspector::Protocol::Runtime::ExecutionContextId>&&);
@@ -72,7 +73,6 @@ private:
std::unique_ptr<Inspector::RuntimeFrontendDispatcher> m_frontendDispatcher;
RefPtr<Inspector::RuntimeBackendDispatcher> m_backendDispatcher;
-
InstrumentingAgents& m_instrumentingAgents;
Page& m_inspectedPage;
diff --git a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp
index 633bce6e8f3c0785632eb7f26d172f6016b3efd9..14f531504bb2b96646d1a48092a0b132b0510f55 100644
--- a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp
+++ b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp
@@ -39,9 +39,9 @@
namespace WebCore {
-UserGestureEmulationScope::UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture)
+UserGestureEmulationScope::UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture, Document* document)
: m_pageChromeClient(inspectedPage.chrome().client())
- , m_gestureIndicator(emulateUserGesture ? Optional<ProcessingUserGestureState>(ProcessingUserGesture) : WTF::nullopt)
+ , m_gestureIndicator(emulateUserGesture ? Optional<ProcessingUserGestureState>(ProcessingUserGesture) : WTF::nullopt, document)
, m_emulateUserGesture(emulateUserGesture)
, m_userWasInteracting(false)
{
diff --git a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h
index b94ed78ad3dbea19543c1fd54653f0481e52fb7c..6341c7ff7ef53577f33c19ecad1b8bfbd674d051 100644
--- a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h
+++ b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h
@@ -38,11 +38,12 @@ namespace WebCore {
class ChromeClient;
class Page;
+class Document;
class UserGestureEmulationScope {
WTF_MAKE_NONCOPYABLE(UserGestureEmulationScope);
public:
- UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture);
+ UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture, Document* document);
~UserGestureEmulationScope();
private:
diff --git a/Source/WebCore/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp
index 7c99510855700d855de43e52803d14d76bf9d562..9f4a76ec0b45783dc92942f78cdccac5291b0ceb 100644
--- a/Source/WebCore/loader/DocumentLoader.cpp
+++ b/Source/WebCore/loader/DocumentLoader.cpp
@@ -1326,8 +1326,6 @@ void DocumentLoader::detachFromFrame()
if (!m_frame)
return;
- InspectorInstrumentation::loaderDetachedFromFrame(*m_frame, *this);
-
observeFrame(nullptr);
}
diff --git a/Source/WebCore/loader/DocumentLoader.h b/Source/WebCore/loader/DocumentLoader.h
index c21678201701d3fa8d41c9ef45ee824eddff64bf..f1f23cf11fd4d646d57118df361ab77a1b5530d2 100644
--- a/Source/WebCore/loader/DocumentLoader.h
+++ b/Source/WebCore/loader/DocumentLoader.h
@@ -166,9 +166,13 @@ public:
WEBCORE_EXPORT virtual void detachFromFrame();
+ virtual void replacedByFragmentNavigation(Frame&) { }
+
WEBCORE_EXPORT FrameLoader* frameLoader() const;
WEBCORE_EXPORT SubresourceLoader* mainResourceLoader() const;
WEBCORE_EXPORT RefPtr<SharedBuffer> mainResourceData() const;
+
+ virtual uint64_t loaderIDForInspector() { return 0; }
DocumentWriter& writer() const { return m_writer; }
diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp
index ded7321a94c6e5cdab3eb888efd802ea964d77bd..3d794684d0cd4993d9317f573477c4c48518a1d3 100644
--- a/Source/WebCore/loader/FrameLoader.cpp
+++ b/Source/WebCore/loader/FrameLoader.cpp
@@ -1171,6 +1171,7 @@ void FrameLoader::loadInSameDocument(const URL& url, SerializedScriptValue* stat
}
m_client->dispatchDidNavigateWithinPage();
+ InspectorInstrumentation::didNavigateWithinPage(m_frame);
m_frame.document()->statePopped(stateObject ? Ref<SerializedScriptValue> { *stateObject } : SerializedScriptValue::nullValue());
m_client->dispatchDidPopStateWithinPage();
@@ -1482,6 +1483,7 @@ void FrameLoader::load(FrameLoadRequest&& request)
void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, NavigationAction&& action, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler<void()>&& completionHandler)
{
+ InspectorInstrumentation::frameScheduledNavigation(m_frame, Seconds(0));
FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadWithNavigationAction: frame load started");
Ref<DocumentLoader> loader = m_client->createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
@@ -1585,6 +1587,8 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t
const String& httpMethod = loader->request().httpMethod();
if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker().loadType(), newURL)) {
+ loader->replacedByFragmentNavigation(m_frame);
+
RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
NavigationAction action { *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission };
@@ -3150,6 +3154,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)
@@ -3912,9 +3918,6 @@ String FrameLoader::referrer() const
void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
{
- if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
- return;
-
Vector<Ref<DOMWrapperWorld>> worlds;
ScriptController::getAllWorlds(worlds);
for (auto& world : worlds)
@@ -3923,13 +3926,13 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
{
- if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.windowProxy().existingJSWindowProxy(world))
- return;
-
- m_client->dispatchDidClearWindowObjectInWorld(world);
+ if (m_frame.windowProxy().existingJSWindowProxy(world)) {
+ if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
+ m_client->dispatchDidClearWindowObjectInWorld(world);
- if (Page* page = m_frame.page())
- page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
+ if (Page* page = m_frame.page())
+ page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
+ }
InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
}
diff --git a/Source/WebCore/loader/LoaderStrategy.h b/Source/WebCore/loader/LoaderStrategy.h
index 6097d2650766a2c87a60426272ae6aba0358b297..9f6e41db65a1745a0d9bb343a762e1960a4b5586 100644
--- a/Source/WebCore/loader/LoaderStrategy.h
+++ b/Source/WebCore/loader/LoaderStrategy.h
@@ -80,6 +80,7 @@ public:
virtual bool isOnLine() const = 0;
virtual void addOnlineStateChangeListener(WTF::Function<void(bool)>&&) = 0;
+ virtual void setEmulateOfflineState(bool) {};
virtual bool shouldPerformSecurityChecks() const { return false; }
virtual bool havePerformedSecurityChecks(const ResourceResponse&) const { return false; }
diff --git a/Source/WebCore/loader/PolicyChecker.cpp b/Source/WebCore/loader/PolicyChecker.cpp
index 276148a63f36cc46ae0cf2bb535c33f2aa07e30b..998e983870098b620cf154819379aa0b039f7e66 100644
--- a/Source/WebCore/loader/PolicyChecker.cpp
+++ b/Source/WebCore/loader/PolicyChecker.cpp
@@ -46,6 +46,7 @@
#include "HTMLFormElement.h"
#include "HTMLFrameOwnerElement.h"
#include "HTMLPlugInElement.h"
+#include "InspectorInstrumentation.h"
#include "Logging.h"
#include <wtf/CompletionHandler.h>
@@ -259,26 +260,32 @@ void FrameLoader::PolicyChecker::checkNewWindowPolicy(NavigationAction&& navigat
auto blobURLLifetimeExtension = extendBlobURLLifetimeIfNecessary(request, nullptr);
+ InspectorInstrumentation::willCheckNewWindowPolicy(m_frame, request.url());
auto requestIdentifier = PolicyCheckIdentifier::create();
m_frame.loader().client().dispatchDecidePolicyForNewWindowAction(navigationAction, request, formState.get(), frameName, requestIdentifier, [frame = makeRef(m_frame), request,
formState = WTFMove(formState), frameName, navigationAction, function = WTFMove(function), blobURLLifetimeExtension = WTFMove(blobURLLifetimeExtension),
requestIdentifier] (PolicyAction policyAction, PolicyCheckIdentifier responseIdentifier) mutable {
- if (!responseIdentifier.isValidFor(requestIdentifier))
+ if (!responseIdentifier.isValidFor(requestIdentifier)) {
+ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false);
return function({ }, nullptr, { }, { }, ShouldContinuePolicyCheck::No);
+ }
switch (policyAction) {
case PolicyAction::Download:
frame->loader().client().startDownload(request);
FALLTHROUGH;
case PolicyAction::Ignore:
+ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false);
function({ }, nullptr, { }, { }, ShouldContinuePolicyCheck::No);
return;
case PolicyAction::StopAllLoads:
ASSERT_NOT_REACHED();
+ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false);
function({ }, nullptr, { }, { }, ShouldContinuePolicyCheck::No);
return;
case PolicyAction::Use:
+ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), true);
function(request, makeWeakPtr(formState.get()), frameName, navigationAction, ShouldContinuePolicyCheck::Yes);
return;
}
diff --git a/Source/WebCore/loader/ProgressTracker.cpp b/Source/WebCore/loader/ProgressTracker.cpp
index e24fded2225f1c1918f454017566717e20484eab..30e4b7a986418c4b4f6c799b858b608206e22bb5 100644
--- a/Source/WebCore/loader/ProgressTracker.cpp
+++ b/Source/WebCore/loader/ProgressTracker.cpp
@@ -154,6 +154,8 @@ void ProgressTracker::progressCompleted(Frame& frame)
if (!m_numProgressTrackedFrames || m_originatingProgressFrame == &frame)
finalProgressComplete();
+ InspectorInstrumentation::frameStoppedLoading(frame);
+
m_client->didChangeEstimatedProgress();
}
@@ -179,8 +181,6 @@ void ProgressTracker::finalProgressComplete()
frame->loader().client().setMainFrameDocumentReady(true);
m_client->progressFinished(*frame);
frame->loader().loadProgressingStatusChanged();
-
- InspectorInstrumentation::frameStoppedLoading(*frame);
}
void ProgressTracker::incrementProgress(unsigned long identifier, const ResourceResponse& response)
diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h
index 6ddd9bc70c30662c4fdf7d644029205ca2a14b99..8b73278bb5164f7fded5bb6946e14d3888d62d3c 100644
--- a/Source/WebCore/page/ChromeClient.h
+++ b/Source/WebCore/page/ChromeClient.h
@@ -286,7 +286,7 @@ public:
#endif
#if ENABLE(ORIENTATION_EVENTS)
- virtual int deviceOrientation() const = 0;
+ virtual int deviceOrientation() const { return 0; }
#endif
#if ENABLE(INPUT_TYPE_COLOR)
diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp
index dd3467cb89c190ac6d60c6f32dbe05895b1c6370..2927d3bfb81b10471089fb3a2189eec386b6771c 100644
--- a/Source/WebCore/page/EventHandler.cpp
+++ b/Source/WebCore/page/EventHandler.cpp
@@ -121,6 +121,7 @@
#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
#include "PlatformTouchEvent.h"
+#include "PointerCaptureController.h"
#endif
#if ENABLE(MAC_GESTURE_EVENTS)
@@ -828,9 +829,7 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
m_mousePressNode = event.targetNode();
m_frame.document()->setFocusNavigationStartingNode(event.targetNode());
-#if ENABLE(DRAG_SUPPORT)
m_dragStartPosition = event.event().position();
-#endif
m_mousePressed = true;
m_selectionInitiationState = HaveNotStartedSelection;
@@ -869,8 +868,6 @@ VisiblePosition EventHandler::selectionExtentRespectingEditingBoundary(const Vis
return targetNode->renderer()->positionForPoint(LayoutPoint(selectionEndPoint), nullptr);
}
-#if ENABLE(DRAG_SUPPORT)
-
#if !PLATFORM(IOS_FAMILY)
bool EventHandler::supportsSelectionUpdatesOnMouseDrag() const
@@ -892,8 +889,10 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
Ref<Frame> protectedFrame(m_frame);
+#if ENABLE(DRAG_SUPPORT)
if (handleDrag(event, checkDragHysteresis))
return true;
+#endif
Node* targetNode = event.targetNode();
if (event.event().button() != LeftButton || !targetNode)
@@ -914,7 +913,9 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
ASSERT(m_mouseDownMayStartSelect || m_mouseDownMayStartAutoscroll);
#endif
+#if ENABLE(DRAG_SUPPORT)
m_mouseDownMayStartDrag = false;
+#endif
if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) {
m_autoscrollController->startAutoscrollForSelection(renderer);
@@ -931,6 +932,8 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
return true;
}
+#if ENABLE(DRAG_SUPPORT)
+
bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
{
// This is a pre-flight check of whether the event might lead to a drag being started. Be careful
@@ -962,6 +965,8 @@ bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
return targetElement && page->dragController().draggableElement(&m_frame, targetElement, result.roundedPointInInnerNodeFrame(), state);
}
+#endif // ENABLE(DRAG_SUPPORT)
+
void EventHandler::updateSelectionForMouseDrag()
{
if (!supportsSelectionUpdatesOnMouseDrag())
@@ -1053,7 +1058,6 @@ void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResul
m_frame.selection().setSelectionByMouseIfDifferent(newSelection, m_frame.selection().granularity(),
FrameSelection::EndPointsAdjustmentMode::AdjustAtBidiBoundary);
}
-#endif // ENABLE(DRAG_SUPPORT)
void EventHandler::lostMouseCapture()
{
@@ -1101,9 +1105,7 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
// on the selection, the selection goes away. However, if we are
// editing, place the caret.
if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != ExtendedSelection
-#if ENABLE(DRAG_SUPPORT)
&& m_dragStartPosition == event.event().position()
-#endif
&& m_frame.selection().isRange()
&& event.event().button() != RightButton) {
VisibleSelection newSelection;
@@ -2064,10 +2066,8 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& platformMouseE
swallowEvent = !dispatchMouseEvent(eventNames().mousemoveEvent, mouseEvent.targetNode(), 0, platformMouseEvent, FireMouseOverOut::Yes);
-#if ENABLE(DRAG_SUPPORT)
if (!swallowEvent)
swallowEvent = handleMouseDraggedEvent(mouseEvent);
-#endif
return swallowEvent;
}
@@ -4234,7 +4234,8 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
allTouchReleased = false;
}
- for (auto& point : points) {
+ for (unsigned index = 0; index < points.size(); index++) {
+ auto& point = points[index];
PlatformTouchPoint::State pointState = point.state();
LayoutPoint pagePoint = documentPointForWindowPoint(m_frame, point.pos());
@@ -4360,6 +4361,9 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
changedTouches[pointState].m_touches->append(WTFMove(touch));
changedTouches[pointState].m_targets.add(touchTarget);
}
+ document.page()->pointerCaptureController().dispatchEventForTouchAtIndex(
+ *touchTarget, event, index, index == 0, *document.windowProxy());
+
}
m_touchPressed = touches->length() > 0;
if (allTouchReleased)
diff --git a/Source/WebCore/page/EventHandler.h b/Source/WebCore/page/EventHandler.h
index e8558865654f934385d280eb39ffa18334a8cd8a..e30d0dc063c3a77dcf739e09fa394a72062efd75 100644
--- a/Source/WebCore/page/EventHandler.h
+++ b/Source/WebCore/page/EventHandler.h
@@ -134,9 +134,7 @@ public:
WEBCORE_EXPORT VisiblePosition selectionExtentRespectingEditingBoundary(const VisibleSelection&, const LayoutPoint&, Node*);
-#if ENABLE(DRAG_SUPPORT)
void updateSelectionForMouseDrag();
-#endif
#if ENABLE(PAN_SCROLLING)
void didPanScrollStart();
@@ -366,10 +364,8 @@ private:
bool handleMousePressEventDoubleClick(const MouseEventWithHitTestResults&);
bool handleMousePressEventTripleClick(const MouseEventWithHitTestResults&);
-#if ENABLE(DRAG_SUPPORT)
bool handleMouseDraggedEvent(const MouseEventWithHitTestResults&, CheckDragHysteresis = ShouldCheckDragHysteresis);
bool shouldAllowMouseDownToStartDrag() const;
-#endif
WEBCORE_EXPORT bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&);
@@ -466,10 +462,8 @@ private:
void defaultTabEventHandler(KeyboardEvent&);
void defaultArrowEventHandler(FocusDirection, KeyboardEvent&);
-#if ENABLE(DRAG_SUPPORT)
OptionSet<DragSourceAction> updateDragSourceActionsAllowed() const;
bool supportsSelectionUpdatesOnMouseDrag() const;
-#endif
// The following are called at the beginning of handleMouseUp and handleDrag.
// If they return true it indicates that they have consumed the event.
@@ -477,9 +471,10 @@ private:
#if ENABLE(DRAG_SUPPORT)
bool eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&);
- void updateSelectionForMouseDrag(const HitTestResult&);
#endif
+ void updateSelectionForMouseDrag(const HitTestResult&);
+
enum class SetOrClearLastScrollbar { Clear, Set };
void updateLastScrollbarUnderMouse(Scrollbar*, SetOrClearLastScrollbar);
@@ -529,10 +524,7 @@ private:
enum SelectionInitiationState { HaveNotStartedSelection, PlacedCaret, ExtendedSelection };
SelectionInitiationState m_selectionInitiationState { HaveNotStartedSelection };
-#if ENABLE(DRAG_SUPPORT)
LayoutPoint m_dragStartPosition;
-#endif
-
Timer m_hoverTimer;
bool m_hasScheduledCursorUpdate { false };
diff --git a/Source/WebCore/page/EventSource.cpp b/Source/WebCore/page/EventSource.cpp
index 757765c3b4872d5a6f92b34e3f2ac67eaaf2dd82..69c4ef67941cee93213ccac1aa04d2cb1db08782 100644
--- a/Source/WebCore/page/EventSource.cpp
+++ b/Source/WebCore/page/EventSource.cpp
@@ -36,6 +36,7 @@
#include "CachedResourceRequestInitiators.h"
#include "ContentSecurityPolicy.h"
#include "EventNames.h"
+#include "InspectorNetworkAgent.h"
#include "MessageEvent.h"
#include "ResourceError.h"
#include "ResourceRequest.h"
@@ -97,6 +98,7 @@ void EventSource::connect()
ASSERT(!m_requestInFlight);
ResourceRequest request { m_url };
+ request.setInitiatorIdentifier(InspectorNetworkAgent::initiatorIdentifierForEventSource());
request.setHTTPMethod("GET");
request.setHTTPHeaderField(HTTPHeaderName::Accept, "text/event-stream");
request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-cache");
diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp
index 59dfffa1a6c2c8ddc316fece00eff8f5226e49b9..7ef8db77940a6bc634ee69c4118ed4f460447eeb 100644
--- a/Source/WebCore/page/Frame.cpp
+++ b/Source/WebCore/page/Frame.cpp
@@ -39,6 +39,7 @@
#include "CachedResourceLoader.h"
#include "Chrome.h"
#include "ChromeClient.h"
+#include "ComposedTreeIterator.h"
#include "DOMWindow.h"
#include "DocumentTimeline.h"
#include "DocumentType.h"
@@ -71,6 +72,7 @@
#include "NavigationScheduler.h"
#include "Navigator.h"
#include "NodeList.h"
+#include "NodeRenderStyle.h"
#include "NodeTraversal.h"
#include "Page.h"
#include "ProcessWarming.h"
@@ -179,6 +181,7 @@ Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, UniqueRef<FrameLoa
void Frame::init()
{
m_loader->init();
+ InspectorInstrumentation::frameAttached(this);
}
Ref<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, UniqueRef<FrameLoaderClient>&& client)
@@ -348,7 +351,7 @@ void Frame::orientationChanged()
int Frame::orientation() const
{
if (m_page)
- return m_page->chrome().client().deviceOrientation();
+ return m_page->orientation();
return 0;
}
#endif // ENABLE(ORIENTATION_EVENTS)
@@ -1133,6 +1136,358 @@ TextStream& operator<<(TextStream& ts, const Frame& frame)
return ts;
}
+void Frame::betterApproximateNode(const IntPoint& testPoint, const NodeQualifier& nodeQualifierFunction, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect)
+{
+ IntRect candidateRect;
+ constexpr OptionSet<HitTestRequest::RequestType> hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowVisibleChildFrameContentOnly };
+ auto* candidate = nodeQualifierFunction(eventHandler().hitTestResultAtPoint(testPoint, hitType), failedNode, &candidateRect);
+
+ // Bail if we have no candidate, or the candidate is already equal to our current best node,
+ // or our candidate is the avoidedNode and there is a current best node.
+ if (!candidate || candidate == best)
+ return;
+
+ // The document should never be considered the best alternative.
+ if (candidate->isDocumentNode())
+ return;
+
+ if (best) {
+ IntRect bestIntersect = intersection(testRect, bestRect);
+ IntRect candidateIntersect = intersection(testRect, candidateRect);
+ // if the candidate intersection is smaller than the current best intersection, bail.
+ if (candidateIntersect.width() * candidateIntersect.height() <= bestIntersect.width() * bestIntersect.height())
+ return;
+ }
+
+ // At this point we either don't have a previous best, or our current candidate has a better intersection.
+ best = candidate;
+ bestPoint = testPoint;
+ bestRect = candidateRect;
+}
+
+bool Frame::hitTestResultAtViewportLocation(const FloatPoint& viewportLocation, HitTestResult& hitTestResult, IntPoint& center)
+{
+ if (!m_doc || !m_doc->renderView())
+ return false;
+
+ FrameView* view = m_view.get();
+ if (!view)
+ return false;
+
+ center = view->windowToContents(roundedIntPoint(viewportLocation));
+ constexpr OptionSet<HitTestRequest::RequestType> hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowVisibleChildFrameContentOnly };
+ hitTestResult = eventHandler().hitTestResultAtPoint(center, hitType);
+ return true;
+}
+
+Node* Frame::qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, const NodeQualifier& nodeQualifierFunction, ShouldApproximate shouldApproximate, ShouldFindRootEditableElement shouldFindRootEditableElement)
+{
+ adjustedViewportLocation = viewportLocation;
+
+ IntPoint testCenter;
+ HitTestResult candidateInfo;
+ if (!hitTestResultAtViewportLocation(viewportLocation, candidateInfo, testCenter))
+ return nullptr;
+
+ IntPoint bestPoint = testCenter;
+
+ // We have the candidate node at the location, check whether it or one of its ancestors passes
+ // the qualifier function, which typically checks if the node responds to a particular event type.
+ Node* approximateNode = nodeQualifierFunction(candidateInfo, 0, 0);
+
+ if (shouldFindRootEditableElement == ShouldFindRootEditableElement::Yes && approximateNode && approximateNode->isContentEditable()) {
+ // If we are in editable content, we look for the root editable element.
+ approximateNode = approximateNode->rootEditableElement();
+ // If we have a focusable node, there is no need to approximate.
+ if (approximateNode)
+ shouldApproximate = ShouldApproximate::No;
+ }
+
+ float scale = page() ? page()->pageScaleFactor() : 1;
+#if PLATFORM(IOS_FAMILY)
+ float ppiFactor = screenPPIFactor();
+#else
+ float ppiFactor = 326; // most popular iPhone PPI
+#endif
+
+ static const float unscaledSearchRadius = 15;
+ int searchRadius = static_cast<int>(unscaledSearchRadius * ppiFactor / scale);
+
+ if (approximateNode && shouldApproximate == ShouldApproximate::Yes) {
+ const float testOffsets[] = {
+ -.3f, -.3f,
+ -.6f, -.6f,
+ +.3f, +.3f,
+ -.9f, -.9f,
+ };
+
+ Node* originalApproximateNode = approximateNode;
+ for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) {
+ IntSize testOffset(testOffsets[n] * searchRadius, testOffsets[n + 1] * searchRadius);
+ IntPoint testPoint = testCenter + testOffset;
+
+ constexpr OptionSet<HitTestRequest::RequestType> hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowChildFrameContent };
+ auto candidateInfo = eventHandler().hitTestResultAtPoint(testPoint, hitType);
+ Node* candidateNode = nodeQualifierFunction(candidateInfo, 0, 0);
+ if (candidateNode && candidateNode->isDescendantOf(originalApproximateNode)) {
+ approximateNode = candidateNode;
+ bestPoint = testPoint;
+ break;
+ }
+ }
+ } else if (!approximateNode && shouldApproximate == ShouldApproximate::Yes) {
+ // Grab the closest parent element of our failed candidate node.
+ Node* candidate = candidateInfo.innerNode();
+ Node* failedNode = candidate;
+
+ while (candidate && !candidate->isElementNode())
+ candidate = candidate->parentInComposedTree();
+
+ if (candidate)
+ failedNode = candidate;
+
+ // The center point was tested earlier.
+ const float testOffsets[] = {
+ -.3f, -.3f,
+ +.3f, -.3f,
+ -.3f, +.3f,
+ +.3f, +.3f,
+ -.6f, -.6f,
+ +.6f, -.6f,
+ -.6f, +.6f,
+ +.6f, +.6f,
+ -1.f, 0,
+ +1.f, 0,
+ 0, +1.f,
+ 0, -1.f,
+ };
+ IntRect bestFrame;
+ IntRect testRect(testCenter, IntSize());
+ testRect.inflate(searchRadius);
+ int currentTestRadius = 0;
+ for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) {
+ IntSize testOffset(testOffsets[n] * searchRadius, testOffsets[n + 1] * searchRadius);
+ IntPoint testPoint = testCenter + testOffset;
+ int testRadius = std::max(abs(testOffset.width()), abs(testOffset.height()));
+ if (testRadius > currentTestRadius) {
+ // Bail out with the best match within a radius
+ currentTestRadius = testRadius;
+ if (approximateNode)
+ break;
+ }
+ betterApproximateNode(testPoint, nodeQualifierFunction, approximateNode, failedNode, bestPoint, bestFrame, testRect);
+ }
+ }
+
+ if (approximateNode) {
+ IntPoint p = m_view->contentsToWindow(bestPoint);
+ adjustedViewportLocation = p;
+ if (shouldFindRootEditableElement == ShouldFindRootEditableElement::Yes && approximateNode->isContentEditable()) {
+ // When in editable content, look for the root editable node again,
+ // since this could be the node found with the approximation.
+ approximateNode = approximateNode->rootEditableElement();
+ }
+ }
+
+ return approximateNode;
+}
+
+Node* Frame::deepestNodeAtLocation(const FloatPoint& viewportLocation)
+{
+ IntPoint center;
+ HitTestResult hitTestResult;
+ if (!hitTestResultAtViewportLocation(viewportLocation, hitTestResult, center))
+ return nullptr;
+
+ return hitTestResult.innerNode();
+}
+
+static bool nodeIsMouseFocusable(Node& node)
+{
+ if (!is<Element>(node))
+ return false;
+
+ auto& element = downcast<Element>(node);
+ if (element.isMouseFocusable())
+ return true;
+
+ if (auto shadowRoot = makeRefPtr(element.shadowRoot())) {
+ if (shadowRoot->delegatesFocus()) {
+ for (auto& node : composedTreeDescendants(element)) {
+ if (is<Element>(node) && downcast<Element>(node).isMouseFocusable())
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool nodeWillRespondToMouseEvents(Node& node)
+{
+ return node.willRespondToMouseClickEvents() || node.willRespondToMouseMoveEvents() || nodeIsMouseFocusable(node);
+}
+
+Node* Frame::approximateNodeAtViewportLocationLegacy(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation)
+{
+ // This function is only used for UIWebView.
+ auto&& ancestorRespondingToClickEvents = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* {
+ bool bodyHasBeenReached = false;
+ bool pointerCursorStillValid = true;
+
+ if (nodeBounds)
+ *nodeBounds = IntRect();
+
+ auto node = hitTestResult.innerNode();
+ if (!node)
+ return nullptr;
+
+ Node* pointerCursorNode = nullptr;
+ for (; node && node != terminationNode; node = node->parentInComposedTree()) {
+ // We only accept pointer nodes before reaching the body tag.
+ if (node->hasTagName(HTMLNames::bodyTag)) {
+ // Make sure we cover the case of an empty editable body.
+ if (!pointerCursorNode && node->isContentEditable())
+ pointerCursorNode = node;
+ bodyHasBeenReached = true;
+ pointerCursorStillValid = false;
+ }
+
+ // If we already have a pointer, and we reach a table, don't accept it.
+ if (pointerCursorNode && (node->hasTagName(HTMLNames::tableTag) || node->hasTagName(HTMLNames::tbodyTag)))
+ pointerCursorStillValid = false;
+
+ // If we haven't reached the body, and we are still paying attention to pointer cursors, and the node has a pointer cursor.
+ if (pointerCursorStillValid && node->renderStyle() && node->renderStyle()->cursor() == CursorType::Pointer)
+ pointerCursorNode = node;
+ else if (pointerCursorNode) {
+ // We want the lowest unbroken chain of pointer cursors.
+ pointerCursorStillValid = false;
+ }
+
+ if (nodeWillRespondToMouseEvents(*node)) {
+ // If we're at the body or higher, use the pointer cursor node (which may be null).
+ if (bodyHasBeenReached)
+ node = pointerCursorNode;
+
+ // If we are interested about the frame, use it.
+ if (nodeBounds) {
+ // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check.
+ if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && is<HTMLAreaElement>(*node))
+ *nodeBounds = snappedIntRect(downcast<HTMLAreaElement>(*node).computeRect(hitTestResult.innerNonSharedNode()->renderer()));
+ else if (node && node->renderer())
+ *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true);
+ }
+
+ return node;
+ }
+ }
+
+ return nullptr;
+ };
+
+ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToClickEvents), ShouldApproximate::Yes);
+}
+
+static inline NodeQualifier ancestorRespondingToClickEventsNodeQualifier(SecurityOrigin* securityOrigin = nullptr)
+{
+ return [securityOrigin](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* {
+ if (nodeBounds)
+ *nodeBounds = IntRect();
+
+ auto node = hitTestResult.innerNode();
+ if (!node || (securityOrigin && !securityOrigin->isSameOriginAs(node->document().securityOrigin())))
+ return nullptr;
+
+ for (; node && node != terminationNode; node = node->parentInComposedTree()) {
+ if (nodeWillRespondToMouseEvents(*node)) {
+ // If we are interested about the frame, use it.
+ if (nodeBounds) {
+ // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check.
+ if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && is<HTMLAreaElement>(*node))
+ *nodeBounds = snappedIntRect(downcast<HTMLAreaElement>(*node).computeRect(hitTestResult.innerNonSharedNode()->renderer()));
+ else if (node && node->renderer())
+ *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true);
+ }
+
+ return node;
+ }
+ }
+
+ return nullptr;
+ };
+}
+
+Node* Frame::nodeRespondingToClickEvents(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, SecurityOrigin* securityOrigin)
+{
+ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, ancestorRespondingToClickEventsNodeQualifier(securityOrigin), ShouldApproximate::Yes);
+}
+
+Node* Frame::nodeRespondingToDoubleClickEvent(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation)
+{
+ auto&& ancestorRespondingToDoubleClickEvent = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* {
+ if (nodeBounds)
+ *nodeBounds = IntRect();
+
+ auto* node = hitTestResult.innerNode();
+ if (!node)
+ return nullptr;
+
+ for (; node && node != terminationNode; node = node->parentInComposedTree()) {
+ if (!node->hasEventListeners(eventNames().dblclickEvent))
+ continue;
+#if ENABLE(TOUCH_EVENTS)
+ if (!node->allowsDoubleTapGesture())
+ continue;
+#endif
+ if (nodeBounds && node->renderer())
+ *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true);
+ return node;
+ }
+ return nullptr;
+ };
+
+ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToDoubleClickEvent), ShouldApproximate::Yes);
+}
+
+Node* Frame::nodeRespondingToInteraction(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation)
+{
+ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, ancestorRespondingToClickEventsNodeQualifier(), ShouldApproximate::Yes, ShouldFindRootEditableElement::No);
+}
+
+Node* Frame::nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation)
+{
+ auto&& ancestorRespondingToScrollWheelEvents = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* {
+ if (nodeBounds)
+ *nodeBounds = IntRect();
+
+ Node* scrollingAncestor = nullptr;
+ for (Node* node = hitTestResult.innerNode(); node && node != terminationNode && !node->hasTagName(HTMLNames::bodyTag); node = node->parentNode()) {
+ RenderObject* renderer = node->renderer();
+ if (!renderer)
+ continue;
+
+ if ((renderer->isTextField() || renderer->isTextArea()) && downcast<RenderTextControl>(*renderer).canScroll()) {
+ scrollingAncestor = node;
+ continue;
+ }
+
+ auto& style = renderer->style();
+
+ if (renderer->hasOverflowClip()
+ && (style.overflowY() == Overflow::Auto || style.overflowY() == Overflow::Scroll
+ || style.overflowX() == Overflow::Auto || style.overflowX() == Overflow::Scroll)) {
+ scrollingAncestor = node;
+ }
+ }
+
+ return scrollingAncestor;
+ };
+
+ FloatPoint adjustedViewportLocation;
+ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToScrollWheelEvents), ShouldApproximate::No);
+}
+
} // namespace WebCore
#undef RELEASE_LOG_ERROR_IF_ALLOWED
diff --git a/Source/WebCore/page/Frame.h b/Source/WebCore/page/Frame.h
index 1289087c0dfe4c553095e6399f24c8fd516cfb01..b62b0d5343e9c8012d2b7f0cd94f0cf32c8ae03b 100644
--- a/Source/WebCore/page/Frame.h
+++ b/Source/WebCore/page/Frame.h
@@ -109,8 +109,8 @@ enum {
};
enum OverflowScrollAction { DoNotPerformOverflowScroll, PerformOverflowScroll };
-using NodeQualifier = Function<Node* (const HitTestResult&, Node* terminationNode, IntRect* nodeBounds)>;
#endif
+using NodeQualifier = Function<Node* (const HitTestResult&, Node* terminationNode, IntRect* nodeBounds)>;
enum {
LayerTreeFlagsIncludeDebugInfo = 1 << 0,
@@ -228,10 +228,6 @@ public:
NSArray *dataDetectionResults() const { return m_dataDetectionResults.get(); }
#endif
-#if PLATFORM(IOS_FAMILY)
- const ViewportArguments& viewportArguments() const;
- WEBCORE_EXPORT void setViewportArguments(const ViewportArguments&);
-
WEBCORE_EXPORT Node* deepestNodeAtLocation(const FloatPoint& viewportLocation);
WEBCORE_EXPORT Node* nodeRespondingToClickEvents(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, SecurityOrigin* = nullptr);
WEBCORE_EXPORT Node* nodeRespondingToDoubleClickEvent(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation);
@@ -239,6 +235,10 @@ public:
WEBCORE_EXPORT Node* nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation);
WEBCORE_EXPORT Node* approximateNodeAtViewportLocationLegacy(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation);
+#if PLATFORM(IOS_FAMILY)
+ const ViewportArguments& viewportArguments() const;
+ WEBCORE_EXPORT void setViewportArguments(const ViewportArguments&);
+
WEBCORE_EXPORT NSArray *wordsInCurrentParagraph() const;
WEBCORE_EXPORT CGRect renderRectForPoint(CGPoint, bool* isReplaced, float* fontSize) const;
@@ -348,7 +348,6 @@ private:
#if ENABLE(DATA_DETECTION)
RetainPtr<NSArray> m_dataDetectionResults;
#endif
-#if PLATFORM(IOS_FAMILY)
void betterApproximateNode(const IntPoint& testPoint, const NodeQualifier&, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect);
bool hitTestResultAtViewportLocation(const FloatPoint& viewportLocation, HitTestResult&, IntPoint& center);
@@ -356,6 +355,7 @@ private:
enum class ShouldFindRootEditableElement : bool { No, Yes };
Node* qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, const NodeQualifier&, ShouldApproximate, ShouldFindRootEditableElement = ShouldFindRootEditableElement::Yes);
+#if PLATFORM(IOS_FAMILY)
void setTimersPausedInternal(bool);
ViewportArguments m_viewportArguments;
diff --git a/Source/WebCore/page/FrameSnapshotting.cpp b/Source/WebCore/page/FrameSnapshotting.cpp
index e2f8a37fb89b421eebfa846e54c47ee795c6a9ab..f31da2c7cb84a027601c68d26232670c1f3ab142 100644
--- a/Source/WebCore/page/FrameSnapshotting.cpp
+++ b/Source/WebCore/page/FrameSnapshotting.cpp
@@ -114,7 +114,12 @@ RefPtr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRect& image
auto buffer = ImageBuffer::create(imageRect.size(), RenderingMode::Unaccelerated, scaleFactor);
if (!buffer)
return nullptr;
+#if !PLATFORM(MAC)
+ buffer->context().scale(scaleFactor);
+#endif
buffer->context().translate(-imageRect.x(), -imageRect.y());
+ if (coordinateSpace != FrameView::ViewCoordinates)
+ buffer->context().scale(1 / frame.page()->pageScaleFactor());
if (!clipRects.isEmpty()) {
Path clipPath;
@@ -123,7 +128,10 @@ RefPtr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRect& image
buffer->context().clipPath(clipPath);
}
- frame.view()->paintContentsForSnapshot(buffer->context(), imageRect, shouldIncludeSelection, coordinateSpace);
+ FloatRect fr = imageRect;
+ if (coordinateSpace != FrameView::ViewCoordinates)
+ fr.scale(frame.page()->pageScaleFactor());
+ frame.view()->paintContentsForSnapshot(buffer->context(), enclosingIntRect(fr), shouldIncludeSelection, coordinateSpace);
return buffer;
}
diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp
index f6ba438dddc56d8e44f7a62219c3d03019285f28..3f7d32b03420cd5f4a2f13ab623f843edcb236e2 100644
--- a/Source/WebCore/page/FrameView.cpp
+++ b/Source/WebCore/page/FrameView.cpp
@@ -3004,7 +3004,7 @@ void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
void FrameView::updateBackgroundRecursively(const Optional<Color>& backgroundColor)
{
-#if HAVE(OS_DARK_MODE_SUPPORT)
+#if HAVE(OS_DARK_MODE_SUPPORT) && (defined(WTF_PLATFORM_MAC) && WTF_PLATFORM_MAC) || (defined(WTF_PLATFORM_IOS_FAMILY) && WTF_PLATFORM_IOS_FAMILY)
Color baseBackgroundColor = backgroundColor.valueOr(RenderTheme::singleton().systemColor(CSSValueAppleSystemControlBackground, styleColorOptions()));
#else
Color baseBackgroundColor = backgroundColor.valueOr(Color::white);
diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp
index 38fd7b29b53eab484e30963b51c8ae525c5d7a38..3c2f2104e3f364d3d6201e3009a448b4db317d03 100644
--- a/Source/WebCore/page/History.cpp
+++ b/Source/WebCore/page/History.cpp
@@ -33,6 +33,7 @@
#include "FrameLoaderClient.h"
#include "HistoryController.h"
#include "HistoryItem.h"
+#include "InspectorInstrumentation.h"
#include "Logging.h"
#include "NavigationScheduler.h"
#include "Page.h"
@@ -260,6 +261,7 @@ ExceptionOr<void> History::stateObjectAdded(RefPtr<SerializedScriptValue>&& data
if (!urlString.isEmpty())
frame->document()->updateURLForPushOrReplaceState(fullURL);
+ InspectorInstrumentation::didNavigateWithinPage(*frame);
if (stateObjectType == StateObjectType::Push) {
frame->loader().history().pushState(WTFMove(data), title, fullURL.string());
diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp
index 0f6aa67e04ed43e1631aa7529e654fe122cb36c4..1bc48cf6b846091b19b514b08015171312f0e965 100644
--- a/Source/WebCore/page/Page.cpp
+++ b/Source/WebCore/page/Page.cpp
@@ -433,6 +433,37 @@ void Page::setOverrideViewportArguments(const Optional<ViewportArguments>& viewp
document->updateViewportArguments();
}
+FloatSize Page::screenSize()
+{
+ return m_overrideScreenSize.valueOr(screenRect(mainFrame().view()).size());
+}
+
+void Page::setOverrideScreenSize(Optional<FloatSize> size)
+{
+ if (size == m_overrideScreenSize)
+ return;
+
+ m_overrideScreenSize = size;
+ if (auto* document = mainFrame().document())
+ document->updateViewportArguments();
+}
+
+#if ENABLE(ORIENTATION_EVENTS)
+int Page::orientation() const
+{
+ return m_overrideOrientation.valueOr(chrome().client().deviceOrientation());
+}
+
+void Page::setOverrideOrientation(Optional<int> orientation)
+{
+ if (orientation == m_overrideOrientation)
+ return;
+
+ m_overrideOrientation = orientation;
+ mainFrame().orientationChanged();
+}
+#endif
+
ScrollingCoordinator* Page::scrollingCoordinator()
{
if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) {
diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h
index 5abb350c6bb91b4e8f0b95299daa44b888bb1ad5..32ac5555d73c1b0d161c257bf9a14d2c8d0cf992 100644
--- a/Source/WebCore/page/Page.h
+++ b/Source/WebCore/page/Page.h
@@ -247,6 +247,9 @@ public:
const Optional<ViewportArguments>& overrideViewportArguments() const { return m_overrideViewportArguments; }
WEBCORE_EXPORT void setOverrideViewportArguments(const Optional<ViewportArguments>&);
+ WEBCORE_EXPORT FloatSize screenSize();
+ void setOverrideScreenSize(Optional<FloatSize> size);
+
static void refreshPlugins(bool reload);
WEBCORE_EXPORT PluginData& pluginData();
void clearPluginData();
@@ -806,6 +809,11 @@ public:
WEBCORE_EXPORT Vector<Ref<Element>> editableElementsInRect(const FloatRect&) const;
+#if ENABLE(ORIENTATION_EVENTS)
+ int orientation() const;
+ void setOverrideOrientation(Optional<int>);
+#endif
+
#if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY)
DeviceOrientationUpdateProvider* deviceOrientationUpdateProvider() const { return m_deviceOrientationUpdateProvider.get(); }
#endif
@@ -1113,6 +1121,11 @@ private:
#endif
Optional<ViewportArguments> m_overrideViewportArguments;
+ Optional<FloatSize> m_overrideScreenSize;
+
+#if ENABLE(ORIENTATION_EVENTS)
+ Optional<int> m_overrideOrientation;
+#endif
#if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY)
RefPtr<DeviceOrientationUpdateProvider> m_deviceOrientationUpdateProvider;
diff --git a/Source/WebCore/page/PointerCaptureController.cpp b/Source/WebCore/page/PointerCaptureController.cpp
index d37f5889e219d828e09ae72343d8ebd3fecfb08f..7b0f956fc187f4747b93f6b8d8b7697c889d5361 100644
--- a/Source/WebCore/page/PointerCaptureController.cpp
+++ b/Source/WebCore/page/PointerCaptureController.cpp
@@ -181,7 +181,7 @@ bool PointerCaptureController::preventsCompatibilityMouseEventsForIdentifier(Poi
return iterator != m_activePointerIdsToCapturingData.end() && iterator->value.preventsCompatibilityMouseEvents;
}
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
+#if ENABLE(TOUCH_EVENTS)
static bool hierarchyHasCapturingEventListeners(Element* target, const AtomString& eventName)
{
for (ContainerNode* curr = target; curr; curr = curr->parentInComposedTree()) {
@@ -463,7 +463,7 @@ void PointerCaptureController::cancelPointer(PointerID pointerId, const IntPoint
capturingData.pendingTargetOverride = nullptr;
capturingData.cancelled = true;
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
+#if ENABLE(TOUCH_EVENTS)
capturingData.previousTarget = nullptr;
#endif
diff --git a/Source/WebCore/page/PointerCaptureController.h b/Source/WebCore/page/PointerCaptureController.h
index 33bdbd20f4aaca7db33e055bdbea79c69800b3db..e8d329292d4b1fe6e49d74cb07a66339e63accdb 100644
--- a/Source/WebCore/page/PointerCaptureController.h
+++ b/Source/WebCore/page/PointerCaptureController.h
@@ -57,7 +57,7 @@ public:
RefPtr<PointerEvent> pointerEventForMouseEvent(const MouseEvent&);
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
+#if ENABLE(TOUCH_EVENTS)
void dispatchEventForTouchAtIndex(EventTarget&, const PlatformTouchEvent&, unsigned, bool isPrimary, WindowProxy&);
#endif
@@ -72,7 +72,7 @@ private:
struct CapturingData {
RefPtr<Element> pendingTargetOverride;
RefPtr<Element> targetOverride;
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
+#if ENABLE(TOUCH_EVENTS)
RefPtr<Element> previousTarget;
#endif
String pointerType;
diff --git a/Source/WebCore/page/RuntimeEnabledFeatures.cpp b/Source/WebCore/page/RuntimeEnabledFeatures.cpp
index e9d30c7c06618177cbab04e35b75735dc291ad1f..d0673b66d9c14e4e3f2317faa29438aa0bdc616e 100644
--- a/Source/WebCore/page/RuntimeEnabledFeatures.cpp
+++ b/Source/WebCore/page/RuntimeEnabledFeatures.cpp
@@ -56,7 +56,11 @@ RuntimeEnabledFeatures& RuntimeEnabledFeatures::sharedFeatures()
#if ENABLE(TOUCH_EVENTS)
bool RuntimeEnabledFeatures::touchEventsEnabled() const
{
- return m_touchEventsEnabled.valueOr(screenHasTouchDevice());
+ return m_touchEventsEnabled.valueOr(platformScreenHasTouchDevice());
+}
+bool RuntimeEnabledFeatures::isTouchPrimaryInputDevice() const
+{
+ return m_touchEventsEnabled.valueOr(platformScreenIsTouchPrimaryInputDevice());
}
#endif
diff --git a/Source/WebCore/page/RuntimeEnabledFeatures.h b/Source/WebCore/page/RuntimeEnabledFeatures.h
index fa200da1f0f350d27d094eb7ce564a862a8bfe00..ab934d9ba02f58338aaad3d30eeff27d8ebc9c05 100644
--- a/Source/WebCore/page/RuntimeEnabledFeatures.h
+++ b/Source/WebCore/page/RuntimeEnabledFeatures.h
@@ -211,6 +211,7 @@ public:
void setMouseEventsSimulationEnabled(bool isEnabled) { m_mouseEventsSimulationEnabled = isEnabled; }
bool touchEventsEnabled() const;
void setTouchEventsEnabled(bool isEnabled) { m_touchEventsEnabled = isEnabled; }
+ bool isTouchPrimaryInputDevice() const;
#endif
bool pageAtRuleSupportEnabled() const { return m_pageAtRuleSupportEnabled; }
diff --git a/Source/WebCore/page/SocketProvider.cpp b/Source/WebCore/page/SocketProvider.cpp
index 3bec0aef174336939838fb1069fffbcb9f3d5604..566ef3806be3c5ccf1bb951251c2a90dba7071a3 100644
--- a/Source/WebCore/page/SocketProvider.cpp
+++ b/Source/WebCore/page/SocketProvider.cpp
@@ -33,7 +33,7 @@ namespace WebCore {
Ref<SocketStreamHandle> SocketProvider::createSocketStreamHandle(const URL& url, SocketStreamHandleClient& client, WebSocketIdentifier, PAL::SessionID sessionID, const String& credentialPartition, const StorageSessionProvider* provider)
{
- return SocketStreamHandleImpl::create(url, client, sessionID, credentialPartition, { }, provider);
+ return SocketStreamHandleImpl::create(url, false, client, sessionID, credentialPartition, { }, provider);
}
RefPtr<ThreadableWebSocketChannel> SocketProvider::createWebSocketChannel(Document&, WebSocketChannelClient&)
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
index 37d5c443785f3df52bddb775cb9c1e66e0dd97b6..f2329ad61fd4f4ad006ca89ba2bdc729278dee0d 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
+++ b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
@@ -299,6 +299,8 @@ bool ContentSecurityPolicy::protocolMatchesSelf(const URL& url) const
template<typename Predicate, typename... Args>
typename std::enable_if<!std::is_convertible<Predicate, ContentSecurityPolicy::ViolatedDirectiveCallback>::value, bool>::type ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, Predicate&& predicate, Args&&... args) const
{
+ if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext))
+ return true;
bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly;
for (auto& policy : m_policies) {
if (policy->isReportOnly() != isReportOnly)
@@ -312,6 +314,8 @@ typename std::enable_if<!std::is_convertible<Predicate, ContentSecurityPolicy::V
template<typename Predicate, typename... Args>
bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const
{
+ if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext))
+ return true;
bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly;
bool isAllowed = true;
for (auto& policy : m_policies) {
@@ -328,6 +332,8 @@ bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposit
template<typename Predicate, typename... Args>
bool ContentSecurityPolicy::allPoliciesAllow(ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const
{
+ if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext))
+ return true;
bool isAllowed = true;
for (auto& policy : m_policies) {
if (const ContentSecurityPolicyDirective* violatedDirective = (policy.get()->*predicate)(std::forward<Args>(args)...)) {
diff --git a/Source/WebCore/page/ios/FrameIOS.mm b/Source/WebCore/page/ios/FrameIOS.mm
index 32d32e59b24265286710a5f3f7053e1816ad9e3b..34f7e01b612710a817debb7f8d25d6bd5f0e9e6d 100644
--- a/Source/WebCore/page/ios/FrameIOS.mm
+++ b/Source/WebCore/page/ios/FrameIOS.mm
@@ -225,354 +225,6 @@ CGRect Frame::renderRectForPoint(CGPoint point, bool* isReplaced, float* fontSiz
return CGRectZero;
}
-void Frame::betterApproximateNode(const IntPoint& testPoint, const NodeQualifier& nodeQualifierFunction, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect)
-{
- IntRect candidateRect;
- constexpr OptionSet<HitTestRequest::RequestType> hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowVisibleChildFrameContentOnly };
- auto* candidate = nodeQualifierFunction(eventHandler().hitTestResultAtPoint(testPoint, hitType), failedNode, &candidateRect);
-
- // Bail if we have no candidate, or the candidate is already equal to our current best node,
- // or our candidate is the avoidedNode and there is a current best node.
- if (!candidate || candidate == best)
- return;
-
- // The document should never be considered the best alternative.
- if (candidate->isDocumentNode())
- return;
-
- if (best) {
- IntRect bestIntersect = intersection(testRect, bestRect);
- IntRect candidateIntersect = intersection(testRect, candidateRect);
- // if the candidate intersection is smaller than the current best intersection, bail.
- if (candidateIntersect.width() * candidateIntersect.height() <= bestIntersect.width() * bestIntersect.height())
- return;
- }
-
- // At this point we either don't have a previous best, or our current candidate has a better intersection.
- best = candidate;
- bestPoint = testPoint;
- bestRect = candidateRect;
-}
-
-bool Frame::hitTestResultAtViewportLocation(const FloatPoint& viewportLocation, HitTestResult& hitTestResult, IntPoint& center)
-{
- if (!m_doc || !m_doc->renderView())
- return false;
-
- FrameView* view = m_view.get();
- if (!view)
- return false;
-
- center = view->windowToContents(roundedIntPoint(viewportLocation));
- constexpr OptionSet<HitTestRequest::RequestType> hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowVisibleChildFrameContentOnly };
- hitTestResult = eventHandler().hitTestResultAtPoint(center, hitType);
- return true;
-}
-
-Node* Frame::qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, const NodeQualifier& nodeQualifierFunction, ShouldApproximate shouldApproximate, ShouldFindRootEditableElement shouldFindRootEditableElement)
-{
- adjustedViewportLocation = viewportLocation;
-
- IntPoint testCenter;
- HitTestResult candidateInfo;
- if (!hitTestResultAtViewportLocation(viewportLocation, candidateInfo, testCenter))
- return nullptr;
-
- IntPoint bestPoint = testCenter;
-
- // We have the candidate node at the location, check whether it or one of its ancestors passes
- // the qualifier function, which typically checks if the node responds to a particular event type.
- Node* approximateNode = nodeQualifierFunction(candidateInfo, 0, 0);
-
- if (shouldFindRootEditableElement == ShouldFindRootEditableElement::Yes && approximateNode && approximateNode->isContentEditable()) {
- // If we are in editable content, we look for the root editable element.
- approximateNode = approximateNode->rootEditableElement();
- // If we have a focusable node, there is no need to approximate.
- if (approximateNode)
- shouldApproximate = ShouldApproximate::No;
- }
-
- float scale = page() ? page()->pageScaleFactor() : 1;
- float ppiFactor = screenPPIFactor();
-
- static const float unscaledSearchRadius = 15;
- int searchRadius = static_cast<int>(unscaledSearchRadius * ppiFactor / scale);
-
- if (approximateNode && shouldApproximate == ShouldApproximate::Yes) {
- const float testOffsets[] = {
- -.3f, -.3f,
- -.6f, -.6f,
- +.3f, +.3f,
- -.9f, -.9f,
- };
-
- Node* originalApproximateNode = approximateNode;
- for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) {
- IntSize testOffset(testOffsets[n] * searchRadius, testOffsets[n + 1] * searchRadius);
- IntPoint testPoint = testCenter + testOffset;
-
- constexpr OptionSet<HitTestRequest::RequestType> hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowChildFrameContent };
- auto candidateInfo = eventHandler().hitTestResultAtPoint(testPoint, hitType);
- Node* candidateNode = nodeQualifierFunction(candidateInfo, 0, 0);
- if (candidateNode && candidateNode->isDescendantOf(originalApproximateNode)) {
- approximateNode = candidateNode;
- bestPoint = testPoint;
- break;
- }
- }
- } else if (!approximateNode && shouldApproximate == ShouldApproximate::Yes) {
- // Grab the closest parent element of our failed candidate node.
- Node* candidate = candidateInfo.innerNode();
- Node* failedNode = candidate;
-
- while (candidate && !candidate->isElementNode())
- candidate = candidate->parentInComposedTree();
-
- if (candidate)
- failedNode = candidate;
-
- // The center point was tested earlier.
- const float testOffsets[] = {
- -.3f, -.3f,
- +.3f, -.3f,
- -.3f, +.3f,
- +.3f, +.3f,
- -.6f, -.6f,
- +.6f, -.6f,
- -.6f, +.6f,
- +.6f, +.6f,
- -1.f, 0,
- +1.f, 0,
- 0, +1.f,
- 0, -1.f,
- };
- IntRect bestFrame;
- IntRect testRect(testCenter, IntSize());
- testRect.inflate(searchRadius);
- int currentTestRadius = 0;
- for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) {
- IntSize testOffset(testOffsets[n] * searchRadius, testOffsets[n + 1] * searchRadius);
- IntPoint testPoint = testCenter + testOffset;
- int testRadius = std::max(abs(testOffset.width()), abs(testOffset.height()));
- if (testRadius > currentTestRadius) {
- // Bail out with the best match within a radius
- currentTestRadius = testRadius;
- if (approximateNode)
- break;
- }
- betterApproximateNode(testPoint, nodeQualifierFunction, approximateNode, failedNode, bestPoint, bestFrame, testRect);
- }
- }
-
- if (approximateNode) {
- IntPoint p = m_view->contentsToWindow(bestPoint);
- adjustedViewportLocation = p;
- if (shouldFindRootEditableElement == ShouldFindRootEditableElement::Yes && approximateNode->isContentEditable()) {
- // When in editable content, look for the root editable node again,
- // since this could be the node found with the approximation.
- approximateNode = approximateNode->rootEditableElement();
- }
- }
-
- return approximateNode;
-}
-
-Node* Frame::deepestNodeAtLocation(const FloatPoint& viewportLocation)
-{
- IntPoint center;
- HitTestResult hitTestResult;
- if (!hitTestResultAtViewportLocation(viewportLocation, hitTestResult, center))
- return nullptr;
-
- return hitTestResult.innerNode();
-}
-
-static bool nodeIsMouseFocusable(Node& node)
-{
- if (!is<Element>(node))
- return false;
-
- auto& element = downcast<Element>(node);
- if (element.isMouseFocusable())
- return true;
-
- if (auto shadowRoot = makeRefPtr(element.shadowRoot())) {
- if (shadowRoot->delegatesFocus()) {
- for (auto& node : composedTreeDescendants(element)) {
- if (is<Element>(node) && downcast<Element>(node).isMouseFocusable())
- return true;
- }
- }
- }
-
- return false;
-}
-
-static bool nodeWillRespondToMouseEvents(Node& node)
-{
- return node.willRespondToMouseClickEvents() || node.willRespondToMouseMoveEvents() || nodeIsMouseFocusable(node);
-}
-
-Node* Frame::approximateNodeAtViewportLocationLegacy(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation)
-{
- // This function is only used for UIWebView.
- auto&& ancestorRespondingToClickEvents = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* {
- bool bodyHasBeenReached = false;
- bool pointerCursorStillValid = true;
-
- if (nodeBounds)
- *nodeBounds = IntRect();
-
- auto node = hitTestResult.innerNode();
- if (!node)
- return nullptr;
-
- Node* pointerCursorNode = nullptr;
- for (; node && node != terminationNode; node = node->parentInComposedTree()) {
- // We only accept pointer nodes before reaching the body tag.
- if (node->hasTagName(HTMLNames::bodyTag)) {
- // Make sure we cover the case of an empty editable body.
- if (!pointerCursorNode && node->isContentEditable())
- pointerCursorNode = node;
- bodyHasBeenReached = true;
- pointerCursorStillValid = false;
- }
-
- // If we already have a pointer, and we reach a table, don't accept it.
- if (pointerCursorNode && (node->hasTagName(HTMLNames::tableTag) || node->hasTagName(HTMLNames::tbodyTag)))
- pointerCursorStillValid = false;
-
- // If we haven't reached the body, and we are still paying attention to pointer cursors, and the node has a pointer cursor.
- if (pointerCursorStillValid && node->renderStyle() && node->renderStyle()->cursor() == CursorType::Pointer)
- pointerCursorNode = node;
- else if (pointerCursorNode) {
- // We want the lowest unbroken chain of pointer cursors.
- pointerCursorStillValid = false;
- }
-
- if (nodeWillRespondToMouseEvents(*node)) {
- // If we're at the body or higher, use the pointer cursor node (which may be null).
- if (bodyHasBeenReached)
- node = pointerCursorNode;
-
- // If we are interested about the frame, use it.
- if (nodeBounds) {
- // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check.
- if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && is<HTMLAreaElement>(*node))
- *nodeBounds = snappedIntRect(downcast<HTMLAreaElement>(*node).computeRect(hitTestResult.innerNonSharedNode()->renderer()));
- else if (node && node->renderer())
- *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true);
- }
-
- return node;
- }
- }
-
- return nullptr;
- };
-
- return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToClickEvents), ShouldApproximate::Yes);
-}
-
-static inline NodeQualifier ancestorRespondingToClickEventsNodeQualifier(SecurityOrigin* securityOrigin = nullptr)
-{
- return [securityOrigin](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* {
- if (nodeBounds)
- *nodeBounds = IntRect();
-
- auto node = hitTestResult.innerNode();
- if (!node || (securityOrigin && !securityOrigin->isSameOriginAs(node->document().securityOrigin())))
- return nullptr;
-
- for (; node && node != terminationNode; node = node->parentInComposedTree()) {
- if (nodeWillRespondToMouseEvents(*node)) {
- // If we are interested about the frame, use it.
- if (nodeBounds) {
- // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check.
- if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && is<HTMLAreaElement>(*node))
- *nodeBounds = snappedIntRect(downcast<HTMLAreaElement>(*node).computeRect(hitTestResult.innerNonSharedNode()->renderer()));
- else if (node && node->renderer())
- *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true);
- }
-
- return node;
- }
- }
-
- return nullptr;
- };
-}
-
-Node* Frame::nodeRespondingToClickEvents(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, SecurityOrigin* securityOrigin)
-{
- return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, ancestorRespondingToClickEventsNodeQualifier(securityOrigin), ShouldApproximate::Yes);
-}
-
-Node* Frame::nodeRespondingToDoubleClickEvent(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation)
-{
- auto&& ancestorRespondingToDoubleClickEvent = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* {
- if (nodeBounds)
- *nodeBounds = IntRect();
-
- auto* node = hitTestResult.innerNode();
- if (!node)
- return nullptr;
-
- for (; node && node != terminationNode; node = node->parentInComposedTree()) {
- if (!node->hasEventListeners(eventNames().dblclickEvent))
- continue;
-#if ENABLE(TOUCH_EVENTS)
- if (!node->allowsDoubleTapGesture())
- continue;
-#endif
- if (nodeBounds && node->renderer())
- *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true);
- return node;
- }
- return nullptr;
- };
-
- return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToDoubleClickEvent), ShouldApproximate::Yes);
-}
-
-Node* Frame::nodeRespondingToInteraction(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation)
-{
- return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, ancestorRespondingToClickEventsNodeQualifier(), ShouldApproximate::Yes, ShouldFindRootEditableElement::No);
-}
-
-Node* Frame::nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation)
-{
- auto&& ancestorRespondingToScrollWheelEvents = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* {
- if (nodeBounds)
- *nodeBounds = IntRect();
-
- Node* scrollingAncestor = nullptr;
- for (Node* node = hitTestResult.innerNode(); node && node != terminationNode && !node->hasTagName(HTMLNames::bodyTag); node = node->parentNode()) {
- RenderObject* renderer = node->renderer();
- if (!renderer)
- continue;
-
- if ((renderer->isTextField() || renderer->isTextArea()) && downcast<RenderTextControl>(*renderer).canScroll()) {
- scrollingAncestor = node;
- continue;
- }
-
- auto& style = renderer->style();
-
- if (renderer->hasOverflowClip()
- && (style.overflowY() == Overflow::Auto || style.overflowY() == Overflow::Scroll
- || style.overflowX() == Overflow::Auto || style.overflowX() == Overflow::Scroll)) {
- scrollingAncestor = node;
- }
- }
-
- return scrollingAncestor;
- };
-
- FloatPoint adjustedViewportLocation;
- return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToScrollWheelEvents), ShouldApproximate::No);
-}
-
int Frame::preferredHeight() const
{
Document* document = this->document();
diff --git a/Source/WebCore/platform/Cairo.cmake b/Source/WebCore/platform/Cairo.cmake
index c1b53605713774dc006d028eda7c6a8213d6cca1..9135e67fa835ab3462b8898a9a75c9f5359eab92 100644
--- a/Source/WebCore/platform/Cairo.cmake
+++ b/Source/WebCore/platform/Cairo.cmake
@@ -16,6 +16,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS
platform/graphics/cairo/ImageBufferCairoBackend.h
platform/graphics/cairo/ImageBufferCairoImageSurfaceBackend.h
platform/graphics/cairo/ImageBufferCairoSurfaceBackend.h
+ platform/graphics/cairo/ImageBufferUtilitiesCairo.h
platform/graphics/cairo/PlatformContextCairo.h
platform/graphics/cairo/RefPtrCairo.h
)
diff --git a/Source/WebCore/platform/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/PlatformScreen.cpp b/Source/WebCore/platform/PlatformScreen.cpp
index ba50b688ab6d0bae5d199fa0bac4b7e2004baf81..0b83a798b00835635a95a0db22173de094ba4035 100644
--- a/Source/WebCore/platform/PlatformScreen.cpp
+++ b/Source/WebCore/platform/PlatformScreen.cpp
@@ -25,6 +25,7 @@
#include "config.h"
#include "PlatformScreen.h"
+#include "RuntimeEnabledFeatures.h"
#if PLATFORM(COCOA)
@@ -72,3 +73,16 @@ const ScreenData* screenData(PlatformDisplayID screenDisplayID)
} // namespace WebCore
#endif // PLATFORM(COCOA)
+
+#if ENABLE(TOUCH_EVENTS)
+namespace WebCore {
+
+bool screenHasTouchDevice() {
+ return RuntimeEnabledFeatures::sharedFeatures().touchEventsEnabled();
+}
+bool screenIsTouchPrimaryInputDevice() {
+ return RuntimeEnabledFeatures::sharedFeatures().isTouchPrimaryInputDevice();
+}
+
+} // namespace WebCore
+#endif
diff --git a/Source/WebCore/platform/PlatformScreen.h b/Source/WebCore/platform/PlatformScreen.h
index 92ce4dd6ec1821a0fc5135f38e233a5ccd04d719..3d723401a109f0e7ec8c052766d5f317f42df6a9 100644
--- a/Source/WebCore/platform/PlatformScreen.h
+++ b/Source/WebCore/platform/PlatformScreen.h
@@ -151,12 +151,14 @@ WEBCORE_EXPORT float screenScaleFactor(UIScreen * = nullptr);
#endif
#if ENABLE(TOUCH_EVENTS)
-#if PLATFORM(GTK) || PLATFORM(WPE)
WEBCORE_EXPORT bool screenHasTouchDevice();
WEBCORE_EXPORT bool screenIsTouchPrimaryInputDevice();
+#if PLATFORM(GTK) || PLATFORM(WPE)
+bool platformScreenHasTouchDevice();
+bool platformScreenIsTouchPrimaryInputDevice();
#else
-constexpr bool screenHasTouchDevice() { return true; }
-constexpr bool screenIsTouchPrimaryInputDevice() { return true; }
+constexpr bool platformScreenHasTouchDevice() { return true; }
+constexpr bool platformScreenIsTouchPrimaryInputDevice() { return true; }
#endif
#endif
diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h
index 387ad285c20dd8fd5eba27f665eee85183e77c6f..4d44ae6f18064102e13de5221e43042870bade9f 100644
--- a/Source/WebCore/platform/ScrollableArea.h
+++ b/Source/WebCore/platform/ScrollableArea.h
@@ -107,7 +107,7 @@ public:
void updateScrollSnapState();
#if ENABLE(TOUCH_EVENTS)
- virtual bool handleTouchEvent(const PlatformTouchEvent&);
+ WEBCORE_EXPORT virtual bool handleTouchEvent(const PlatformTouchEvent&);
#endif
#if PLATFORM(IOS_FAMILY)
diff --git a/Source/WebCore/platform/graphics/FontCascade.h b/Source/WebCore/platform/graphics/FontCascade.h
index 25c258b54271e01bee288fd83c7f015797bb399a..0de7f70b41402deb092ca341a5e36cb8e1c44eb2 100644
--- a/Source/WebCore/platform/graphics/FontCascade.h
+++ b/Source/WebCore/platform/graphics/FontCascade.h
@@ -283,7 +283,8 @@ private:
return true;
if (textRenderingMode == TextRenderingMode::OptimizeSpeed)
return false;
-#if PLATFORM(COCOA) || USE(FREETYPE)
+ // WIN: quick fix for https://bugs.webkit.org/show_bug.cgi?id=201213
+#if PLATFORM(COCOA) || USE(FREETYPE) || PLATFORM(WIN)
return true;
#else
return false;
diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp
index d79728555b7db9b59cb615c55a7a7a6851cb57c8..61d3cc4b488e35ef9e1afa1ce3ac5f5d60ebe9a7 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp
@@ -48,6 +48,13 @@
#include <wtf/glib/GUniquePtr.h>
#endif
+#if PLATFORM(WPE) || PLATFORM(WIN)
+#include <stdio.h> // Needed by jpeglib.h for FILE.
+extern "C" {
+#include "jpeglib.h"
+}
+#endif
+
namespace WebCore {
#if !PLATFORM(GTK)
@@ -65,8 +72,75 @@ static bool encodeImage(cairo_surface_t* image, const String& mimeType, Vector<u
return cairo_surface_write_to_png_stream(image, writeFunction, output) == CAIRO_STATUS_SUCCESS;
}
-Vector<uint8_t> data(cairo_surface_t* image, const String& mimeType, Optional<double>)
+static Vector<uint8_t> encodeJpeg(cairo_surface_t* image, int quality)
+{
+ if (cairo_surface_get_type(image) != CAIRO_SURFACE_TYPE_IMAGE) {
+ fprintf(stderr, "Unexpected cairo surface type: %d\n", cairo_surface_get_type(image));
+ return { };
+ }
+
+ if (cairo_image_surface_get_format(image) != CAIRO_FORMAT_ARGB32) {
+ fprintf(stderr, "Unexpected surface image format: %d\n", cairo_image_surface_get_format(image));
+ return { };
+ }
+
+ struct jpeg_compress_struct info;
+ struct jpeg_error_mgr error;
+ info.err = jpeg_std_error(&error);
+ jpeg_create_compress(&info);
+
+ unsigned char* bufferPtr = nullptr;
+ unsigned long bufferSize;
+ jpeg_mem_dest(&info, &bufferPtr, &bufferSize);
+ info.image_width = cairo_image_surface_get_width(image);
+ info.image_height = cairo_image_surface_get_height(image);
+
+#ifndef LIBJPEG_TURBO_VERSION
+ COMPILE_ASSERT(false, only_libjpeg_turbo_is_supported);
+#endif
+
+#if CPU(LITTLE_ENDIAN)
+ info.in_color_space = JCS_EXT_BGRA;
+#else
+ info.in_color_space = JCS_EXT_ARGB;
+#endif
+ // # of color components in input image
+ info.input_components = 4;
+
+ jpeg_set_defaults(&info);
+ jpeg_set_quality(&info, quality, true);
+
+ jpeg_start_compress(&info, true);
+
+ while (info.next_scanline < info.image_height)
+ {
+ JSAMPROW row = cairo_image_surface_get_data(image) + (info.next_scanline * cairo_image_surface_get_stride(image));
+ if (jpeg_write_scanlines(&info, &row, 1) != 1) {
+ fprintf(stderr, "JPEG library failed to encode line\n");
+ break;
+ }
+ }
+
+ jpeg_finish_compress(&info);
+ jpeg_destroy_compress(&info);
+
+ Vector<uint8_t> output;
+ output.append(bufferPtr, bufferSize);
+ // Cannot use unique_ptr as bufferPtr changes during compression. GUniquePtr would work
+ // but it's under GLib and won't work on Windows.
+ free(bufferPtr);
+ return output;
+}
+
+Vector<uint8_t> data(cairo_surface_t* image, const String& mimeType, Optional<double> quality)
{
+ if (mimeType == "image/jpeg") {
+ int qualityPercent = 100;
+ if (quality)
+ qualityPercent = static_cast<int>(*quality * 100.0 + 0.5);
+ return encodeJpeg(image, qualityPercent);
+ }
+
Vector<uint8_t> encodedImage;
if (!image || !encodeImage(image, mimeType, &encodedImage))
return { };
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h
index bc87758878d5163a938af8242c7a6800ea9bd13c..3d0751f8dfe1124bbe054daa2fa0c7552fecab32 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h
@@ -42,7 +42,7 @@ WEBCORE_EXPORT uint8_t verifyImageBufferIsBigEnough(const void* buffer, size_t b
CFStringRef jpegUTI();
RetainPtr<CFStringRef> utiFromImageBufferMIMEType(const String&);
-bool encodeImage(CGImageRef, CFStringRef uti, Optional<double> quality, CFMutableDataRef);
+WEBCORE_EXPORT bool encodeImage(CGImageRef, CFStringRef uti, Optional<double> quality, CFMutableDataRef);
String dataURL(CFDataRef, const String& mimeType);
String dataURL(const ImageData&, const String& mimeType, Optional<double> quality);
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp
index 20bf2f4f984cc7f2bb73c6da559f0800a33a149c..f32f8564dd6bc19fbf615fb104cca5abfe39b361 100644
--- a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp
+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "GraphicsContextGLOpenGL.h"
-#if ENABLE(GRAPHICS_CONTEXT_GL) && USE(OPENGL)
+#if !PLATFORM(WIN) && ENABLE(GRAPHICS_CONTEXT_GL) && USE(OPENGL)
#include "ExtensionsGLOpenGL.h"
#include "IntRect.h"
diff --git a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp
index 774a52a28693bc51dde10a0875ea379afb06fd3c..cd714a7298fe4f5d2c9b580697a5c4cd22d25870 100644
--- a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp
+++ b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp
@@ -172,6 +172,33 @@ static Vector<unsigned> stringIndicesFromClusters(const Vector<WORD>& clusters,
return stringIndices;
}
+static int compactScriptItemsIfNeeded(const UChar* cp, unsigned stringLength, Vector<SCRIPT_ITEM>& items, int numItems, const Font* font)
+{
+ // https://bugs.webkit.org/show_bug.cgi?id=201214
+ // Uniscribe is overly aggressive in separating the runs. It'll split "3d_rotation" into "3", "d", "_" and "rotation" and we
+ // will ScriptShape them separately. As a result, a ligature for "3d_rotation" in the Material icon set
+ // (https://www.materialui.co/icon/3d-rotation) will not be used. A quick and dirty hack is to glue them back here, only making
+ // this apply to the readable characters, digits and _.
+
+ if (!numItems)
+ return numItems;
+
+ if (font->platformData().isSystemFont() || font->platformData().hasVariations())
+ return numItems;
+
+ bool allGoodCharacters = true;
+ for (unsigned i = 0; allGoodCharacters && i < stringLength; ++i) {
+ const UChar c = cp[i];
+ allGoodCharacters = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_';
+ }
+ if (!allGoodCharacters)
+ return numItems;
+
+ // Consume entire string into a single run. |items| is at least numItems + 1 long.
+ items[1] = items[numItems];
+ return 1;
+}
+
void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned stringLength, unsigned stringLocation, const Font* font)
{
if (!font) {
@@ -201,6 +228,8 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp,
}
items.resize(numItems + 1);
+ numItems = compactScriptItemsIfNeeded(cp, stringLength, items, numItems, font);
+
for (int i = 0; i < numItems; i++) {
// Determine the string for this item.
const UChar* str = cp + items[i].iCharPos;
diff --git a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
index 0516e70973e0078de6ad0216375d34dd9ef51a8d..ffd9a02deb5518e0c8c77b156815c11eb4b16829 100644
--- a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
+++ b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
@@ -37,8 +37,10 @@
#include "WindowsKeyboardCodes.h"
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
+#include <wtf/HashMap.h>
#include <wtf/HexNumber.h>
#include <wtf/glib/GUniquePtr.h>
+#include <mutex>
namespace WebCore {
@@ -1294,6 +1296,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode)
}
+static const HashMap<int, unsigned>& gdkToWindowsKeyCodeMap()
+{
+ static HashMap<int, unsigned>* result;
+ static std::once_flag once;
+ std::call_once(
+ once,
+ [] {
+ const unsigned gdkKeyCodes[] = {
+ GDK_KEY_Cancel,
+ // FIXME: non-keypad keys should take precedence, so we skip GDK_KEY_KP_*
+ // GDK_KEY_KP_0,
+ // GDK_KEY_KP_1,
+ // GDK_KEY_KP_2,
+ // GDK_KEY_KP_3,
+ // GDK_KEY_KP_4,
+ // GDK_KEY_KP_5,
+ // GDK_KEY_KP_6,
+ // GDK_KEY_KP_7,
+ // GDK_KEY_KP_8,
+ // GDK_KEY_KP_9,
+ // GDK_KEY_KP_Multiply,
+ // GDK_KEY_KP_Add,
+ // GDK_KEY_KP_Subtract,
+ // GDK_KEY_KP_Decimal,
+ // GDK_KEY_KP_Divide,
+ // GDK_KEY_KP_Page_Up,
+ // GDK_KEY_KP_Page_Down,
+ // GDK_KEY_KP_End,
+ // GDK_KEY_KP_Home,
+ // GDK_KEY_KP_Left,
+ // GDK_KEY_KP_Up,
+ // GDK_KEY_KP_Right,
+ // GDK_KEY_KP_Down,
+ GDK_KEY_BackSpace,
+ // GDK_KEY_ISO_Left_Tab,
+ // GDK_KEY_3270_BackTab,
+ GDK_KEY_Tab,
+ GDK_KEY_Clear,
+ // GDK_KEY_ISO_Enter,
+ // GDK_KEY_KP_Enter,
+ GDK_KEY_Return,
+ GDK_KEY_Menu,
+ GDK_KEY_Pause,
+ GDK_KEY_AudioPause,
+ GDK_KEY_Caps_Lock,
+ GDK_KEY_Kana_Lock,
+ GDK_KEY_Kana_Shift,
+ GDK_KEY_Hangul,
+ GDK_KEY_Hangul_Hanja,
+ GDK_KEY_Kanji,
+ GDK_KEY_Escape,
+ GDK_KEY_space,
+ GDK_KEY_Page_Up,
+ GDK_KEY_Page_Down,
+ GDK_KEY_End,
+ GDK_KEY_Home,
+ GDK_KEY_Left,
+ GDK_KEY_Up,
+ GDK_KEY_Right,
+ GDK_KEY_Down,
+ GDK_KEY_Select,
+ GDK_KEY_Print,
+ GDK_KEY_Execute,
+ GDK_KEY_Insert,
+ GDK_KEY_KP_Insert,
+ GDK_KEY_Delete,
+ GDK_KEY_KP_Delete,
+ GDK_KEY_Help,
+ GDK_KEY_0,
+ GDK_KEY_parenright,
+ GDK_KEY_1,
+ GDK_KEY_exclam,
+ GDK_KEY_2,
+ GDK_KEY_at,
+ GDK_KEY_3,
+ GDK_KEY_numbersign,
+ GDK_KEY_4,
+ GDK_KEY_dollar,
+ GDK_KEY_5,
+ GDK_KEY_percent,
+ GDK_KEY_6,
+ GDK_KEY_asciicircum,
+ GDK_KEY_7,
+ GDK_KEY_ampersand,
+ GDK_KEY_8,
+ GDK_KEY_asterisk,
+ GDK_KEY_9,
+ GDK_KEY_parenleft,
+ GDK_KEY_a,
+ GDK_KEY_A,
+ GDK_KEY_b,
+ GDK_KEY_B,
+ GDK_KEY_c,
+ GDK_KEY_C,
+ GDK_KEY_d,
+ GDK_KEY_D,
+ GDK_KEY_e,
+ GDK_KEY_E,
+ GDK_KEY_f,
+ GDK_KEY_F,
+ GDK_KEY_g,
+ GDK_KEY_G,
+ GDK_KEY_h,
+ GDK_KEY_H,
+ GDK_KEY_i,
+ GDK_KEY_I,
+ GDK_KEY_j,
+ GDK_KEY_J,
+ GDK_KEY_k,
+ GDK_KEY_K,
+ GDK_KEY_l,
+ GDK_KEY_L,
+ GDK_KEY_m,
+ GDK_KEY_M,
+ GDK_KEY_n,
+ GDK_KEY_N,
+ GDK_KEY_o,
+ GDK_KEY_O,
+ GDK_KEY_p,
+ GDK_KEY_P,
+ GDK_KEY_q,
+ GDK_KEY_Q,
+ GDK_KEY_r,
+ GDK_KEY_R,
+ GDK_KEY_s,
+ GDK_KEY_S,
+ GDK_KEY_t,
+ GDK_KEY_T,
+ GDK_KEY_u,
+ GDK_KEY_U,
+ GDK_KEY_v,
+ GDK_KEY_V,
+ GDK_KEY_w,
+ GDK_KEY_W,
+ GDK_KEY_x,
+ GDK_KEY_X,
+ GDK_KEY_y,
+ GDK_KEY_Y,
+ GDK_KEY_z,
+ GDK_KEY_Z,
+ GDK_KEY_Meta_L,
+ GDK_KEY_Meta_R,
+ GDK_KEY_Sleep,
+ GDK_KEY_Num_Lock,
+ GDK_KEY_Scroll_Lock,
+ GDK_KEY_Shift_L,
+ GDK_KEY_Shift_R,
+ GDK_KEY_Control_L,
+ GDK_KEY_Control_R,
+ GDK_KEY_Alt_L,
+ GDK_KEY_Alt_R,
+ GDK_KEY_Back,
+ GDK_KEY_Forward,
+ GDK_KEY_Refresh,
+ GDK_KEY_Stop,
+ GDK_KEY_Search,
+ GDK_KEY_Favorites,
+ GDK_KEY_HomePage,
+ GDK_KEY_AudioMute,
+ GDK_KEY_AudioLowerVolume,
+ GDK_KEY_AudioRaiseVolume,
+ GDK_KEY_AudioNext,
+ GDK_KEY_AudioPrev,
+ GDK_KEY_AudioStop,
+ GDK_KEY_AudioMedia,
+ GDK_KEY_semicolon,
+ GDK_KEY_colon,
+ GDK_KEY_plus,
+ GDK_KEY_equal,
+ GDK_KEY_comma,
+ GDK_KEY_less,
+ GDK_KEY_minus,
+ GDK_KEY_underscore,
+ GDK_KEY_period,
+ GDK_KEY_greater,
+ GDK_KEY_slash,
+ GDK_KEY_question,
+ GDK_KEY_asciitilde,
+ GDK_KEY_quoteleft,
+ GDK_KEY_bracketleft,
+ GDK_KEY_braceleft,
+ GDK_KEY_backslash,
+ GDK_KEY_bar,
+ GDK_KEY_bracketright,
+ GDK_KEY_braceright,
+ GDK_KEY_quoteright,
+ GDK_KEY_quotedbl,
+ GDK_KEY_AudioRewind,
+ GDK_KEY_AudioForward,
+ GDK_KEY_AudioPlay,
+ GDK_KEY_F1,
+ GDK_KEY_F2,
+ GDK_KEY_F3,
+ GDK_KEY_F4,
+ GDK_KEY_F5,
+ GDK_KEY_F6,
+ GDK_KEY_F7,
+ GDK_KEY_F8,
+ GDK_KEY_F9,
+ GDK_KEY_F10,
+ GDK_KEY_F11,
+ GDK_KEY_F12,
+ GDK_KEY_F13,
+ GDK_KEY_F14,
+ GDK_KEY_F15,
+ GDK_KEY_F16,
+ GDK_KEY_F17,
+ GDK_KEY_F18,
+ GDK_KEY_F19,
+ GDK_KEY_F20,
+ GDK_KEY_F21,
+ GDK_KEY_F22,
+ GDK_KEY_F23,
+ GDK_KEY_F24,
+ GDK_KEY_VoidSymbol,
+ GDK_KEY_Red,
+ GDK_KEY_Green,
+ GDK_KEY_Yellow,
+ GDK_KEY_Blue,
+ GDK_KEY_PowerOff,
+ GDK_KEY_AudioRecord,
+ GDK_KEY_Display,
+ GDK_KEY_Subtitle,
+ GDK_KEY_Video
+ };
+ result = new HashMap<int, unsigned>();
+ for (unsigned gdkKeyCode : gdkKeyCodes) {
+ int winKeyCode = PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(gdkKeyCode);
+ // If several gdk key codes map to the same win key code first one is used.
+ result->add(winKeyCode, gdkKeyCode);
+ }
+ });
+ return *result;
+}
+
+unsigned PlatformKeyboardEvent::gdkKeyCodeForWindowsKeyCode(int keycode)
+{
+ return gdkToWindowsKeyCodeMap().get(keycode);
+}
+
String PlatformKeyboardEvent::singleCharacterString(unsigned val)
{
switch (val) {
diff --git a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp
index e0e8809d8f39614b2b6bb8c7cf0f02652d574fe7..5d05504ec57869c9d6c6562c4237640099c295cd 100644
--- a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp
+++ b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp
@@ -218,7 +218,7 @@ bool screenSupportsExtendedColor(Widget*)
}
#if ENABLE(TOUCH_EVENTS)
-bool screenHasTouchDevice()
+bool platformScreenHasTouchDevice()
{
auto* display = gdk_display_get_default();
if (!display)
@@ -228,7 +228,7 @@ bool screenHasTouchDevice()
return seat ? gdk_seat_get_capabilities(seat) & GDK_SEAT_CAPABILITY_TOUCH : true;
}
-bool screenIsTouchPrimaryInputDevice()
+bool platformScreenIsTouchPrimaryInputDevice()
{
auto* display = gdk_display_get_default();
if (!display)
diff --git a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp
index a34dc220bbb9a92b40dfb463e8724e81ac745b2c..8ecedd5dae88469366a619b96960598c1232a32d 100644
--- a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp
+++ b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp
@@ -30,8 +30,10 @@
#include "WindowsKeyboardCodes.h"
#include <wpe/wpe.h>
+#include <wtf/HashMap.h>
#include <wtf/HexNumber.h>
#include <wtf/text/StringBuilder.h>
+#include <mutex>
namespace WebCore {
@@ -1291,6 +1293,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(unsigned keycode)
return 0;
}
+static const HashMap<int, unsigned>& WPEToWindowsKeyCodeMap()
+{
+ static HashMap<int, unsigned>* result;
+ static std::once_flag once;
+ std::call_once(
+ once,
+ [] {
+ const unsigned WPEKeyCodes[] = {
+ WPE_KEY_Cancel,
+ // FIXME: non-keypad keys should take precedence, so we skip WPE_KEY_KP_*
+ // WPE_KEY_KP_0,
+ // WPE_KEY_KP_1,
+ // WPE_KEY_KP_2,
+ // WPE_KEY_KP_3,
+ // WPE_KEY_KP_4,
+ // WPE_KEY_KP_5,
+ // WPE_KEY_KP_6,
+ // WPE_KEY_KP_7,
+ // WPE_KEY_KP_8,
+ // WPE_KEY_KP_9,
+ // WPE_KEY_KP_Multiply,
+ // WPE_KEY_KP_Add,
+ // WPE_KEY_KP_Subtract,
+ // WPE_KEY_KP_Decimal,
+ // WPE_KEY_KP_Divide,
+ // WPE_KEY_KP_Page_Up,
+ // WPE_KEY_KP_Page_Down,
+ // WPE_KEY_KP_End,
+ // WPE_KEY_KP_Home,
+ // WPE_KEY_KP_Left,
+ // WPE_KEY_KP_Up,
+ // WPE_KEY_KP_Right,
+ // WPE_KEY_KP_Down,
+ WPE_KEY_BackSpace,
+ // WPE_KEY_ISO_Left_Tab,
+ // WPE_KEY_3270_BackTab,
+ WPE_KEY_Tab,
+ WPE_KEY_Clear,
+ // WPE_KEY_ISO_Enter,
+ // WPE_KEY_KP_Enter,
+ WPE_KEY_Return,
+ WPE_KEY_Menu,
+ WPE_KEY_Pause,
+ WPE_KEY_AudioPause,
+ WPE_KEY_Caps_Lock,
+ WPE_KEY_Kana_Lock,
+ WPE_KEY_Kana_Shift,
+ WPE_KEY_Hangul,
+ WPE_KEY_Hangul_Hanja,
+ WPE_KEY_Kanji,
+ WPE_KEY_Escape,
+ WPE_KEY_space,
+ WPE_KEY_Page_Up,
+ WPE_KEY_Page_Down,
+ WPE_KEY_End,
+ WPE_KEY_Home,
+ WPE_KEY_Left,
+ WPE_KEY_Up,
+ WPE_KEY_Right,
+ WPE_KEY_Down,
+ WPE_KEY_Select,
+ WPE_KEY_Print,
+ WPE_KEY_Execute,
+ WPE_KEY_Insert,
+ WPE_KEY_KP_Insert,
+ WPE_KEY_Delete,
+ WPE_KEY_KP_Delete,
+ WPE_KEY_Help,
+ WPE_KEY_0,
+ WPE_KEY_parenright,
+ WPE_KEY_1,
+ WPE_KEY_exclam,
+ WPE_KEY_2,
+ WPE_KEY_at,
+ WPE_KEY_3,
+ WPE_KEY_numbersign,
+ WPE_KEY_4,
+ WPE_KEY_dollar,
+ WPE_KEY_5,
+ WPE_KEY_percent,
+ WPE_KEY_6,
+ WPE_KEY_asciicircum,
+ WPE_KEY_7,
+ WPE_KEY_ampersand,
+ WPE_KEY_8,
+ WPE_KEY_asterisk,
+ WPE_KEY_9,
+ WPE_KEY_parenleft,
+ WPE_KEY_a,
+ WPE_KEY_A,
+ WPE_KEY_b,
+ WPE_KEY_B,
+ WPE_KEY_c,
+ WPE_KEY_C,
+ WPE_KEY_d,
+ WPE_KEY_D,
+ WPE_KEY_e,
+ WPE_KEY_E,
+ WPE_KEY_f,
+ WPE_KEY_F,
+ WPE_KEY_g,
+ WPE_KEY_G,
+ WPE_KEY_h,
+ WPE_KEY_H,
+ WPE_KEY_i,
+ WPE_KEY_I,
+ WPE_KEY_j,
+ WPE_KEY_J,
+ WPE_KEY_k,
+ WPE_KEY_K,
+ WPE_KEY_l,
+ WPE_KEY_L,
+ WPE_KEY_m,
+ WPE_KEY_M,
+ WPE_KEY_n,
+ WPE_KEY_N,
+ WPE_KEY_o,
+ WPE_KEY_O,
+ WPE_KEY_p,
+ WPE_KEY_P,
+ WPE_KEY_q,
+ WPE_KEY_Q,
+ WPE_KEY_r,
+ WPE_KEY_R,
+ WPE_KEY_s,
+ WPE_KEY_S,
+ WPE_KEY_t,
+ WPE_KEY_T,
+ WPE_KEY_u,
+ WPE_KEY_U,
+ WPE_KEY_v,
+ WPE_KEY_V,
+ WPE_KEY_w,
+ WPE_KEY_W,
+ WPE_KEY_x,
+ WPE_KEY_X,
+ WPE_KEY_y,
+ WPE_KEY_Y,
+ WPE_KEY_z,
+ WPE_KEY_Z,
+ WPE_KEY_Meta_L,
+ WPE_KEY_Meta_R,
+ WPE_KEY_Sleep,
+ WPE_KEY_Num_Lock,
+ WPE_KEY_Scroll_Lock,
+ WPE_KEY_Shift_L,
+ WPE_KEY_Shift_R,
+ WPE_KEY_Control_L,
+ WPE_KEY_Control_R,
+ WPE_KEY_Alt_L,
+ WPE_KEY_Alt_R,
+ WPE_KEY_Back,
+ WPE_KEY_Forward,
+ WPE_KEY_Refresh,
+ WPE_KEY_Stop,
+ WPE_KEY_Search,
+ WPE_KEY_Favorites,
+ WPE_KEY_HomePage,
+ WPE_KEY_AudioMute,
+ WPE_KEY_AudioLowerVolume,
+ WPE_KEY_AudioRaiseVolume,
+ WPE_KEY_AudioNext,
+ WPE_KEY_AudioPrev,
+ WPE_KEY_AudioStop,
+ WPE_KEY_AudioMedia,
+ WPE_KEY_semicolon,
+ WPE_KEY_colon,
+ WPE_KEY_plus,
+ WPE_KEY_equal,
+ WPE_KEY_comma,
+ WPE_KEY_less,
+ WPE_KEY_minus,
+ WPE_KEY_underscore,
+ WPE_KEY_period,
+ WPE_KEY_greater,
+ WPE_KEY_slash,
+ WPE_KEY_question,
+ WPE_KEY_asciitilde,
+ WPE_KEY_quoteleft,
+ WPE_KEY_bracketleft,
+ WPE_KEY_braceleft,
+ WPE_KEY_backslash,
+ WPE_KEY_bar,
+ WPE_KEY_bracketright,
+ WPE_KEY_braceright,
+ WPE_KEY_quoteright,
+ WPE_KEY_quotedbl,
+ WPE_KEY_AudioRewind,
+ WPE_KEY_AudioForward,
+ WPE_KEY_AudioPlay,
+ WPE_KEY_F1,
+ WPE_KEY_F2,
+ WPE_KEY_F3,
+ WPE_KEY_F4,
+ WPE_KEY_F5,
+ WPE_KEY_F6,
+ WPE_KEY_F7,
+ WPE_KEY_F8,
+ WPE_KEY_F9,
+ WPE_KEY_F10,
+ WPE_KEY_F11,
+ WPE_KEY_F12,
+ WPE_KEY_F13,
+ WPE_KEY_F14,
+ WPE_KEY_F15,
+ WPE_KEY_F16,
+ WPE_KEY_F17,
+ WPE_KEY_F18,
+ WPE_KEY_F19,
+ WPE_KEY_F20,
+ WPE_KEY_F21,
+ WPE_KEY_F22,
+ WPE_KEY_F23,
+ WPE_KEY_F24,
+ WPE_KEY_VoidSymbol,
+ WPE_KEY_Red,
+ WPE_KEY_Green,
+ WPE_KEY_Yellow,
+ WPE_KEY_Blue,
+ WPE_KEY_PowerOff,
+ WPE_KEY_AudioRecord,
+ WPE_KEY_Display,
+ WPE_KEY_Subtitle,
+ WPE_KEY_Video
+ };
+ result = new HashMap<int, unsigned>();
+ for (unsigned WPEKeyCode : WPEKeyCodes) {
+ int winKeyCode = PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(WPEKeyCode);
+ // If several gdk key codes map to the same win key code first one is used.
+ result->add(winKeyCode, WPEKeyCode);
+ }
+ });
+ return *result;
+}
+
+unsigned PlatformKeyboardEvent::WPEKeyCodeForWindowsKeyCode(int keycode)
+{
+ return WPEToWindowsKeyCodeMap().get(keycode);
+}
+
String PlatformKeyboardEvent::singleCharacterString(unsigned val)
{
switch (val) {
diff --git a/Source/WebCore/platform/network/HTTPHeaderMap.cpp b/Source/WebCore/platform/network/HTTPHeaderMap.cpp
index 39cb560e54bf9efd2dad6e1fb60dd0f609daf6bf..91c132460d4b466f61a8c579f70329fdde3b130f 100644
--- a/Source/WebCore/platform/network/HTTPHeaderMap.cpp
+++ b/Source/WebCore/platform/network/HTTPHeaderMap.cpp
@@ -205,8 +205,11 @@ void HTTPHeaderMap::add(HTTPHeaderName name, const String& value)
auto index = m_commonHeaders.findMatching([&](auto& header) {
return header.key == name;
});
+ // Align with Chromium and Firefox, but just for SetCookies where it is critical:
+ // https://bit.ly/2HCa0iq
+ String separator = name == HTTPHeaderName::SetCookie ? "\n " : ", ";
if (index != notFound)
- m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, ", ", value);
+ m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, separator, value);
else
m_commonHeaders.append(CommonHeader { name, value });
}
diff --git a/Source/WebCore/platform/network/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<bool> m_isOnLine;
+ Optional<bool> m_emulatedIsOnLine;
Vector<WTF::Function<void(bool)>> m_listeners;
Timer m_updateStateTimer;
diff --git a/Source/WebCore/platform/network/ResourceResponseBase.h b/Source/WebCore/platform/network/ResourceResponseBase.h
index ddab08a247db7b194fcc980308e12eb3f9bda697..cae230a8cfd31a633727574ee088c0fae4024e83 100644
--- a/Source/WebCore/platform/network/ResourceResponseBase.h
+++ b/Source/WebCore/platform/network/ResourceResponseBase.h
@@ -211,6 +211,8 @@ public:
bool containsInvalidHTTPHeaders() const;
+ HTTPHeaderMap m_httpRequestHeaderFields;
+
protected:
enum InitLevel {
Uninitialized,
@@ -293,6 +295,7 @@ void ResourceResponseBase::encode(Encoder& encoder) const
encoder << m_httpStatusText;
encoder << m_httpVersion;
encoder << m_httpHeaderFields;
+ encoder << m_httpRequestHeaderFields;
// We don't want to put the networkLoadMetrics info
// into the disk cache, because we will never use the old info.
@@ -365,6 +368,12 @@ bool ResourceResponseBase::decode(Decoder& decoder, ResourceResponseBase& respon
return false;
response.m_httpHeaderFields = WTFMove(*httpHeaderFields);
+ Optional<HTTPHeaderMap> httpRequestHeaderFields;
+ decoder >> httpRequestHeaderFields;
+ if (!httpRequestHeaderFields)
+ return false;
+ response.m_httpRequestHeaderFields = WTFMove(*httpRequestHeaderFields);
+
// The networkLoadMetrics info is only send over IPC and not stored in disk cache.
if constexpr (Decoder::isIPCDecoder) {
Optional<Box<NetworkLoadMetrics>> networkLoadMetrics;
diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h
index d677280d2b5e7b053a240c155d64bc881f1737bb..1be949e09982b34366d162e6d45ebc51a76dcfb0 100644
--- a/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h
+++ b/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h
@@ -47,7 +47,7 @@ class SocketStreamHandleClient;
class SocketStreamHandleImpl : public SocketStreamHandle {
public:
- static Ref<SocketStreamHandleImpl> create(const URL& url, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, client, sessionID, credentialPartition, WTFMove(auditData), provider)); }
+ static Ref<SocketStreamHandleImpl> create(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, ignoreCertificateErrors, client, sessionID, credentialPartition, WTFMove(auditData), provider)); }
virtual ~SocketStreamHandleImpl();
@@ -61,7 +61,7 @@ private:
Optional<size_t> platformSendInternal(const uint8_t*, size_t);
bool sendPendingData();
- WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String& credentialPartition, SourceApplicationAuditToken&&, const StorageSessionProvider*);
+ WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, bool ignoreCertificateErrors, SocketStreamHandleClient&, PAL::SessionID, const String& credentialPartition, SourceApplicationAuditToken&&, const StorageSessionProvider*);
void createStreams();
void scheduleStreams();
void chooseProxy();
@@ -106,6 +106,7 @@ private:
String m_credentialPartition;
SourceApplicationAuditToken m_auditData;
RefPtr<const StorageSessionProvider> m_storageSessionProvider;
+ bool m_ignoreCertificateErrors { false };
StreamBuffer<uint8_t, 1024 * 1024> m_buffer;
static const unsigned maxBufferSize = 100 * 1024 * 1024;
diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp b/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp
index 9915f0ceacaf946eb4af2d6b740f7226e344b78d..4382ccde112e3c21892a4dd28fba416a6db90a62 100644
--- a/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp
@@ -96,7 +96,7 @@ static inline auto callbacksRunLoopMode()
#endif
}
-SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider)
+SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider)
: SocketStreamHandle(url, client)
, m_connectingSubstate(New)
, m_connectionType(Unknown)
@@ -104,6 +104,7 @@ SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandl
, m_credentialPartition(credentialPartition)
, m_auditData(WTFMove(auditData))
, m_storageSessionProvider(provider)
+ , m_ignoreCertificateErrors(ignoreCertificateErrors)
{
LOG(Network, "SocketStreamHandle %p new client %p", this, &m_client);
@@ -360,7 +361,7 @@ void SocketStreamHandleImpl::createStreams()
}
if (shouldUseSSL()) {
- CFBooleanRef validateCertificateChain = DeprecatedGlobalSettings::allowsAnySSLCertificate() ? kCFBooleanFalse : kCFBooleanTrue;
+ CFBooleanRef validateCertificateChain = m_ignoreCertificateErrors || DeprecatedGlobalSettings::allowsAnySSLCertificate() ? kCFBooleanFalse : kCFBooleanTrue;
const void* keys[] = {
kCFStreamSSLPeerName,
kCFStreamSSLLevel,
diff --git a/Source/WebCore/platform/network/curl/CookieJarDB.h b/Source/WebCore/platform/network/curl/CookieJarDB.h
index 7c0ea47ece4ff0d472ce595c91ea1cfa90b25ca7..1c44229a18fe90f6e5e0c0056dddd09acadfe49b 100644
--- a/Source/WebCore/platform/network/curl/CookieJarDB.h
+++ b/Source/WebCore/platform/network/curl/CookieJarDB.h
@@ -72,7 +72,7 @@ public:
WEBCORE_EXPORT ~CookieJarDB();
private:
- CookieAcceptPolicy m_acceptPolicy { CookieAcceptPolicy::Always };
+ CookieAcceptPolicy m_acceptPolicy { CookieAcceptPolicy::OnlyFromMainDocumentDomain };
String m_databasePath;
bool m_detectedDatabaseCorruption { false };
diff --git a/Source/WebCore/platform/network/curl/CurlStream.cpp b/Source/WebCore/platform/network/curl/CurlStream.cpp
index 1b15af01bcc0eab910fc3b9e8a8d463b7c668519..c11f0b310810fad74eacbd2c41ff16c2507111f1 100644
--- a/Source/WebCore/platform/network/curl/CurlStream.cpp
+++ b/Source/WebCore/platform/network/curl/CurlStream.cpp
@@ -33,7 +33,7 @@
namespace WebCore {
-CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, URL&& url)
+CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, bool ignoreCertificateErrors, URL&& url)
: m_scheduler(scheduler)
, m_streamID(streamID)
{
@@ -45,6 +45,9 @@ CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, UR
m_curlHandle->setUrl(WTFMove(url));
m_curlHandle->enableConnectionOnly();
+ if (ignoreCertificateErrors)
+ m_curlHandle->disableServerTrustEvaluation();
+
auto errorCode = m_curlHandle->perform();
if (errorCode != CURLE_OK) {
diff --git a/Source/WebCore/platform/network/curl/CurlStream.h b/Source/WebCore/platform/network/curl/CurlStream.h
index 313b0173da5cd404a1e3fcad9573b8ff7c3abd4f..020980a0f61d47e8c7929bfaab2f8394d014766d 100644
--- a/Source/WebCore/platform/network/curl/CurlStream.h
+++ b/Source/WebCore/platform/network/curl/CurlStream.h
@@ -50,12 +50,12 @@ public:
virtual void didFail(CurlStreamID, CURLcode) = 0;
};
- static std::unique_ptr<CurlStream> create(CurlStreamScheduler& scheduler, CurlStreamID streamID, URL&& url)
+ static std::unique_ptr<CurlStream> create(CurlStreamScheduler& scheduler, CurlStreamID streamID, bool ignoreCertificateErrors, URL&& url)
{
- return WTF::makeUnique<CurlStream>(scheduler, streamID, WTFMove(url));
+ return WTF::makeUnique<CurlStream>(scheduler, streamID, ignoreCertificateErrors, WTFMove(url));
}
- CurlStream(CurlStreamScheduler&, CurlStreamID, URL&&);
+ CurlStream(CurlStreamScheduler&, CurlStreamID, bool ignoreCertificateErrors, URL&&);
virtual ~CurlStream();
void send(UniqueArray<uint8_t>&&, size_t);
diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp
index 3fb8759984aa31a7d44baa2f69afe2fee461ea4f..bb7ad47477d97fa1eaff5d3da6b9a3705ff1e32f 100644
--- a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp
+++ b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp
@@ -40,7 +40,7 @@ CurlStreamScheduler::~CurlStreamScheduler()
ASSERT(isMainThread());
}
-CurlStreamID CurlStreamScheduler::createStream(const URL& url, CurlStream::Client& client)
+CurlStreamID CurlStreamScheduler::createStream(const URL& url, bool ignoreCertificateErrors, CurlStream::Client& client)
{
ASSERT(isMainThread());
@@ -51,8 +51,8 @@ CurlStreamID CurlStreamScheduler::createStream(const URL& url, CurlStream::Clien
auto streamID = m_currentStreamID;
m_clientList.add(streamID, &client);
- callOnWorkerThread([this, streamID, url = url.isolatedCopy()]() mutable {
- m_streamList.add(streamID, CurlStream::create(*this, streamID, WTFMove(url)));
+ callOnWorkerThread([this, streamID, ignoreCertificateErrors, url = url.isolatedCopy()]() mutable {
+ m_streamList.add(streamID, CurlStream::create(*this, streamID, ignoreCertificateErrors, WTFMove(url)));
});
return streamID;
diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.h b/Source/WebCore/platform/network/curl/CurlStreamScheduler.h
index 7d881206c9689f433227969c9b7f9ff268bdaaed..2e8118f11f87fa5f32adcedc165aec8220b36d58 100644
--- a/Source/WebCore/platform/network/curl/CurlStreamScheduler.h
+++ b/Source/WebCore/platform/network/curl/CurlStreamScheduler.h
@@ -38,7 +38,7 @@ public:
CurlStreamScheduler();
virtual ~CurlStreamScheduler();
- CurlStreamID createStream(const URL&, CurlStream::Client&);
+ CurlStreamID createStream(const URL&, bool ignoreCertificateErrors, CurlStream::Client&);
void destroyStream(CurlStreamID);
void send(CurlStreamID, UniqueArray<uint8_t>&&, size_t);
diff --git a/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h
index fad4ef9198118f5e6e5ed7d3c14b99e574593451..a2d59843896f252fccdddbb94c5275eec6300f1b 100644
--- a/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h
+++ b/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h
@@ -44,7 +44,7 @@ class StorageSessionProvider;
class SocketStreamHandleImpl : public SocketStreamHandle, public CurlStream::Client {
public:
- static Ref<SocketStreamHandleImpl> create(const URL& url, SocketStreamHandleClient& client, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, client, provider)); }
+ static Ref<SocketStreamHandleImpl> create(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, ignoreCertificateErrors, client, provider)); }
virtual ~SocketStreamHandleImpl();
@@ -53,7 +53,7 @@ public:
WEBCORE_EXPORT void platformClose() final;
private:
- WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&, const StorageSessionProvider*);
+ WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, bool ignoreCertificateErrors, SocketStreamHandleClient&, const StorageSessionProvider*);
size_t bufferedAmount() final;
Optional<size_t> platformSendInternal(const uint8_t*, size_t);
diff --git a/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp b/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp
index cae8c43d60fcf6a3d69c58a7436516f923d227cb..e6b03f378929abbd4437f8507ea2f6c563edcff7 100644
--- a/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp
+++ b/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp
@@ -43,7 +43,7 @@
namespace WebCore {
-SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandleClient& client, const StorageSessionProvider* provider)
+SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, const StorageSessionProvider* provider)
: SocketStreamHandle(url, client)
, m_storageSessionProvider(provider)
, m_scheduler(CurlContext::singleton().streamScheduler())
@@ -52,7 +52,7 @@ SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandl
if (m_url.protocolIs("wss") && DeprecatedGlobalSettings::allowsAnySSLCertificate())
CurlContext::singleton().sslHandle().setIgnoreSSLErrors(true);
- m_streamID = m_scheduler.createStream(m_url, *this);
+ m_streamID = m_scheduler.createStream(m_url, ignoreCertificateErrors, *this);
}
SocketStreamHandleImpl::~SocketStreamHandleImpl()
diff --git a/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h
index 3ecf866005da6da9cec7c7930e6a4f93cb39d6e0..d81dc9ac0c433e00ab4ad73e206856098ab9230e 100644
--- a/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h
+++ b/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h
@@ -47,7 +47,7 @@ class StorageSessionProvider;
class SocketStreamHandleImpl final : public SocketStreamHandle {
public:
- static Ref<SocketStreamHandleImpl> create(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider*)
+ static Ref<SocketStreamHandleImpl> create(const URL&, bool, SocketStreamHandleClient&, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider*)
{
RELEASE_ASSERT_NOT_REACHED();
}
diff --git a/Source/WebCore/platform/win/KeyEventWin.cpp b/Source/WebCore/platform/win/KeyEventWin.cpp
index 44737686187a06a92c408ea60b63a48ac8481334..c754a763688b52e7ddd47493296ef9b0c6adc527 100644
--- a/Source/WebCore/platform/win/KeyEventWin.cpp
+++ b/Source/WebCore/platform/win/KeyEventWin.cpp
@@ -239,10 +239,16 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(HWND, WPARAM code, LPARAM keyData,
{
}
-void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type, bool)
+void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardsCompatibility)
{
- // No KeyDown events on Windows to disambiguate.
- ASSERT_NOT_REACHED();
+ m_type = type;
+ if (type == PlatformEvent::RawKeyDown) {
+ m_text = String();
+ m_unmodifiedText = String();
+ } else {
+ m_keyIdentifier = String();
+ m_windowsVirtualKeyCode = 0;
+ }
}
bool PlatformKeyboardEvent::currentCapsLockState()
diff --git a/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp b/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp
index 6b859de7a16bf05610f70cc561c15358a0f4b6be..6e09d6979042c69729c89c509bc0d9c944efbb5a 100644
--- a/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp
+++ b/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp
@@ -87,12 +87,12 @@ bool screenSupportsExtendedColor(Widget*)
}
#if ENABLE(TOUCH_EVENTS)
-bool screenHasTouchDevice()
+bool platformScreenHasTouchDevice()
{
return true;
}
-bool screenIsTouchPrimaryInputDevice()
+bool platformScreenIsTouchPrimaryInputDevice()
{
return true;
}
diff --git a/Source/WebCore/rendering/RenderTextControl.cpp b/Source/WebCore/rendering/RenderTextControl.cpp
index f575e13a0b6b3ae2d94c35ef90f5d5e0718678f4..8fa11add43a3a5e8609273657eaf3e6fab0c91dc 100644
--- a/Source/WebCore/rendering/RenderTextControl.cpp
+++ b/Source/WebCore/rendering/RenderTextControl.cpp
@@ -218,13 +218,13 @@ void RenderTextControl::layoutExcludedChildren(bool relayoutChildren)
}
}
-#if PLATFORM(IOS_FAMILY)
bool RenderTextControl::canScroll() const
{
auto innerText = innerTextElement();
return innerText && innerText->renderer() && innerText->renderer()->hasOverflowClip();
}
+#if PLATFORM(IOS_FAMILY)
int RenderTextControl::innerLineHeight() const
{
auto innerText = innerTextElement();
diff --git a/Source/WebCore/rendering/RenderTextControl.h b/Source/WebCore/rendering/RenderTextControl.h
index 69b193b1ff28bf2d0e58be6ae3152da8d9229a90..9b8327958cbc21e46a5720f558156b00e1c289a8 100644
--- a/Source/WebCore/rendering/RenderTextControl.h
+++ b/Source/WebCore/rendering/RenderTextControl.h
@@ -36,9 +36,9 @@ public:
WEBCORE_EXPORT HTMLTextFormControlElement& textFormControlElement() const;
-#if PLATFORM(IOS_FAMILY)
bool canScroll() const;
+#if PLATFORM(IOS_FAMILY)
// Returns the line height of the inner renderer.
int innerLineHeight() const override;
#endif
diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.cpp b/Source/WebKit/NetworkProcess/NetworkProcess.cpp
index 0bb857305384cb35d78a64dac9434d7fc824d9f5..2907b8ecc3cb8aa3334c3dcc1ca85abe4a126835 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"
@@ -551,6 +550,41 @@ void NetworkProcess::destroySession(PAL::SessionID sessionID)
#endif
}
+void NetworkProcess::getAllCookies(PAL::SessionID sessionID, CompletionHandler<void(Vector<WebCore::Cookie>&&)>&& completionHandler)
+{
+ if (auto* networkStorageSession = storageSession(sessionID)) {
+ completionHandler(networkStorageSession->getAllCookies());
+ return;
+ }
+ completionHandler({ });
+}
+
+void NetworkProcess::setCookies(PAL::SessionID sessionID, Vector<WebCore::Cookie> cookies, CompletionHandler<void(bool)>&& completionHandler) {
+ if (auto* networkStorageSession = storageSession(sessionID)) {
+ for (auto cookie : cookies)
+ networkStorageSession->setCookie(cookie);
+ completionHandler(true);
+ return;
+ }
+ completionHandler(false);
+}
+
+void NetworkProcess::deleteAllCookies(PAL::SessionID sessionID, CompletionHandler<void(bool)>&& completionHandler)
+{
+ if (auto* networkStorageSession = storageSession(sessionID)) {
+ networkStorageSession->deleteAllCookies();
+ completionHandler(true);
+ return;
+ }
+ completionHandler(false);
+}
+
+void NetworkProcess::setIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignore)
+{
+ if (auto* networkSession = this->networkSession(sessionID))
+ networkSession->setIgnoreCertificateErrors(ignore);
+}
+
#if ENABLE(RESOURCE_LOAD_STATISTICS)
void NetworkProcess::dumpResourceLoadStatistics(PAL::SessionID sessionID, CompletionHandler<void(String)>&& completionHandler)
{
diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h
index 1a77fab961df2e5e3061269f592a2c4c86946f9d..4e951e3e763885b49ded089f3c11b07064336cf8 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.h
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.h
@@ -77,6 +77,7 @@ class SessionID;
namespace WebCore {
class CertificateInfo;
+struct Cookie;
class CurlProxySettings;
class ProtectionSpace;
class StorageQuotaManager;
@@ -204,6 +205,11 @@ public:
void addWebsiteDataStore(WebsiteDataStoreParameters&&);
+ void getAllCookies(PAL::SessionID, CompletionHandler<void(Vector<WebCore::Cookie>&&)>&&);
+ void setCookies(PAL::SessionID, Vector<WebCore::Cookie>, CompletionHandler<void(bool)>&&);
+ void deleteAllCookies(PAL::SessionID, CompletionHandler<void(bool)>&&);
+ void setIgnoreCertificateErrors(PAL::SessionID, bool);
+
#if ENABLE(RESOURCE_LOAD_STATISTICS)
void clearPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
void clearUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
index 20ffbcc3fcdfadea3c0a3496c52822484ffdaa15..545ff20b5d34d516541158f40aff91454ab1fb81 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
@@ -79,6 +79,11 @@ messages -> NetworkProcess LegacyReceiver {
PreconnectTo(PAL::SessionID sessionID, WebKit::WebPageProxyIdentifier webPageProxyID, WebCore::PageIdentifier webPageID, URL url, String userAgent, enum:uint8_t WebCore::StoredCredentialsPolicy storedCredentialsPolicy, enum:bool Optional<WebKit::NavigatingToAppBoundDomain> isNavigatingToAppBoundDomain);
+ GetAllCookies(PAL::SessionID sessionID) -> (Vector<WebCore::Cookie> cookies) Async
+ SetCookies(PAL::SessionID sessionID, Vector<WebCore::Cookie> cookies) -> (bool success) Async
+ DeleteAllCookies(PAL::SessionID sessionID) -> (bool success) Async
+ SetIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignoreTLSErrors)
+
#if ENABLE(RESOURCE_LOAD_STATISTICS)
ClearPrevalentResource(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async
ClearUserInteraction(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async
diff --git a/Source/WebKit/NetworkProcess/NetworkSession.h b/Source/WebKit/NetworkProcess/NetworkSession.h
index 2fa262d507102c0dbe2a8376a25a424119ea87be..a33f8558a0352e801ee9665ae8342abf77504ce1 100644
--- a/Source/WebKit/NetworkProcess/NetworkSession.h
+++ b/Source/WebKit/NetworkProcess/NetworkSession.h
@@ -144,6 +144,9 @@ public:
bool isStaleWhileRevalidateEnabled() const { return m_isStaleWhileRevalidateEnabled; }
+ void setIgnoreCertificateErrors(bool ignore) { m_ignoreCertificateErrors = ignore; }
+ bool ignoreCertificateErrors() { return m_ignoreCertificateErrors; }
+
#if ENABLE(SERVICE_WORKER)
void addSoftUpdateLoader(std::unique_ptr<ServiceWorkerSoftUpdateLoader>&& loader) { m_softUpdateLoaders.add(WTFMove(loader)); }
void removeSoftUpdateLoader(ServiceWorkerSoftUpdateLoader* loader) { m_softUpdateLoaders.remove(loader); }
@@ -176,6 +179,7 @@ protected:
#endif
bool m_isStaleWhileRevalidateEnabled { false };
UniqueRef<AdClickAttributionManager> m_adClickAttribution;
+ bool m_ignoreCertificateErrors { false };
HashSet<Ref<NetworkResourceLoader>> m_keptAliveLoads;
diff --git a/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp b/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
index 5b489cc538f7c071510106c58f5c094ec9a8e1b8..20d0718eb896bcd9f97fd80572844a5727d84e40 100644
--- a/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
+++ b/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
@@ -44,7 +44,7 @@ Ref<NetworkSocketStream> NetworkSocketStream::create(NetworkProcess& networkProc
NetworkSocketStream::NetworkSocketStream(NetworkProcess& networkProcess, URL&& url, PAL::SessionID sessionID, const String& credentialPartition, WebSocketIdentifier identifier, IPC::Connection& connection, SourceApplicationAuditToken&& auditData)
: m_identifier(identifier)
, m_connection(connection)
- , m_impl(SocketStreamHandleImpl::create(url, *this, sessionID, credentialPartition, WTFMove(auditData), NetworkStorageSessionProvider::create(networkProcess, sessionID).ptr()))
+ , m_impl(SocketStreamHandleImpl::create(url, networkProcess.networkSession(sessionID)->ignoreCertificateErrors(), *this, sessionID, credentialPartition, WTFMove(auditData), NetworkStorageSessionProvider::create(networkProcess, sessionID).ptr()))
, m_delayFailTimer(*this, &NetworkSocketStream::sendDelayedFailMessage)
{
}
diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
index 8a8ab0b9b831caf48fa22453098afb24aaa8f4de..ef6d00552b15870a72189d76a744455434d28bf8 100644
--- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
+++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
@@ -661,7 +661,7 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa& session, Se
NegotiatedLegacyTLS negotiatedLegacyTLS = NegotiatedLegacyTLS::No;
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
- if (NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(challenge))
+ if (sessionCocoa->ignoreCertificateErrors() || sessionCocoa->allowsSpecificHTTPSCertificateForHost(challenge))
return completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
#if HAVE(TLS_PROTOCOL_VERSION_T)
@@ -914,6 +914,13 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa& session, Se
// NetworkLoadMetrics. For example, PerformanceTiming.
resourceResponse.setDeprecatedNetworkLoadMetrics(WebCore::copyTimingData([dataTask _timingData]));
+ __block WebCore::HTTPHeaderMap requestHeaders;
+ NSURLSessionTaskTransactionMetrics *m = dataTask._incompleteTaskMetrics.transactionMetrics.lastObject;
+ [m.request.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(NSString *name, NSString *value, BOOL *) {
+ requestHeaders.set(String(name), String(value));
+ }];
+ resourceResponse.m_httpRequestHeaderFields = WTFMove(requestHeaders);
+
auto completionHandlerCopy = Block_copy(completionHandler);
networkDataTask->didReceiveResponse(WTFMove(resourceResponse), negotiatedLegacyTLS, [completionHandlerCopy, taskIdentifier](WebCore::PolicyAction policyAction) {
#if !LOG_DISABLED
diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp
index 27f8ef54e561d6c3e812f8d4dc4cc133634fb4eb..a8a0c6fecd5f4fc816b02dccf276ed92573ad7b2 100644
--- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp
+++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp
@@ -26,9 +26,13 @@
#include "config.h"
#include "NetworkDataTaskCurl.h"
+#include "APIError.h"
#include "AuthenticationChallengeDisposition.h"
#include "AuthenticationManager.h"
+#include "DataReference.h"
+#include "Download.h"
#include "NetworkSessionCurl.h"
+#include "NetworkProcess.h"
#include <WebCore/AuthenticationChallenge.h>
#include <WebCore/CookieJar.h>
#include <WebCore/CurlRequest.h>
@@ -39,6 +43,8 @@
#include <WebCore/SameSiteInfo.h>
#include <WebCore/ShouldRelaxThirdPartyCookieBlocking.h>
#include <WebCore/SynchronousLoaderClient.h>
+#include <WebCore/TextEncoding.h>
+#include <wtf/FileSystem.h>
namespace WebKit {
@@ -78,6 +84,8 @@ NetworkDataTaskCurl::NetworkDataTaskCurl(NetworkSession& session, NetworkDataTas
m_curlRequest->setUserPass(m_initialCredential.user(), m_initialCredential.password());
m_curlRequest->setAuthenticationScheme(ProtectionSpaceAuthenticationSchemeHTTPBasic);
}
+ if (m_session->ignoreCertificateErrors())
+ m_curlRequest->disableServerTrustEvaluation();
m_curlRequest->setStartTime(m_startTime);
m_curlRequest->start();
}
@@ -152,6 +160,7 @@ void NetworkDataTaskCurl::curlDidReceiveResponse(CurlRequest& request, CurlRespo
m_response = ResourceResponse(receivedResponse);
m_response.setCertificateInfo(WTFMove(receivedResponse.certificateInfo));
m_response.setDeprecatedNetworkLoadMetrics(Box<NetworkLoadMetrics>::create(WTFMove(receivedResponse.networkLoadMetrics)));
+ m_response.m_httpRequestHeaderFields = request.resourceRequest().httpHeaderFields();
handleCookieHeaders(request.resourceRequest(), receivedResponse);
@@ -179,7 +188,12 @@ void NetworkDataTaskCurl::curlDidReceiveBuffer(CurlRequest&, Ref<SharedBuffer>&&
auto protectedThis = makeRef(*this);
if (state() == State::Canceling || state() == State::Completed || (!m_client && !isDownload()))
return;
-
+ if (isDownload()) {
+ FileSystem::PlatformFileHandle file = FileSystem::openFile(m_pendingDownloadLocation, FileSystem::FileOpenMode::Write);
+ FileSystem::writeToFile(file, buffer->data(), buffer->size());
+ FileSystem::closeFile(file);
+ return;
+ }
m_client->didReceiveData(WTFMove(buffer));
}
@@ -188,6 +202,12 @@ void NetworkDataTaskCurl::curlDidComplete(CurlRequest&, NetworkLoadMetrics&& net
if (state() == State::Canceling || state() == State::Completed || (!m_client && !isDownload()))
return;
+ if (isDownload()) {
+ auto* download = m_session->networkProcess().downloadManager().download(m_pendingDownloadID);
+ ASSERT(download);
+ download->didFinish();
+ return;
+ }
m_client->didCompleteWithError({ }, WTFMove(networkLoadMetrics));
}
@@ -201,6 +221,13 @@ void NetworkDataTaskCurl::curlDidFailWithError(CurlRequest& request, ResourceErr
return;
}
+ if (isDownload()) {
+ auto* download = m_session->networkProcess().downloadManager().download(m_pendingDownloadID);
+ ASSERT(download);
+ download->didFail(resourceError, IPC::DataReference());
+ return;
+ }
+
m_client->didCompleteWithError(resourceError);
}
@@ -238,6 +265,18 @@ void NetworkDataTaskCurl::invokeDidReceiveResponse()
case PolicyAction::Ignore:
invalidateAndCancel();
break;
+ case PolicyAction::Download: {
+ FileSystem::deleteFile(m_pendingDownloadLocation);
+ auto& downloadManager = m_session->networkProcess().downloadManager();
+ auto download = makeUnique<Download>(downloadManager, m_pendingDownloadID, *this, *m_session, suggestedFilename());
+ auto* downloadPtr = download.get();
+ downloadManager.dataTaskBecameDownloadTask(m_pendingDownloadID, WTFMove(download));
+ downloadPtr->didCreateDestination(m_pendingDownloadLocation);
+
+ if (m_curlRequest)
+ m_curlRequest->completeDidReceiveResponse();
+ break;
+ }
default:
notImplemented();
break;
@@ -320,6 +359,8 @@ void NetworkDataTaskCurl::willPerformHTTPRedirection()
m_curlRequest->setUserPass(m_initialCredential.user(), m_initialCredential.password());
m_curlRequest->setAuthenticationScheme(ProtectionSpaceAuthenticationSchemeHTTPBasic);
}
+ if (m_session->ignoreCertificateErrors())
+ m_curlRequest->disableServerTrustEvaluation();
m_curlRequest->setStartTime(m_startTime);
m_curlRequest->start();
@@ -503,4 +544,16 @@ bool NetworkDataTaskCurl::isThirdPartyRequest(const WebCore::ResourceRequest& re
return !WebCore::areRegistrableDomainsEqual(request.url(), request.firstPartyForCookies());
}
+String NetworkDataTaskCurl::suggestedFilename() const
+{
+ if (!m_suggestedFilename.isEmpty())
+ return m_suggestedFilename;
+
+ String suggestedFilename = m_response.suggestedFilename();
+ if (!suggestedFilename.isEmpty())
+ return suggestedFilename;
+
+ return decodeURLEscapeSequences(m_response.url().lastPathComponent());
+}
+
} // namespace WebKit
diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h
index 4c120d6830582861432e5e58fba5707206350cd0..3509c62ac2c970fdcf78db2503c0cc4259f56dbd 100644
--- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h
+++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h
@@ -85,6 +85,7 @@ private:
void appendCookieHeader(WebCore::ResourceRequest&);
void handleCookieHeaders(const WebCore::ResourceRequest&, const WebCore::CurlResponse&);
+ String suggestedFilename() const override;
bool isThirdPartyRequest(const WebCore::ResourceRequest&);
bool shouldBlockCookies(const WebCore::ResourceRequest&);
diff --git a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
index c99bcb07366b88ceb0c4f2a8382750f0e2d99b50..e7325b8f817cc73bf835b706d6cc382b6acc0ed2 100644
--- a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
+++ b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
@@ -444,6 +444,8 @@ bool NetworkDataTaskSoup::tlsConnectionAcceptCertificate(GTlsCertificate* certif
{
ASSERT(m_soupRequest);
URL url = soupURIToURL(soup_request_get_uri(m_soupRequest.get()));
+ if (m_session->ignoreCertificateErrors())
+ return true;
auto error = static_cast<NetworkSessionSoup&>(*m_session).soupNetworkSession().checkTLSErrors(url, certificate, tlsErrors);
if (!error)
return true;
@@ -893,6 +895,7 @@ void NetworkDataTaskSoup::didGetHeaders()
const char* headerValue;
while (soup_message_headers_iter_next(&headersIter, &headerName, &headerValue))
requestHeaders.set(String(headerName), String(headerValue));
+ m_response.m_httpRequestHeaderFields = requestHeaders;
m_networkLoadMetrics.requestHeaders = WTFMove(requestHeaders);
}
}
diff --git a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
index 66ff36eec2db1699a9bc2bce8fe0d5124ce19ed2..cc2bda254ce55d574c36b07dbaf95093c782e3a0 100644
--- a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
+++ b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
@@ -112,6 +112,11 @@ static gboolean webSocketAcceptCertificateCallback(GTlsConnection* connection, G
return !session->soupNetworkSession().checkTLSErrors(soupURIToURL(soup_message_get_uri(soupMessage)), certificate, errors);
}
+static gboolean webSocketAcceptCertificateCallbackIgnoreTLSErrors(GTlsConnection* connection, GTlsCertificate* certificate, GTlsCertificateFlags errors, NetworkSessionSoup* session)
+{
+ return TRUE;
+}
+
static void webSocketMessageNetworkEventCallback(SoupMessage* soupMessage, GSocketClientEvent event, GIOStream* connection, NetworkSessionSoup* session)
{
if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING)
@@ -121,6 +126,15 @@ static void webSocketMessageNetworkEventCallback(SoupMessage* soupMessage, GSock
g_signal_connect(connection, "accept-certificate", G_CALLBACK(webSocketAcceptCertificateCallback), session);
}
+static void webSocketMessageNetworkEventCallbackIgnoreTLSErrors(SoupMessage* soupMessage, GSocketClientEvent event, GIOStream* connection)
+{
+ if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING)
+ return;
+
+ g_object_set_data(G_OBJECT(connection), "wk-soup-message", soupMessage);
+ g_signal_connect(connection, "accept-certificate", G_CALLBACK(webSocketAcceptCertificateCallbackIgnoreTLSErrors), soupMessage);
+}
+
std::unique_ptr<WebSocketTask> NetworkSessionSoup::createWebSocketTask(NetworkSocketChannel& channel, const ResourceRequest& request, const String& protocol)
{
GUniquePtr<SoupURI> soupURI = request.createSoupURI();
@@ -129,8 +143,12 @@ std::unique_ptr<WebSocketTask> NetworkSessionSoup::createWebSocketTask(NetworkSo
GRefPtr<SoupMessage> soupMessage = adoptGRef(soup_message_new_from_uri(SOUP_METHOD_GET, soupURI.get()));
request.updateSoupMessage(soupMessage.get(), blobRegistry());
- if (request.url().protocolIs("wss"))
- g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallback), this);
+ if (request.url().protocolIs("wss")) {
+ if (ignoreCertificateErrors())
+ g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallbackIgnoreTLSErrors), this);
+ else
+ g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallback), this);
+ }
return makeUnique<WebSocketTask>(channel, soupSession(), soupMessage.get(), protocol);
}
diff --git a/Source/WebKit/PlatformGTK.cmake b/Source/WebKit/PlatformGTK.cmake
index 715d38d76b891489ef95a74e31389b8844ebf102..d86a1c3cdee68b5646a109d9bf56056634c54cb2 100644
--- a/Source/WebKit/PlatformGTK.cmake
+++ b/Source/WebKit/PlatformGTK.cmake
@@ -444,6 +444,9 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES
${GSTREAMER_PBUTILS_INCLUDE_DIRS}
${GTK_INCLUDE_DIRS}
${LIBSOUP_INCLUDE_DIRS}
+# Playwright begin
+ ${LIBVPX_INCLUDE_DIRS}
+# Playwright end
)
if (USE_WPE_RENDERER)
@@ -497,9 +500,18 @@ if (USE_LIBWEBRTC)
list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES
"${THIRDPARTY_DIR}/libwebrtc/Source/"
"${THIRDPARTY_DIR}/libwebrtc/Source/webrtc"
+# Playwright begin
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include"
+# Playwright end
)
endif ()
+# Playwright begin
+list(APPEND WebKit_PRIVATE_INCLUDE_DIRECTORIES
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm"
+)
+# Playwright end
+
# To generate WebKitEnumTypes.h we want to use all installed headers, except WebKitEnumTypes.h itself.
set(WebKit2GTK_ENUM_GENERATION_HEADERS ${WebKit2GTK_INSTALLED_HEADERS})
list(REMOVE_ITEM WebKit2GTK_ENUM_GENERATION_HEADERS ${DERIVED_SOURCES_WEBKIT2GTK_API_DIR}/WebKitEnumTypes.h)
diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake
index a0d83b7d0a54da2e9c9c39b56473743ae48fa9b4..d3b097c89887fb69d374d904691390594c2acd88 100644
--- a/Source/WebKit/PlatformWPE.cmake
+++ b/Source/WebKit/PlatformWPE.cmake
@@ -257,6 +257,7 @@ list(APPEND WebKit_INCLUDE_DIRECTORIES
"${WEBKIT_DIR}/UIProcess/API/wpe"
"${WEBKIT_DIR}/UIProcess/CoordinatedGraphics"
"${WEBKIT_DIR}/UIProcess/geoclue"
+ "${WEBKIT_DIR}/UIProcess/glib"
"${WEBKIT_DIR}/UIProcess/gstreamer"
"${WEBKIT_DIR}/UIProcess/linux"
"${WEBKIT_DIR}/UIProcess/soup"
@@ -281,8 +282,17 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES
${GIO_UNIX_INCLUDE_DIRS}
${GLIB_INCLUDE_DIRS}
${LIBSOUP_INCLUDE_DIRS}
+# Playwright begin
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include"
+# Playwright end
)
+# Playwright begin
+list(APPEND WebKit_PRIVATE_INCLUDE_DIRECTORIES
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm"
+)
+# Playwright end
+
list(APPEND WebKit_LIBRARIES
Cairo::Cairo
Freetype::Freetype
diff --git a/Source/WebKit/PlatformWin.cmake b/Source/WebKit/PlatformWin.cmake
index 75a506d6a95c9b02afadf47edd259b725b8a2f6d..36f8ac2934c509eff9566f135c2a499eceb42fd8 100644
--- a/Source/WebKit/PlatformWin.cmake
+++ b/Source/WebKit/PlatformWin.cmake
@@ -58,8 +58,12 @@ list(APPEND WebKit_SOURCES
UIProcess/WebsiteData/win/WebsiteDataStoreWin.cpp
+ UIProcess/win/InspectorTargetProxyWin.cpp
+ UIProcess/win/InspectorPlaywrightAgentClientWin.cpp
UIProcess/win/PageClientImpl.cpp
UIProcess/win/WebContextMenuProxyWin.cpp
+ UIProcess/win/WebPageInspectorEmulationAgentWin.cpp
+ UIProcess/win/WebPageInspectorInputAgentWin.cpp
UIProcess/win/WebPageProxyWin.cpp
UIProcess/win/WebPopupMenuProxyWin.cpp
UIProcess/win/WebProcessPoolWin.cpp
@@ -116,6 +120,63 @@ list(APPEND WebKit_INCLUDE_DIRECTORIES
"${WEBKIT_DIR}/win"
)
+# Playwright begin
+list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include"
+ "${LIBVPX_CUSTOM_INCLUDE_DIR}"
+)
+
+list(APPEND WebKit_PRIVATE_INCLUDE_DIRECTORIES
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm"
+)
+
+list(APPEND WebKit_SOURCES
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm/mkvmuxer/mkvmuxer.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm/mkvmuxer/mkvmuxerutil.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm/mkvmuxer/mkvwriter.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_common.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_gcc.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_win.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_argb.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from_argb.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_jpeg.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_to_argb.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_to_i420.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/cpu_id.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/mjpeg_decoder.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/mjpeg_validate.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/planar_functions.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon64.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_any.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_argb.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_common.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_gcc.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon64.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_win.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_any.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_common.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_gcc.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon64.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_win.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_any.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_argb.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_common.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_gcc.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon64.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_win.cc"
+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/video_common.cc"
+)
+# Playwright end
+
set(WebKitCommonIncludeDirectories ${WebKit_INCLUDE_DIRECTORIES})
set(WebKitCommonSystemIncludeDirectories ${WebKit_SYSTEM_INCLUDE_DIRECTORIES})
@@ -169,6 +230,7 @@ if (${WTF_PLATFORM_WIN_CAIRO})
OpenSSL::SSL
mfuuid.lib
strmiids.lib
+ ${LIBVPX_CUSTOM_LIBRARY}
)
endif ()
diff --git a/Source/WebKit/Shared/API/c/wpe/WebKit.h b/Source/WebKit/Shared/API/c/wpe/WebKit.h
index 898e30b370db8176e886fbbde0cd960e38a64818..74945e06fac0eb14936578de6a599a123364a63a 100644
--- a/Source/WebKit/Shared/API/c/wpe/WebKit.h
+++ b/Source/WebKit/Shared/API/c/wpe/WebKit.h
@@ -78,6 +78,7 @@
// From Source/WebKit/UIProcess/API/C
#include <WebKit/WKBackForwardListItemRef.h>
#include <WebKit/WKBackForwardListRef.h>
+#include <WebKit/WKBrowserInspector.h>
#include <WebKit/WKContext.h>
#include <WebKit/WKContextConfigurationRef.h>
#include <WebKit/WKCredential.h>
diff --git a/Source/WebKit/Shared/NativeWebKeyboardEvent.h b/Source/WebKit/Shared/NativeWebKeyboardEvent.h
index fd2b55f40fdd3d82d6d6947dc33ad31f24f4c1c7..bb1487b1efcbab2fd7ccf79a50eae99ecf4b4cab 100644
--- a/Source/WebKit/Shared/NativeWebKeyboardEvent.h
+++ b/Source/WebKit/Shared/NativeWebKeyboardEvent.h
@@ -33,6 +33,7 @@
#if USE(APPKIT)
#include <wtf/RetainPtr.h>
OBJC_CLASS NSView;
+OBJC_CLASS NSEvent;
#endif
#if PLATFORM(GTK)
@@ -65,19 +66,35 @@ public:
#if USE(APPKIT)
// FIXME: Share iOS's HandledByInputMethod enum here instead of passing a boolean.
NativeWebKeyboardEvent(NSEvent *, bool handledByInputMethod, bool replacesSoftSpace, const Vector<WebCore::KeypressCommand>&);
+ NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp, Vector<WebCore::KeypressCommand>&& commands)
+ : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp, WTFMove(commands))
+ {
+ }
#elif PLATFORM(GTK)
NativeWebKeyboardEvent(const NativeWebKeyboardEvent&);
NativeWebKeyboardEvent(GdkEvent*, const String&, Vector<String>&& commands);
NativeWebKeyboardEvent(const String&, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&);
NativeWebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, Vector<String>&& commands, bool isKeypad, OptionSet<Modifier>);
+ NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp, Vector<String>&& commands)
+ : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp, WTFMove(commands))
+ {
+ }
#elif PLATFORM(IOS_FAMILY)
enum class HandledByInputMethod : bool { No, Yes };
NativeWebKeyboardEvent(::WebEvent *, HandledByInputMethod);
#elif USE(LIBWPE)
enum class HandledByInputMethod : bool { No, Yes };
NativeWebKeyboardEvent(struct wpe_input_keyboard_event*, const String&, HandledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&);
+ NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
+ : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp)
+ {
+ }
#elif PLATFORM(WIN)
NativeWebKeyboardEvent(HWND, UINT message, WPARAM, LPARAM, Vector<MSG>&& pendingCharEvents);
+ NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
+ : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp)
+ {
+ }
#endif
#if USE(APPKIT)
diff --git a/Source/WebKit/Shared/NativeWebMouseEvent.h b/Source/WebKit/Shared/NativeWebMouseEvent.h
index 5e37f73510f73961d97ce8b42de0e1935a170d9b..7e30ef0830d7d98717b7e0cd3935cc2b1803518f 100644
--- a/Source/WebKit/Shared/NativeWebMouseEvent.h
+++ b/Source/WebKit/Shared/NativeWebMouseEvent.h
@@ -76,6 +76,11 @@ public:
NativeWebMouseEvent(HWND, UINT message, WPARAM, LPARAM, bool);
#endif
+#if PLATFORM(GTK) || USE(LIBWPE) || PLATFORM(WIN)
+ NativeWebMouseEvent(Type type, Button button, unsigned short buttons, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, float deltaX, float deltaY, float deltaZ, int clickCount, OptionSet<Modifier> modifiers, WallTime timestamp)
+ : WebMouseEvent(type, button, buttons, position, globalPosition, deltaX, deltaY, deltaZ, clickCount, modifiers, timestamp) { }
+#endif
+
#if USE(APPKIT)
NSEvent* nativeEvent() const { return m_nativeEvent.get(); }
#elif PLATFORM(GTK)
diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
index 3379596be69d924ae0ca6d8f9f1ffb01b20c3d6c..2d022ccfed88937fa4d6fa5283740f62336d714d 100644
--- a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
+++ b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
@@ -1461,6 +1461,9 @@ void ArgumentCoder<WindowFeatures>::encode(Encoder& encoder, const WindowFeature
encoder << windowFeatures.resizable;
encoder << windowFeatures.fullscreen;
encoder << windowFeatures.dialog;
+ encoder << windowFeatures.noopener;
+ encoder << windowFeatures.noreferrer;
+ encoder << windowFeatures.additionalFeatures;
}
bool ArgumentCoder<WindowFeatures>::decode(Decoder& decoder, WindowFeatures& windowFeatures)
@@ -1489,6 +1492,12 @@ bool ArgumentCoder<WindowFeatures>::decode(Decoder& decoder, WindowFeatures& win
return false;
if (!decoder.decode(windowFeatures.dialog))
return false;
+ if (!decoder.decode(windowFeatures.noopener))
+ return false;
+ if (!decoder.decode(windowFeatures.noreferrer))
+ return false;
+ if (!decoder.decode(windowFeatures.additionalFeatures))
+ return false;
return true;
}
diff --git a/Source/WebKit/Shared/WebEvent.h b/Source/WebKit/Shared/WebEvent.h
index 3ae6504779d3917a79f69f32b58260afeda270b4..72d44c33953cc13bf2ed7c762b4f9a7b88571b56 100644
--- a/Source/WebKit/Shared/WebEvent.h
+++ b/Source/WebKit/Shared/WebEvent.h
@@ -31,6 +31,7 @@
#include <wtf/EnumTraits.h>
#include <wtf/OptionSet.h>
+#include <wtf/RefCounted.h>
#include <wtf/WallTime.h>
#include <wtf/text/WTFString.h>
diff --git a/Source/WebKit/Shared/WebKeyboardEvent.cpp b/Source/WebKit/Shared/WebKeyboardEvent.cpp
index bc4322286484e6afdd49353fae6a8fb3cd5e66f2..7af88c4e93f6a0ea61dd107699c04c0695f7842f 100644
--- a/Source/WebKit/Shared/WebKeyboardEvent.cpp
+++ b/Source/WebKit/Shared/WebKeyboardEvent.cpp
@@ -35,6 +35,7 @@ WebKeyboardEvent::WebKeyboardEvent()
{
}
+
#if USE(APPKIT)
WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, const Vector<WebCore::KeypressCommand>& commands, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
@@ -56,6 +57,24 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String&
ASSERT(isKeyboardEventType(type));
}
+WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp, Vector<WebCore::KeypressCommand>&& commands)
+ : WebEvent(type, modifiers, timestamp)
+ , m_text(text)
+ , m_unmodifiedText(text)
+ , m_key(key)
+ , m_code(code)
+ , m_keyIdentifier(keyIdentifier)
+ , m_windowsVirtualKeyCode(windowsVirtualKeyCode)
+ , m_nativeVirtualKeyCode(nativeVirtualKeyCode)
+ , m_macCharCode(0)
+ , m_commands(WTFMove(commands))
+ , m_isAutoRepeat(isAutoRepeat)
+ , m_isKeypad(isKeypad)
+ , m_isSystemKey(isSystemKey)
+{
+ ASSERT(isKeyboardEventType(type));
+}
+
#elif PLATFORM(GTK)
WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&& preeditUnderlines, Optional<EditingRange>&& preeditSelectionRange, Vector<String>&& commands, bool isKeypad, OptionSet<Modifier> modifiers, WallTime timestamp)
@@ -79,6 +98,24 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String&
ASSERT(isKeyboardEventType(type));
}
+WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp, Vector<String>&& commands)
+ : WebEvent(type, modifiers, timestamp)
+ , m_text(text)
+ , m_unmodifiedText(text)
+ , m_key(key)
+ , m_code(code)
+ , m_keyIdentifier(keyIdentifier)
+ , m_windowsVirtualKeyCode(windowsVirtualKeyCode)
+ , m_nativeVirtualKeyCode(nativeVirtualKeyCode)
+ , m_macCharCode(0)
+ , m_commands(WTFMove(commands))
+ , m_isAutoRepeat(isAutoRepeat)
+ , m_isKeypad(isKeypad)
+ , m_isSystemKey(isSystemKey)
+{
+ ASSERT(isKeyboardEventType(type));
+}
+
#elif PLATFORM(IOS_FAMILY)
WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
@@ -144,6 +181,27 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String&
#endif
+#if PLATFORM(WIN) || USE(LIBWPE)
+
+WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
+ : WebEvent(type, modifiers, timestamp)
+ , m_text(text)
+ , m_unmodifiedText(text)
+ , m_key(key)
+ , m_code(code)
+ , m_keyIdentifier(keyIdentifier)
+ , m_windowsVirtualKeyCode(windowsVirtualKeyCode)
+ , m_nativeVirtualKeyCode(nativeVirtualKeyCode)
+ , m_macCharCode(0)
+ , m_isAutoRepeat(isAutoRepeat)
+ , m_isKeypad(isKeypad)
+ , m_isSystemKey(isSystemKey)
+{
+ ASSERT(isKeyboardEventType(type));
+}
+
+#endif
+
WebKeyboardEvent::~WebKeyboardEvent()
{
}
diff --git a/Source/WebKit/Shared/WebKeyboardEvent.h b/Source/WebKit/Shared/WebKeyboardEvent.h
index cb8029dc46dc2531f5cc23409dc6d2f11d5a3b49..a0e673b9680b0013d56920e525f358e333b06b0b 100644
--- a/Source/WebKit/Shared/WebKeyboardEvent.h
+++ b/Source/WebKit/Shared/WebKeyboardEvent.h
@@ -43,14 +43,18 @@ public:
#if USE(APPKIT)
WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, const Vector<WebCore::KeypressCommand>&, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
+ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp, Vector<WebCore::KeypressCommand>&& commands);
#elif PLATFORM(GTK)
WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&, Vector<String>&& commands, bool isKeypad, OptionSet<Modifier>, WallTime timestamp);
+ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp, Vector<String>&& commands);
#elif PLATFORM(IOS_FAMILY)
WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
#elif USE(LIBWPE)
WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&, bool isKeypad, OptionSet<Modifier>, WallTime timestamp);
+ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
#else
WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
+ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
#endif
const String& text() const { return m_text; }
diff --git a/Source/WebKit/Shared/WebPageCreationParameters.cpp b/Source/WebKit/Shared/WebPageCreationParameters.cpp
index cfe8492b8d2ef574e79d330dacfc014cd0c1caa9..c1b97e24bde07507132574b5b94084f3d39f8fc3 100644
--- a/Source/WebKit/Shared/WebPageCreationParameters.cpp
+++ b/Source/WebKit/Shared/WebPageCreationParameters.cpp
@@ -149,6 +149,8 @@ void WebPageCreationParameters::encode(IPC::Encoder& encoder) const
encoder << crossOriginAccessControlCheckEnabled;
encoder << processDisplayName;
+ encoder << shouldPauseInInspectorWhenShown;
+
encoder << shouldCaptureAudioInUIProcess;
encoder << shouldCaptureAudioInGPUProcess;
encoder << shouldCaptureVideoInUIProcess;
@@ -475,7 +477,10 @@ Optional<WebPageCreationParameters> WebPageCreationParameters::decode(IPC::Decod
if (!processDisplayName)
return WTF::nullopt;
parameters.processDisplayName = WTFMove(*processDisplayName);
-
+
+ if (!decoder.decode(parameters.shouldPauseInInspectorWhenShown))
+ return WTF::nullopt;
+
if (!decoder.decode(parameters.shouldCaptureAudioInUIProcess))
return WTF::nullopt;
diff --git a/Source/WebKit/Shared/WebPageCreationParameters.h b/Source/WebKit/Shared/WebPageCreationParameters.h
index b565293db82cd22ff895f37e504367a0bf531cec..e820ea8693c0b2acfa738e8ac762c29696829b01 100644
--- a/Source/WebKit/Shared/WebPageCreationParameters.h
+++ b/Source/WebKit/Shared/WebPageCreationParameters.h
@@ -237,6 +237,8 @@ struct WebPageCreationParameters {
WebCore::ShouldRelaxThirdPartyCookieBlocking shouldRelaxThirdPartyCookieBlocking { WebCore::ShouldRelaxThirdPartyCookieBlocking::No };
+ bool shouldPauseInInspectorWhenShown { false };
+
#if PLATFORM(GTK)
String themeName;
#endif
diff --git a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
index c76a9e1f7dae7a31c4048d8f00d849a18ebaff23..1cfd9c7acb69dea69783c42b3f427929509782a4 100644
--- a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
+++ b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
@@ -50,7 +50,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(Type type, const String& text, co
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(const NativeWebKeyboardEvent& event)
- : WebKeyboardEvent(event.type(), event.text(), event.key(), event.code(), event.keyIdentifier(), event.windowsVirtualKeyCode(), event.nativeVirtualKeyCode(), event.handledByInputMethod(), Optional<Vector<WebCore::CompositionUnderline>>(event.preeditUnderlines()), Optional<EditingRange>(event.preeditSelectionRange()), Vector<String>(event.commands()), event.isKeypad(), event.modifiers(), event.timestamp())
+ : WebKeyboardEvent(event)
, m_nativeEvent(event.nativeEvent() ? gdk_event_copy(event.nativeEvent()) : nullptr)
{
}
diff --git a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
index 66fcf27bcdd78e9c4d2b73e1e05830575bc9c05d..656c79494d4224b958ce338c5ebe0f0bfb8d8977 100644
--- a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
+++ b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
@@ -54,7 +54,7 @@ NativeWebMouseEvent::NativeWebMouseEvent(Type type, Button button, unsigned shor
}
NativeWebMouseEvent::NativeWebMouseEvent(const NativeWebMouseEvent& event)
- : WebMouseEvent(event.type(), event.button(), event.buttons(), event.position(), event.globalPosition(), event.deltaX(), event.deltaY(), event.deltaZ(), event.clickCount(), event.modifiers(), event.timestamp())
+ : WebMouseEvent(event)
, m_nativeEvent(event.nativeEvent() ? gdk_event_copy(const_cast<GdkEvent*>(event.nativeEvent())) : nullptr)
{
}
diff --git a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
index 2a9db4f8acafe9d64d5d4ebd9913aa161ea0f4c0..f151ef4e8e6abb5e3044771c235139d48e8aa7cf 100644
--- a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
+++ b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "WebTouchEvent.h"
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
#include "WebCoreArgumentCoders.h"
@@ -79,4 +79,4 @@ Optional<WebPlatformTouchPoint> WebPlatformTouchPoint::decode(IPC::Decoder& deco
} // namespace WebKit
-#endif // ENABLE(TOUCH_EVENTS)
+#endif // ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
diff --git a/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp b/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp
index e40a6e172bfd2b75076fd4053da643ebab9eb81f..2516655bbc9e5bc863537a554c5faac0f6fc1a09 100644
--- a/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp
+++ b/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "WebTouchEvent.h"
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
#include "ArgumentCoders.h"
#include "WebCoreArgumentCoders.h"
@@ -71,4 +71,4 @@ bool WebTouchEvent::decode(IPC::Decoder& decoder, WebTouchEvent& result)
} // namespace WebKit
-#endif // ENABLE(TOUCH_EVENTS)
+#endif // ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
diff --git a/Source/WebKit/Shared/win/WebEventFactory.cpp b/Source/WebKit/Shared/win/WebEventFactory.cpp
index 88d53d236cd6d62735f03678a04ca9c198dddacb..b8f8efc57ab00dc5725660c5a8ad56a3e6384de5 100644
--- a/Source/WebKit/Shared/win/WebEventFactory.cpp
+++ b/Source/WebKit/Shared/win/WebEventFactory.cpp
@@ -473,7 +473,7 @@ WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(HWND hwnd, UINT message
}
#if ENABLE(TOUCH_EVENTS)
-WebTouchEvent WebEventFactory::createWebTouchEvent(const GdkEvent* event, Vector<WebPlatformTouchPoint>&& touchPoints)
+WebTouchEvent WebEventFactory::createWebTouchEvent()
{
return WebTouchEvent();
}
diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt
index e0ab7436badc3463749466334719b45edfd2b306..7b4dc47c42411da19d2dfe983dfe6178df3848aa 100644
--- a/Source/WebKit/Sources.txt
+++ b/Source/WebKit/Sources.txt
@@ -275,16 +275,20 @@ Shared/WebsiteData/WebsiteData.cpp
UIProcess/AuxiliaryProcessProxy.cpp
UIProcess/BackgroundProcessResponsivenessTimer.cpp
+UIProcess/BrowserInspectorPipe.cpp
UIProcess/DeviceIdHashSaltStorage.cpp
UIProcess/DrawingAreaProxy.cpp
UIProcess/FrameLoadState.cpp
UIProcess/GeolocationPermissionRequestManagerProxy.cpp
UIProcess/GeolocationPermissionRequestProxy.cpp
+UIProcess/InspectorDialogAgent.cpp
+UIProcess/InspectorPlaywrightAgent.cpp
UIProcess/LegacyGlobalSettings.cpp
UIProcess/PageLoadState.cpp
UIProcess/ProcessAssertion.cpp
UIProcess/ProcessThrottler.cpp
UIProcess/ProvisionalPageProxy.cpp
+UIProcess/RemoteInspectorPipe.cpp
UIProcess/ResponsivenessTimer.cpp
UIProcess/SuspendedPageProxy.cpp
UIProcess/SystemPreviewController.cpp
@@ -322,6 +326,8 @@ UIProcess/WebOpenPanelResultListenerProxy.cpp
UIProcess/WebPageDiagnosticLoggingClient.cpp
UIProcess/WebPageGroup.cpp
UIProcess/WebPageInjectedBundleClient.cpp
+UIProcess/WebPageInspectorEmulationAgent.cpp
+UIProcess/WebPageInspectorInputAgent.cpp
UIProcess/WebPageProxy.cpp
UIProcess/WebPasteboardProxy.cpp
UIProcess/WebPreferences.cpp
@@ -441,6 +447,9 @@ UIProcess/Inspector/WebPageDebuggable.cpp
UIProcess/Inspector/WebPageInspectorController.cpp
UIProcess/Inspector/Agents/InspectorBrowserAgent.cpp
+UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
+UIProcess/Inspector/Agents/ScreencastEncoder.cpp
+UIProcess/Inspector/Agents/WebMFileWriter.cpp
UIProcess/Media/AudioSessionRoutingArbitratorProxy.cpp
UIProcess/Media/MediaUsageManager.cpp
diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt
index 99bea1fb59e96d6a00ef1bba08a724b1f2887004..8cbb1ca3828e4e4af28707251b48631abe5542b5 100644
--- a/Source/WebKit/SourcesCocoa.txt
+++ b/Source/WebKit/SourcesCocoa.txt
@@ -246,6 +246,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
@@ -410,6 +411,7 @@ UIProcess/Inspector/ios/WKInspectorHighlightView.mm
UIProcess/Inspector/ios/WKInspectorNodeSearchGestureRecognizer.mm
UIProcess/Inspector/mac/RemoteWebInspectorProxyMac.mm
+UIProcess/Inspector/mac/ScreencastEncoderMac.mm
UIProcess/Inspector/mac/WebInspectorProxyMac.mm
UIProcess/Inspector/mac/WKInspectorViewController.mm
UIProcess/Inspector/mac/WKInspectorWKWebView.mm
diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt
index 663c2e39a58564f401765c73ade79b7cf490e62c..20bf355bf41e99ab659a42e24a34011789866de8 100644
--- a/Source/WebKit/SourcesGTK.txt
+++ b/Source/WebKit/SourcesGTK.txt
@@ -124,6 +124,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
@@ -236,6 +237,7 @@ UIProcess/WebsiteData/unix/WebsiteDataStoreUnix.cpp
UIProcess/cairo/BackingStoreCairo.cpp @no-unify
+UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
UIProcess/glib/WebProcessPoolGLib.cpp
UIProcess/glib/WebProcessProxyGLib.cpp
UIProcess/glib/WebsiteDataStoreGLib.cpp @no-unify
@@ -251,6 +253,7 @@ UIProcess/gtk/ClipboardGtk3.cpp @no-unify
UIProcess/gtk/ClipboardGtk4.cpp @no-unify
UIProcess/gtk/GestureController.cpp
UIProcess/gtk/HardwareAccelerationManager.cpp
+UIProcess/gtk/InspectorTargetProxyGtk.cpp
UIProcess/gtk/KeyBindingTranslator.cpp
UIProcess/gtk/PointerLockManager.cpp @no-unify
UIProcess/gtk/PointerLockManagerWayland.cpp @no-unify
@@ -261,6 +264,8 @@ UIProcess/gtk/WaylandCompositor.cpp @no-unify
UIProcess/gtk/WebColorPickerGtk.cpp
UIProcess/gtk/WebContextMenuProxyGtk.cpp
UIProcess/gtk/WebDataListSuggestionsDropdownGtk.cpp
+UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp
+UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp
UIProcess/gtk/WebPageProxyGtk.cpp @no-unify
UIProcess/gtk/WebPasteboardProxyGtk.cpp
UIProcess/gtk/WebPopupMenuProxyGtk.cpp
diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt
index 5f35531de116eb5de98f24cdf8cbc66c30e47508..5430009f5a26c02607eb6e9961800b76df1601f6 100644
--- a/Source/WebKit/SourcesWPE.txt
+++ b/Source/WebKit/SourcesWPE.txt
@@ -116,6 +116,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
@@ -194,7 +195,7 @@ UIProcess/Automation/wpe/WebAutomationSessionWPE.cpp
UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
UIProcess/geoclue/GeoclueGeolocationProvider.cpp
-
+UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
UIProcess/glib/WebProcessPoolGLib.cpp
UIProcess/glib/WebProcessProxyGLib.cpp
UIProcess/glib/WebsiteDataStoreGLib.cpp @no-unify
@@ -216,6 +217,10 @@ UIProcess/linux/MemoryPressureMonitor.cpp
UIProcess/soup/WebCookieManagerProxySoup.cpp
UIProcess/soup/WebProcessPoolSoup.cpp
+UIProcess/wpe/InspectorTargetProxyWPE.cpp
+UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp
+UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
+
UIProcess/wpe/WebPageProxyWPE.cpp
WebProcess/GPU/media/gstreamer/VideoLayerRemoteGStreamer.cpp
diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
index 18585f61bb6ecabec39ff0c03b862c65856dca24..21bab039d1f6116ebf9c59bc42a695a45f4701e8 100644
--- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
+++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
@@ -53,6 +53,9 @@ Ref<ProcessPoolConfiguration> ProcessPoolConfiguration::copy()
copy->m_ignoreSynchronousMessagingTimeoutsForTesting = this->m_ignoreSynchronousMessagingTimeoutsForTesting;
copy->m_attrStyleEnabled = this->m_attrStyleEnabled;
copy->m_overrideLanguages = this->m_overrideLanguages;
+#if PLATFORM(MAC)
+ copy->m_forceOverlayScrollbars = this->m_forceOverlayScrollbars;
+#endif
copy->m_alwaysRunsAtBackgroundPriority = this->m_alwaysRunsAtBackgroundPriority;
copy->m_shouldTakeUIBackgroundAssertion = this->m_shouldTakeUIBackgroundAssertion;
copy->m_shouldCaptureDisplayInUIProcess = this->m_shouldCaptureDisplayInUIProcess;
diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
index 64924902f19811792537a15a32ed4d706daf9670..28906745477d89bb0e7c2b9c3f1523d2d76803d6 100644
--- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
+++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
@@ -98,6 +98,11 @@ public:
const Vector<WTF::String>& overrideLanguages() const { return m_overrideLanguages; }
void setOverrideLanguages(Vector<WTF::String>&& languages) { m_overrideLanguages = WTFMove(languages); }
+#if PLATFORM(MAC)
+ bool forceOverlayScrollbars() const { return m_forceOverlayScrollbars; }
+ void setForceOverlayScrollbars(bool forceOverlayScrollbars) { m_forceOverlayScrollbars = forceOverlayScrollbars; }
+#endif
+
bool alwaysRunsAtBackgroundPriority() const { return m_alwaysRunsAtBackgroundPriority; }
void setAlwaysRunsAtBackgroundPriority(bool alwaysRunsAtBackgroundPriority) { m_alwaysRunsAtBackgroundPriority = alwaysRunsAtBackgroundPriority; }
@@ -157,6 +162,9 @@ private:
bool m_ignoreSynchronousMessagingTimeoutsForTesting { false };
bool m_attrStyleEnabled { false };
Vector<WTF::String> m_overrideLanguages;
+#if PLATFORM(MAC)
+ bool m_forceOverlayScrollbars { false };
+#endif
bool m_alwaysRunsAtBackgroundPriority { false };
bool m_shouldTakeUIBackgroundAssertion { true };
bool m_shouldCaptureDisplayInUIProcess { DEFAULT_CAPTURE_DISPLAY_IN_UI_PROCESS };
diff --git a/Source/WebKit/UIProcess/API/APIUIClient.h b/Source/WebKit/UIProcess/API/APIUIClient.h
index aa7d89c01e73520ce3ee04226b9ae85970bfaa6e..3de061e6128f07304954af89b601e334ca076929 100644
--- a/Source/WebKit/UIProcess/API/APIUIClient.h
+++ b/Source/WebKit/UIProcess/API/APIUIClient.h
@@ -94,6 +94,7 @@ public:
virtual void runJavaScriptAlert(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function<void()>&& completionHandler) { completionHandler(); }
virtual void runJavaScriptConfirm(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function<void(bool)>&& completionHandler) { completionHandler(false); }
virtual void runJavaScriptPrompt(WebKit::WebPageProxy&, const WTF::String&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function<void(const WTF::String&)>&& completionHandler) { completionHandler(WTF::String()); }
+ virtual void handleJavaScriptDialog(WebKit::WebPageProxy&, bool, const WTF::String&) { }
virtual void setStatusText(WebKit::WebPageProxy*, const WTF::String&) { }
virtual void mouseDidMoveOverElement(WebKit::WebPageProxy&, const WebKit::WebHitTestResultData&, OptionSet<WebKit::WebEvent::Modifier>, Object*) { }
diff --git a/Source/WebKit/UIProcess/API/C/WKInspector.cpp b/Source/WebKit/UIProcess/API/C/WKInspector.cpp
index 39327c5c9230591e4f52e4574c416e36687788f0..450033d87fefb743ab7240ce317fae221f91dcf5 100644
--- a/Source/WebKit/UIProcess/API/C/WKInspector.cpp
+++ b/Source/WebKit/UIProcess/API/C/WKInspector.cpp
@@ -28,6 +28,11 @@
#if !PLATFORM(IOS_FAMILY)
+#if PLATFORM(WIN)
+#include "BrowserInspectorPipe.h"
+#include "InspectorPlaywrightAgentClientWin.h"
+#endif
+
#include "WKAPICast.h"
#include "WebInspectorProxy.h"
#include "WebPageProxy.h"
@@ -130,4 +135,11 @@ void WKInspectorToggleElementSelection(WKInspectorRef inspectorRef)
toImpl(inspectorRef)->toggleElementSelection();
}
+void WKInspectorInitializeRemoteInspectorPipe(ConfigureDataStoreCallback configureDataStore, CreatePageCallback createPage, QuitCallback quit)
+{
+#if PLATFORM(WIN)
+ initializeBrowserInspectorPipe(makeUnique<InspectorPlaywrightAgentClientWin>(configureDataStore, createPage, quit));
+#endif
+}
+
#endif // !PLATFORM(IOS_FAMILY)
diff --git a/Source/WebKit/UIProcess/API/C/WKInspector.h b/Source/WebKit/UIProcess/API/C/WKInspector.h
index 026121d114c5fcad84c1396be8d692625beaa3bd..edd6e5cae033124c589959a42522fde07a42fdf6 100644
--- a/Source/WebKit/UIProcess/API/C/WKInspector.h
+++ b/Source/WebKit/UIProcess/API/C/WKInspector.h
@@ -66,6 +66,10 @@ WK_EXPORT void WKInspectorTogglePageProfiling(WKInspectorRef inspector);
WK_EXPORT bool WKInspectorIsElementSelectionActive(WKInspectorRef inspector);
WK_EXPORT void WKInspectorToggleElementSelection(WKInspectorRef inspector);
+typedef void (*ConfigureDataStoreCallback)(WKWebsiteDataStoreRef dataStore);
+typedef WKPageRef (*CreatePageCallback)(WKPageConfigurationRef configuration);
+typedef void (*QuitCallback)();
+WK_EXPORT void WKInspectorInitializeRemoteInspectorPipe(ConfigureDataStoreCallback, CreatePageCallback, QuitCallback);
#ifdef __cplusplus
}
#endif
diff --git a/Source/WebKit/UIProcess/API/C/WKPage.cpp b/Source/WebKit/UIProcess/API/C/WKPage.cpp
index 4369cdd825b5157fb010c3f81ae78e660daa74fc..5a02d375ca9b572b755e596eb9a3455c4b195d40 100644
--- a/Source/WebKit/UIProcess/API/C/WKPage.cpp
+++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp
@@ -1692,6 +1692,13 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient
completionHandler(String());
}
+ void handleJavaScriptDialog(WebPageProxy& page, bool accept, const String& value) final {
+ if (m_client.handleJavaScriptDialog) {
+ m_client.handleJavaScriptDialog(toAPI(&page), accept, toAPI(value.impl()), m_client.base.clientInfo);
+ return;
+ }
+ }
+
void setStatusText(WebPageProxy* page, const String& text) final
{
if (!m_client.setStatusText)
@@ -1752,6 +1759,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient
{
if (!m_client.didNotHandleKeyEvent)
return;
+ if (!event.nativeEvent())
+ return;
m_client.didNotHandleKeyEvent(toAPI(page), event.nativeEvent(), m_client.base.clientInfo);
}
diff --git a/Source/WebKit/UIProcess/API/C/WKPageUIClient.h b/Source/WebKit/UIProcess/API/C/WKPageUIClient.h
index b6388155cd3036e666110f1925616afd37e868ba..c21275123dc4581f51730a2d27deac37c5d30572 100644
--- a/Source/WebKit/UIProcess/API/C/WKPageUIClient.h
+++ b/Source/WebKit/UIProcess/API/C/WKPageUIClient.h
@@ -90,6 +90,7 @@ typedef void (*WKPageRunBeforeUnloadConfirmPanelCallback)(WKPageRef page, WKStri
typedef void (*WKPageRunJavaScriptAlertCallback)(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptAlertResultListenerRef listener, const void *clientInfo);
typedef void (*WKPageRunJavaScriptConfirmCallback)(WKPageRef page, WKStringRef message, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptConfirmResultListenerRef listener, const void *clientInfo);
typedef void (*WKPageRunJavaScriptPromptCallback)(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptPromptResultListenerRef listener, const void *clientInfo);
+typedef void (*WKPageHandleJavaScriptDialogCallback)(WKPageRef page, bool accept, WKStringRef value, const void *clientInfo);
typedef void (*WKPageRequestStorageAccessConfirmCallback)(WKPageRef page, WKFrameRef frame, WKStringRef requestingDomain, WKStringRef currentDomain, WKPageRequestStorageAccessConfirmResultListenerRef listener, const void *clientInfo);
typedef void (*WKPageTakeFocusCallback)(WKPageRef page, WKFocusDirection direction, const void *clientInfo);
typedef void (*WKPageFocusCallback)(WKPageRef page, const void *clientInfo);
@@ -1351,6 +1352,7 @@ typedef struct WKPageUIClientV14 {
// Version 14.
WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel;
+ WKPageHandleJavaScriptDialogCallback handleJavaScriptDialog;
} WKPageUIClientV14;
#ifdef __cplusplus
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h
index cad87f3ef2ab93d93a74cec0c34b47c695de6bc6..66145a384638b97ee08516e56e1e86a83713c634 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h
@@ -123,6 +123,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;
+/*! @abstract Handle a JavaScript dialog.
+ @param webView The web view invoking the delegate method.
+ @param accept Whether to accept the dialog.
+ @param value Value to use for prompt dialog.
+ */
+- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(nullable NSString *)value;
+
#if TARGET_OS_IPHONE
/*! @abstract Allows your app to determine whether or not the given element should show a preview.
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h
index 245580d7e15679b82a61c4639850da02d81a4e1e..5fd5c4afbdc167f817b4ae961f446ec44a0ae2c1 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h
@@ -24,7 +24,6 @@
*/
#import <WebKit/WKFoundation.h>
-
#import <WebKit/WKWebsiteDataRecord.h>
NS_ASSUME_NONNULL_BEGIN
@@ -79,6 +78,8 @@ WK_CLASS_AVAILABLE(macos(10.11), ios(9.0))
/*! @abstract Returns the cookie store representing HTTP cookies in this website data store. */
@property (nonatomic, readonly) WKHTTPCookieStore *httpCookieStore WK_API_AVAILABLE(macos(10.13), ios(11.0));
+- (uint64_t)sessionID;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
index 76fdac0e900f4e2f0f54f6cf21d8bf706a20b212..b0039533b013e4555d93bd2ad94b77f11545715c 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
@@ -44,6 +44,7 @@
#import <WebCore/Credential.h>
#import <WebCore/RegistrationDatabase.h>
#import <WebCore/VersionChecks.h>
+#import <pal/SessionID.h>
#import <wtf/BlockPtr.h>
#import <wtf/URL.h>
#import <wtf/WeakObjCPtr.h>
@@ -198,6 +199,11 @@ static WallTime toSystemClockTime(NSDate *date)
});
}
+- (uint64_t) sessionID
+{
+ return _websiteDataStore->sessionID().toUInt64();
+}
+
static Vector<WebKit::WebsiteDataRecord> toWebsiteDataRecords(NSArray *dataRecords)
{
Vector<WebKit::WebsiteDataRecord> result;
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h
new file mode 100644
index 0000000000000000000000000000000000000000..5fabe06a3289689246c36dfd96eb9900a48b2b0f
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebKit/WKFoundation.h>
+#import <WebKit/WKProcessPool.h>
+#import <WebKit/WKWebsiteDataStore.h>
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class WKWebView;
+
+WK_CLASS_AVAILABLE(macos(10.14.0))
+@interface _WKBrowserContext : NSObject
+@property (nonatomic, strong) WKWebsiteDataStore *dataStore;
+@property (nonatomic, strong) WKProcessPool *processPool;
+@end
+
+@protocol _WKBrowserInspectorDelegate <NSObject>
+- (WKWebView *)createNewPage:(uint64_t)sessionID;
+- (_WKBrowserContext *)createBrowserContext:(NSString *)proxyServer WithBypassList:(NSString *)proxyBypassList;
+- (void)deleteBrowserContext:(uint64_t)sessionID;
+- (void)quit;
+@end
+
+WK_CLASS_AVAILABLE(macos(10.14.0))
+@interface _WKBrowserInspector : NSObject
++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless;
+@end
+
+
+NS_ASSUME_NONNULL_END
+
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm
new file mode 100644
index 0000000000000000000000000000000000000000..e7143513ea2be8e1cdab5c86a28643fffea626dd
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "_WKBrowserInspector.h"
+
+#include "BrowserInspectorPipe.h"
+#include "InspectorPlaywrightAgentClientMac.h"
+#include "PageClientImplMac.h"
+#include "WebKit2Initialize.h"
+
+#import "WKWebView.h"
+
+using namespace WebKit;
+
+@implementation _WKBrowserInspector
+
++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless
+{
+#if ENABLE(REMOTE_INSPECTOR)
+ InitializeWebKit2();
+ PageClientImpl::setHeadless(headless);
+ initializeBrowserInspectorPipe(makeUnique<InspectorPlaywrightAgentClientMac>(delegate));
+#endif
+}
+
+@end
+
+@implementation _WKBrowserContext
+- (void)dealloc
+{
+ [_dataStore release];
+ [_processPool release];
+ _dataStore = nil;
+ _processPool = nil;
+ [super dealloc];
+}
+@end
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
index 7226cc2cb605d2384b5fdf9210ac731b41610c1e..7883367044356751886f5c1f89250c29fcc58d3a 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
@@ -62,6 +62,7 @@ WK_CLASS_AVAILABLE(macos(10.10), ios(8.0))
#endif
@property (nonatomic) pid_t presentingApplicationPID WK_API_AVAILABLE(macos(10.13), ios(11.0));
@property (nonatomic) BOOL processSwapsOnNavigation WK_API_AVAILABLE(macos(10.14), ios(12.0));
+@property (nonatomic) BOOL forceOverlayScrollbars WK_API_AVAILABLE(macos(10.14));
@property (nonatomic) BOOL alwaysKeepAndReuseSwappedProcesses WK_API_AVAILABLE(macos(10.14), ios(12.0));
@property (nonatomic) BOOL processSwapsOnWindowOpenWithOpener WK_API_AVAILABLE(macos(10.14), ios(12.0));
@property (nonatomic) BOOL prewarmsProcessesAutomatically WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
index b4c35e8854c61055655aeff2bfb909cdc542839c..11d685c58d7c148430dd664636f5d51e251800c7 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
@@ -231,6 +231,16 @@
return _processPoolConfiguration->processSwapsOnNavigation();
}
+- (void)setForceOverlayScrollbars:(BOOL)force
+{
+ _processPoolConfiguration->setForceOverlayScrollbars(force);
+}
+
+- (BOOL)forceOverlayScrollbars
+{
+ return _processPoolConfiguration->forceOverlayScrollbars();
+}
+
- (void)setPrewarmsProcessesAutomatically:(BOOL)prewarms
{
_processPoolConfiguration->setIsAutomaticProcessWarmingEnabled(prewarms);
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm
index 4e40b8b7a75f5f70355d01dd7557cdb1baafc44c..522af164965a5f57853349ad1d18fabf85b38dab 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 "_WKRemoteWebInspectorViewControllerPrivate.h"
+#import "WKWebViewPrivate.h"
#if PLATFORM(MAC)
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h
index e4cf5a2dc102f596d3aefe8c647b6f5aa9b79b02..ff44bb597a9cc8c6c8742000443e57c221531e53 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h
@@ -31,6 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
@class _WKUserContentWorld;
@class WKContentWorld;
@class WKWebView;
+@class WKContentWorld;
typedef NS_ENUM(NSInteger, _WKUserStyleLevel) {
_WKUserStyleUserLevel,
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm
index 7915ea3b2f65da48cf4ea982025a93e4e18a7ffa..158bdf1d097c2d98765e362e1f8e6629f8c20350 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm
@@ -34,6 +34,7 @@
#import "WebKit2Initialize.h"
#import "WebPageProxy.h"
#import "_WKUserContentWorldInternal.h"
+#import <WebKit/WKContentWorldInternal.h>
#import <wtf/cocoa/VectorCocoa.h>
@implementation _WKUserStyleSheet
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..54529a23f53cebe6f8a96873ca6c2f31f0481ae0
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebKitBrowserInspector.h"
+
+#include "BrowserInspectorPipe.h"
+#include "InspectorPlaywrightAgentClientGLib.h"
+#include "WebKitBrowserInspectorPrivate.h"
+#include "WebKitWebViewPrivate.h"
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/WTFGType.h>
+
+/**
+ * SECTION: WebKitBrowserInspector
+ * @Short_description: Access to the WebKit browser inspector
+ * @Title: WebKitBrowserInspector
+ *
+ * The WebKit Browser Inspector is an experimental API that provides
+ * access to the inspector via the remote debugging protocol. The protocol
+ * allows to create ephemeral contexts and create pages in them and then
+ * manipulate them using the inspector commands. This may be useful for
+ * the browser automation or remote debugging.
+ *
+ * Currently the protocol can be exposed to the parent process via a unix
+ * pipe.
+ */
+
+enum {
+ CREATE_NEW_PAGE,
+ QUIT_APPLICATION,
+
+ LAST_SIGNAL
+};
+
+struct _WebKitBrowserInspectorPrivate {
+ int unused { 0 };
+};
+
+WEBKIT_DEFINE_TYPE(WebKitBrowserInspector, webkit_browser_inspector, G_TYPE_OBJECT)
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+static void webkit_browser_inspector_class_init(WebKitBrowserInspectorClass* findClass)
+{
+ GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass);
+
+ /**
+ * WebKitBrowserInspector::create-new-page:
+ * @inspector: the #WebKitBrowserInspector on which the signal is emitted
+ *
+ * Emitted when the inspector is requested to create a new page in the provided
+ * #WebKitWebContext.
+ *
+ * This signal is emitted when inspector receives 'Browser.createPage' command
+ * from its remote client. If the signal is not handled the command will fail.
+ *
+ * Returns: %WebKitWebView that contains created page.
+ */
+ signals[CREATE_NEW_PAGE] = g_signal_new(
+ "create-new-page",
+ G_TYPE_FROM_CLASS(gObjectClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitBrowserInspectorClass, create_new_page),
+ nullptr, nullptr,
+ g_cclosure_marshal_generic,
+#if PLATFORM(GTK)
+ GTK_TYPE_WIDGET,
+#else
+ WEBKIT_TYPE_WEB_VIEW,
+#endif
+ 1,
+ WEBKIT_TYPE_WEB_CONTEXT);
+
+ /**
+ * WebKitBrowserInspector::quit-application:
+ * @inspector: the #WebKitBrowserInspector on which the signal is emitted
+ *
+ * Emitted when the inspector is requested to close the browser application.
+ *
+ * This signal is emitted when inspector receives 'Browser.close' command
+ * from its remote client. If the signal is not handled the command will fail.
+ */
+ signals[QUIT_APPLICATION] = g_signal_new(
+ "quit-application",
+ G_TYPE_FROM_CLASS(gObjectClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitBrowserInspectorClass, quit_application),
+ nullptr, nullptr,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext* context)
+{
+ WebKitWebView* newWebView;
+ g_signal_emit(webkit_browser_inspector_get_default(), signals[CREATE_NEW_PAGE], 0, context, &newWebView);
+ if (!newWebView)
+ return nullptr;
+ return &webkitWebViewGetPage(newWebView);
+}
+
+void webkitBrowserInspectorQuitApplication()
+{
+ g_signal_emit(webkit_browser_inspector_get_default(), signals[QUIT_APPLICATION], 0, NULL);
+}
+
+static gpointer createWebKitBrowserInspector(gpointer)
+{
+ static GRefPtr<WebKitBrowserInspector> browserInspector = adoptGRef(WEBKIT_BROWSER_INSPECTOR(g_object_new(WEBKIT_TYPE_BROWSER_INSPECTOR, nullptr)));
+ return browserInspector.get();
+}
+
+/**
+ * webkit_browser_inspector_get_default:
+ *
+ * Gets the default instance of the browser inspector.
+ *
+ * Returns: (transfer none): a #WebKitBrowserInspector
+ */
+WebKitBrowserInspector* webkit_browser_inspector_get_default(void)
+{
+ static GOnce onceInit = G_ONCE_INIT;
+ return WEBKIT_BROWSER_INSPECTOR(g_once(&onceInit, createWebKitBrowserInspector, 0));
+}
+
+/**
+ * webkit_browser_inspector_initialize_pipe:
+ *
+ * Creates browser inspector and configures pipe handler to communicate with
+ * the parent process.
+ */
+void webkit_browser_inspector_initialize_pipe(const char* defaultProxyURI, const char* const* ignoreHosts)
+{
+ WebKit::initializeBrowserInspectorPipe(makeUnique<WebKit::InspectorPlaywrightAgentClientGlib>(defaultProxyURI, ignoreHosts));
+}
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0b1da48465c850f541532ed961d1b778bea6028
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "WebKitBrowserInspector.h"
+#include "WebPageProxy.h"
+
+WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext*);
+void webkitBrowserInspectorQuitApplication();
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
index 2ceb2b4f49f409bbe6e6810115e36d0c84f83b5d..16d2062b746b80ace6f39d779e9c3b8796b581b1 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
+++ b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
@@ -93,6 +93,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 f7faa5880bf02b28157276b60ca100ed38fbf990..aaa967adaa366a72ce5229efb96a01864546a543 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
+++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
@@ -120,8 +120,8 @@ enum {
PROP_LOCAL_STORAGE_DIRECTORY,
#endif
PROP_WEBSITE_DATA_MANAGER,
-#if PLATFORM(GTK)
PROP_PSON_ENABLED,
+#if PLATFORM(GTK)
#if !USE(GTK4)
PROP_USE_SYSYEM_APPEARANCE_FOR_SCROLLBARS
#endif
@@ -206,8 +206,8 @@ struct _WebKitWebContextPrivate {
RefPtr<WebProcessPool> processPool;
bool clientsDetached;
-#if PLATFORM(GTK)
bool psonEnabled;
+#if PLATFORM(GTK)
#if !USE(GTK4)
bool useSystemAppearanceForScrollbars;
#endif
@@ -306,11 +306,9 @@ WEBKIT_DEFINE_TYPE(WebKitWebContext, webkit_web_context, G_TYPE_OBJECT)
static const char* injectedBundleDirectory()
{
-#if ENABLE(DEVELOPER_MODE)
const char* bundleDirectory = g_getenv("WEBKIT_INJECTED_BUNDLE_PATH");
if (bundleDirectory && g_file_test(bundleDirectory, G_FILE_TEST_IS_DIR))
return bundleDirectory;
-#endif
#if PLATFORM(GTK)
static const char* injectedBundlePath = LIBDIR G_DIR_SEPARATOR_S "webkit2gtk-" WEBKITGTK_API_VERSION_STRING
@@ -335,10 +333,10 @@ static void webkitWebContextGetProperty(GObject* object, guint propID, GValue* v
case PROP_WEBSITE_DATA_MANAGER:
g_value_set_object(value, webkit_web_context_get_website_data_manager(context));
break;
-#if PLATFORM(GTK)
case PROP_PSON_ENABLED:
g_value_set_boolean(value, context->priv->psonEnabled);
break;
+#if PLATFORM(GTK)
#if !USE(GTK4)
case PROP_USE_SYSYEM_APPEARANCE_FOR_SCROLLBARS:
g_value_set_boolean(value, webkit_web_context_get_use_system_appearance_for_scrollbars(context));
@@ -365,10 +363,10 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa
context->priv->websiteDataManager = manager ? WEBKIT_WEBSITE_DATA_MANAGER(manager) : nullptr;
break;
}
-#if PLATFORM(GTK)
case PROP_PSON_ENABLED:
context->priv->psonEnabled = g_value_get_boolean(value);
break;
+#if PLATFORM(GTK)
#if !USE(GTK4)
case PROP_USE_SYSYEM_APPEARANCE_FOR_SCROLLBARS:
webkit_web_context_set_use_system_appearance_for_scrollbars(context, g_value_get_boolean(value));
@@ -380,10 +378,19 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa
}
}
+static int webkitWebContext = 0;
+
+int webkitWebContextExistingCount()
+{
+ return webkitWebContext;
+}
+
static void webkitWebContextConstructed(GObject* object)
{
G_OBJECT_CLASS(webkit_web_context_parent_class)->constructed(object);
+ ++webkitWebContext;
+
GUniquePtr<char> bundleFilename(g_build_filename(injectedBundleDirectory(), INJECTED_BUNDLE_FILENAME, nullptr));
WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(object);
@@ -391,8 +398,8 @@ static void webkitWebContextConstructed(GObject* object)
API::ProcessPoolConfiguration configuration;
configuration.setInjectedBundlePath(FileSystem::stringFromFileSystemRepresentation(bundleFilename.get()));
-#if PLATFORM(GTK)
configuration.setProcessSwapsOnNavigation(priv->psonEnabled);
+#if PLATFORM(GTK)
#if !USE(GTK4)
configuration.setUseSystemAppearanceForScrollbars(priv->useSystemAppearanceForScrollbars);
#endif
@@ -429,6 +436,8 @@ static void webkitWebContextConstructed(GObject* object)
static void webkitWebContextDispose(GObject* object)
{
+ --webkitWebContext;
+
WebKitWebContextPrivate* priv = WEBKIT_WEB_CONTEXT(object)->priv;
if (!priv->clientsDetached) {
priv->clientsDetached = true;
@@ -501,7 +510,6 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass
WEBKIT_TYPE_WEBSITE_DATA_MANAGER,
static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
-#if PLATFORM(GTK)
/**
* WebKitWebContext:process-swap-on-cross-site-navigation-enabled:
*
@@ -525,6 +533,7 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass
FALSE,
static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
+#if PLATFORM(GTK)
#if !USE(GTK4)
/**
* WebKitWebContext:use-system-appearance-for-scrollbars:
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h
index 78d1578f94793e9e59a3d4d2b33e79ea8530fa04..493cdadac3873508b3efa3048638e73a13f4c976 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h
+++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h
@@ -45,3 +45,4 @@ void webkitWebContextInitializeNotificationPermissions(WebKitWebContext*);
#if ENABLE(REMOTE_INSPECTOR)
void webkitWebContextWillCloseAutomationSession(WebKitWebContext*);
#endif
+int webkitWebContextExistingCount();
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
index 59feaad5599ee1c9fea8354d19e6eb525cf8168b..c5f0b4a8111eaebfa4ee3ae76cf267c951180f34 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
+++ b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
@@ -31,6 +31,7 @@
#include "WebCertificateInfo.h"
#include "WebContextMenuItem.h"
#include "WebContextMenuItemData.h"
+#include "WebPageInspectorController.h"
#include "WebKitAuthenticationRequestPrivate.h"
#include "WebKitBackForwardListPrivate.h"
#include "WebKitContextMenuClient.h"
@@ -132,6 +133,7 @@ enum {
CLOSE,
SCRIPT_DIALOG,
+ SCRIPT_DIALOG_HANDLED,
DECIDE_POLICY,
PERMISSION_REQUEST,
@@ -435,6 +437,9 @@ void WebKitWebViewClient::handleDownloadRequest(WKWPE::View&, DownloadProxy& dow
void WebKitWebViewClient::frameDisplayed(WKWPE::View&)
{
+ if (RefPtr<cairo_surface_t> surface = adoptRef(webkitWebViewBackendTakeScreenshot(m_webView->priv->backend.get())))
+ getPage(m_webView).inspectorController().didPaint(surface.get());
+
{
SetForScope<bool> inFrameDisplayedGuard(m_webView->priv->inFrameDisplayed, true);
for (const auto& callback : m_webView->priv->frameDisplayedCallbacks) {
@@ -465,6 +470,7 @@ void WebKitWebViewClient::didReceiveUserMessage(WKWPE::View&, UserMessage&& mess
{
webkitWebViewDidReceiveUserMessage(m_webView, WTFMove(message), WTFMove(completionHandler));
}
+
#endif
static gboolean webkitWebViewLoadFail(WebKitWebView* webView, WebKitLoadEvent, const char* failingURI, GError* error)
@@ -1592,6 +1598,15 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_SCRIPT_DIALOG);
+ signals[SCRIPT_DIALOG_HANDLED] = g_signal_new(
+ "script-dialog-handled",
+ G_TYPE_FROM_CLASS(webViewClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitWebViewClass, script_dialog),
+ g_signal_accumulator_true_handled, nullptr,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN, 1);
+
/**
* WebKitWebView::decide-policy:
* @web_view: the #WebKitWebView on which the signal is emitted
@@ -2485,6 +2500,23 @@ void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const
webkit_script_dialog_unref(webView->priv->currentScriptDialog);
}
+void webkitWebViewHandleJavaScriptDialog(WebKitWebView* webView, bool accept, const String& value) {
+ auto* dialog = webView->priv->currentScriptDialog;
+#if PLATFORM(WPE)
+ dialog->isUserHandled = false;
+#endif
+ webkit_script_dialog_ref(dialog);
+ if (!value.isNull())
+ webkitWebViewSetCurrentScriptDialogUserInput(webView, value);
+ if (accept)
+ webkitWebViewAcceptCurrentScriptDialog(webView);
+ else
+ webkitWebViewDismissCurrentScriptDialog(webView);
+ gboolean returnValue;
+ g_signal_emit(webView, signals[SCRIPT_DIALOG_HANDLED], 0, dialog, &returnValue);
+ webkit_script_dialog_unref(dialog);
+}
+
bool webkitWebViewIsShowingScriptDialog(WebKitWebView* webView)
{
if (!webView->priv->currentScriptDialog)
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h
index b9e56fc55fd7dfa821f789264b0c15f9b4c7b412..4138d5b42077f735264ac7a168cce329ebaa89c3 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h
+++ b/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h
@@ -60,6 +60,7 @@ void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message, Fun
void webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message, Function<void(bool)>&& completionHandler);
void webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText, Function<void(const String&)>&& completionHandler);
void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView*, const CString& message, Function<void(bool)>&& completionHandler);
+void webkitWebViewHandleJavaScriptDialog(WebKitWebView*, bool accept, const String& value);
bool webkitWebViewIsShowingScriptDialog(WebKitWebView*);
bool webkitWebViewIsScriptDialogRunning(WebKitWebView*, WebKitScriptDialog*);
String webkitWebViewGetCurrentScriptDialogMessage(WebKitWebView*);
diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
index 57139e2d910cf1834d071d482b3967194dd0fda1..3b6ecd1ace15fdaded93b9207446f2810aaf7dbd 100644
--- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
+++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
@@ -241,6 +241,8 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool
{
if (wasEventHandled || event.type() != WebEvent::Type::KeyDown || !event.nativeEvent())
return;
+ if (!event.nativeEvent())
+ return;
WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(m_viewWidget);
webkitWebViewBaseForwardNextKeyEvent(webkitWebViewBase);
diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f1a0173a5641d6f158d815b8f7b9ea66f65c26d
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION)
+#error "Only <webkit2/webkit2.h> can be included directly."
+#endif
+
+#ifndef WebKitBrowserInspector_h
+#define WebKitBrowserInspector_h
+
+#include <glib-object.h>
+#include <webkit2/WebKitDefines.h>
+#include <webkit2/WebKitWebView.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_BROWSER_INSPECTOR (webkit_browser_inspector_get_type())
+#define WEBKIT_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspector))
+#define WEBKIT_IS_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_BROWSER_INSPECTOR))
+#define WEBKIT_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass))
+#define WEBKIT_IS_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_BROWSER_INSPECTOR))
+#define WEBKIT_BROWSER_INSPECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass))
+
+typedef struct _WebKitBrowserInspector WebKitBrowserInspector;
+typedef struct _WebKitBrowserInspectorClass WebKitBrowserInspectorClass;
+typedef struct _WebKitBrowserInspectorPrivate WebKitBrowserInspectorPrivate;
+
+struct _WebKitBrowserInspector {
+ GObject parent;
+
+ WebKitBrowserInspectorPrivate *priv;
+};
+
+struct _WebKitBrowserInspectorClass {
+ GObjectClass parent_class;
+
+ WebKitWebView *(* create_new_page) (WebKitBrowserInspector *browser_inspector,
+ WebKitWebContext *context);
+ WebKitWebView *(* quit_application) (WebKitBrowserInspector *browser_inspector);
+
+ void (*_webkit_reserved0) (void);
+ void (*_webkit_reserved1) (void);
+ void (*_webkit_reserved2) (void);
+ void (*_webkit_reserved3) (void);
+};
+
+WEBKIT_API GType
+webkit_browser_inspector_get_type (void);
+
+WEBKIT_API WebKitBrowserInspector *
+webkit_browser_inspector_get_default (void);
+
+WEBKIT_API void
+webkit_browser_inspector_initialize_pipe (const char* defaultProxyURI,
+ const char* const* ignoreHosts);
+
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp
index f4c7c7a40351e8d1df8ddb615b12cda6e228592c..13fa06163ba552c584a40aec7669689ba48584b9 100644
--- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp
+++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp
@@ -2266,6 +2266,11 @@ void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase)
#endif
}
+WebKit::AcceleratedBackingStore* webkitWebViewBaseGetAcceleratedBackingStore(WebKitWebViewBase* webkitWebViewBase)
+{
+ return webkitWebViewBase->priv->acceleratedBackingStore.get();
+}
+
void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
{
ASSERT(webkitWebViewBase->priv->acceleratedBackingStore);
diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
index d09aea45d94fb7367ba88fdf8326dea1209d02ce..dac8f3ec62ace87fc82c997feb950733aa59a996 100644
--- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
+++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
@@ -27,6 +27,7 @@
#pragma once
+#include "AcceleratedBackingStore.h"
#include "APIPageConfiguration.h"
#include "GestureController.h"
#include "InputMethodState.h"
@@ -120,3 +121,5 @@ void webkitWebViewBaseDidLosePointerLock(WebKitWebViewBase*);
void webkitWebViewBaseSetInputMethodContext(WebKitWebViewBase*, WebKitInputMethodContext*);
WebKitInputMethodContext* webkitWebViewBaseGetInputMethodContext(WebKitWebViewBase*);
void webkitWebViewBaseSynthesizeCompositionKeyPress(WebKitWebViewBase*, const String& text, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<WebKit::EditingRange>&&);
+
+WebKit::AcceleratedBackingStore* webkitWebViewBaseGetAcceleratedBackingStore(WebKitWebViewBase*);
diff --git a/Source/WebKit/UIProcess/API/gtk/webkit2.h b/Source/WebKit/UIProcess/API/gtk/webkit2.h
index c358118360a38c7b462227aa4ab8388bd7942c3e..70bdfbda231b481e8c5ac34fe6d8825f2350d71e 100644
--- a/Source/WebKit/UIProcess/API/gtk/webkit2.h
+++ b/Source/WebKit/UIProcess/API/gtk/webkit2.h
@@ -32,6 +32,7 @@
#include <webkit2/WebKitAutomationSession.h>
#include <webkit2/WebKitBackForwardList.h>
#include <webkit2/WebKitBackForwardListItem.h>
+#include <webkit2/WebKitBrowserInspector.h>
#include <webkit2/WebKitContextMenu.h>
#include <webkit2/WebKitContextMenuActions.h>
#include <webkit2/WebKitContextMenuItem.h>
diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp
index 2e758227c7274e8a1297c35bfea7ffc2861f6759..160fbce41d7fb868fc8acaab815e7b80593865e6 100644
--- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp
+++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp
@@ -194,7 +194,7 @@ WebCore::IntPoint PageClientImpl::accessibilityScreenToRootView(const WebCore::I
WebCore::IntRect PageClientImpl::rootViewToAccessibilityScreen(const WebCore::IntRect& rect)
{
- return rootViewToScreen(rect);
+ return rootViewToScreen(rect);
}
void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool)
diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb1a540d341b07581ec87b922b7d007ce45ba989
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if !defined(__WEBKIT_H_INSIDE__) && !defined(WEBKIT2_COMPILATION)
+#error "Only <wpe/webkit.h> can be included directly."
+#endif
+
+#ifndef WebKitBrowserInspector_h
+#define WebKitBrowserInspector_h
+
+#include <glib-object.h>
+#include <wpe/WebKitDefines.h>
+#include <wpe/WebKitWebView.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_BROWSER_INSPECTOR (webkit_browser_inspector_get_type())
+#define WEBKIT_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspector))
+#define WEBKIT_IS_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_BROWSER_INSPECTOR))
+#define WEBKIT_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass))
+#define WEBKIT_IS_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_BROWSER_INSPECTOR))
+#define WEBKIT_BROWSER_INSPECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass))
+
+typedef struct _WebKitBrowserInspector WebKitBrowserInspector;
+typedef struct _WebKitBrowserInspectorClass WebKitBrowserInspectorClass;
+typedef struct _WebKitBrowserInspectorPrivate WebKitBrowserInspectorPrivate;
+
+struct _WebKitBrowserInspector {
+ GObject parent;
+
+ WebKitBrowserInspectorPrivate *priv;
+};
+
+struct _WebKitBrowserInspectorClass {
+ GObjectClass parent_class;
+
+ WebKitWebView *(* create_new_page) (WebKitBrowserInspector *browser_inspector,
+ WebKitWebContext *context);
+ WebKitWebView *(* quit_application) (WebKitBrowserInspector *browser_inspector);
+
+ void (*_webkit_reserved0) (void);
+ void (*_webkit_reserved1) (void);
+ void (*_webkit_reserved2) (void);
+ void (*_webkit_reserved3) (void);
+};
+
+WEBKIT_API GType
+webkit_browser_inspector_get_type (void);
+
+WEBKIT_API WebKitBrowserInspector *
+webkit_browser_inspector_get_default (void);
+
+WEBKIT_API void
+webkit_browser_inspector_initialize_pipe (const char* defaultProxyURI,
+ const char* const* ignoreHosts);
+
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp
index e0fc205b39095cf8aae201a1dcca520461c60de4..872186ad99a7b82f0c61705ff6c5ae4453e5e1d4 100644
--- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp
+++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp
@@ -54,6 +54,7 @@ struct _WebKitWebViewBackend {
struct wpe_view_backend* backend;
GDestroyNotify notifyCallback;
gpointer notifyCallbackData;
+ take_screenshot_callback screenshotCallback;
int referenceCount { 1 };
};
@@ -116,6 +117,19 @@ struct wpe_view_backend* webkit_web_view_backend_get_wpe_backend(WebKitWebViewBa
return viewBackend->backend;
}
+void webkit_web_view_backend_set_screenshot_callback(WebKitWebViewBackend *view_backend, take_screenshot_callback callback)
+{
+ view_backend->screenshotCallback = callback;
+}
+
+cairo_surface_t* webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend* view_backend)
+{
+ if (!view_backend->screenshotCallback)
+ return nullptr;
+
+ return view_backend->screenshotCallback(view_backend->notifyCallbackData);
+}
+
namespace WTF {
template <> WebKitWebViewBackend* refGPtr(WebKitWebViewBackend* ptr)
diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h
index 6663964d5abac79e123d90e0351590884c66aa72..13ba5e7c3895c6e4efda95f1f90b9baea1c1bf30 100644
--- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h
+++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h
@@ -27,6 +27,7 @@
#include <glib-object.h>
#include <wpe/WebKitDefines.h>
#include <wpe/wpe.h>
+#include <cairo.h>
G_BEGIN_DECLS
@@ -44,6 +45,12 @@ webkit_web_view_backend_new (struct wpe_view_backend *backend,
WEBKIT_API struct wpe_view_backend *
webkit_web_view_backend_get_wpe_backend (WebKitWebViewBackend *view_backend);
+typedef cairo_surface_t* (*take_screenshot_callback)(gpointer user_data);
+
+WEBKIT_API void
+webkit_web_view_backend_set_screenshot_callback (WebKitWebViewBackend *view_backend,
+ take_screenshot_callback callback);
+
G_END_DECLS
#endif /* WebKitWebViewBackend_h */
diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h
index e4b92ace1531090ae38a7aec3d3d4febf19aee84..43690f9ef4969a39084501613bfc00a77fd5df49 100644
--- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h
+++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h
@@ -31,3 +31,5 @@ template <> void derefGPtr(WebKitWebViewBackend* ptr);
}
void webkitWebViewBackendUnref(WebKitWebViewBackend*);
+
+cairo_surface_t* webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend*);
diff --git a/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt b/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt
index 0ee250e56338cda7332d70508582a59a7ad21c80..c875e31ed4476d1f5923572d07d02ec85a93184d 100644
--- a/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt
+++ b/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt
@@ -317,6 +317,8 @@ WEBKIT_TYPE_WEB_VIEW_BACKEND
WebKitWebViewBackend
webkit_web_view_backend_get_wpe_backend
webkit_web_view_backend_new
+take_screenshot_callback
+webkit_web_view_backend_set_screenshot_callback
<SUBSECTION Private>
webkit_web_view_backend_get_type
diff --git a/Source/WebKit/UIProcess/API/wpe/webkit.h b/Source/WebKit/UIProcess/API/wpe/webkit.h
index 27c680d46428d349b0d1119f12da56ff283a60aa..1980aff7d662a1eea450d2db78b41f12a04f715e 100644
--- a/Source/WebKit/UIProcess/API/wpe/webkit.h
+++ b/Source/WebKit/UIProcess/API/wpe/webkit.h
@@ -32,6 +32,7 @@
#include <wpe/WebKitAutomationSession.h>
#include <wpe/WebKitBackForwardList.h>
#include <wpe/WebKitBackForwardListItem.h>
+#include <wpe/WebKitBrowserInspector.h>
#include <wpe/WebKitContextMenu.h>
#include <wpe/WebKitContextMenuActions.h>
#include <wpe/WebKitContextMenuItem.h>
diff --git a/Source/WebKit/UIProcess/BackingStore.h b/Source/WebKit/UIProcess/BackingStore.h
index fe3c63e61f778762dc2c2080c74ec53fdf8c2e5f..c43a8226c9be702e248f1712e465efa396ee8969 100644
--- a/Source/WebKit/UIProcess/BackingStore.h
+++ b/Source/WebKit/UIProcess/BackingStore.h
@@ -60,6 +60,7 @@ public:
#if USE(CAIRO)
typedef cairo_t* PlatformGraphicsContext;
+ cairo_surface_t* surface() const;
#elif USE(DIRECT2D)
struct DXConnections {
ID3D11DeviceContext1* immediateContext { nullptr };
diff --git a/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dc8af6fe1c57bcd62d605fd1daa3da13361858bb
--- /dev/null
+++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BrowserInspectorPipe.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgent.h"
+#include "RemoteInspectorPipe.h"
+#include <wtf/NeverDestroyed.h>
+#include "InspectorPlaywrightAgentClient.h"
+
+namespace WebKit {
+
+void initializeBrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client)
+{
+ class BrowserInspectorPipe {
+ public:
+ BrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client)
+ : m_playwrightAgent(std::move(client))
+ , m_remoteInspectorPipe(m_playwrightAgent)
+ {
+ }
+
+ InspectorPlaywrightAgent m_playwrightAgent;
+ RemoteInspectorPipe m_remoteInspectorPipe;
+ };
+
+ static NeverDestroyed<BrowserInspectorPipe> pipe(std::move(client));
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/BrowserInspectorPipe.h b/Source/WebKit/UIProcess/BrowserInspectorPipe.h
new file mode 100644
index 0000000000000000000000000000000000000000..cd66887de171cda7d15a8e4dc6dbff63665dc619
--- /dev/null
+++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+namespace WebKit {
+
+class InspectorPlaywrightAgentClient;
+
+void initializeBrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client);
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h
index 454c61ffdefecc476d1560c7c43f5b5d345f281d..6de7509037b7683ddd403ee247bdf2845ce4e87a 100644
--- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h
+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h
@@ -27,6 +27,8 @@
#if HAVE(APP_SSO)
+#include <wtf/Forward.h>
+#include <wtf/CompletionHandler.h>
#include "SOAuthorizationSession.h"
#include <wtf/CompletionHandler.h>
@@ -39,6 +41,8 @@ class NavigationAction;
namespace WebKit {
+class WebPageProxy;
+
// FSM: Idle => Active => Completed
class PopUpSOAuthorizationSession final : public SOAuthorizationSession {
public:
diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/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 8a094745c1f24be105dbb02ab91e307b31d486b1..95d3fee2eefac113def2eace3cd40a6f06fa74d3 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*, FrameInfoData&&, Function<void()>&& completionHandler) final;
void runJavaScriptConfirm(WebPageProxy&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function<void(bool)>&& completionHandler) final;
void runJavaScriptPrompt(WebPageProxy&, const WTF::String&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function<void(const WTF::String&)>&&) final;
+ void handleJavaScriptDialog(WebKit::WebPageProxy&, bool accept, const WTF::String&) final;
void presentStorageAccessConfirmDialog(const WTF::String& requestingDomain, const WTF::String& currentDomain, CompletionHandler<void(bool)>&&);
void requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler<void(bool)>&&) final;
void decidePolicyForGeolocationPermissionRequest(WebPageProxy&, WebFrameProxy&, const FrameInfoData&, Function<void(bool)>&) final;
@@ -174,6 +175,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 d0338f8d6e3b9a13df2af153acb5deb38e1fcd9b..12f2d19b10de8ac14eb078f8ec6c67cf861985cc 100644
--- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
+++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
@@ -104,6 +104,7 @@ void UIDelegate::setDelegate(id <WKUIDelegate> delegate)
m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)];
m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)];
+ m_delegateMethods.webViewHandleJavaScriptDialogValue = [delegate respondsToSelector:@selector(webView:handleJavaScriptDialog:value:)];
m_delegateMethods.webViewRequestStorageAccessPanelUnderFirstPartyCompletionHandler = [delegate respondsToSelector:@selector(_webView:requestStorageAccessPanelForDomain:underCurrentDomain:completionHandler:)];
m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
m_delegateMethods.webViewRequestGeolocationPermissionForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestGeolocationPermissionForFrame:decisionHandler:)];
@@ -345,6 +346,15 @@ void UIDelegate::UIClient::runJavaScriptPrompt(WebPageProxy& page, const WTF::St
}).get()];
}
+void UIDelegate::UIClient::handleJavaScriptDialog(WebKit::WebPageProxy&, bool accept, const WTF::String& value) {
+ if (!m_uiDelegate.m_delegateMethods.webViewHandleJavaScriptDialogValue)
+ return;
+ auto delegate = m_uiDelegate.m_delegate.get();
+ if (!delegate)
+ return;
+ [delegate webView:m_uiDelegate.m_webView handleJavaScriptDialog:accept value:value];
+}
+
void UIDelegate::UIClient::requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler<void(bool)>&& 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 75f4d583532cd9d567fe6450f308ff346957b298..35ebba671a485feedcbf656a1fa34421e94fb201 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
+++ b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
@@ -436,7 +436,7 @@ void WebProcessPool::platformInitializeWebProcess(const WebProcessProxy& process
auto screenProperties = WebCore::collectScreenProperties();
parameters.screenProperties = WTFMove(screenProperties);
#if PLATFORM(MAC)
- parameters.useOverlayScrollbars = ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay);
+ parameters.useOverlayScrollbars = m_configuration->forceOverlayScrollbars() || ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay);
#endif
#if PLATFORM(IOS)
@@ -702,8 +702,8 @@ void WebProcessPool::registerNotificationObservers()
#if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
m_scrollerStyleNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSPreferredScrollerStyleDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
- auto scrollbarStyle = [NSScroller preferredScrollerStyle];
- sendToAllProcesses(Messages::WebProcess::ScrollerStylePreferenceChanged(scrollbarStyle));
+ bool useOverlayScrollbars = m_configuration->forceOverlayScrollbars() || ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay);
+ sendToAllProcesses(Messages::WebProcess::ScrollerStylePreferenceChanged(useOverlayScrollbars));
}];
#endif
diff --git a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
index 70084ece22ea8fb1ce6d4d6f4d0e4300d0b46781..11ec3abcf31e2e4b9e0c44bbee0c3f15ff248af0 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
+++ b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
@@ -491,6 +491,9 @@ public:
void provideDataForPasteboard(NSPasteboard *, NSString *type);
NSArray *namesOfPromisedFilesDroppedAtDestination(NSURL *dropDestination);
+// Paywright begin
+ RetainPtr<CGImageRef> takeSnapshotForAutomation();
+// Paywright end
RefPtr<ViewSnapshot> takeViewSnapshot();
void saveBackForwardSnapshotForCurrentItem();
void saveBackForwardSnapshotForItem(WebBackForwardListItem&);
diff --git a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
index d06013b887b2c82650962cf581d1b7fe598bfcae..8753478696db815004598f82453037eb7d838647 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
+++ b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
@@ -4513,6 +4513,18 @@ static RetainPtr<CGImageRef> takeWindowSnapshot(CGSWindowID windowID, bool captu
return adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, windowID, imageOptions));
}
+// Paywright begin
+RetainPtr<CGImageRef> WebViewImpl::takeSnapshotForAutomation() {
+ NSWindow *window = [m_view window];
+
+ CGSWindowID windowID = (CGSWindowID)window.windowNumber;
+ if (!windowID || !window.isVisible)
+ return nullptr;
+
+ return takeWindowSnapshot(windowID, true);
+}
+// Paywright end
+
RefPtr<ViewSnapshot> WebViewImpl::takeViewSnapshot()
{
NSWindow *window = [m_view window];
diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
index 5a51b9ec1d68feecb5cf46a10d07c62785ad1fb0..1e165124020ac9e520123a0503d2a4ec30d7c32b 100644
--- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
+++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
@@ -32,13 +32,16 @@
#include "DrawingAreaProxyMessages.h"
#include "LayerTreeContext.h"
#include "UpdateInfo.h"
+#include "WebPageInspectorController.h"
#include "WebPageProxy.h"
#include "WebPreferences.h"
#include "WebProcessProxy.h"
#include <WebCore/PlatformDisplay.h>
#include <WebCore/Region.h>
+#include <wtf/Vector.h>
#if PLATFORM(GTK)
+#include "WebKitWebViewBasePrivate.h"
#include <gtk/gtk.h>
#endif
@@ -51,6 +54,13 @@
#include <d3d11_1.h>
#endif
+#if PLATFORM(WIN)
+#include <cairo-win32.h>
+#include <windows.h>
+#include <WebCore/HWndDC.h>
+#include <WebCore/RefPtrCairo.h>
+#endif
+
namespace WebKit {
using namespace WebCore;
@@ -119,6 +129,10 @@ void DrawingAreaProxyCoordinatedGraphics::paint(BackingStore::PlatformGraphicsCo
void DrawingAreaProxyCoordinatedGraphics::sizeDidChange()
{
+ for (auto& value : m_callbacks)
+ value();
+ m_callbacks.clear();
+
#if USE(DIRECT2D)
m_backingStore = nullptr;
#endif
@@ -133,6 +147,11 @@ void DrawingAreaProxyCoordinatedGraphics::deviceScaleFactorDidChange()
backingStoreStateDidChange(RespondImmediately);
}
+void DrawingAreaProxyCoordinatedGraphics::waitForSizeUpdate(Function<void ()>&& callback)
+{
+ m_callbacks.append(WTFMove(callback));
+}
+
void DrawingAreaProxyCoordinatedGraphics::waitForBackingStoreUpdateOnNextPaint()
{
m_hasReceivedFirstUpdate = true;
@@ -238,6 +257,45 @@ void DrawingAreaProxyCoordinatedGraphics::updateAcceleratedCompositingMode(uint6
updateAcceleratedCompositingMode(layerTreeContext);
}
+#if PLATFORM(WIN)
+void DrawingAreaProxyCoordinatedGraphics::didChangeAcceleratedCompositingMode(bool enabled)
+{
+ m_isInAcceleratedCompositingMode = enabled;
+}
+#endif
+
+#if !PLATFORM(WPE)
+void DrawingAreaProxyCoordinatedGraphics::captureFrame()
+{
+ RefPtr<cairo_surface_t> surface;
+#if PLATFORM(WIN)
+ HWndDC dc;
+ if (m_isInAcceleratedCompositingMode) {
+ dc.setHWnd(m_webPageProxy.viewWidget());
+ surface = adoptRef(cairo_win32_surface_create(dc));
+#else
+ if (isInAcceleratedCompositingMode()) {
+# if PLATFORM(GTK)
+ AcceleratedBackingStore* backingStore = webkitWebViewBaseGetAcceleratedBackingStore(WEBKIT_WEB_VIEW_BASE(m_webPageProxy.viewWidget()));
+ if (!backingStore)
+ return;
+
+ surface = backingStore->surface();
+# else
+ fprintf(stderr, "captureFrame() is not supported in accelerated compositing mode on this platform.\n");
+# endif
+#endif
+ } else if (m_backingStore) {
+ surface = m_backingStore->surface();
+ }
+
+ if (!surface)
+ return;
+
+ m_webPageProxy.inspectorController().didPaint(surface.get());
+}
+#endif
+
#if !PLATFORM(WPE)
void DrawingAreaProxyCoordinatedGraphics::incorporateUpdate(const UpdateInfo& updateInfo)
{
diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h
index d7695088e7cfc4f638f157338754f9f157489749..f99c2b7c2a2b5fa666aa7db96a124717eee0e922 100644
--- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h
+++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h
@@ -30,6 +30,7 @@
#include "BackingStore.h"
#include "DrawingAreaProxy.h"
#include "LayerTreeContext.h"
+#include <wtf/Function.h>
#include <wtf/RunLoop.h>
namespace WebCore {
@@ -49,6 +50,10 @@ public:
bool isInAcceleratedCompositingMode() const { return !m_layerTreeContext.isEmpty(); }
const LayerTreeContext& layerTreeContext() const { return m_layerTreeContext; }
+ void waitForSizeUpdate(Function<void ()>&&);
+#if !PLATFORM(WPE)
+ void captureFrame();
+#endif
private:
// DrawingAreaProxy
@@ -63,6 +68,9 @@ private:
void enterAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext&) override;
void exitAcceleratedCompositingMode(uint64_t backingStoreStateID, const UpdateInfo&) override;
void updateAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext&) override;
+#if PLATFORM(WIN)
+ void didChangeAcceleratedCompositingMode(bool enabled) override;
+#endif
#if !PLATFORM(WPE)
void incorporateUpdate(const UpdateInfo&);
@@ -126,12 +134,18 @@ private:
// For a new Drawing Area don't draw anything until the WebProcess has sent over the first content.
bool m_hasReceivedFirstUpdate { false };
+ Vector<Function<void ()>> m_callbacks;
+
#if !PLATFORM(WPE)
bool m_isBackingStoreDiscardable { true };
std::unique_ptr<BackingStore> m_backingStore;
RunLoop::Timer<DrawingAreaProxyCoordinatedGraphics> m_discardBackingStoreTimer;
#endif
std::unique_ptr<DrawingMonitor> m_drawingMonitor;
+
+#if PLATFORM(WIN)
+ bool m_isInAcceleratedCompositingMode { false };
+#endif
};
} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp
index 29c17beb33ed676c9c444a4d72a601f4cd077f36..a0bb6e0682768e86ca7bec9b1a3f28bb5c309b95 100644
--- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp
+++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp
@@ -42,8 +42,10 @@
#include <WebCore/MIMETypeRegistry.h>
#include <WebCore/ResourceResponseBase.h>
#include <wtf/FileSystem.h>
+#include <wtf/NeverDestroyed.h>
#include <wtf/text/CString.h>
#include <wtf/text/WTFString.h>
+#include <wtf/UUID.h>
namespace WebKit {
using namespace WebCore;
@@ -56,7 +58,10 @@ DownloadProxy::DownloadProxy(DownloadProxyMap& downloadProxyMap, WebsiteDataStor
, m_request(resourceRequest)
, m_originatingPage(makeWeakPtr(originatingPage))
, m_frameInfo(API::FrameInfo::create(FrameInfoData { frameInfoData }, originatingPage))
+ , m_uuid(createCanonicalUUIDString())
{
+ if (auto* instrumentation = m_dataStore->downloadInstrumentation())
+ instrumentation->downloadCreated(m_uuid, m_request, frameInfoData, originatingPage);
}
DownloadProxy::~DownloadProxy() = default;
@@ -75,6 +80,8 @@ void DownloadProxy::cancel(CompletionHandler<void(API::Data*)>&& completionHandl
m_legacyResumeData = createData(resumeData);
completionHandler(m_legacyResumeData.get());
m_downloadProxyMap.downloadFinished(*this);
+ if (auto* instrumentation = m_dataStore->downloadInstrumentation())
+ instrumentation->downloadFinished(m_uuid, "canceled"_s);
});
} else
completionHandler(nullptr);
@@ -147,6 +154,20 @@ void DownloadProxy::didReceiveData(uint64_t bytesWritten, uint64_t totalBytesWri
void DownloadProxy::decideDestinationWithSuggestedFilename(const WebCore::ResourceResponse& response, const String& suggestedFilename, CompletionHandler<void(String, SandboxExtension::Handle, AllowOverwrite)>&& completionHandler)
{
+ if (auto* instrumentation = m_dataStore->downloadInstrumentation())
+ instrumentation->downloadFilenameSuggested(m_uuid, suggestedFilename);
+
+ if (m_dataStore->allowDownloadForAutomation()) {
+ SandboxExtension::Handle sandboxExtensionHandle;
+ String destination;
+ if (*m_dataStore->allowDownloadForAutomation()) {
+ destination = FileSystem::pathByAppendingComponent(m_dataStore->downloadPathForAutomation(), m_uuid);
+ SandboxExtension::createHandle(destination, SandboxExtension::Type::ReadWrite, sandboxExtensionHandle);
+ }
+ completionHandler(destination, WTFMove(sandboxExtensionHandle), AllowOverwrite::Yes);
+ return;
+ }
+
m_client->decideDestinationWithSuggestedFilename(*this, response, ResourceResponseBase::sanitizeSuggestedFilename(suggestedFilename), [completionHandler = WTFMove(completionHandler)] (AllowOverwrite allowOverwrite, String destination) mutable {
SandboxExtension::Handle sandboxExtensionHandle;
if (!destination.isNull())
@@ -164,6 +185,8 @@ void DownloadProxy::didCreateDestination(const String& path)
void DownloadProxy::didFinish()
{
m_client->didFinish(*this);
+ if (auto* instrumentation = m_dataStore->downloadInstrumentation())
+ instrumentation->downloadFinished(m_uuid, String());
// This can cause the DownloadProxy object to be deleted.
m_downloadProxyMap.downloadFinished(*this);
@@ -174,6 +197,8 @@ void DownloadProxy::didFail(const ResourceError& error, const IPC::DataReference
m_legacyResumeData = createData(resumeData);
m_client->didFail(*this, error);
+ if (auto* instrumentation = m_dataStore->downloadInstrumentation())
+ instrumentation->downloadFinished(m_uuid, error.localizedDescription());
// This can cause the DownloadProxy object to be deleted.
m_downloadProxyMap.downloadFinished(*this);
diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h
index 0718e893ab255bb3a35df7eda9c3292c1f718a4c..6f549c5a5eb744b4c48f5dca6b4b80474f3586af 100644
--- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h
+++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h
@@ -134,6 +134,7 @@ private:
Vector<URL> m_redirectChain;
bool m_wasUserInitiated { true };
Ref<API::FrameInfo> m_frameInfo;
+ String m_uuid;
};
} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.h b/Source/WebKit/UIProcess/DrawingAreaProxy.h
index 59cdfdafab1d85ea3a5aecb3cd2293e6dfb1eb8d..2c9d8122919bed0b6d7e6f600e5b0c0f9732d1ff 100644
--- a/Source/WebKit/UIProcess/DrawingAreaProxy.h
+++ b/Source/WebKit/UIProcess/DrawingAreaProxy.h
@@ -75,6 +75,7 @@ public:
const WebCore::IntSize& size() const { return m_size; }
bool setSize(const WebCore::IntSize&, const WebCore::IntSize& scrollOffset = { });
+ void waitForSizeUpdate(Function<void ()>&&);
#if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER)
// The timeout we use when waiting for a DidUpdateGeometry message.
@@ -160,6 +161,9 @@ private:
virtual void update(uint64_t /* backingStoreStateID */, const UpdateInfo&) { }
virtual void didUpdateBackingStoreState(uint64_t /* backingStoreStateID */, const UpdateInfo&, const LayerTreeContext&) { }
virtual void exitAcceleratedCompositingMode(uint64_t /* backingStoreStateID */, const UpdateInfo&) { }
+#endif
+#if PLATFORM(WIN)
+ virtual void didChangeAcceleratedCompositingMode(bool) { }
#endif
bool m_startedReceivingMessages { false };
};
diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in b/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in
index b0722e7da81e56530deb570b82ed7cfece970362..05ec3e3ea97ba49135a27d7f9b91f14c507d9318 100644
--- a/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in
+++ b/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in
@@ -36,4 +36,7 @@ messages -> DrawingAreaProxy NotRefCounted {
DidUpdateBackingStoreState(uint64_t backingStoreStateID, WebKit::UpdateInfo updateInfo, WebKit::LayerTreeContext context)
ExitAcceleratedCompositingMode(uint64_t backingStoreStateID, WebKit::UpdateInfo updateInfo)
#endif
+#if PLATFORM(WIN)
+ DidChangeAcceleratedCompositingMode(bool enabled)
+#endif
}
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..31abb688f09ce933d4eb33f09873ac38d788f1b2
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorScreencastAgent.h"
+
+#include "GenericCallback.h"
+#include "PageClient.h"
+#include "ScreencastEncoder.h"
+#include "WebPageInspectorController.h"
+#include "WebPageProxy.h"
+#include "WebsiteDataStore.h"
+#include <JavaScriptCore/InspectorFrontendDispatchers.h>
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <WebCore/NotImplemented.h>
+#include <wtf/RunLoop.h>
+#include <wtf/UUID.h>
+
+#if USE(CAIRO)
+#include "DrawingAreaProxyCoordinatedGraphics.h"
+#include "DrawingAreaProxy.h"
+#endif
+
+namespace WebKit {
+
+using namespace Inspector;
+
+InspectorScreencastAgent::InspectorScreencastAgent(BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page)
+ : InspectorAgentBase("Screencast"_s)
+ , m_backendDispatcher(ScreencastBackendDispatcher::create(backendDispatcher, this))
+ , m_page(page)
+{
+}
+
+InspectorScreencastAgent::~InspectorScreencastAgent()
+{
+}
+
+void InspectorScreencastAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
+{
+}
+
+void InspectorScreencastAgent::willDestroyFrontendAndBackend(DisconnectReason)
+{
+ if (!m_encoder)
+ return;
+
+ // The agent may be destroyed when the callback is invoked.
+ m_encoder->finish([sessionID = m_page.websiteDataStore().sessionID(), screencastID = WTFMove(m_currentScreencastID)] {
+ if (WebPageInspectorController::observer())
+ WebPageInspectorController::observer()->didFinishScreencast(sessionID, screencastID);
+ });
+
+ m_encoder = nullptr;
+}
+
+#if USE(CAIRO)
+void InspectorScreencastAgent::didPaint(cairo_surface_t* surface)
+{
+ if (m_encoder)
+ m_encoder->encodeFrame(surface, m_page.drawingArea()->size());
+}
+#endif
+
+Inspector::Protocol::ErrorStringOr<String /* screencastID */> InspectorScreencastAgent::start(const String& file, int width, int height, Optional<double>&& scale)
+{
+ if (m_encoder)
+ return makeUnexpected("Already recording"_s);
+
+ if (width < 10 || width > 10000 || height < 10 || height > 10000)
+ return makeUnexpected("Invalid size"_s);
+
+ if (scale && (*scale <= 0 || *scale > 1))
+ return makeUnexpected("Unsupported scale"_s);
+
+ String errorString;
+ m_encoder = ScreencastEncoder::create(errorString, file, WebCore::IntSize(width, height), WTFMove(scale));
+ if (!m_encoder)
+ return makeUnexpected(errorString);
+
+ m_currentScreencastID = createCanonicalUUIDString();
+
+#if PLATFORM(MAC)
+ m_encoder->setOffsetTop(m_page.pageClient().browserToolbarHeight());
+#endif
+#if !PLATFORM(WPE)
+ scheduleFrameEncoding();
+#endif
+ // Force at least one frame on WPE.
+ m_page.forceRepaint(VoidCallback::create([] (CallbackBase::Error) { }));
+
+ return { { m_currentScreencastID } };
+}
+
+void InspectorScreencastAgent::stop(Ref<StopCallback>&& callback)
+{
+ if (!m_encoder) {
+ callback->sendFailure("Not recording"_s);
+ return;
+ }
+
+ // The agent may be destroyed when the callback is invoked.
+ m_encoder->finish([sessionID = m_page.websiteDataStore().sessionID(), screencastID = WTFMove(m_currentScreencastID), callback = WTFMove(callback)] {
+ if (WebPageInspectorController::observer())
+ WebPageInspectorController::observer()->didFinishScreencast(sessionID, screencastID);
+ callback->sendSuccess();
+ });
+ m_encoder = nullptr;
+}
+
+#if !PLATFORM(WPE)
+void InspectorScreencastAgent::scheduleFrameEncoding()
+{
+ if (!m_encoder)
+ return;
+
+ RunLoop::main().dispatchAfter(Seconds(1.0 / ScreencastEncoder::fps), [agent = makeWeakPtr(this)]() mutable {
+ if (!agent)
+ return;
+
+ agent->encodeFrame();
+ agent->scheduleFrameEncoding();
+ });
+}
+#endif
+
+#if PLATFORM(MAC)
+void InspectorScreencastAgent::encodeFrame()
+{
+ if (m_encoder)
+ m_encoder->encodeFrame(m_page.pageClient().takeSnapshotForAutomation());
+}
+#endif
+
+#if USE(CAIRO) && !PLATFORM(WPE)
+void InspectorScreencastAgent::encodeFrame()
+{
+ if (!m_encoder)
+ return;
+
+ if (auto* drawingArea = m_page.drawingArea())
+ static_cast<DrawingAreaProxyCoordinatedGraphics*>(drawingArea)->captureFrame();
+}
+#endif
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..0d4a837cbb0bbba71e32ed083a4c4cfe9b5e4a27
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/WeakPtr.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+class ScreencastFrontendDispatcher;
+}
+
+namespace WebKit {
+
+class ScreencastEncoder;
+class WebPageProxy;
+
+class InspectorScreencastAgent : public Inspector::InspectorAgentBase, public Inspector::ScreencastBackendDispatcherHandler, public CanMakeWeakPtr<InspectorScreencastAgent> {
+ WTF_MAKE_NONCOPYABLE(InspectorScreencastAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorScreencastAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page);
+ ~InspectorScreencastAgent() override;
+
+ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+#if USE(CAIRO)
+ void didPaint(cairo_surface_t*);
+#endif
+
+ Inspector::Protocol::ErrorStringOr<String /* screencastID */> start(const String& file, int width, int height, Optional<double>&& scale) override;
+ void stop(Ref<StopCallback>&&) override;
+
+
+private:
+#if !PLATFORM(WPE)
+ void scheduleFrameEncoding();
+ void encodeFrame();
+#endif
+
+ Ref<Inspector::ScreencastBackendDispatcher> m_backendDispatcher;
+ WebPageProxy& m_page;
+ RefPtr<ScreencastEncoder> m_encoder;
+ String m_currentScreencastID;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bc0bca0fcd5fe15d6ace9acb6bd21045633dc0de
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2010, The WebM Project authors. All rights reserved.
+ * Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScreencastEncoder.h"
+
+#include "WebMFileWriter.h"
+#include <algorithm>
+#include <libyuv.h>
+#include <vpx/vp8.h>
+#include <vpx/vp8cx.h>
+#include <vpx/vpx_encoder.h>
+#include <wtf/RunLoop.h>
+#include <wtf/UniqueArray.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/text/StringConcatenateNumbers.h>
+
+#if USE(CAIRO)
+#include <WebCore/RefPtrCairo.h>
+#endif
+
+using namespace WebCore;
+
+namespace WebKit {
+
+namespace {
+
+// Number of timebase unints per one frame.
+constexpr int timeScale = 1000;
+
+// Defines the dimension of a macro block. This is used to compute the active
+// map for the encoder.
+const int kMacroBlockSize = 16;
+
+void createImage(unsigned int width, unsigned int height,
+ std::unique_ptr<vpx_image_t>& out_image,
+ std::unique_ptr<uint8_t[]>& out_image_buffer) {
+ std::unique_ptr<vpx_image_t> image(new vpx_image_t());
+ memset(image.get(), 0, sizeof(vpx_image_t));
+
+ // libvpx seems to require both to be assigned.
+ image->d_w = width;
+ image->w = width;
+ image->d_h = height;
+ image->h = height;
+
+ // I420
+ image->fmt = VPX_IMG_FMT_YV12;
+ image->x_chroma_shift = 1;
+ image->y_chroma_shift = 1;
+
+ // libyuv's fast-path requires 16-byte aligned pointers and strides, so pad
+ // the Y, U and V planes' strides to multiples of 16 bytes.
+ const int y_stride = ((image->w - 1) & ~15) + 16;
+ const int uv_unaligned_stride = y_stride >> image->x_chroma_shift;
+ const int uv_stride = ((uv_unaligned_stride - 1) & ~15) + 16;
+
+ // libvpx accesses the source image in macro blocks, and will over-read
+ // if the image is not padded out to the next macroblock: crbug.com/119633.
+ // Pad the Y, U and V planes' height out to compensate.
+ // Assuming macroblocks are 16x16, aligning the planes' strides above also
+ // macroblock aligned them.
+ static_assert(kMacroBlockSize == 16, "macroblock_size_not_16");
+ const int y_rows = ((image->h - 1) & ~(kMacroBlockSize-1)) + kMacroBlockSize;
+ const int uv_rows = y_rows >> image->y_chroma_shift;
+
+ // Allocate a YUV buffer large enough for the aligned data & padding.
+ const int buffer_size = y_stride * y_rows + 2*uv_stride * uv_rows;
+ std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[buffer_size]);
+
+ // Reset image value to 128 so we just need to fill in the y plane.
+ memset(image_buffer.get(), 128, buffer_size);
+
+ // Fill in the information for |image_|.
+ unsigned char* uchar_buffer =
+ reinterpret_cast<unsigned char*>(image_buffer.get());
+ image->planes[0] = uchar_buffer;
+ image->planes[1] = image->planes[0] + y_stride * y_rows;
+ image->planes[2] = image->planes[1] + uv_stride * uv_rows;
+ image->stride[0] = y_stride;
+ image->stride[1] = uv_stride;
+ image->stride[2] = uv_stride;
+
+ out_image = std::move(image);
+ out_image_buffer = std::move(image_buffer);
+}
+
+} // namespace
+
+class ScreencastEncoder::VPXFrame {
+ WTF_MAKE_NONCOPYABLE(VPXFrame);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+#if USE(CAIRO)
+ explicit VPXFrame(RefPtr<cairo_surface_t>&& surface)
+ : m_surface(WTFMove(surface))
+ { }
+#elif PLATFORM(MAC)
+ VPXFrame(RetainPtr<CGImageRef> windowImage, Optional<double> scale, int offsetTop)
+ : m_windowImage(WTFMove(windowImage))
+ , m_scale(scale)
+ , m_offsetTop(offsetTop)
+ { }
+#endif
+
+ void setDuration(Seconds duration) { m_duration = duration; }
+ Seconds duration() const { return m_duration; }
+
+ void convertToVpxImage(vpx_image_t* image)
+ {
+#if USE(CAIRO)
+ // Convert the updated region to YUV ready for encoding.
+ const uint8_t* argb_data = cairo_image_surface_get_data(m_surface.get());
+ int argb_stride = cairo_image_surface_get_stride(m_surface.get());
+#elif PLATFORM(MAC)
+ int argb_stride = image->w * 4;
+ UniqueArray<uint8_t> buffer = makeUniqueArray<uint8_t>(argb_stride * image->h);
+ uint8_t* argb_data = buffer.get();
+ ScreencastEncoder::imageToARGB(m_windowImage.get(), argb_data, image->w, image->h, m_scale, m_offsetTop);
+#endif
+ const int y_stride = image->stride[0];
+ ASSERT(image->stride[1] == image->stride[2]);
+ const int uv_stride = image->stride[1];
+ uint8_t* y_data = image->planes[0];
+ uint8_t* u_data = image->planes[1];
+ uint8_t* v_data = image->planes[2];
+
+ // TODO: redraw only damaged regions?
+ libyuv::ARGBToI420(argb_data, argb_stride,
+ y_data, y_stride,
+ u_data, uv_stride,
+ v_data, uv_stride,
+ image->w, image->h);
+ }
+
+private:
+#if USE(CAIRO)
+ RefPtr<cairo_surface_t> m_surface;
+#elif PLATFORM(MAC)
+ RetainPtr<CGImageRef> m_windowImage;
+ Optional<double> m_scale;
+ int m_offsetTop { 0 };
+#endif
+ Seconds m_duration;
+};
+
+
+class ScreencastEncoder::VPXCodec {
+public:
+ VPXCodec(vpx_codec_ctx_t codec, vpx_codec_enc_cfg_t cfg, FILE* file)
+ : m_encoderQueue(WorkQueue::create("Screencast encoder"))
+ , m_codec(codec)
+ , m_cfg(cfg)
+ , m_file(file)
+ , m_writer(new WebMFileWriter(file, &m_cfg))
+ {
+ createImage(cfg.g_w, cfg.g_h, m_image, m_imageBuffer);
+ }
+
+ void encodeFrameAsync(std::unique_ptr<VPXFrame>&& frame)
+ {
+ m_encoderQueue->dispatch([this, frame = WTFMove(frame)] {
+ frame->convertToVpxImage(m_image.get());
+ double frameCount = frame->duration().seconds() * fps;
+ // For long duration repeat frame at 1 fps to ensure last frame duration is short enough.
+ // TODO: figure out why simply passing duration doesn't work well.
+ for (;frameCount > 1.5; frameCount -= 1) {
+ encodeFrame(m_image.get(), timeScale);
+ }
+ encodeFrame(m_image.get(), std::max<int>(1, frameCount * timeScale));
+ });
+ }
+
+ void finishAsync(Function<void()>&& callback)
+ {
+ m_encoderQueue->dispatch([this, callback = WTFMove(callback)] {
+ finish();
+ callback();
+ });
+ }
+
+private:
+ bool encodeFrame(vpx_image_t *img, int duration)
+ {
+ vpx_codec_iter_t iter = nullptr;
+ const vpx_codec_cx_pkt_t *pkt = nullptr;
+ int flags = 0;
+ const vpx_codec_err_t res = vpx_codec_encode(&m_codec, img, m_pts, duration, flags, VPX_DL_REALTIME);
+ if (res != VPX_CODEC_OK) {
+ fprintf(stderr, "Failed to encode frame: %s\n", vpx_codec_error(&m_codec));
+ return false;
+ }
+
+ bool gotPkts = false;
+ while ((pkt = vpx_codec_get_cx_data(&m_codec, &iter)) != nullptr) {
+ gotPkts = true;
+
+ if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
+ if (!m_writer->writeFrame(pkt)) {
+ fprintf(stderr, "Failed to write compressed frame\n");
+ return false;
+ }
+ bool keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
+ ++m_frameCount;
+ fprintf(stderr, " #%03d %spts=%" PRId64 " sz=%zd\n", m_frameCount, keyframe ? "[K] " : "", pkt->data.frame.pts, pkt->data.frame.sz);
+ m_pts += pkt->data.frame.duration;
+ }
+ }
+
+ return gotPkts;
+ }
+
+ void finish()
+ {
+ // Flush encoder.
+ while (encodeFrame(nullptr, 1))
+ ++m_frameCount;
+
+ m_writer->finish();
+ fclose(m_file);
+ fprintf(stderr, "ScreencastEncoder::finish %d frames\n", m_frameCount);
+ }
+
+ Ref<WorkQueue> m_encoderQueue;
+ vpx_codec_ctx_t m_codec;
+ vpx_codec_enc_cfg_t m_cfg;
+ FILE* m_file { nullptr };
+ std::unique_ptr<WebMFileWriter> m_writer;
+ int m_frameCount { 0 };
+ int64_t m_pts { 0 };
+ std::unique_ptr<uint8_t[]> m_imageBuffer;
+ std::unique_ptr<vpx_image_t> m_image;
+};
+
+ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec>&& vpxCodec, IntSize size, Optional<double> scale)
+ : m_vpxCodec(WTFMove(vpxCodec))
+ , m_size(size)
+ , m_scale(scale)
+{
+ ASSERT(!size.isZero());
+}
+
+ScreencastEncoder::~ScreencastEncoder()
+{
+}
+
+RefPtr<ScreencastEncoder> ScreencastEncoder::create(String& errorString, const String& filePath, IntSize size, Optional<double> scale)
+{
+ vpx_codec_iface_t* codec_interface = vpx_codec_vp8_cx();
+ if (!codec_interface) {
+ errorString = "Codec not found.";
+ return nullptr;
+ }
+
+ if (size.width() <= 0 || size.height() <= 0 || (size.width() % 2) != 0 || (size.height() % 2) != 0) {
+ errorString = makeString("Invalid frame size: "_s, size.width(), "x"_s, size.height());
+ return nullptr;
+ }
+
+ vpx_codec_enc_cfg_t cfg;
+ memset(&cfg, 0, sizeof(cfg));
+ vpx_codec_err_t error = vpx_codec_enc_config_default(codec_interface, &cfg, 0);
+ if (error) {
+ errorString = makeString("Failed to get default codec config: "_s, vpx_codec_err_to_string(error));
+ return nullptr;
+ }
+
+ cfg.g_w = size.width();
+ cfg.g_h = size.height();
+ cfg.g_timebase.num = 1;
+ cfg.g_timebase.den = fps * timeScale;
+ cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
+
+ vpx_codec_ctx_t codec;
+ if (vpx_codec_enc_init(&codec, codec_interface, &cfg, 0)) {
+ errorString = makeString("Failed to initialize encoder: "_s, vpx_codec_error(&codec));
+ return nullptr;
+ }
+
+ FILE* file = fopen(filePath.utf8().data(), "wb");
+ if (!file) {
+ errorString = makeString("Failed to open file '", filePath, "' for writing: ", strerror(errno));
+ return nullptr;
+ }
+
+ std::unique_ptr<VPXCodec> vpxCodec(new VPXCodec(codec, cfg, file));
+ fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface));
+ return adoptRef(new ScreencastEncoder(WTFMove(vpxCodec), size, scale));
+}
+
+void ScreencastEncoder::flushLastFrame()
+{
+ MonotonicTime now = MonotonicTime::now();
+ if (m_lastFrameTimestamp) {
+ // If previous frame encoding failed for some rason leave the timestampt intact.
+ if (!m_lastFrame)
+ return;
+
+ Seconds seconds = now - m_lastFrameTimestamp;
+ m_lastFrame->setDuration(seconds);
+ m_vpxCodec->encodeFrameAsync(WTFMove(m_lastFrame));
+ }
+ m_lastFrameTimestamp = now;
+}
+
+#if USE(CAIRO)
+void ScreencastEncoder::encodeFrame(cairo_surface_t* drawingAreaSurface, IntSize size)
+{
+ fprintf(stderr, "ScreencastEncoder::encodeFrame\n");
+ flushLastFrame();
+ // Note that in WPE drawing area size is updated asynchronously and may differ from acutal
+ // size of the surface.
+ if (size.isZero()) {
+ fprintf(stderr, "Cairo surface size is 0\n");
+ return;
+ }
+
+ // TODO: adjust device scale factor?
+ RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m_size.width(), m_size.height()));
+ {
+ RefPtr<cairo_t> cr = adoptRef(cairo_create(surface.get()));
+
+ // TODO: compare to libyuv scale functions?
+ cairo_matrix_t transform;
+ if (m_scale) {
+ cairo_matrix_init_scale(&transform, *m_scale, *m_scale);
+ cairo_transform(cr.get(), &transform);
+ } else if (size.width() > m_size.width() || size.height() > m_size.height()) {
+ // If no scale is specified shrink to fit the frame.
+ double scale = std::min(static_cast<double>(m_size.width()) / size.width(),
+ static_cast<double>(m_size.height()) / size.height());
+ cairo_matrix_init_scale(&transform, scale, scale);
+ cairo_transform(cr.get(), &transform);
+ }
+
+ // Record top left part of the drawing area that fits into the frame.
+ cairo_set_source_surface(cr.get(), drawingAreaSurface, 0, 0);
+ cairo_paint(cr.get());
+ }
+ cairo_surface_flush(surface.get());
+
+ m_lastFrame = makeUnique<VPXFrame>(WTFMove(surface));
+}
+#elif PLATFORM(MAC)
+void ScreencastEncoder::encodeFrame(RetainPtr<CGImageRef>&& windowImage)
+{
+ fprintf(stderr, "ScreencastEncoder::encodeFrame\n");
+ flushLastFrame();
+
+ m_lastFrame = makeUnique<VPXFrame>(WTFMove(windowImage), m_scale, m_offsetTop);
+}
+#endif
+
+void ScreencastEncoder::finish(Function<void()>&& callback)
+{
+ if (!m_vpxCodec) {
+ callback();
+ return;
+ }
+
+ flushLastFrame();
+ m_vpxCodec->finishAsync([protectRef = makeRef(*this), callback = WTFMove(callback)] () mutable {
+ RunLoop::main().dispatch([callback = WTFMove(callback)] {
+ callback();
+ });
+ });
+}
+
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..c9ff0442e072d54c089540d291b7963688b6474b
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <WebCore/IntSize.h>
+#include <wtf/Forward.h>
+#include <wtf/MonotonicTime.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/WeakPtr.h>
+
+#if USE(CAIRO)
+#include <cairo.h>
+#endif
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class ScreencastEncoder : public ThreadSafeRefCounted<ScreencastEncoder> {
+ WTF_MAKE_NONCOPYABLE(ScreencastEncoder);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ static constexpr int fps = 25;
+
+ static RefPtr<ScreencastEncoder> create(String& errorString, const String& filePath, WebCore::IntSize, Optional<double> scale);
+
+ class VPXCodec;
+ ScreencastEncoder(std::unique_ptr<VPXCodec>&&, WebCore::IntSize, Optional<double> scale);
+ ~ScreencastEncoder();
+
+#if USE(CAIRO)
+ void encodeFrame(cairo_surface_t*, WebCore::IntSize);
+#elif PLATFORM(MAC)
+ void encodeFrame(RetainPtr<CGImageRef>&&);
+ void setOffsetTop(int offset) { m_offsetTop = offset;}
+#endif
+
+ void finish(Function<void()>&& callback);
+
+private:
+ void flushLastFrame();
+#if PLATFORM(MAC)
+ static void imageToARGB(CGImageRef, uint8_t* rgba_data, int width, int height, Optional<double> scale, int offsetTop);
+#endif
+
+ std::unique_ptr<VPXCodec> m_vpxCodec;
+ const WebCore::IntSize m_size;
+ Optional<double> m_scale;
+ MonotonicTime m_lastFrameTimestamp;
+ class VPXFrame;
+ std::unique_ptr<VPXFrame> m_lastFrame;
+#if PLATFORM(MAC)
+ int m_offsetTop { 0 };
+#endif
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.cpp b/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9b269b356e206f0252245a1497adb0d05128c9b4
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebMFileWriter.h"
+
+#include <string>
+#include "mkvmuxer/mkvmuxerutil.h"
+
+namespace WebKit {
+
+WebMFileWriter::WebMFileWriter(FILE* file, vpx_codec_enc_cfg_t* cfg)
+ : m_cfg(cfg)
+ , m_writer(new mkvmuxer::MkvWriter(file))
+ , m_segment(new mkvmuxer::Segment()) {
+ m_segment->Init(m_writer.get());
+ m_segment->set_mode(mkvmuxer::Segment::kFile);
+ m_segment->OutputCues(true);
+
+ mkvmuxer::SegmentInfo* info = m_segment->GetSegmentInfo();
+ std::string version = "Playwright " + std::string(vpx_codec_version_str());
+ info->set_writing_app(version.c_str());
+
+ // Add vp8 track.
+ m_videoTrackId = m_segment->AddVideoTrack(
+ static_cast<int>(m_cfg->g_w), static_cast<int>(m_cfg->g_h), 0);
+ if (!m_videoTrackId) {
+ fprintf(stderr, "Failed to add video track\n");
+ }
+}
+
+WebMFileWriter::~WebMFileWriter() {}
+
+bool WebMFileWriter::writeFrame(const vpx_codec_cx_pkt_t* pkt) {
+ int64_t pts_ns = pkt->data.frame.pts * 1000000000ll * m_cfg->g_timebase.num /
+ m_cfg->g_timebase.den;
+ return m_segment->AddFrame(static_cast<uint8_t*>(pkt->data.frame.buf),
+ pkt->data.frame.sz, m_videoTrackId, pts_ns,
+ pkt->data.frame.flags & VPX_FRAME_IS_KEY);
+}
+
+void WebMFileWriter::finish() {
+ m_segment->Finalize();
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.h b/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2ce910f3fd7f587add552275b7e7176cf8b2723
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <memory>
+#include <stdio.h>
+#include <stdlib.h>
+#include "vpx/vpx_encoder.h"
+
+#include "mkvmuxer/mkvmuxer.h"
+#include "mkvmuxer/mkvwriter.h"
+
+namespace WebKit {
+
+class WebMFileWriter {
+public:
+ WebMFileWriter(FILE*, vpx_codec_enc_cfg_t* cfg);
+ ~WebMFileWriter();
+
+ bool writeFrame(const vpx_codec_cx_pkt_t* pkt);
+ void finish();
+
+private:
+ vpx_codec_enc_cfg_t* m_cfg = nullptr;
+ std::unique_ptr<mkvmuxer::MkvWriter> m_writer;
+ std::unique_ptr<mkvmuxer::Segment> m_segment;
+ uint64_t m_videoTrackId = 0;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp
index 6928ca2fbfb6939062e3cd14bb7ba6f2fdc87f5f..621b99e233ed5cf504fedbd3ca3209c03bcd611f 100644
--- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp
+++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp
@@ -27,11 +27,10 @@
#include "InspectorTargetProxy.h"
#include "ProvisionalPageProxy.h"
-#include "WebFrameProxy.h"
+#include "WebPageInspectorController.h"
#include "WebPageInspectorTarget.h"
#include "WebPageMessages.h"
#include "WebPageProxy.h"
-#include "WebProcessProxy.h"
namespace WebKit {
@@ -39,18 +38,17 @@ using namespace Inspector;
std::unique_ptr<InspectorTargetProxy> InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type)
{
- return makeUnique<InspectorTargetProxy>(page, targetId, type);
+ return makeUnique<InspectorTargetProxy>(page, nullptr, targetId, type);
}
-std::unique_ptr<InspectorTargetProxy> InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId, Inspector::InspectorTargetType type)
+std::unique_ptr<InspectorTargetProxy> InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId)
{
- auto target = InspectorTargetProxy::create(provisionalPage.page(), targetId, type);
- target->m_provisionalPage = makeWeakPtr(provisionalPage);
- return target;
+ return makeUnique<InspectorTargetProxy>(provisionalPage.page(), &provisionalPage, targetId, Inspector::InspectorTargetType::Page);
}
-InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type)
+InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, ProvisionalPageProxy* provisionalPage, const String& targetId, Inspector::InspectorTargetType type)
: m_page(page)
+ , m_provisionalPage(makeWeakPtr(provisionalPage))
, m_identifier(targetId)
, m_type(type)
{
@@ -97,6 +95,31 @@ void InspectorTargetProxy::didCommitProvisionalTarget()
m_provisionalPage = nullptr;
}
+void InspectorTargetProxy::willResume()
+{
+ if (m_page.hasRunningProcess())
+ m_page.send(Messages::WebPage::ResumeInspectorIfPausedInNewWindow());
+}
+
+void InspectorTargetProxy::activate(String& error)
+{
+ if (m_type != Inspector::InspectorTargetType::Page)
+ return InspectorTarget::activate(error);
+
+ platformActivate(error);
+}
+
+void InspectorTargetProxy::close(String& error, bool runBeforeUnload)
+{
+ if (m_type != Inspector::InspectorTargetType::Page)
+ return InspectorTarget::close(error, runBeforeUnload);
+
+ if (runBeforeUnload)
+ m_page.tryClose();
+ else
+ m_page.closePage();
+}
+
bool InspectorTargetProxy::isProvisional() const
{
return !!m_provisionalPage;
diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h
index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..79f3ff84327dc075ec96983e04db4b10343b7fae 100644
--- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h
+++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h
@@ -37,13 +37,13 @@ class WebPageProxy;
// NOTE: This UIProcess side InspectorTarget doesn't care about the frontend channel, since
// any target -> frontend messages will be routed to the WebPageProxy with a targetId.
-class InspectorTargetProxy final : public Inspector::InspectorTarget {
+class InspectorTargetProxy : public Inspector::InspectorTarget {
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(InspectorTargetProxy);
public:
static std::unique_ptr<InspectorTargetProxy> create(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
- static std::unique_ptr<InspectorTargetProxy> create(ProvisionalPageProxy&, const String& targetId, Inspector::InspectorTargetType);
- InspectorTargetProxy(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
+ static std::unique_ptr<InspectorTargetProxy> create(ProvisionalPageProxy&, const String& targetId);
+ InspectorTargetProxy(WebPageProxy&, ProvisionalPageProxy*, const String& targetId, Inspector::InspectorTargetType);
~InspectorTargetProxy() = default;
Inspector::InspectorTargetType type() const final { return m_type; }
@@ -55,12 +55,17 @@ public:
void connect(Inspector::FrontendChannel::ConnectionType) override;
void disconnect() override;
void sendMessageToTargetBackend(const String&) override;
+ void activate(String& error) override;
+ void close(String& error, bool runBeforeUnload) override;
private:
+ void willResume() override;
+ void platformActivate(String& error) const;
+
WebPageProxy& m_page;
+ WeakPtr<ProvisionalPageProxy> m_provisionalPage;
String m_identifier;
Inspector::InspectorTargetType m_type;
- WeakPtr<ProvisionalPageProxy> m_provisionalPage;
};
} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
index 1861cff806131196ea49b4f8aca6665beebbf6e8..901c0fdd6bc1bd62b078a07cc9dd3a4c46c2bfd8 100644
--- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
+++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
@@ -26,12 +26,20 @@
#include "config.h"
#include "WebPageInspectorController.h"
+#include "APINavigation.h"
#include "InspectorBrowserAgent.h"
+#include "InspectorDialogAgent.h"
+#include "InspectorScreencastAgent.h"
#include "ProvisionalPageProxy.h"
#include "WebFrameProxy.h"
#include "WebPageInspectorAgentBase.h"
+#include "WebPageInspectorEmulationAgent.h"
+#include "WebPageInspectorInputAgent.h"
#include "WebPageInspectorTarget.h"
#include "WebPageProxy.h"
+#include "WebPreferences.h"
+#include <WebCore/ResourceError.h>
+#include <WebCore/WindowFeatures.h>
#include <JavaScriptCore/InspectorAgentBase.h>
#include <JavaScriptCore/InspectorBackendDispatcher.h>
#include <JavaScriptCore/InspectorBackendDispatchers.h>
@@ -48,27 +56,108 @@ static String getTargetID(const ProvisionalPageProxy& provisionalPage)
return WebPageInspectorTarget::toTargetID(provisionalPage.webPageID());
}
+WebPageInspectorControllerObserver* WebPageInspectorController::s_observer = nullptr;
+
+void WebPageInspectorController::setObserver(WebPageInspectorControllerObserver* observer)
+{
+ s_observer = observer;
+}
+
+WebPageInspectorControllerObserver* WebPageInspectorController::observer() {
+ return s_observer;
+}
+
WebPageInspectorController::WebPageInspectorController(WebPageProxy& page)
: m_frontendRouter(FrontendRouter::create())
, m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
, m_page(page)
{
- auto targetAgent = makeUnique<InspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
- m_targetAgent = targetAgent.get();
- m_agents.append(WTFMove(targetAgent));
}
void WebPageInspectorController::init()
{
+ auto targetAgent = makeUnique<InspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
+ m_targetAgent = targetAgent.get();
+ m_agents.append(WTFMove(targetAgent));
+ auto emulationAgent = makeUnique<WebPageInspectorEmulationAgent>(m_backendDispatcher.get(), m_page);
+ m_emulationAgent = emulationAgent.get();
+ m_agents.append(WTFMove(emulationAgent));
+ auto inputAgent = makeUnique<WebPageInspectorInputAgent>(m_backendDispatcher.get(), m_page);
+ m_inputAgent = inputAgent.get();
+ m_agents.append(WTFMove(inputAgent));
+ m_agents.append(makeUnique<InspectorDialogAgent>(m_backendDispatcher.get(), m_frontendRouter.get(), m_page));
+ auto screencastAgent = makeUnique<InspectorScreencastAgent>(m_backendDispatcher.get(), m_frontendRouter.get(), m_page);
+ m_screecastAgent = screencastAgent.get();
+ m_agents.append(WTFMove(screencastAgent));
+ 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();
+}
+
+void WebPageInspectorController::willCreateNewPage(const WebCore::WindowFeatures& features, const URL& url)
+{
+ if (s_observer)
+ s_observer->willCreateNewPage(m_page, features, url);
+}
+
+void WebPageInspectorController::didShowPage()
+{
+ if (m_frontendRouter->hasFrontends())
+ m_emulationAgent->didShowPage();
+}
+
+void WebPageInspectorController::didProcessAllPendingKeyboardEvents()
+{
+ if (m_frontendRouter->hasFrontends())
+ m_inputAgent->didProcessAllPendingKeyboardEvents();
+}
+
+void WebPageInspectorController::didProcessAllPendingMouseEvents()
+{
+ if (m_frontendRouter->hasFrontends())
+ m_inputAgent->didProcessAllPendingMouseEvents();
}
bool WebPageInspectorController::hasLocalFrontend() const
@@ -82,6 +171,17 @@ void WebPageInspectorController::connectFrontend(Inspector::FrontendChannel& fro
bool connectingFirstFrontend = !m_frontendRouter->hasFrontends();
+ // HACK: forcefully disconnect remote connections to show local inspector starting with initial
+ // agents' state.
+ if (frontendChannel.connectionType() == Inspector::FrontendChannel::ConnectionType::Local &&
+ !connectingFirstFrontend && !m_frontendRouter->hasLocalFrontend()) {
+ disconnectAllFrontends();
+ connectingFirstFrontend = true;
+ }
+
+ if (connectingFirstFrontend)
+ adjustPageSettings();
+
m_frontendRouter->connectFrontend(frontendChannel);
if (connectingFirstFrontend)
@@ -100,8 +200,10 @@ void WebPageInspectorController::disconnectFrontend(FrontendChannel& frontendCha
m_frontendRouter->disconnectFrontend(frontendChannel);
bool disconnectingLastFrontend = !m_frontendRouter->hasFrontends();
- if (disconnectingLastFrontend)
+ if (disconnectingLastFrontend) {
m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectorDestroyed);
+ m_pendingNavigations.clear();
+ }
m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
@@ -124,6 +226,8 @@ void WebPageInspectorController::disconnectAllFrontends()
// Disconnect any remaining remote frontends.
m_frontendRouter->disconnectAllFrontends();
+ m_pendingNavigations.clear();
+
m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
#if ENABLE(REMOTE_INSPECTOR)
@@ -150,6 +254,66 @@ void WebPageInspectorController::setIndicating(bool indicating)
}
#endif
+#if USE(CAIRO)
+void WebPageInspectorController::didPaint(cairo_surface_t* surface)
+{
+ if (!m_frontendRouter->hasFrontends())
+ return;
+
+ m_screecastAgent->didPaint(surface);
+}
+#endif
+
+
+void WebPageInspectorController::navigate(WebCore::ResourceRequest&& request, WebFrameProxy* frame, NavigationHandler&& completionHandler)
+{
+ auto navigation = m_page.loadRequestForInspector(WTFMove(request), frame);
+ if (!navigation) {
+ completionHandler("Failed to navigate"_s, 0);
+ return;
+ }
+
+ m_pendingNavigations.set(navigation->navigationID(), WTFMove(completionHandler));
+}
+
+void WebPageInspectorController::didReceivePolicyDecision(WebCore::PolicyAction action, uint64_t navigationID)
+{
+ if (!m_frontendRouter->hasFrontends())
+ return;
+
+ if (!navigationID)
+ return;
+
+ auto completionHandler = m_pendingNavigations.take(navigationID);
+ if (!completionHandler)
+ return;
+
+ if (action == WebCore::PolicyAction::Ignore)
+ completionHandler("Navigation cancelled"_s, 0);
+ else
+ completionHandler(String(), navigationID);
+}
+
+void WebPageInspectorController::didDestroyNavigation(uint64_t navigationID)
+{
+ if (!m_frontendRouter->hasFrontends())
+ return;
+
+ auto completionHandler = m_pendingNavigations.take(navigationID);
+ if (!completionHandler)
+ return;
+
+ // Inspector initiated navigation is destroyed before policy check only when it
+ // becomes a fragment navigation (which always reuses current navigation).
+ completionHandler(String(), 0);
+}
+
+void WebPageInspectorController::didFailProvisionalLoadForFrame(uint64_t navigationID, const WebCore::ResourceError& error)
+{
+ if (s_observer)
+ s_observer->didFailProvisionalLoad(m_page, navigationID, error.localizedDescription());
+}
+
void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
{
addTarget(InspectorTargetProxy::create(m_page, targetId, type));
@@ -169,6 +333,32 @@ void WebPageInspectorController::sendMessageToInspectorFrontend(const String& ta
m_targetAgent->sendMessageFromTargetToFrontend(targetId, message);
}
+void WebPageInspectorController::setPauseOnStart(bool shouldPause)
+{
+ ASSERT(m_frontendRouter->hasFrontends());
+ m_targetAgent->setPauseOnStart(shouldPause);
+}
+
+bool WebPageInspectorController::shouldPauseLoading() const
+{
+ if (!m_frontendRouter->hasFrontends())
+ return false;
+
+ if (!m_page.isPageOpenedByDOMShowingInitialEmptyDocument())
+ return false;
+
+ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_page.webPageID()));
+ ASSERT(target);
+ return target->isPaused();
+}
+
+void WebPageInspectorController::setContinueLoadingCallback(WTF::Function<void()>&& callback)
+{
+ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_page.webPageID()));
+ ASSERT(target);
+ target->setResumeCallback(WTFMove(callback));
+}
+
bool WebPageInspectorController::shouldPauseLoading(const ProvisionalPageProxy& provisionalPage) const
{
if (!m_frontendRouter->hasFrontends())
@@ -188,7 +378,7 @@ void WebPageInspectorController::setContinueLoadingCallback(const ProvisionalPag
void WebPageInspectorController::didCreateProvisionalPage(ProvisionalPageProxy& provisionalPage)
{
- addTarget(InspectorTargetProxy::create(provisionalPage, getTargetID(provisionalPage), Inspector::InspectorTargetType::Page));
+ addTarget(InspectorTargetProxy::create(provisionalPage, getTargetID(provisionalPage)));
}
void WebPageInspectorController::willDestroyProvisionalPage(const ProvisionalPageProxy& provisionalPage)
@@ -241,4 +431,20 @@ void WebPageInspectorController::addTarget(std::unique_ptr<InspectorTargetProxy>
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);
+
+ // Enable popup debugging.
+ // TODO: allow to set preferences over the inspector protocol or find a better place for this.
+ m_page.preferences().setJavaScriptCanOpenWindowsAutomatically(true);
+}
+
} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
index f9c26832d3e91e8d747c5c1e0f0d76c34f4c3096..8b73efbba93362d8eebcc3a52158d8b0f6e4c59d 100644
--- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
+++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
@@ -26,17 +26,35 @@
#pragma once
#include "InspectorTargetProxy.h"
+#include "ProcessTerminationReason.h"
#include <JavaScriptCore/InspectorAgentRegistry.h>
#include <JavaScriptCore/InspectorTargetAgent.h>
#include <WebCore/PageIdentifier.h>
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
#include <wtf/text/WTFString.h>
+#include <wtf/URL.h>
+
+#if USE(CAIRO)
+#include <cairo.h>
+#endif
namespace Inspector {
class BackendDispatcher;
class FrontendChannel;
class FrontendRouter;
+class InspectorTarget;
+}
+
+namespace WebCore {
+class ResourceError;
+class ResourceRequest;
+enum class PolicyAction : uint8_t;
+struct WindowFeatures;
+}
+
+namespace PAL {
+class SessionID;
}
namespace WebKit {
@@ -44,6 +62,23 @@ namespace WebKit {
class InspectorBrowserAgent;
struct WebPageAgentContext;
+class InspectorScreencastAgent;
+class WebFrameProxy;
+class WebPageInspectorEmulationAgent;
+class WebPageInspectorInputAgent;
+
+class WebPageInspectorControllerObserver {
+public:
+ virtual void didCreateInspectorController(WebPageProxy&) = 0;
+ virtual void willDestroyInspectorController(WebPageProxy&) = 0;
+ virtual void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error) = 0;
+ virtual void willCreateNewPage(WebPageProxy&, const WebCore::WindowFeatures&, const URL&) = 0;
+ virtual void didFinishScreencast(const PAL::SessionID& sessionID, const String& screencastID) = 0;
+
+protected:
+ virtual ~WebPageInspectorControllerObserver() = default;
+};
+
class WebPageInspectorController {
WTF_MAKE_NONCOPYABLE(WebPageInspectorController);
WTF_MAKE_FAST_ALLOCATED;
@@ -51,7 +86,20 @@ public:
WebPageInspectorController(WebPageProxy&);
void init();
+ void didFinishAttachingToWebProcess();
+
+ static void setObserver(WebPageInspectorControllerObserver*);
+ static WebPageInspectorControllerObserver* observer();
+
void pageClosed();
+ bool pageCrashed(ProcessTerminationReason);
+
+ void willCreateNewPage(const WebCore::WindowFeatures&, const URL&);
+
+ void didShowPage();
+
+ void didProcessAllPendingKeyboardEvents();
+ void didProcessAllPendingMouseEvents();
bool hasLocalFrontend() const;
@@ -64,11 +112,25 @@ public:
#if ENABLE(REMOTE_INSPECTOR)
void setIndicating(bool);
#endif
+#if USE(CAIRO)
+ void didPaint(cairo_surface_t*);
+#endif
+ using NavigationHandler = Function<void(const String&, uint64_t)>;
+ void navigate(WebCore::ResourceRequest&&, WebFrameProxy*, NavigationHandler&&);
+ void didReceivePolicyDecision(WebCore::PolicyAction action, uint64_t navigationID);
+ void didDestroyNavigation(uint64_t navigationID);
+
+ void didFailProvisionalLoadForFrame(uint64_t navigationID, const WebCore::ResourceError& error);
void createInspectorTarget(const String& targetId, Inspector::InspectorTargetType);
void destroyInspectorTarget(const String& targetId);
void sendMessageToInspectorFrontend(const String& targetId, const String& message);
+ void setPauseOnStart(bool);
+
+ bool shouldPauseLoading() const;
+ void setContinueLoadingCallback(WTF::Function<void()>&&);
+
bool shouldPauseLoading(const ProvisionalPageProxy&) const;
void setContinueLoadingCallback(const ProvisionalPageProxy&, WTF::Function<void()>&&);
@@ -84,6 +146,7 @@ private:
void createLazyAgents();
void addTarget(std::unique_ptr<InspectorTargetProxy>&&);
+ void adjustPageSettings();
Ref<Inspector::FrontendRouter> m_frontendRouter;
Ref<Inspector::BackendDispatcher> m_backendDispatcher;
@@ -92,11 +155,17 @@ private:
WebPageProxy& m_page;
Inspector::InspectorTargetAgent* m_targetAgent { nullptr };
+ WebPageInspectorEmulationAgent* m_emulationAgent { nullptr };
+ WebPageInspectorInputAgent* m_inputAgent { nullptr };
+ InspectorScreencastAgent* m_screecastAgent { nullptr };
HashMap<String, std::unique_ptr<InspectorTargetProxy>> m_targets;
InspectorBrowserAgent* m_enabledBrowserAgent;
bool m_didCreateLazyAgents { false };
+ HashMap<uint64_t, NavigationHandler> m_pendingNavigations;
+
+ static WebPageInspectorControllerObserver* s_observer;
};
} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/mac/ScreencastEncoderMac.mm b/Source/WebKit/UIProcess/Inspector/mac/ScreencastEncoderMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..0700f3624b34ab536f4101a12ba5fbd9a81e9a58
--- /dev/null
+++ b/Source/WebKit/UIProcess/Inspector/mac/ScreencastEncoderMac.mm
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScreencastEncoder.h"
+
+#include <algorithm>
+#include <CoreGraphics/CoreGraphics.h>
+#include <wtf/RetainPtr.h>
+
+namespace WebKit {
+
+void ScreencastEncoder::imageToARGB(CGImageRef image, uint8_t* argb_data, int width, int height, Optional<double> scale, int offsetTop)
+{
+ size_t bitsPerComponent = 8;
+ size_t bytesPerPixel = 4;
+ size_t bytesPerRow = bytesPerPixel * width;
+ RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
+ RetainPtr<CGContextRef> context = adoptCF(CGBitmapContextCreate(argb_data, width, height, bitsPerComponent, bytesPerRow, colorSpace.get(), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little));
+ double imageWidth = CGImageGetWidth(image);
+ double imageHeight = CGImageGetHeight(image);
+ // TODO: exclude controls from original screenshot
+ double pageHeight = imageHeight - offsetTop;
+ double ratio = 1;
+ if (scale) {
+ ratio = *scale;
+ } else if (imageWidth > width || pageHeight > height) {
+ ratio = std::min(width / imageWidth, height / pageHeight);
+ }
+ imageWidth *= ratio;
+ imageHeight *= ratio;
+ pageHeight *= ratio;
+ CGContextDrawImage(context.get(), CGRectMake(0, height - pageHeight, imageWidth, imageHeight), image);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/InspectorDialogAgent.cpp b/Source/WebKit/UIProcess/InspectorDialogAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..663f92f0df76042cf6385b056f8a917d688259f9
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorDialogAgent.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorDialogAgent.h"
+
+#include "APINavigation.h"
+#include "APIUIClient.h"
+#include "WebPageProxy.h"
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+
+
+namespace WebKit {
+
+using namespace Inspector;
+
+InspectorDialogAgent::InspectorDialogAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page)
+ : InspectorAgentBase("Dialog"_s)
+ , m_frontendDispatcher(makeUnique<DialogFrontendDispatcher>(frontendRouter))
+ , m_backendDispatcher(DialogBackendDispatcher::create(backendDispatcher, this))
+ , m_page(page)
+{
+}
+
+InspectorDialogAgent::~InspectorDialogAgent()
+{
+ disable();
+}
+
+void InspectorDialogAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
+{
+}
+
+void InspectorDialogAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
+{
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorDialogAgent::enable()
+{
+ if (m_page.inspectorDialogAgent())
+ return makeUnexpected("Dialog domain is already enabled."_s);
+
+ m_page.setInspectorDialogAgent(this);
+ return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorDialogAgent::disable()
+{
+ if (m_page.inspectorDialogAgent() != this)
+ return { };
+
+ m_page.setInspectorDialogAgent(nullptr);
+ return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorDialogAgent::handleJavaScriptDialog(bool accept, const String& value)
+{
+ m_page.uiClient().handleJavaScriptDialog(m_page, accept, value);
+ return { };
+}
+
+void InspectorDialogAgent::javascriptDialogOpening(const String& type, const String& message, const String& defaultValue) {
+ m_frontendDispatcher->javascriptDialogOpening(type, message, defaultValue);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/InspectorDialogAgent.h b/Source/WebKit/UIProcess/InspectorDialogAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..d0e11ed81a6257c011df23d5870da7403f8e9fe4
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorDialogAgent.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "WebEvent.h"
+
+#include <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+#include <JavaScriptCore/InspectorFrontendDispatchers.h>
+
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+namespace Inspector {
+class FrontendChannel;
+class FrontendRouter;
+}
+
+namespace WebKit {
+
+class NativeWebKeyboardEvent;
+class WebPageProxy;
+
+class InspectorDialogAgent : public Inspector::InspectorAgentBase, public Inspector::DialogBackendDispatcherHandler {
+ WTF_MAKE_NONCOPYABLE(InspectorDialogAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorDialogAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page);
+ ~InspectorDialogAgent() override;
+
+ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+ Inspector::Protocol::ErrorStringOr<void> enable() override;
+ Inspector::Protocol::ErrorStringOr<void> disable() override;
+ Inspector::Protocol::ErrorStringOr<void> handleJavaScriptDialog(bool accept, const String& promptText) override;
+
+ void javascriptDialogOpening(const String& type, const String& message, const String& defaultValue = String());
+
+private:
+ void platformHandleJavaScriptDialog(bool accept, const String* promptText);
+ std::unique_ptr<Inspector::DialogFrontendDispatcher> m_frontendDispatcher;
+ Ref<Inspector::DialogBackendDispatcher> m_backendDispatcher;
+ WebPageProxy& m_page;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..04d06589d224df007a9a1c3b3ffcf3d56b1744a3
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp
@@ -0,0 +1,882 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorPlaywrightAgent.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "APIPageConfiguration.h"
+#include "FrameInfoData.h"
+#include "InspectorPlaywrightAgentClient.h"
+#include "InspectorTargetProxy.h"
+#include "NetworkProcessMessages.h"
+#include "NetworkProcessProxy.h"
+#include "PageClient.h"
+#include "WebAutomationSession.h"
+#include "WebGeolocationManagerProxy.h"
+#include "WebGeolocationPosition.h"
+#include "WebInspectorUtilities.h"
+#include "WebPageInspectorController.h"
+#include "WebPageInspectorTarget.h"
+#include "WebPageProxy.h"
+#include "WebProcessPool.h"
+#include "WebProcessProxy.h"
+#include <WebCore/FrameIdentifier.h>
+#include <WebCore/GeolocationPositionData.h>
+#include <WebCore/InspectorPageAgent.h>
+#include <WebCore/ProcessIdentifier.h>
+#include <WebCore/ResourceRequest.h>
+#include <WebCore/WindowFeatures.h>
+#include <JavaScriptCore/InspectorBackendDispatcher.h>
+#include <JavaScriptCore/InspectorFrontendChannel.h>
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <pal/SessionID.h>
+#include <stdlib.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/HexNumber.h>
+#include <wtf/URL.h>
+
+
+using namespace Inspector;
+
+namespace WebKit {
+
+class InspectorPlaywrightAgent::PageProxyChannel : public FrontendChannel {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ PageProxyChannel(FrontendChannel& frontendChannel, String browserContextID, String pageProxyID, WebPageProxy& page)
+ : m_browserContextID(browserContextID)
+ , m_pageProxyID(pageProxyID)
+ , m_frontendChannel(frontendChannel)
+ , m_page(page)
+ {
+ }
+
+ ~PageProxyChannel() override = default;
+
+ void dispatchMessageFromFrontend(const String& message)
+ {
+ m_page.inspectorController().dispatchMessageFromFrontend(message);
+ }
+
+ WebPageProxy& page() { return m_page; }
+
+ void disconnect()
+ {
+ m_page.inspectorController().disconnectFrontend(*this);
+ }
+
+private:
+ ConnectionType connectionType() const override { return m_frontendChannel.connectionType(); }
+ void sendMessageToFrontend(const String& message) override
+ {
+ m_frontendChannel.sendMessageToFrontend(addTabIdToMessage(message));
+ }
+
+ String addTabIdToMessage(const String& message) {
+ RefPtr<JSON::Value> parsedMessage = JSON::Value::parseJSON(message);
+ if (!parsedMessage)
+ return message;
+
+ RefPtr<JSON::Object> messageObject = parsedMessage->asObject();
+ if (!messageObject)
+ return message;
+
+ messageObject->setString("browserContextId"_s, m_browserContextID);
+ messageObject->setString("pageProxyId"_s, m_pageProxyID);
+ return messageObject->toJSONString();
+ }
+
+ String m_browserContextID;
+ String m_pageProxyID;
+ FrontendChannel& m_frontendChannel;
+ WebPageProxy& m_page;
+};
+
+namespace {
+
+String toBrowserContextIDProtocolString(const PAL::SessionID& sessionID)
+{
+ StringBuilder builder;
+ builder.append(hex(sessionID.toUInt64(), 16));
+ return builder.toString();
+}
+
+String toPageProxyIDProtocolString(const WebPageProxy& page)
+{
+ return makeString(page.identifier().toUInt64());
+}
+
+
+static Ref<JSON::ArrayOf<String>> getEnabledWindowFeatures(const WebCore::WindowFeatures& features) {
+ auto result = JSON::ArrayOf<String>::create();
+ if (features.x)
+ result->addItem("left=" + String::number(*features.x));
+ if (features.y)
+ result->addItem("top=" + String::number(*features.y));
+ if (features.width)
+ result->addItem("width=" + String::number(*features.width));
+ if (features.height)
+ result->addItem("height=" + String::number(*features.height));
+ if (features.menuBarVisible)
+ result->addItem("menubar");
+ if (features.toolBarVisible)
+ result->addItem("toolbar");
+ if (features.statusBarVisible)
+ result->addItem("status");
+ if (features.locationBarVisible)
+ result->addItem("location");
+ if (features.scrollbarsVisible)
+ result->addItem("scrollbars");
+ if (features.resizable)
+ result->addItem("resizable");
+ if (features.fullscreen)
+ result->addItem("fullscreen");
+ if (features.dialog)
+ result->addItem("dialog");
+ if (features.noopener)
+ result->addItem("noopener");
+ if (features.noreferrer)
+ result->addItem("noreferrer");
+ for (const auto& additionalFeature : features.additionalFeatures)
+ result->addItem(additionalFeature);
+ return result;
+}
+
+Inspector::Protocol::Playwright::CookieSameSitePolicy cookieSameSitePolicy(WebCore::Cookie::SameSitePolicy policy)
+{
+ switch (policy) {
+ case WebCore::Cookie::SameSitePolicy::None:
+ return Inspector::Protocol::Playwright::CookieSameSitePolicy::None;
+ case WebCore::Cookie::SameSitePolicy::Lax:
+ return Inspector::Protocol::Playwright::CookieSameSitePolicy::Lax;
+ case WebCore::Cookie::SameSitePolicy::Strict:
+ return Inspector::Protocol::Playwright::CookieSameSitePolicy::Strict;
+ }
+ ASSERT_NOT_REACHED();
+ return Inspector::Protocol::Playwright::CookieSameSitePolicy::None;
+}
+
+Ref<Inspector::Protocol::Playwright::Cookie> buildObjectForCookie(const WebCore::Cookie& cookie)
+{
+ return Inspector::Protocol::Playwright::Cookie::create()
+ .setName(cookie.name)
+ .setValue(cookie.value)
+ .setDomain(cookie.domain)
+ .setPath(cookie.path)
+ .setExpires(cookie.expires.valueOr(-1))
+ .setHttpOnly(cookie.httpOnly)
+ .setSecure(cookie.secure)
+ .setSession(cookie.session)
+ .setSameSite(cookieSameSitePolicy(cookie.sameSite))
+ .release();
+}
+
+} // namespace
+
+BrowserContext::BrowserContext() = default;
+
+BrowserContext::~BrowserContext() = default;
+
+class InspectorPlaywrightAgent::BrowserContextDeletion {
+ WTF_MAKE_NONCOPYABLE(BrowserContextDeletion);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ BrowserContextDeletion(std::unique_ptr<BrowserContext>&& context, size_t numberOfPages, Ref<DeleteContextCallback>&& callback)
+ : m_browserContext(WTFMove(context))
+ , m_numberOfPages(numberOfPages)
+ , m_callback(WTFMove(callback)) { }
+
+ void didDestroyPage(const WebPageProxy& page)
+ {
+ ASSERT(m_browserContext->dataStore->sessionID() == page.sessionID());
+ // Check if new pages have been created during the context destruction and
+ // close all of them if necessary.
+ if (m_numberOfPages == 1) {
+ auto pages = m_browserContext->pages;
+ size_t numberOfPages = pages.size();
+ if (numberOfPages > 1) {
+ m_numberOfPages = numberOfPages;
+ for (auto* existingPage : pages) {
+ if (existingPage != &page)
+ existingPage->closePage();
+ }
+ }
+ }
+ --m_numberOfPages;
+ if (m_numberOfPages)
+ return;
+ m_callback->sendSuccess();
+ }
+
+ bool isFinished() const { return !m_numberOfPages; }
+
+ BrowserContext* context() const { return m_browserContext.get(); }
+
+private:
+ std::unique_ptr<BrowserContext> m_browserContext;
+ size_t m_numberOfPages;
+ Ref<DeleteContextCallback> m_callback;
+};
+
+
+InspectorPlaywrightAgent::InspectorPlaywrightAgent(std::unique_ptr<InspectorPlaywrightAgentClient> client)
+ : m_frontendChannel(nullptr)
+ , m_frontendRouter(FrontendRouter::create())
+ , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
+ , m_client(std::move(client))
+ , m_frontendDispatcher(makeUnique<PlaywrightFrontendDispatcher>(m_frontendRouter))
+ , m_playwrightDispatcher(PlaywrightBackendDispatcher::create(m_backendDispatcher.get(), this))
+{
+}
+
+InspectorPlaywrightAgent::~InspectorPlaywrightAgent()
+{
+ if (m_frontendChannel)
+ disconnectFrontend();
+}
+
+void InspectorPlaywrightAgent::connectFrontend(FrontendChannel& frontendChannel)
+{
+ ASSERT(!m_frontendChannel);
+ m_frontendChannel = &frontendChannel;
+ WebPageInspectorController::setObserver(this);
+
+ m_frontendRouter->connectFrontend(frontendChannel);
+}
+
+void InspectorPlaywrightAgent::disconnectFrontend()
+{
+ ASSERT(m_frontendChannel);
+
+ disable();
+
+ m_frontendRouter->disconnectFrontend(*m_frontendChannel);
+ ASSERT(!m_frontendRouter->hasFrontends());
+
+ WebPageInspectorController::setObserver(nullptr);
+ m_frontendChannel = nullptr;
+}
+
+void InspectorPlaywrightAgent::dispatchMessageFromFrontend(const String& message)
+{
+ m_backendDispatcher->dispatch(message, [&](const RefPtr<JSON::Object>& messageObject) {
+ RefPtr<JSON::Value> idValue;
+ if (!messageObject->getValue("id"_s, idValue))
+ return BackendDispatcher::InterceptionResult::Continue;
+ RefPtr<JSON::Value> pageProxyIDValue;
+ if (!messageObject->getValue("pageProxyId"_s, pageProxyIDValue))
+ return BackendDispatcher::InterceptionResult::Continue;
+
+ String pageProxyID;
+ if (!pageProxyIDValue->asString(pageProxyID)) {
+ m_backendDispatcher->reportProtocolError(BackendDispatcher::InvalidRequest, "The type of 'pageProxyId' must be string"_s);
+ m_backendDispatcher->sendPendingErrors();
+ return BackendDispatcher::InterceptionResult::Intercepted;
+ }
+
+ if (auto pageProxyChannel = m_pageProxyChannels.get(pageProxyID)) {
+ pageProxyChannel->dispatchMessageFromFrontend(message);
+ return BackendDispatcher::InterceptionResult::Intercepted;
+ }
+
+ Optional<int> requestId = idValue->asInteger();
+ if (!requestId) {
+ m_backendDispatcher->reportProtocolError(BackendDispatcher::InvalidRequest, "The type of 'id' must be number"_s);
+ m_backendDispatcher->sendPendingErrors();
+ return BackendDispatcher::InterceptionResult::Intercepted;
+ }
+
+ m_backendDispatcher->reportProtocolError(*requestId, BackendDispatcher::InvalidParams, "Cannot find page proxy with provided 'pageProxyId'"_s);
+ m_backendDispatcher->sendPendingErrors();
+ return BackendDispatcher::InterceptionResult::Intercepted;
+ });
+}
+
+void InspectorPlaywrightAgent::didCreateInspectorController(WebPageProxy& page)
+{
+ if (!m_isEnabled)
+ return;
+
+ if (isInspectorProcessPool(page.process().processPool()))
+ return;
+
+ ASSERT(m_frontendChannel);
+
+ String browserContextID = toBrowserContextIDProtocolString(page.sessionID());
+ String pageProxyID = toPageProxyIDProtocolString(page);
+ auto* opener = page.configuration().relatedPage();
+ String openerId;
+ if (opener)
+ openerId = toPageProxyIDProtocolString(*opener);
+
+ BrowserContext* browserContext = getExistingBrowserContext(browserContextID);
+ browserContext->pages.add(&page);
+ m_frontendDispatcher->pageProxyCreated(browserContextID, pageProxyID, openerId);
+
+ // Auto-connect to all new pages.
+ auto pageProxyChannel = makeUnique<PageProxyChannel>(*m_frontendChannel, browserContextID, pageProxyID, page);
+ page.inspectorController().connectFrontend(*pageProxyChannel);
+ // Always pause new targets if controlled remotely.
+ page.inspectorController().setPauseOnStart(true);
+ m_pageProxyChannels.set(pageProxyID, WTFMove(pageProxyChannel));
+}
+
+void InspectorPlaywrightAgent::willDestroyInspectorController(WebPageProxy& page)
+{
+ if (!m_isEnabled)
+ return;
+
+ if (isInspectorProcessPool(page.process().processPool()))
+ return;
+
+ String browserContextID = toBrowserContextIDProtocolString(page.sessionID());
+ BrowserContext* browserContext = getExistingBrowserContext(browserContextID);
+ browserContext->pages.remove(&page);
+ m_frontendDispatcher->pageProxyDestroyed(toPageProxyIDProtocolString(page));
+
+ auto it = m_browserContextDeletions.find(browserContextID);
+ if (it != m_browserContextDeletions.end()) {
+ it->value->didDestroyPage(page);
+ if (it->value->isFinished())
+ m_browserContextDeletions.remove(it);
+ }
+
+ String pageProxyID = toPageProxyIDProtocolString(page);
+ auto channelIt = m_pageProxyChannels.find(pageProxyID);
+ ASSERT(channelIt != m_pageProxyChannels.end());
+ channelIt->value->disconnect();
+ m_pageProxyChannels.remove(channelIt);
+}
+
+void InspectorPlaywrightAgent::didFailProvisionalLoad(WebPageProxy& page, uint64_t navigationID, const String& error)
+{
+ if (!m_isEnabled)
+ return;
+
+ m_frontendDispatcher->provisionalLoadFailed(
+ toPageProxyIDProtocolString(page),
+ String::number(navigationID), error);
+}
+
+void InspectorPlaywrightAgent::willCreateNewPage(WebPageProxy& page, const WebCore::WindowFeatures& features, const URL& url)
+{
+ if (!m_isEnabled)
+ return;
+
+ m_frontendDispatcher->windowOpen(
+ toPageProxyIDProtocolString(page),
+ url.string(),
+ getEnabledWindowFeatures(features));
+}
+
+void InspectorPlaywrightAgent::didFinishScreencast(const PAL::SessionID& sessionID, const String& screencastID)
+{
+ if (!m_isEnabled)
+ return;
+
+ m_frontendDispatcher->screencastFinished(screencastID);
+}
+
+static WebsiteDataStore* findDefaultWebsiteDataStore() {
+ WebsiteDataStore* result = nullptr;
+ WebsiteDataStore::forEachWebsiteDataStore([&result] (WebsiteDataStore& dataStore) {
+ if (dataStore.isPersistent()) {
+ RELEASE_ASSERT(result == nullptr);
+ result = &dataStore;
+ }
+ });
+ return result;
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorPlaywrightAgent::enable()
+{
+ if (m_isEnabled)
+ return { };
+
+ m_isEnabled = true;
+
+ auto* defaultDataStore = findDefaultWebsiteDataStore();
+ if (!m_defaultContext && defaultDataStore) {
+ auto context = std::make_unique<BrowserContext>();
+ m_defaultContext = context.get();
+ context->processPool = WebProcessPool::allProcessPools().first();
+ context->dataStore = defaultDataStore;
+ // Add default context to the map so that we can easily find it for
+ // created/deleted pages.
+ PAL::SessionID sessionID = context->dataStore->sessionID();
+ m_browserContexts.set(toBrowserContextIDProtocolString(sessionID), WTFMove(context));
+ }
+
+ WebsiteDataStore::forEachWebsiteDataStore([this] (WebsiteDataStore& dataStore) {
+ dataStore.setDownloadInstrumentation(this);
+ });
+ for (auto& pool : WebProcessPool::allProcessPools()) {
+ for (auto& process : pool->processes()) {
+ for (auto* page : process->pages())
+ didCreateInspectorController(*page);
+ }
+ }
+ return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorPlaywrightAgent::disable()
+{
+ if (!m_isEnabled)
+ return { };
+
+ m_isEnabled = false;
+
+ for (auto it = m_pageProxyChannels.begin(); it != m_pageProxyChannels.end(); ++it)
+ it->value->disconnect();
+ m_pageProxyChannels.clear();
+
+ WebsiteDataStore::forEachWebsiteDataStore([] (WebsiteDataStore& dataStore) {
+ dataStore.setDownloadInstrumentation(nullptr);
+ dataStore.setDownloadForAutomation(Optional<bool>(), String());
+ });
+ for (auto& it : m_browserContexts) {
+ it.value->dataStore->setDownloadInstrumentation(nullptr);
+ it.value->pages.clear();
+ }
+ m_browserContextDeletions.clear();
+ return { };
+}
+
+void InspectorPlaywrightAgent::close(Ref<CloseCallback>&& callback)
+{
+ Vector<WebPageProxy*> pages;
+ // If Web Process crashed it will be disconnected from its pool until
+ // the page reloads. So we cannot discover such processes and the pages
+ // by traversing all process pools and their processes. Instead we look at
+ // all existing Web Processes wether in a pool or not.
+ for (auto* process : WebProcessProxy::allProcessesForInspector()) {
+ for (auto* page : process->pages())
+ pages.append(page);
+ }
+ for (auto* page : pages)
+ page->closePage();
+
+ if (!WebProcessPool::allProcessPools().size()) {
+ m_client->closeBrowser();
+ callback->sendSuccess();
+ return;
+ }
+
+ if (!m_defaultContext) {
+ m_client->closeBrowser();
+ callback->sendSuccess();
+ return;
+ }
+
+ m_defaultContext->dataStore->syncLocalStorage([this, callback = WTFMove(callback)] () {
+ if (!callback->isActive())
+ return;
+
+ if (m_client == nullptr) {
+ callback->sendFailure("no platform delegate to close browser");
+ } else {
+ m_client->closeBrowser();
+ callback->sendSuccess();
+ }
+ });
+
+}
+
+Inspector::Protocol::ErrorStringOr<String /* browserContextID */> InspectorPlaywrightAgent::createContext(const String& proxyServer, const String& proxyBypassList)
+{
+ String errorString;
+ std::unique_ptr<BrowserContext> browserContext = m_client->createBrowserContext(errorString, proxyServer, proxyBypassList);
+ if (!browserContext)
+ return makeUnexpected(errorString);
+
+ // Ensure network process.
+ browserContext->dataStore->networkProcess();
+ browserContext->dataStore->setDownloadInstrumentation(this);
+
+ PAL::SessionID sessionID = browserContext->dataStore->sessionID();
+ String browserContextID = toBrowserContextIDProtocolString(sessionID);
+ m_browserContexts.set(browserContextID, WTFMove(browserContext));
+ return browserContextID;
+}
+
+void InspectorPlaywrightAgent::deleteContext(const String& browserContextID, Ref<DeleteContextCallback>&& callback)
+{
+ String errorString;
+ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!lookupBrowserContext(errorString, browserContextID)) {
+ callback->sendFailure(errorString);
+ return;
+ }
+
+ if (browserContext == m_defaultContext) {
+ callback->sendFailure("Cannot delete default context"_s);
+ return;
+ }
+
+ auto pages = browserContext->pages;
+ PAL::SessionID sessionID = browserContext->dataStore->sessionID();
+ auto contextHolder = m_browserContexts.take(browserContextID);
+ if (pages.isEmpty()) {
+ callback->sendSuccess();
+ } else {
+ m_browserContextDeletions.set(browserContextID, makeUnique<BrowserContextDeletion>(WTFMove(contextHolder), pages.size(), WTFMove(callback)));
+ for (auto* page : pages)
+ page->closePage();
+ }
+ m_client->deleteBrowserContext(errorString, sessionID);
+}
+
+Inspector::Protocol::ErrorStringOr<String /* pageProxyID */> InspectorPlaywrightAgent::createPage(const String& browserContextID)
+{
+ String errorString;
+ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!browserContext)
+ return makeUnexpected(errorString);
+
+ RefPtr<WebPageProxy> page = m_client->createPage(errorString, *browserContext);
+ if (!page)
+ return makeUnexpected(errorString);
+
+ return toPageProxyIDProtocolString(*page);
+}
+
+WebFrameProxy* InspectorPlaywrightAgent::frameForID(const String& frameID, String& error)
+{
+ size_t dotPos = frameID.find(".");
+ if (dotPos == notFound) {
+ error = "Invalid frame id"_s;
+ return nullptr;
+ }
+
+ if (!frameID.isAllASCII()) {
+ error = "Invalid frame id"_s;
+ return nullptr;
+ }
+
+ String processIDString = frameID.left(dotPos);
+ uint64_t pid = strtoull(processIDString.ascii().data(), 0, 10);
+ auto processID = makeObjectIdentifier<WebCore::ProcessIdentifierType>(pid);
+ WebProcessProxy* process = WebProcessProxy::processForIdentifier(processID);
+ if (!process) {
+ error = "Cannot find web process for the frame id"_s;
+ return nullptr;
+ }
+
+ String frameIDString = frameID.substring(dotPos + 1);
+ uint64_t frameIDNumber = strtoull(frameIDString.ascii().data(), 0, 10);
+ auto frameIdentifier = makeObjectIdentifier<WebCore::FrameIdentifierType>(frameIDNumber);
+ WebFrameProxy* frame = process->webFrame(frameIdentifier);
+ if (!frame) {
+ error = "Cannot find web frame for the frame id"_s;
+ return nullptr;
+ }
+
+ return frame;
+}
+
+void InspectorPlaywrightAgent::navigate(const String& url, const String& pageProxyID, const String& frameID, const String& referrer, Ref<NavigateCallback>&& callback)
+{
+ auto* pageProxyChannel = m_pageProxyChannels.get(pageProxyID);
+ if (!pageProxyChannel) {
+ callback->sendFailure("Cannot find page proxy with provided 'pageProxyId'"_s);
+ return;
+ }
+
+ WebCore::ResourceRequest resourceRequest { url };
+
+ if (!!referrer)
+ resourceRequest.setHTTPReferrer(referrer);
+
+ if (!resourceRequest.url().isValid()) {
+ callback->sendFailure("Cannot navigate to invalid URL"_s);
+ return;
+ }
+
+ WebFrameProxy* frame = nullptr;
+ if (!!frameID) {
+ String error;
+ frame = frameForID(frameID, error);
+ if (!frame) {
+ callback->sendFailure(error);
+ return;
+ }
+
+ if (frame->page() != &pageProxyChannel->page()) {
+ callback->sendFailure("Frame with specified is not from the specified page"_s);
+ return;
+ }
+ }
+
+ pageProxyChannel->page().inspectorController().navigate(WTFMove(resourceRequest), frame, [callback = WTFMove(callback)](const String& error, uint64_t navigationID) {
+ if (!error.isEmpty()) {
+ callback->sendFailure(error);
+ return;
+ }
+
+ String navigationIDString;
+ if (navigationID)
+ navigationIDString = String::number(navigationID);
+ callback->sendSuccess(navigationIDString);
+ });
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorPlaywrightAgent::setIgnoreCertificateErrors(const String& browserContextID, bool ignore)
+{
+ String errorString;
+ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return makeUnexpected(errorString);
+
+ PAL::SessionID sessionID = browserContext->dataStore->sessionID();
+ NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess();
+ networkProcess.send(Messages::NetworkProcess::SetIgnoreCertificateErrors(sessionID, ignore), 0);
+ return { };
+}
+
+void InspectorPlaywrightAgent::getAllCookies(const String& browserContextID, Ref<GetAllCookiesCallback>&& callback) {
+ String errorString;
+ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty()) {
+ callback->sendFailure(errorString);
+ return;
+ }
+
+ PAL::SessionID sessionID = browserContext->dataStore->sessionID();
+ NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess();
+ networkProcess.sendWithAsyncReply(Messages::NetworkProcess::GetAllCookies(sessionID),
+ [callback = WTFMove(callback)](Vector<WebCore::Cookie> allCookies) {
+ if (!callback->isActive())
+ return;
+ auto cookies = JSON::ArrayOf<Inspector::Protocol::Playwright::Cookie>::create();
+ for (const auto& cookie : allCookies)
+ cookies->addItem(buildObjectForCookie(cookie));
+ callback->sendSuccess(WTFMove(cookies));
+ }, 0);
+}
+
+void InspectorPlaywrightAgent::setCookies(const String& browserContextID, Ref<JSON::Array>&& in_cookies, Ref<SetCookiesCallback>&& callback) {
+ String errorString;
+ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty()) {
+ callback->sendFailure(errorString);
+ return;
+ }
+
+ NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess();
+ PAL::SessionID sessionID = browserContext->dataStore->sessionID();
+
+ Vector<WebCore::Cookie> cookies;
+ for (unsigned i = 0; i < in_cookies->length(); ++i) {
+ RefPtr<JSON::Value> item = in_cookies->get(i);
+ RefPtr<JSON::Object> obj = item->asObject();
+ if (!obj) {
+ callback->sendFailure("Invalid cookie payload format"_s);
+ return;
+ }
+
+ WebCore::Cookie cookie;
+ cookie.name = obj->getString("name");
+ cookie.value = obj->getString("value");
+ cookie.domain = obj->getString("domain");
+ cookie.path = obj->getString("path");
+ if (!cookie.name || !cookie.value || !cookie.domain || !cookie.path) {
+ callback->sendFailure("Invalid file payload format"_s);
+ return;
+ }
+
+ Optional<double> expires = obj->getDouble("expires");
+ if (expires && *expires != -1)
+ cookie.expires = *expires;
+ if (Optional<bool> value = obj->getBoolean("httpOnly"))
+ cookie.httpOnly = *value;
+ if (Optional<bool> value = obj->getBoolean("secure"))
+ cookie.secure = *value;
+ if (Optional<bool> value = obj->getBoolean("session"))
+ cookie.session = *value;
+ String sameSite;
+ if (obj->getString("sameSite", sameSite)) {
+ if (sameSite == "None")
+ cookie.sameSite = WebCore::Cookie::SameSitePolicy::None;
+ if (sameSite == "Lax")
+ cookie.sameSite = WebCore::Cookie::SameSitePolicy::Lax;
+ if (sameSite == "Strict")
+ cookie.sameSite = WebCore::Cookie::SameSitePolicy::Strict;
+ }
+ cookies.append(WTFMove(cookie));
+ }
+
+ networkProcess.sendWithAsyncReply(Messages::NetworkProcess::SetCookies(sessionID, WTFMove(cookies)),
+ [callback = WTFMove(callback)](bool success) {
+ if (!callback->isActive())
+ return;
+
+ if (success)
+ callback->sendSuccess();
+ else
+ callback->sendFailure("Internal error: no network storage"_s);
+ callback->sendSuccess();
+ }, 0);
+}
+
+void InspectorPlaywrightAgent::deleteAllCookies(const String& browserContextID, Ref<DeleteAllCookiesCallback>&& callback) {
+ String errorString;
+ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty()) {
+ callback->sendFailure(errorString);
+ return;
+ }
+
+ NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess();
+ PAL::SessionID sessionID = browserContext->dataStore->sessionID();
+ networkProcess.sendWithAsyncReply(Messages::NetworkProcess::DeleteAllCookies(sessionID),
+ [callback = WTFMove(callback)](bool success) {
+ if (!callback->isActive())
+ return;
+ if (success)
+ callback->sendSuccess();
+ else
+ callback->sendFailure("Internal error: no network storage"_s);
+ }, 0);
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorPlaywrightAgent::setLanguages(Ref<JSON::Array>&& languages, const String& browserContextID)
+{
+ String errorString;
+ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return makeUnexpected(errorString);
+
+ Vector<String> items;
+ for (const auto& value : languages.get()) {
+ String language;
+ if (!value->asString(language))
+ return makeUnexpected("Language must be a string"_s);
+
+ items.append(language);
+ }
+
+ browserContext->dataStore->setLanguagesForAutomation(WTFMove(items));
+ return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorPlaywrightAgent::setDownloadBehavior(const String& behavior, const String& downloadPath, const String& browserContextID)
+{
+ String errorString;
+ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return makeUnexpected(errorString);
+
+ Optional<bool> allow;
+ if (behavior == "allow"_s)
+ allow = true;
+ if (behavior == "deny"_s)
+ allow = false;
+ browserContext->dataStore->setDownloadForAutomation(allow, downloadPath);
+ return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorPlaywrightAgent::setGeolocationOverride(const String& browserContextID, RefPtr<JSON::Object>&& geolocation)
+{
+ String errorString;
+ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return makeUnexpected(errorString);
+
+ auto* geoManager = browserContext->processPool->supplement<WebGeolocationManagerProxy>();
+ if (!geoManager)
+ return makeUnexpected("Internal error: geolocation manager is not available."_s);
+
+ if (geolocation) {
+ Optional<double> timestamp = geolocation->getDouble("timestamp");
+ Optional<double> latitude = geolocation->getDouble("latitude");
+ Optional<double> longitude = geolocation->getDouble("longitude");
+ Optional<double> accuracy = geolocation->getDouble("accuracy");
+ if (!timestamp || !latitude || !longitude || !accuracy)
+ return makeUnexpected("Invalid geolocation format"_s);
+
+ auto position = WebGeolocationPosition::create(WebCore::GeolocationPositionData(*timestamp, *latitude, *longitude, *accuracy));
+ geoManager->providerDidChangePosition(&position.get());
+ } else {
+ geoManager->providerDidFailToDeterminePosition("Position unavailable"_s);
+ }
+ return { };
+}
+
+void InspectorPlaywrightAgent::downloadCreated(const String& uuid, const WebCore::ResourceRequest& request, const FrameInfoData& frameInfoData, WebPageProxy* page)
+{
+ if (!m_isEnabled)
+ return;
+ String frameID = WebCore::InspectorPageAgent::makeFrameID(page->process().coreProcessIdentifier(), frameInfoData.frameID ? *frameInfoData.frameID : page->mainFrame()->frameID());
+ m_frontendDispatcher->downloadCreated(
+ toPageProxyIDProtocolString(*page),
+ frameID,
+ uuid, request.url().string());
+}
+
+void InspectorPlaywrightAgent::downloadFilenameSuggested(const String& uuid, const String& suggestedFilename)
+{
+ if (!m_isEnabled)
+ return;
+ m_frontendDispatcher->downloadFilenameSuggested(uuid, suggestedFilename);
+}
+
+void InspectorPlaywrightAgent::downloadFinished(const String& uuid, const String& error)
+{
+ if (!m_isEnabled)
+ return;
+ m_frontendDispatcher->downloadFinished(uuid, error);
+}
+
+BrowserContext* InspectorPlaywrightAgent::getExistingBrowserContext(const String& browserContextID)
+{
+ BrowserContext* browserContext = m_browserContexts.get(browserContextID);
+ if (browserContext)
+ return browserContext;
+
+ auto it = m_browserContextDeletions.find(browserContextID);
+ RELEASE_ASSERT(it != m_browserContextDeletions.end());
+ return it->value->context();
+}
+
+BrowserContext* InspectorPlaywrightAgent::lookupBrowserContext(ErrorString& errorString, const String& browserContextID)
+{
+ if (!browserContextID) {
+ if (!m_defaultContext)
+ errorString = "Browser started with no default context"_s;
+ return m_defaultContext;
+ }
+
+ BrowserContext* browserContext = m_browserContexts.get(browserContextID);
+ if (!browserContext)
+ errorString = "Could not find browser context for given id"_s;
+ return browserContext;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b6cd5c9357c90ac81c0c2d197699855062926af
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgentClient.h"
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+#include "WebPageInspectorController.h"
+#include "WebProcessPool.h"
+#include <wtf/HashMap.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+class PlaywrightFrontendDispatcher;
+}
+
+namespace PAL {
+class SessionID;
+}
+
+namespace WebKit {
+
+class WebFrameProxy;
+
+class InspectorPlaywrightAgent final
+ : public WebPageInspectorControllerObserver
+ , public Inspector::PlaywrightBackendDispatcherHandler
+ , public DownloadInstrumentation {
+ WTF_MAKE_NONCOPYABLE(InspectorPlaywrightAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ explicit InspectorPlaywrightAgent(std::unique_ptr<InspectorPlaywrightAgentClient> client);
+ ~InspectorPlaywrightAgent() override;
+
+ // Transport
+ void connectFrontend(Inspector::FrontendChannel&);
+ void disconnectFrontend();
+ void dispatchMessageFromFrontend(const String& message);
+
+private:
+ class BrowserContextDeletion;
+ class PageProxyChannel;
+ class TargetHandler;
+
+ // WebPageInspectorControllerObserver
+ void didCreateInspectorController(WebPageProxy&) override;
+ void willDestroyInspectorController(WebPageProxy&) override;
+ void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error) override;
+ void willCreateNewPage(WebPageProxy&, const WebCore::WindowFeatures&, const URL&) override;
+ void didFinishScreencast(const PAL::SessionID& sessionID, const String& screencastID) override;
+
+ // PlaywrightDispatcherHandler
+ Inspector::Protocol::ErrorStringOr<void> enable() override;
+ Inspector::Protocol::ErrorStringOr<void> disable() override;
+ void close(Ref<CloseCallback>&&) override;
+ Inspector::Protocol::ErrorStringOr<String /* browserContextID */> createContext(const String& proxyServer, const String& proxyBypassList) override;
+ void deleteContext(const String& browserContextID, Ref<DeleteContextCallback>&& callback) override;
+ Inspector::Protocol::ErrorStringOr<String /* pageProxyID */> createPage(const String& browserContextID) override;
+ void navigate(const String& url, const String& pageProxyID, const String& frameId, const String& referrer, Ref<NavigateCallback>&&) override;
+ Inspector::Protocol::ErrorStringOr<void> setIgnoreCertificateErrors(const String& browserContextID, bool ignore) override;
+
+ void getAllCookies(const String& browserContextID, Ref<GetAllCookiesCallback>&&) override;
+ void setCookies(const String& browserContextID, Ref<JSON::Array>&& in_cookies, Ref<SetCookiesCallback>&&) override;
+ void deleteAllCookies(const String& browserContextID, Ref<DeleteAllCookiesCallback>&&) override;
+
+ Inspector::Protocol::ErrorStringOr<void> setGeolocationOverride(const String& browserContextID, RefPtr<JSON::Object>&& geolocation) override;
+ Inspector::Protocol::ErrorStringOr<void> setLanguages(Ref<JSON::Array>&& languages, const String& browserContextID) override;
+ Inspector::Protocol::ErrorStringOr<void> setDownloadBehavior(const String& behavior, const String& downloadPath, const String& browserContextID) override;
+
+ // DownloadInstrumentation
+ void downloadCreated(const String& uuid, const WebCore::ResourceRequest&, const FrameInfoData& frameInfoData, WebPageProxy* page) override;
+ void downloadFilenameSuggested(const String& uuid, const String& suggestedFilename) override;
+ void downloadFinished(const String& uuid, const String& error) override;
+
+ BrowserContext* getExistingBrowserContext(const String& browserContextID);
+ BrowserContext* lookupBrowserContext(Inspector::ErrorString&, const String& browserContextID);
+ WebFrameProxy* frameForID(const String& frameID, String& error);
+
+ Inspector::FrontendChannel* m_frontendChannel { nullptr };
+ Ref<Inspector::FrontendRouter> m_frontendRouter;
+ Ref<Inspector::BackendDispatcher> m_backendDispatcher;
+ std::unique_ptr<InspectorPlaywrightAgentClient> m_client;
+ std::unique_ptr<Inspector::PlaywrightFrontendDispatcher> m_frontendDispatcher;
+ Ref<Inspector::PlaywrightBackendDispatcher> m_playwrightDispatcher;
+ HashMap<String, std::unique_ptr<PageProxyChannel>> m_pageProxyChannels;
+ BrowserContext* m_defaultContext;
+ HashMap<String, std::unique_ptr<BrowserContext>> m_browserContexts;
+ HashMap<String, std::unique_ptr<BrowserContextDeletion>> m_browserContextDeletions;
+ bool m_isEnabled { false };
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h b/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h
new file mode 100644
index 0000000000000000000000000000000000000000..11c8eadafca764aa549cb27c24967e15e6975774
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include <memory>
+#include <pal/SessionID.h>
+#include <wtf/Forward.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/RefCounted.h>
+
+namespace WebKit {
+
+class WebsiteDataStore;
+class WebPageProxy;
+class WebProcessPool;
+
+class BrowserContext {
+ WTF_MAKE_NONCOPYABLE(BrowserContext);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ BrowserContext();
+ ~BrowserContext();
+
+ RefPtr<WebsiteDataStore> dataStore;
+ RefPtr<WebProcessPool> processPool;
+ HashSet<WebPageProxy*> pages;
+};
+
+class InspectorPlaywrightAgentClient {
+public:
+ virtual ~InspectorPlaywrightAgentClient() = default;
+ virtual RefPtr<WebKit::WebPageProxy> createPage(WTF::String& error, const BrowserContext& context) = 0;
+ virtual void closeBrowser() = 0;
+ virtual std::unique_ptr<BrowserContext> createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) = 0;
+ virtual void deleteBrowserContext(WTF::String& error, PAL::SessionID) = 0;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp
index 7a14cfba15c103a2d4fe263fa49d25af3c396ec2..3ee0e154349661632799057c71f1d1f1551c2d69 100644
--- a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp
+++ b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp
@@ -96,8 +96,11 @@ void ProcessLauncher::launchProcess()
STARTUPINFO startupInfo { };
startupInfo.cb = sizeof(startupInfo);
- startupInfo.dwFlags = STARTF_USESHOWWINDOW;
+ startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
startupInfo.wShowWindow = SW_HIDE;
+ startupInfo.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+ startupInfo.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+ startupInfo.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
PROCESS_INFORMATION processInformation { };
BOOL result = ::CreateProcess(0, commandLine.data(), 0, 0, true, 0, 0, 0, &startupInfo, &processInformation);
diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h
index c4c71874a10da9b541fee2820808c1e50d3fa92b..12fd60e8ad5482e7faab2ba9c6b6990a213e432a 100644
--- a/Source/WebKit/UIProcess/PageClient.h
+++ b/Source/WebKit/UIProcess/PageClient.h
@@ -265,7 +265,7 @@ public:
virtual void showSafeBrowsingWarning(const SafeBrowsingWarning&, CompletionHandler<void(Variant<ContinueUnsafeLoad, URL>&&)>&& completionHandler) { completionHandler(ContinueUnsafeLoad::Yes); }
virtual void clearSafeBrowsingWarning() { }
virtual void clearSafeBrowsingWarningIfForMainFrameNavigation() { }
-
+
#if ENABLE(DRAG_SUPPORT)
#if PLATFORM(GTK)
virtual void startDrag(WebCore::SelectionData&&, OptionSet<WebCore::DragOperation>, RefPtr<ShareableBitmap>&& dragImage) = 0;
@@ -304,6 +304,11 @@ public:
virtual void selectionDidChange() = 0;
#endif
+// Paywright begin
+#if PLATFORM(COCOA)
+ virtual RetainPtr<CGImageRef> takeSnapshotForAutomation() = 0;
+#endif
+// Paywright end
#if PLATFORM(COCOA) || PLATFORM(GTK)
virtual RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&) = 0;
#endif
@@ -320,6 +325,7 @@ public:
virtual WebCore::IntRect rootViewToAccessibilityScreen(const WebCore::IntRect&) = 0;
#if PLATFORM(MAC)
virtual WebCore::IntRect rootViewToWindow(const WebCore::IntRect&) = 0;
+ virtual int browserToolbarHeight() const { return 0; }
#endif
#if PLATFORM(IOS_FAMILY)
virtual void didNotHandleTapAsClick(const WebCore::IntPoint&) = 0;
@@ -368,7 +374,7 @@ public:
virtual void setTextIndicator(Ref<WebCore::TextIndicator>, WebCore::TextIndicatorWindowLifetime) = 0;
virtual void clearTextIndicator(WebCore::TextIndicatorWindowDismissalAnimation) = 0;
virtual void setTextIndicatorAnimationProgress(float) = 0;
-
+
virtual void didPerformDictionaryLookup(const WebCore::DictionaryPopupInfo&) = 0;
#endif
@@ -499,7 +505,7 @@ public:
virtual bool hasSafeBrowsingWarning() const { return false; }
virtual void setMouseEventPolicy(WebCore::MouseEventPolicy) { }
-
+
#if PLATFORM(MAC)
virtual void didPerformImmediateActionHitTest(const WebHitTestResultData&, bool contentPreventsDefault, API::Object*) = 0;
virtual NSObject *immediateActionAnimationControllerForHitTestResult(RefPtr<API::HitTestResult>, uint64_t, RefPtr<API::Object>) = 0;
diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9593d0c3cc694309a18ae791a3f6ea0725f9b0cb
--- /dev/null
+++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RemoteInspectorPipe.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgent.h"
+#include <JavaScriptCore/InspectorFrontendChannel.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+#include <wtf/UniqueArray.h>
+#include <wtf/Vector.h>
+#include <wtf/WorkQueue.h>
+
+#if OS(UNIX)
+#include <stdio.h>
+#include <unistd.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <io.h>
+#endif
+
+namespace WebKit {
+
+namespace {
+
+const int readFD = 3;
+const int writeFD = 4;
+
+const size_t kWritePacketSize = 1 << 16;
+
+#if PLATFORM(WIN)
+HANDLE readHandle;
+HANDLE writeHandle;
+#endif
+
+size_t ReadBytes(void* buffer, size_t size, bool exact_size)
+{
+ size_t bytesRead = 0;
+ while (bytesRead < size) {
+#if PLATFORM(WIN)
+ DWORD sizeRead = 0;
+ bool hadError = !ReadFile(readHandle, static_cast<char*>(buffer) + bytesRead,
+ size - bytesRead, &sizeRead, nullptr);
+#else
+ int sizeRead = read(readFD, static_cast<char*>(buffer) + bytesRead,
+ size - bytesRead);
+ if (sizeRead < 0 && errno == EINTR)
+ continue;
+ bool hadError = sizeRead <= 0;
+#endif
+ if (hadError) {
+ return 0;
+ }
+ bytesRead += sizeRead;
+ if (!exact_size)
+ break;
+ }
+ return bytesRead;
+}
+
+void WriteBytes(const char* bytes, size_t size)
+{
+ size_t totalWritten = 0;
+ while (totalWritten < size) {
+ size_t length = size - totalWritten;
+ if (length > kWritePacketSize)
+ length = kWritePacketSize;
+#if PLATFORM(WIN)
+ DWORD bytesWritten = 0;
+ bool hadError = !WriteFile(writeHandle, bytes + totalWritten, static_cast<DWORD>(length), &bytesWritten, nullptr);
+#else
+ int bytesWritten = write(writeFD, bytes + totalWritten, length);
+ if (bytesWritten < 0 && errno == EINTR)
+ continue;
+ bool hadError = bytesWritten <= 0;
+#endif
+ if (hadError)
+ return;
+ totalWritten += bytesWritten;
+ }
+}
+
+} // namespace
+
+class RemoteInspectorPipe::RemoteFrontendChannel : public Inspector::FrontendChannel {
+ WTF_MAKE_FAST_ALLOCATED;
+
+public:
+ RemoteFrontendChannel()
+ : m_senderQueue(WorkQueue::create("Inspector pipe writer"))
+ {
+ }
+
+ ~RemoteFrontendChannel() override = default;
+
+ ConnectionType connectionType() const override
+ {
+ return ConnectionType::Remote;
+ }
+
+ void sendMessageToFrontend(const String& message) override
+ {
+ m_senderQueue->dispatch([message = message.isolatedCopy()]() {
+ WriteBytes(message.ascii().data(), message.length());
+ WriteBytes("\0", 1);
+ });
+ }
+
+private:
+ Ref<WorkQueue> m_senderQueue;
+};
+
+RemoteInspectorPipe::RemoteInspectorPipe(InspectorPlaywrightAgent& playwrightAgent)
+ : m_playwrightAgent(playwrightAgent)
+{
+ // Initialize main loop before creating WorkQueue
+ WTF::initializeMainThread();
+ m_remoteFrontendChannel = makeUnique<RemoteFrontendChannel>();
+ start();
+}
+
+RemoteInspectorPipe::~RemoteInspectorPipe()
+{
+ stop();
+}
+
+bool RemoteInspectorPipe::start()
+{
+ if (m_receiverThread)
+ return true;
+
+#if PLATFORM(WIN)
+ readHandle = reinterpret_cast<HANDLE>(_get_osfhandle(readFD));
+ writeHandle = reinterpret_cast<HANDLE>(_get_osfhandle(writeFD));
+#endif
+
+ m_playwrightAgent.connectFrontend(*m_remoteFrontendChannel);
+ m_terminated = false;
+ m_receiverThread = Thread::create("Inspector pipe reader", [this] {
+ workerRun();
+ });
+ return true;
+}
+
+void RemoteInspectorPipe::stop()
+{
+ if (!m_receiverThread)
+ return;
+
+ m_playwrightAgent.disconnectFrontend();
+
+ m_terminated = true;
+ m_receiverThread->waitForCompletion();
+ m_receiverThread = nullptr;
+}
+
+void RemoteInspectorPipe::workerRun()
+{
+ const size_t bufSize = 256 * 1024;
+ auto buffer = makeUniqueArray<char>(bufSize);
+ Vector<char> line;
+ while (!m_terminated) {
+ size_t size = ReadBytes(buffer.get(), bufSize, false);
+ if (!size)
+ break;
+ size_t start = 0;
+ size_t end = line.size();
+ line.append(buffer.get(), size);
+ while (true) {
+ for (; end < line.size(); ++end) {
+ if (line[end] == '\0')
+ break;
+ }
+ if (end == line.size())
+ break;
+
+ if (end > start) {
+ String message = String::fromUTF8(line.data() + start, end - start);
+ RunLoop::main().dispatch([this, message] {
+ if (!m_terminated)
+ m_playwrightAgent.dispatchMessageFromFrontend(message);
+ });
+ }
+ ++end;
+ start = end;
+ }
+ if (start != 0 && start < line.size())
+ memmove(line.data(), line.data() + start, line.size() - start);
+ line.shrink(line.size() - start);
+ }
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.h b/Source/WebKit/UIProcess/RemoteInspectorPipe.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d04f9290135069359ce6bf8726546482fd1dc95
--- /dev/null
+++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include <wtf/Ref.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Threading.h>
+
+namespace Inspector {
+class FrontendChannel;
+}
+
+namespace WebKit {
+
+class InspectorPlaywrightAgent;
+
+class RemoteInspectorPipe {
+ WTF_MAKE_NONCOPYABLE(RemoteInspectorPipe);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ explicit RemoteInspectorPipe(InspectorPlaywrightAgent&);
+ ~RemoteInspectorPipe();
+
+private:
+ class RemoteFrontendChannel;
+
+ bool start();
+ void stop();
+
+ void workerRun();
+
+ RefPtr<Thread> m_receiverThread;
+ std::atomic<bool> m_terminated { false };
+ std::unique_ptr<Inspector::FrontendChannel> m_remoteFrontendChannel;
+ InspectorPlaywrightAgent& m_playwrightAgent;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm b/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm
index 4dc97e89390e85aaa55ede4ef2801e1b678b3dde..b522b3b792ae4e04beb6fbb3567913ed29f59f79 100644
--- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm
+++ b/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm
@@ -140,14 +140,14 @@ static Optional<Vector<Ref<AuthenticatorAssertionResponse>>> getExistingCredenti
}
auto& responseMap = decodedResponse->getMap();
- auto it = responseMap.find(CBOR(kEntityIdMapKey));
+ auto it = responseMap.find(CBOR(fido::kEntityIdMapKey));
if (it == responseMap.end() || !it->second.isByteString()) {
ASSERT_NOT_REACHED();
return WTF::nullopt;
}
auto& userHandle = it->second.getByteString();
- it = responseMap.find(CBOR(kEntityNameMapKey));
+ it = responseMap.find(CBOR(fido::kEntityNameMapKey));
if (it == responseMap.end() || !it->second.isString()) {
ASSERT_NOT_REACHED();
return WTF::nullopt;
@@ -291,8 +291,8 @@ void LocalAuthenticator::continueMakeCredentialAfterUserVerification(SecAccessCo
const auto& secAttrLabel = creationOptions.rp.id;
cbor::CBORValue::MapValue userEntityMap;
- userEntityMap[cbor::CBORValue(kEntityIdMapKey)] = cbor::CBORValue(creationOptions.user.idVector);
- userEntityMap[cbor::CBORValue(kEntityNameMapKey)] = cbor::CBORValue(creationOptions.user.name);
+ userEntityMap[cbor::CBORValue(fido::kEntityIdMapKey)] = cbor::CBORValue(creationOptions.user.idVector);
+ userEntityMap[cbor::CBORValue(fido::kEntityNameMapKey)] = cbor::CBORValue(creationOptions.user.name);
auto userEntity = cbor::CBORWriter::write(cbor::CBORValue(WTFMove(userEntityMap)));
ASSERT(userEntity);
auto secAttrApplicationTag = toNSData(*userEntity);
diff --git a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h b/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h
index ff90d3de4349c9a3385c20c059729b8e22ebe2e5..d5c4f2cd715551ddef6f5af93ada65cbe78ad213 100644
--- a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h
+++ b/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h
@@ -28,6 +28,7 @@
#if ENABLE(WEB_AUTHN)
#include "LocalConnection.h"
+#include <WebCore/AuthenticatorAssertionResponse.h>
#include <WebCore/MockWebAuthenticationConfiguration.h>
namespace WebKit {
diff --git a/Source/WebKit/UIProcess/WebContextMenuProxy.h b/Source/WebKit/UIProcess/WebContextMenuProxy.h
index 2d2c5765c01f2680749a8f193d61fb666a08ab86..4a26ae64fee4c7e57e0336361ad92f9b024b5349 100644
--- a/Source/WebKit/UIProcess/WebContextMenuProxy.h
+++ b/Source/WebKit/UIProcess/WebContextMenuProxy.h
@@ -43,6 +43,7 @@ public:
virtual ~WebContextMenuProxy();
virtual void show();
+ virtual void hide() {}
WebPageProxy* page() const { return m_page.get(); }
diff --git a/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp b/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp
index 04f3227cd55c992a42cd96a3f25d697aed7965a2..f0d36935f47bab03ea2ec50b705092068ecd3efa 100644
--- a/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp
+++ b/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp
@@ -128,7 +128,8 @@ void WebGeolocationManagerProxy::startUpdating(IPC::Connection& connection, WebP
if (!wasUpdating) {
m_provider->setEnableHighAccuracy(*this, isHighAccuracyEnabled());
m_provider->startUpdating(*this);
- } else if (m_lastPosition)
+ }
+ if (m_lastPosition)
connection.send(Messages::WebGeolocationManager::DidChangePosition(m_lastPosition.value()), 0);
}
diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e6e700e846ea091a190b6b1f5c5636fed4389909
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebPageInspectorEmulationAgent.h"
+
+#include "APIPageConfiguration.h"
+#include "WebPageProxy.h"
+#include "WebPreferences.h"
+#include "PageClient.h"
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <WebCore/Credential.h>
+
+
+namespace WebKit {
+
+using namespace Inspector;
+
+WebPageInspectorEmulationAgent::WebPageInspectorEmulationAgent(BackendDispatcher& backendDispatcher, WebPageProxy& page)
+ : InspectorAgentBase("Emulation"_s)
+ , m_backendDispatcher(EmulationBackendDispatcher::create(backendDispatcher, this))
+ , m_page(page)
+{
+}
+
+WebPageInspectorEmulationAgent::~WebPageInspectorEmulationAgent()
+{
+}
+
+void WebPageInspectorEmulationAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
+{
+}
+
+void WebPageInspectorEmulationAgent::willDestroyFrontendAndBackend(DisconnectReason)
+{
+ m_commandsToRunWhenShown.clear();
+}
+
+void WebPageInspectorEmulationAgent::setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref<SetDeviceMetricsOverrideCallback>&& callback)
+{
+#if PLATFORM(GTK)
+ // On gtk, fixed layout doesn't work with compositing enabled
+ // FIXME: This turns off compositing forever, even if fixedLayout is disabled.
+ if (fixedlayout) {
+ auto copy = m_page.preferences().copy();
+ copy->setAcceleratedCompositingEnabled(false);
+ m_page.setPreferences(copy);
+ }
+#endif
+
+ m_page.setCustomDeviceScaleFactor(deviceScaleFactor);
+ m_page.setUseFixedLayout(fixedlayout);
+ if (!m_page.pageClient().isViewVisible() && m_page.configuration().relatedPage()) {
+ m_commandsToRunWhenShown.append([this, width, height, callback = WTFMove(callback)]() mutable {
+ setSize(width, height, WTFMove(callback));
+ });
+ } else {
+ setSize(width, height, WTFMove(callback));
+ }
+}
+
+void WebPageInspectorEmulationAgent::setSize(int width, int height, Ref<SetDeviceMetricsOverrideCallback>&& callback)
+{
+ platformSetSize(width, height, [callback = WTFMove(callback)](const String& error) {
+ if (error.isEmpty())
+ callback->sendSuccess();
+ else
+ callback->sendFailure(error);
+ });
+}
+
+Inspector::Protocol::ErrorStringOr<void> WebPageInspectorEmulationAgent::setJavaScriptEnabled(bool enabled)
+{
+ auto copy = m_page.preferences().copy();
+ copy->setJavaScriptEnabled(enabled);
+ m_page.setPreferences(copy);
+ return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> WebPageInspectorEmulationAgent::setAuthCredentials(const String& username, const String& password)
+{
+ if (!!username && !!password)
+ m_page.setAuthCredentialsForAutomation(WebCore::Credential(username, password, CredentialPersistencePermanent));
+ else
+ m_page.setAuthCredentialsForAutomation(Optional<WebCore::Credential>());
+ return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> WebPageInspectorEmulationAgent::setActiveAndFocused(Optional<bool>&& active)
+{
+ m_page.setActiveForAutomation(WTFMove(active));
+ return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> WebPageInspectorEmulationAgent::grantPermissions(const String& origin, Ref<JSON::Array>&& values)
+{
+ HashSet<String> set;
+ for (const auto& value : values.get()) {
+ String name;
+ if (!value->asString(name))
+ return makeUnexpected("Permission must be a string"_s);
+
+ set.add(name);
+ }
+ m_permissions.set(origin, WTFMove(set));
+ m_page.setPermissionsForAutomation(m_permissions);
+ return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> WebPageInspectorEmulationAgent::resetPermissions()
+{
+ m_permissions.clear();
+ m_page.setPermissionsForAutomation(m_permissions);
+ return { };
+}
+
+void WebPageInspectorEmulationAgent::didShowPage()
+{
+ for (auto& command : m_commandsToRunWhenShown)
+ command();
+ m_commandsToRunWhenShown.clear();
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..1353851472668b3e77c19db54f224c0ca151e9d3
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+
+#include <wtf/Forward.h>
+#include <wtf/Function.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+}
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class WebPageInspectorEmulationAgent : public Inspector::InspectorAgentBase, public Inspector::EmulationBackendDispatcherHandler {
+ WTF_MAKE_NONCOPYABLE(WebPageInspectorEmulationAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ WebPageInspectorEmulationAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page);
+ ~WebPageInspectorEmulationAgent() override;
+
+ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+ void setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref<SetDeviceMetricsOverrideCallback>&&) override;
+ Inspector::Protocol::ErrorStringOr<void> setJavaScriptEnabled(bool enabled) override;
+ Inspector::Protocol::ErrorStringOr<void> setAuthCredentials(const String&, const String&) override;
+ Inspector::Protocol::ErrorStringOr<void> setActiveAndFocused(Optional<bool>&&) override;
+ Inspector::Protocol::ErrorStringOr<void> grantPermissions(const String& origin, Ref<JSON::Array>&& permissions) override;
+ Inspector::Protocol::ErrorStringOr<void> resetPermissions() override;
+
+ void didShowPage();
+
+private:
+ void setSize(int width, int height, Ref<SetDeviceMetricsOverrideCallback>&& callback);
+ void platformSetSize(int width, int height, Function<void (const String& error)>&&);
+
+ Ref<Inspector::EmulationBackendDispatcher> m_backendDispatcher;
+ WebPageProxy& m_page;
+ Vector<Function<void()>> m_commandsToRunWhenShown;
+ HashMap<String, HashSet<String>> m_permissions;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5c16e0ef1e1593d8a1d26b149d0415136501ac6d
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebPageInspectorInputAgent.h"
+
+#include "NativeWebKeyboardEvent.h"
+#include "NativeWebMouseEvent.h"
+#include "WebPageProxy.h"
+#include <wtf/MathExtras.h>
+#include <wtf/HexNumber.h>
+
+#include "WebPageMessages.h"
+
+namespace WebKit {
+
+using namespace Inspector;
+
+namespace {
+
+template<class T>
+class CallbackList {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ ~CallbackList()
+ {
+ for (const auto& callback : m_callbacks)
+ callback->sendFailure("Page closed");
+ }
+
+ void append(Ref<T>&& callback)
+ {
+ m_callbacks.append(WTFMove(callback));
+ }
+
+ void sendSuccess()
+ {
+ for (const auto& callback : m_callbacks)
+ callback->sendSuccess();
+ m_callbacks.clear();
+ }
+
+private:
+ Vector<Ref<T>> m_callbacks;
+};
+
+} // namespace
+
+class WebPageInspectorInputAgent::KeyboardCallbacks : public CallbackList<Inspector::InputBackendDispatcherHandler::DispatchKeyEventCallback> {
+};
+
+class WebPageInspectorInputAgent::MouseCallbacks : public CallbackList<Inspector::InputBackendDispatcherHandler::DispatchMouseEventCallback> {
+};
+
+WebPageInspectorInputAgent::WebPageInspectorInputAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page)
+ : InspectorAgentBase("Input"_s)
+ , m_backendDispatcher(InputBackendDispatcher::create(backendDispatcher, this))
+ , m_page(page)
+{
+}
+
+WebPageInspectorInputAgent::~WebPageInspectorInputAgent() = default;
+
+void WebPageInspectorInputAgent::didProcessAllPendingKeyboardEvents()
+{
+ m_keyboardCallbacks->sendSuccess();
+}
+
+void WebPageInspectorInputAgent::didProcessAllPendingMouseEvents()
+{
+ m_mouseCallbacks->sendSuccess();
+}
+
+void WebPageInspectorInputAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
+{
+ m_keyboardCallbacks = makeUnique<KeyboardCallbacks>();
+ m_mouseCallbacks = makeUnique<MouseCallbacks>();
+}
+
+void WebPageInspectorInputAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
+{
+ m_keyboardCallbacks = nullptr;
+ m_mouseCallbacks = nullptr;
+}
+
+static String keyIdentifierForKey(const String& key)
+{
+ if (key.length() == 1)
+ return makeString("U+", hex(toASCIIUpper(key.characterAt(0)), 4));
+ if (key == "Delete")
+ return "U+007F";
+ if (key == "Backspace")
+ return "U+0008";
+ if (key == "ArrowUp")
+ return "Up";
+ if (key == "ArrowDown")
+ return "Down";
+ if (key == "ArrowLeft")
+ return "Left";
+ if (key == "ArrowRight")
+ return "Right";
+ if (key == "Tab")
+ return "U+0009";
+ if (key == "Pause")
+ return "Pause";
+ if (key == "ScrollLock")
+ return "Scroll";
+ return key;
+}
+
+void WebPageInspectorInputAgent::dispatchKeyEvent(const String& type, Optional<int>&& modifiers, const String& text, const String& unmodifiedText, const String& code, const String& key, Optional<int>&& windowsVirtualKeyCode, Optional<int>&& nativeVirtualKeyCode, Optional<bool>&& autoRepeat, Optional<bool>&& isKeypad, Optional<bool>&& isSystemKey, RefPtr<JSON::Array>&& commands, Ref<Inspector::InputBackendDispatcherHandler::DispatchKeyEventCallback>&& callback)
+{
+ WebKit::WebEvent::Type eventType;
+ if (type == "keyDown") {
+ eventType = WebKit::WebEvent::KeyDown;
+ } else if (type == "keyUp") {
+ eventType = WebKit::WebEvent::KeyUp;
+ } else {
+ callback->sendFailure("Unsupported event type.");
+ return;
+ }
+ OptionSet<WebEvent::Modifier> eventModifiers;
+ if (modifiers)
+ eventModifiers = eventModifiers.fromRaw(*modifiers);
+ int eventWindowsVirtualKeyCode = 0;
+ if (windowsVirtualKeyCode)
+ eventWindowsVirtualKeyCode = *windowsVirtualKeyCode;
+ int eventNativeVirtualKeyCode = 0;
+ if (nativeVirtualKeyCode)
+ eventNativeVirtualKeyCode = *nativeVirtualKeyCode;
+ Vector<String> eventCommands;
+ if (commands) {
+ for (const auto& value : *commands) {
+ String command;
+ if (!value->asString(command)) {
+ callback->sendFailure("Command must be string");
+ return;
+ }
+ eventCommands.append(command);
+ }
+ }
+
+ String keyIdentifier = keyIdentifierForKey(key);
+
+ bool eventIsAutoRepeat = false;
+ if (autoRepeat)
+ eventIsAutoRepeat = *autoRepeat;
+ bool eventIsKeypad = false;
+ if (isKeypad)
+ eventIsKeypad = *isKeypad;
+ bool eventIsSystemKey = false;
+ if (isSystemKey)
+ eventIsSystemKey = *isSystemKey;
+ WallTime timestamp = WallTime::now();
+
+ m_keyboardCallbacks->append(WTFMove(callback));
+ platformDispatchKeyEvent(
+ eventType,
+ text,
+ unmodifiedText,
+ key,
+ code,
+ keyIdentifier,
+ eventWindowsVirtualKeyCode,
+ eventNativeVirtualKeyCode,
+ eventIsAutoRepeat,
+ eventIsKeypad,
+ eventIsSystemKey,
+ eventModifiers,
+ eventCommands,
+ timestamp);
+}
+
+void WebPageInspectorInputAgent::dispatchMouseEvent(const String& type, int x, int y, Optional<int>&& modifiers, const String& button, Optional<int>&& buttons, Optional<int>&& clickCount, Optional<int>&& deltaX, Optional<int>&& deltaY, Ref<DispatchMouseEventCallback>&& callback)
+{
+ WebEvent::Type eventType = WebEvent::NoType;
+ if (type == "down")
+ eventType = WebEvent::MouseDown;
+ else if (type == "up")
+ eventType = WebEvent::MouseUp;
+ else if (type == "move")
+ eventType = WebEvent::MouseMove;
+ else {
+ callback->sendFailure("Unsupported event type");
+ return;
+ }
+
+ OptionSet<WebEvent::Modifier> eventModifiers;
+ if (modifiers)
+ eventModifiers = eventModifiers.fromRaw(*modifiers);
+
+ WebMouseEvent::Button eventButton = WebMouseEvent::NoButton;
+ if (!!button) {
+ if (button == "left")
+ eventButton = WebMouseEvent::LeftButton;
+ else if (button == "middle")
+ eventButton = WebMouseEvent::MiddleButton;
+ else if (button == "right")
+ eventButton = WebMouseEvent::RightButton;
+ else if (button == "none")
+ eventButton = WebMouseEvent::NoButton;
+ else {
+ callback->sendFailure("Unsupported eventButton");
+ return;
+ }
+ }
+
+ unsigned short eventButtons = 0;
+ if (buttons)
+ eventButtons = *buttons;
+
+ int eventClickCount = 0;
+ if (clickCount)
+ eventClickCount = *clickCount;
+ int eventDeltaX = 0;
+ if (deltaX)
+ eventDeltaX = *deltaX;
+ int eventDeltaY = 0;
+ if (deltaY)
+ eventDeltaY = *deltaY;
+ m_mouseCallbacks->append(WTFMove(callback));
+
+ // Convert css coordinates to view coordinates (dip).
+ double totalScale = m_page.pageScaleFactor() * m_page.viewScaleFactor();
+ x = clampToInteger(roundf(x * totalScale));
+ y = clampToInteger(roundf(y * totalScale));
+ eventDeltaX = clampToInteger(roundf(eventDeltaX * totalScale));
+ eventDeltaY = clampToInteger(roundf(eventDeltaY * totalScale));
+
+#if PLATFORM(MAC)
+ platformDispatchMouseEvent(type, x, y, WTFMove(modifiers), button, WTFMove(clickCount));
+#elif PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)
+ WallTime timestamp = WallTime::now();
+ NativeWebMouseEvent event(
+ eventType,
+ eventButton,
+ eventButtons,
+ {x, y},
+ WebCore::IntPoint(),
+ eventDeltaX,
+ eventDeltaY,
+ 0,
+ eventClickCount,
+ eventModifiers,
+ timestamp);
+ m_page.handleMouseEvent(event);
+#endif
+}
+
+void WebPageInspectorInputAgent::dispatchTapEvent(int x, int y, Optional<int>&& modifiers, Ref<DispatchTapEventCallback>&& callback) {
+ m_page.sendWithAsyncReply(Messages::WebPage::FakeTouchTap(IntPoint(x, y), modifiers ? *modifiers : 0), [callback]() {
+ callback->sendSuccess();
+ });
+}
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..05a71c27eae03f2cdf3bcba31a8b108b09b54178
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "WebEvent.h"
+#include "WebKeyboardEvent.h"
+#include <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+}
+
+namespace WebKit {
+
+class NativeWebKeyboardEvent;
+class WebPageProxy;
+
+class WebPageInspectorInputAgent : public Inspector::InspectorAgentBase, public Inspector::InputBackendDispatcherHandler {
+ WTF_MAKE_NONCOPYABLE(WebPageInspectorInputAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ WebPageInspectorInputAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page);
+ ~WebPageInspectorInputAgent() override;
+
+ void didProcessAllPendingKeyboardEvents();
+ void didProcessAllPendingMouseEvents();
+
+ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+ // Protocol handler
+ void dispatchKeyEvent(const String& type, Optional<int>&& modifiers, const String& text, const String& unmodifiedText, const String& code, const String& key, Optional<int>&& windowsVirtualKeyCode, Optional<int>&& nativeVirtualKeyCode, Optional<bool>&& autoRepeat, Optional<bool>&& isKeypad, Optional<bool>&& isSystemKey, RefPtr<JSON::Array>&&, Ref<DispatchKeyEventCallback>&& callback) override;
+ void dispatchMouseEvent(const String& type, int x, int y, Optional<int>&& modifiers, const String& button, Optional<int>&& buttons, Optional<int>&& clickCount, Optional<int>&& deltaX, Optional<int>&& deltaY, Ref<DispatchMouseEventCallback>&& callback) override;
+ void dispatchTapEvent(int x, int y, Optional<int>&& modifiers, Ref<DispatchTapEventCallback>&& callback) override;
+
+private:
+ void platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& commands, WallTime timestamp);
+#if PLATFORM(WPE)
+ void platformDispatchMouseEvent(WebMouseEvent::Type type, int x, int y, WebMouseEvent::Button button, OptionSet<WebEvent::Modifier> modifiers);
+#endif
+#if PLATFORM(MAC)
+ void platformDispatchMouseEvent(const String& type, int x, int y, Optional<int>&& modifier, const String& button, Optional<int>&& clickCount);
+#endif
+
+ Ref<Inspector::InputBackendDispatcher> m_backendDispatcher;
+ WebPageProxy& m_page;
+ // Keep track of currently active modifiers across multiple keystrokes.
+ // Most platforms do not track current modifiers from synthesized events.
+ unsigned m_currentModifiers { 0 };
+ class KeyboardCallbacks;
+ std::unique_ptr<KeyboardCallbacks> m_keyboardCallbacks;
+ class MouseCallbacks;
+ std::unique_ptr<MouseCallbacks> m_mouseCallbacks;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp
index 4300e1f522ff522748f2b1df9137df7a4d26c5a4..497f141ce1e6488c0897339338bc7044abc83c3d 100644
--- a/Source/WebKit/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp
@@ -984,6 +984,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason)
m_pageLoadState.didSwapWebProcesses();
if (reason != ProcessLaunchReason::InitialProcess)
m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
+ m_inspectorController->didFinishAttachingToWebProcess();
}
void WebPageProxy::didAttachToRunningProcess()
@@ -1296,6 +1297,21 @@ WebProcessProxy& WebPageProxy::ensureRunningProcess()
return m_process;
}
+RefPtr<API::Navigation> WebPageProxy::loadRequestForInspector(WebCore::ResourceRequest&& request, WebFrameProxy* frame)
+{
+ if (!frame || frame == mainFrame())
+ return loadRequest(WTFMove(request), WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow);
+
+ auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
+ LoadParameters loadParameters;
+ loadParameters.navigationID = navigation->navigationID();
+ loadParameters.request = WTFMove(request);
+ loadParameters.shouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow;
+ loadParameters.shouldTreatAsContinuingLoad = false;
+ m_process->send(Messages::WebPage::LoadRequestInFrameForInspector(loadParameters, frame->frameID()), m_webPageID);
+ return navigation;
+}
+
RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData)
{
if (m_isClosed)
@@ -1755,6 +1771,31 @@ void WebPageProxy::setControlledByAutomation(bool controlled)
websiteDataStore().networkProcess().send(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation), 0);
}
+void WebPageProxy::setAuthCredentialsForAutomation(Optional<WebCore::Credential>&& credentials)
+{
+ m_credentialsForAutomation = WTFMove(credentials);
+}
+
+void WebPageProxy::setPermissionsForAutomation(const HashMap<String, HashSet<String>>& permissions)
+{
+ m_permissionsForAutomation = permissions;
+}
+
+void WebPageProxy::setActiveForAutomation(Optional<bool> active) {
+ m_activeForAutomation = active;
+ OptionSet<ActivityState::Flag> state;
+ state.add(ActivityState::IsFocused);
+ state.add(ActivityState::WindowIsActive);
+ state.add(ActivityState::IsVisible);
+ state.add(ActivityState::IsVisibleOrOccluded);
+ activityStateDidChange(state);
+}
+
+void WebPageProxy::logToStderr(const String& str)
+{
+ fprintf(stderr, "RENDERER: %s\n", str.utf8().data());
+}
+
void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
{
MESSAGE_CHECK(m_process, !targetId.isEmpty());
@@ -1894,6 +1935,25 @@ void WebPageProxy::updateActivityState(OptionSet<ActivityState::Flag> flagsToUpd
{
bool wasVisible = isViewVisible();
m_activityState.remove(flagsToUpdate);
+
+
+ if (m_activeForAutomation) {
+ if (*m_activeForAutomation) {
+ if (flagsToUpdate & ActivityState::IsFocused)
+ m_activityState.add(ActivityState::IsFocused);
+ if (flagsToUpdate & ActivityState::WindowIsActive)
+ m_activityState.add(ActivityState::WindowIsActive);
+ if (flagsToUpdate & ActivityState::IsVisible)
+ m_activityState.add(ActivityState::IsVisible);
+ if (flagsToUpdate & ActivityState::IsVisibleOrOccluded)
+ m_activityState.add(ActivityState::IsVisibleOrOccluded);
+ }
+ flagsToUpdate.remove(ActivityState::IsFocused);
+ flagsToUpdate.remove(ActivityState::WindowIsActive);
+ flagsToUpdate.remove(ActivityState::IsVisible);
+ flagsToUpdate.remove(ActivityState::IsVisibleOrOccluded);
+ }
+
if (flagsToUpdate & ActivityState::IsFocused && pageClient().isViewFocused())
m_activityState.add(ActivityState::IsFocused);
if (flagsToUpdate & ActivityState::WindowIsActive && pageClient().isViewWindowActive())
@@ -2775,7 +2835,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();
@@ -2808,7 +2868,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
@@ -3227,6 +3287,7 @@ void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, A
void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, RefPtr<API::WebsitePolicies>&& websitePolicies, Ref<PolicyDecisionSender>&& sender, Optional<SandboxExtension::Handle> sandboxExtensionHandle, WillContinueLoadInNewProcess willContinueLoadInNewProcess)
{
+ m_inspectorController->didReceivePolicyDecision(action, navigation ? navigation->navigationID() : 0);
if (!hasRunningProcess()) {
sender->send(PolicyDecision { sender->identifier(), isNavigatingToAppBoundDomain(), PolicyAction::Ignore, 0, WTF::nullopt, WTF::nullopt });
return;
@@ -3923,6 +3984,11 @@ void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
m_pageScaleFactor = scaleFactor;
}
+void WebPageProxy::viewScaleFactorDidChange(double scaleFactor)
+{
+ m_viewScaleFactor = scaleFactor;
+}
+
void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
{
m_pluginScaleFactor = pluginScaleFactor;
@@ -4339,6 +4405,7 @@ void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
// FIXME: Message check the navigationID.
m_navigationState->didDestroyNavigation(navigationID);
+ m_inspectorController->didDestroyNavigation(navigationID);
}
void WebPageProxy::didStartProvisionalLoadForFrame(FrameIdentifier frameID, FrameInfoData&& frameInfo, ResourceRequest&& request, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData)
@@ -4561,6 +4628,8 @@ void WebPageProxy::didFailProvisionalLoadForFrameShared(Ref<WebProcessProxy>&& p
m_failingProvisionalLoadURL = { };
+ m_inspectorController->didFailProvisionalLoadForFrame(navigationID, error);
+
// If the provisional page's load fails then we destroy the provisional page.
if (m_provisionalPage && m_provisionalPage->mainFrame() == frame && willContinueLoading == WillContinueLoading::No)
m_provisionalPage = nullptr;
@@ -5007,7 +5076,14 @@ void WebPageProxy::decidePolicyForNavigationActionAsync(FrameIdentifier frameID,
NavigationActionData&& navigationActionData, FrameInfoData&& originatingFrameInfo, Optional<WebPageProxyIdentifier> originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&& request,
IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData& userData, uint64_t listenerID)
{
- decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, WTFMove(navigationActionData), WTFMove(originatingFrameInfo), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
+ if (m_inspectorController->shouldPauseLoading()) {
+ m_inspectorController->setContinueLoadingCallback([this, protectedThis = makeRef(*this), frameID, frameInfo = WTFMove(frameInfo), identifier, navigationID, navigationActionData = WTFMove(navigationActionData),
+ originatingFrameInfo = WTFMove(originatingFrameInfo), originatingPageID, originalRequest, request = WTFMove(request), requestBody = WTFMove(requestBody), redirectResponse = WTFMove(redirectResponse), userData, listenerID] () mutable {
+ decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, WTFMove(navigationActionData), WTFMove(originatingFrameInfo), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
+ });
+ } else {
+ decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, WTFMove(navigationActionData), WTFMove(originatingFrameInfo), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
+ }
}
void WebPageProxy::decidePolicyForNavigationActionAsyncShared(Ref<WebProcessProxy>&& process, PageIdentifier webPageID, FrameIdentifier frameID, FrameInfoData&& frameInfo,
@@ -5524,6 +5600,7 @@ void WebPageProxy::createNewPage(FrameInfoData&& originatingFrameInfoData, WebPa
auto* originatingPage = m_process->webPage(originatingPageID);
auto originatingFrameInfo = API::FrameInfo::create(WTFMove(originatingFrameInfoData), originatingPage);
auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : URL();
+ m_inspectorController->willCreateNewPage(windowFeatures, request.url());
auto completionHandler = [this, protectedThis = makeRef(*this), mainFrameURL, request, reply = WTFMove(reply), adClickAttribution = navigationActionData.adClickAttribution] (RefPtr<WebPageProxy> newPage) mutable {
if (!newPage) {
reply(WTF::nullopt, WTF::nullopt);
@@ -5554,6 +5631,7 @@ void WebPageProxy::createNewPage(FrameInfoData&& originatingFrameInfoData, WebPa
void WebPageProxy::showPage()
{
m_uiClient->showPage(this);
+ m_inspectorController->didShowPage();
}
void WebPageProxy::exitFullscreenImmediately()
@@ -5589,6 +5667,10 @@ void WebPageProxy::closePage()
if (isClosed())
return;
+#if ENABLE(CONTEXT_MENUS)
+ if (m_activeContextMenu)
+ m_activeContextMenu->hide();
+#endif
RELEASE_LOG_IF_ALLOWED(Process, "closePage:");
pageClient().clearAllEditCommands();
m_uiClient->close(this);
@@ -5608,6 +5690,8 @@ void WebPageProxy::runJavaScriptAlert(FrameIdentifier frameID, FrameInfoData&& f
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(frameInfo), WTFMove(reply));
}
@@ -5625,6 +5709,8 @@ void WebPageProxy::runJavaScriptConfirm(FrameIdentifier frameID, FrameInfoData&&
if (auto* automationSession = process().processPool().automationSession())
automationSession->willShowJavaScriptDialog(*this);
}
+ if (m_inspectorDialogAgent)
+ m_inspectorDialogAgent->javascriptDialogOpening("confirm"_s, message);
m_uiClient->runJavaScriptConfirm(*this, message, frame, WTFMove(frameInfo), WTFMove(reply));
}
@@ -5643,6 +5729,8 @@ void WebPageProxy::runJavaScriptPrompt(FrameIdentifier frameID, FrameInfoData&&
if (auto* automationSession = process().processPool().automationSession())
automationSession->willShowJavaScriptDialog(*this);
}
+ if (m_inspectorDialogAgent)
+ m_inspectorDialogAgent->javascriptDialogOpening("prompt"_s, message, defaultValue);
m_uiClient->runJavaScriptPrompt(*this, message, defaultValue, frame, WTFMove(frameInfo), WTFMove(reply));
}
@@ -5798,6 +5886,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(FrameIdentifier frameID, FrameInf
return;
}
}
+ if (m_inspectorDialogAgent)
+ m_inspectorDialogAgent->javascriptDialogOpening("beforeunload"_s, message);
// Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer and the tryClose timer.
m_process->stopResponsivenessTimer();
@@ -6944,6 +7034,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
if (auto* automationSession = process().processPool().automationSession())
automationSession->mouseEventsFlushedForPage(*this);
didFinishProcessingAllPendingMouseEvents();
+ m_inspectorController->didProcessAllPendingMouseEvents();
}
break;
}
@@ -6970,7 +7061,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
case WebEvent::RawKeyDown:
case WebEvent::Char: {
LOG(KeyHandling, "WebPageProxy::didReceiveEvent: %s (queue empty %d)", webKeyboardEventTypeString(type), m_keyEventQueue.isEmpty());
-
MESSAGE_CHECK(m_process, !m_keyEventQueue.isEmpty());
auto event = m_keyEventQueue.takeFirst();
MESSAGE_CHECK(m_process, type == event.type());
@@ -6989,7 +7079,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
// The call to doneWithKeyEvent may close this WebPage.
// Protect against this being destroyed.
Ref<WebPageProxy> protect(*this);
-
pageClient().doneWithKeyEvent(event, handled);
if (!handled)
m_uiClient->didNotHandleKeyEvent(this, event);
@@ -6998,6 +7087,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
if (!canProcessMoreKeyEvents) {
if (auto* automationSession = process().processPool().automationSession())
automationSession->keyboardEventsFlushedForPage(*this);
+ m_inspectorController->didProcessAllPendingKeyboardEvents();
}
break;
}
@@ -7409,7 +7499,6 @@ static bool shouldReloadAfterProcessTermination(ProcessTerminationReason reason)
void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason)
{
RELEASE_LOG_ERROR_IF_ALLOWED(Loading, "dispatchProcessDidTerminate: reason = %d", reason);
-
// We notify the client asynchronously because several pages may share the same process
// and we want to make sure all pages are aware their process has crashed before the
// the client reacts to the process termination.
@@ -7417,7 +7506,10 @@ void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason)
if (!weakThis)
return;
- bool handledByClient = false;
+ bool handledByClient = m_inspectorController->pageCrashed(reason);
+ if (handledByClient)
+ return;
+
if (m_loaderClient)
handledByClient = reason != ProcessTerminationReason::RequestedByClient && m_loaderClient->processDidCrash(*this);
else
@@ -7703,6 +7795,7 @@ static const Vector<ASCIILiteral>& attachmentElementServices()
WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& process, DrawingAreaProxy& drawingArea, RefPtr<API::WebsitePolicies>&& websitePolicies)
{
+
WebPageCreationParameters parameters;
parameters.processDisplayName = configuration().processDisplayName();
@@ -7862,6 +7955,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc
parameters.shouldRelaxThirdPartyCookieBlocking = m_configuration->shouldRelaxThirdPartyCookieBlocking();
parameters.canUseCredentialStorage = m_canUseCredentialStorage;
+ parameters.shouldPauseInInspectorWhenShown = m_inspectorController->shouldPauseLoading();
+
#if PLATFORM(GTK)
parameters.themeName = pageClient().themeName();
#endif
@@ -7931,6 +8026,14 @@ void WebPageProxy::gamepadActivity(const Vector<GamepadData>& gamepadDatas, Even
void WebPageProxy::didReceiveAuthenticationChallengeProxy(Ref<AuthenticationChallengeProxy>&& authenticationChallenge, NegotiatedLegacyTLS negotiatedLegacyTLS)
{
+ if (m_credentialsForAutomation.hasValue()) {
+ if (m_credentialsForAutomation->isEmpty() || authenticationChallenge->core().previousFailureCount()) {
+ authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::PerformDefaultHandling);
+ return;
+ }
+ authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::UseCredential, *m_credentialsForAutomation);
+ return;
+ }
if (negotiatedLegacyTLS == NegotiatedLegacyTLS::Yes) {
m_navigationClient->shouldAllowLegacyTLS(*this, authenticationChallenge.get(), [this, protectedThis = makeRef(*this), authenticationChallenge] (bool shouldAllowLegacyTLS) {
if (shouldAllowLegacyTLS)
@@ -8016,7 +8119,8 @@ void WebPageProxy::requestGeolocationPermissionForFrame(GeolocationIdentifier ge
MESSAGE_CHECK(m_process, frame);
// FIXME: Geolocation should probably be using toString() as its string representation instead of databaseIdentifier().
- auto origin = API::SecurityOrigin::create(frameInfo.securityOrigin.securityOrigin());
+ auto securityOrigin = frameInfo.securityOrigin.securityOrigin();
+ auto origin = API::SecurityOrigin::create(securityOrigin);
auto request = m_geolocationPermissionRequestManager.createRequest(geolocationID);
Function<void(bool)> completionHandler = [request = WTFMove(request)](bool allowed) {
if (allowed)
@@ -8025,6 +8129,14 @@ void WebPageProxy::requestGeolocationPermissionForFrame(GeolocationIdentifier ge
request->deny();
};
+ auto permissions = m_permissionsForAutomation.find(securityOrigin->toString());
+ if (permissions == m_permissionsForAutomation.end())
+ permissions = m_permissionsForAutomation.find("*");
+ if (permissions != m_permissionsForAutomation.end()) {
+ completionHandler(permissions->value.contains("geolocation"));
+ return;
+ }
+
// FIXME: Once iOS migrates to the new WKUIDelegate SPI, clean this up
// and make it one UIClient call that calls the completionHandler with false
// if there is no delegate instead of returning the completionHandler
diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h
index 7cefbfc6945edfe43ae56c2d564c0e81e95bb4a6..968e6495ce2de6906cf68150e67d0de382aedc56 100644
--- a/Source/WebKit/UIProcess/WebPageProxy.h
+++ b/Source/WebKit/UIProcess/WebPageProxy.h
@@ -37,6 +37,7 @@
#include "GeolocationIdentifier.h"
#include "GeolocationPermissionRequestManagerProxy.h"
#include "HiddenPageThrottlingAutoIncreasesCounter.h"
+#include "InspectorDialogAgent.h"
#include "LayerTreeContext.h"
#include "MediaPlaybackState.h"
#include "MessageSender.h"
@@ -512,6 +513,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();
@@ -583,6 +586,11 @@ public:
void setPageLoadStateObserver(std::unique_ptr<PageLoadState::Observer>&&);
+ void setAuthCredentialsForAutomation(Optional<WebCore::Credential>&&);
+ void setPermissionsForAutomation(const HashMap<String, HashSet<String>>&);
+ void setActiveForAutomation(Optional<bool> active);
+ void logToStderr(const String& str);
+
void initializeWebPage();
void setDrawingArea(std::unique_ptr<DrawingAreaProxy>&&);
@@ -608,6 +616,7 @@ public:
void closePage();
void addPlatformLoadParameters(WebProcessProxy&, LoadParameters&);
+ RefPtr<API::Navigation> loadRequestForInspector(WebCore::ResourceRequest&&, WebFrameProxy*);
RefPtr<API::Navigation> loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemesButNotAppLinks, API::Object* userData = nullptr);
RefPtr<API::Navigation> loadFile(const String& fileURL, const String& resourceDirectoryURL, API::Object* userData = nullptr);
RefPtr<API::Navigation> loadData(const IPC::DataReference&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData = nullptr, WebCore::ShouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow);
@@ -1107,6 +1116,7 @@ public:
#endif
void pageScaleFactorDidChange(double);
+ void viewScaleFactorDidChange(double);
void pluginScaleFactorDidChange(double);
void pluginZoomFactorDidChange(double);
@@ -1425,6 +1435,8 @@ public:
#if PLATFORM(COCOA) || PLATFORM(GTK)
RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&);
+#elif PLATFORM(WPE)
+ RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&) { return nullptr; }
#endif
#if ENABLE(WEB_CRYPTO)
@@ -2430,6 +2442,7 @@ private:
String m_overrideContentSecurityPolicy;
RefPtr<WebInspectorProxy> m_inspector;
+ InspectorDialogAgent* m_inspectorDialogAgent { nullptr };
#if ENABLE(FULLSCREEN_API)
std::unique_ptr<WebFullScreenManagerProxy> m_fullScreenManager;
@@ -2865,6 +2878,9 @@ private:
RefPtr<API::Object> messageBody;
};
Vector<InjectedBundleMessage> m_pendingInjectedBundleMessages;
+ Optional<WebCore::Credential> m_credentialsForAutomation;
+ HashMap<String, HashSet<String>> m_permissionsForAutomation;
+ Optional<bool> m_activeForAutomation;
#if PLATFORM(IOS_FAMILY) && ENABLE(DEVICE_ORIENTATION)
std::unique_ptr<WebDeviceOrientationUpdateProviderProxy> m_webDeviceOrientationUpdateProviderProxy;
diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in
index 012307ee3dd1908731acd63e7b79932a39ea0fc8..2c8f025e7610fa80e2a206cd0d821d35f733ad85 100644
--- a/Source/WebKit/UIProcess/WebPageProxy.messages.in
+++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in
@@ -29,6 +29,7 @@ messages -> WebPageProxy {
RunJavaScriptConfirm(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, String message) -> (bool result) Synchronous
RunJavaScriptPrompt(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, String message, String defaultValue) -> (String result) Synchronous
MouseDidMoveOverElement(struct WebKit::WebHitTestResultData hitTestResultData, uint32_t modifiers, WebKit::UserData userData)
+ LogToStderr(String text)
#if ENABLE(NETSCAPE_PLUGIN_API)
UnavailablePluginButtonClicked(uint32_t pluginUnavailabilityReason, String mimeType, String pluginURLString, String pluginspageAttributeURLString, String frameURLString, String pageURLString)
@@ -207,6 +208,7 @@ messages -> WebPageProxy {
#endif
PageScaleFactorDidChange(double scaleFactor)
+ ViewScaleFactorDidChange(double scaleFactor)
PluginScaleFactorDidChange(double zoomFactor)
PluginZoomFactorDidChange(double zoomFactor)
diff --git a/Source/WebKit/UIProcess/WebProcessPool.cpp b/Source/WebKit/UIProcess/WebProcessPool.cpp
index e0451fb48b2d27780a1ade9cf3d12f66b4e44e4b..424418990fdf7d8d204d7e017d184620a75dfecb 100644
--- a/Source/WebKit/UIProcess/WebProcessPool.cpp
+++ b/Source/WebKit/UIProcess/WebProcessPool.cpp
@@ -528,6 +528,14 @@ void WebProcessPool::establishWorkerContextConnectionToNetworkProcess(NetworkPro
// Arbitrarily choose the first process pool to host the service worker process.
auto* processPool = processPools()[0];
+ // Playwright begin
+ for (auto& process : websiteDataStore->processes()) {
+ if (process.processPoolIfExists()) {
+ processPool = process.processPoolIfExists();
+ break;
+ }
+ }
+ // Playwright end
ASSERT(processPool);
WebProcessProxy* serviceWorkerProcessProxy { nullptr };
@@ -764,7 +772,10 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa
#endif
parameters.cacheModel = LegacyGlobalSettings::singleton().cacheModel();
- parameters.overrideLanguages = configuration().overrideLanguages();
+ if (websiteDataStore && websiteDataStore->languagesForAutomation().size())
+ parameters.overrideLanguages = websiteDataStore->languagesForAutomation();
+ else
+ parameters.overrideLanguages = configuration().overrideLanguages();
parameters.urlSchemesRegisteredAsEmptyDocument = copyToVector(m_schemesToRegisterAsEmptyDocument);
parameters.urlSchemesRegisteredAsSecure = copyToVector(LegacyGlobalSettings::singleton().schemesToRegisterAsSecure());
diff --git a/Source/WebKit/UIProcess/WebProcessProxy.cpp b/Source/WebKit/UIProcess/WebProcessProxy.cpp
index 19863f5616e52c864ab264f1016e63bc9d8ff35d..158c9c6811ed61c2eb5d1829716f8ed3dd0cfeda 100644
--- a/Source/WebKit/UIProcess/WebProcessProxy.cpp
+++ b/Source/WebKit/UIProcess/WebProcessProxy.cpp
@@ -117,6 +117,11 @@ HashMap<ProcessIdentifier, WebProcessProxy*>& WebProcessProxy::allProcesses()
return map;
}
+Vector<WebProcessProxy*> WebProcessProxy::allProcessesForInspector()
+{
+ return copyToVector(allProcesses().values());
+}
+
WebProcessProxy* WebProcessProxy::processForIdentifier(ProcessIdentifier identifier)
{
return allProcesses().get(identifier);
diff --git a/Source/WebKit/UIProcess/WebProcessProxy.h b/Source/WebKit/UIProcess/WebProcessProxy.h
index 11e840a1998c57c66102df987d0f267a7b2c6040..f655644eac17673987b62c78a77e1c1714056930 100644
--- a/Source/WebKit/UIProcess/WebProcessProxy.h
+++ b/Source/WebKit/UIProcess/WebProcessProxy.h
@@ -132,6 +132,7 @@ public:
~WebProcessProxy();
static void forWebPagesWithOrigin(PAL::SessionID, const WebCore::SecurityOriginData&, const Function<void(WebPageProxy&)>&);
+ static Vector<WebProcessProxy*> allProcessesForInspector();
WebConnection* webConnection() const { return m_webConnection.get(); }
diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
index dad20701bd39893985c842c8a1866a5f50ce5fd5..b8596574da4974fe58df1ae956a622b33f0a9a18 100644
--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
@@ -2310,6 +2310,17 @@ void WebsiteDataStore::renameOriginInWebsiteData(URL&& oldName, URL&& newName, O
networkProcess().renameOriginInWebsiteData(m_sessionID, oldName, newName, dataTypes, WTFMove(completionHandler));
}
+void WebsiteDataStore::setLanguagesForAutomation(Vector<String>&& languages)
+{
+ m_languagesForAutomation = WTFMove(languages);
+}
+
+void WebsiteDataStore::setDownloadForAutomation(Optional<bool> allow, const String& downloadPath)
+{
+ m_allowDownloadForAutomation = allow;
+ m_downloadPathForAutomation = downloadPath;
+}
+
#if ENABLE(APP_BOUND_DOMAINS)
void WebsiteDataStore::hasAppBoundSession(CompletionHandler<void(bool)>&& completionHandler) const
{
diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
index f3fe66d05941aa3f17dc293252f507c25fbc1bce..05b2e11b7c021d0cfb023edbe1f432f7cf0e8071 100644
--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
@@ -92,6 +92,7 @@ enum class CacheModel : uint8_t;
enum class WebsiteDataFetchOption : uint8_t;
enum class WebsiteDataType : uint32_t;
+struct FrameInfoData;
struct NetworkProcessConnectionInfo;
struct WebsiteDataRecord;
struct WebsiteDataStoreParameters;
@@ -106,6 +107,16 @@ enum class StorageAccessPromptStatus;
struct PluginModuleInfo;
#endif
+class WebsiteDataStore;
+
+class DownloadInstrumentation {
+public:
+ virtual void downloadCreated(const String& uuid, const WebCore::ResourceRequest&, const FrameInfoData& frameInfoData, WebPageProxy* page) = 0;
+ virtual void downloadFilenameSuggested(const String& uuid, const String& suggestedFilename) = 0;
+ virtual void downloadFinished(const String& uuid, const String& error) = 0;
+ virtual ~DownloadInstrumentation() = default;
+};
+
class WebsiteDataStore : public API::ObjectImpl<API::Object::Type::WebsiteDataStore>, public Identified<WebsiteDataStore>, public CanMakeWeakPtr<WebsiteDataStore> {
public:
static Ref<WebsiteDataStore> defaultDataStore();
@@ -275,11 +286,13 @@ public:
const WebCore::CurlProxySettings& networkProxySettings() const { return m_proxySettings; }
#endif
-#if USE(SOUP)
+#if USE(SOUP) || PLATFORM(COCOA) || PLATFORM(WIN)
void setPersistentCredentialStorageEnabled(bool);
bool persistentCredentialStorageEnabled() const { return m_persistentCredentialStorageEnabled && isPersistent(); }
void setIgnoreTLSErrors(bool);
bool ignoreTLSErrors() const { return m_ignoreTLSErrors; }
+#endif
+#if USE(SOUP)
void setNetworkProxySettings(WebCore::SoupNetworkProxySettings&&);
const WebCore::SoupNetworkProxySettings& networkProxySettings() const { return m_networkProxySettings; }
#endif
@@ -332,6 +345,14 @@ public:
static WTF::String defaultJavaScriptConfigurationDirectory();
static bool http3Enabled();
+ void setLanguagesForAutomation(Vector<String>&&);
+ Vector<String>& languagesForAutomation() { return m_languagesForAutomation; };
+ void setDownloadForAutomation(Optional<bool> allow, const String& downloadPath);
+ Optional<bool> allowDownloadForAutomation() { return m_allowDownloadForAutomation; };
+ String downloadPathForAutomation() { return m_downloadPathForAutomation; };
+ void setDownloadInstrumentation(DownloadInstrumentation* instrumentation) { m_downloadInstrumentation = instrumentation; };
+ DownloadInstrumentation* downloadInstrumentation() { return m_downloadInstrumentation; };
+
void resetQuota(CompletionHandler<void()>&&);
#if ENABLE(APP_BOUND_DOMAINS)
@@ -416,9 +437,11 @@ private:
WebCore::CurlProxySettings m_proxySettings;
#endif
-#if USE(SOUP)
+#if USE(SOUP) || PLATFORM(COCOA) || PLATFORM(WIN)
bool m_persistentCredentialStorageEnabled { true };
bool m_ignoreTLSErrors { true };
+#endif
+#if USE(SOUP)
WebCore::SoupNetworkProxySettings m_networkProxySettings;
#endif
@@ -443,6 +466,11 @@ private:
RefPtr<API::HTTPCookieStore> m_cookieStore;
RefPtr<NetworkProcessProxy> m_networkProcess;
+ Vector<String> m_languagesForAutomation;
+ Optional<bool> m_allowDownloadForAutomation;
+ String m_downloadPathForAutomation;
+ DownloadInstrumentation* m_downloadInstrumentation { nullptr };
+
#if HAVE(APP_SSO)
UniqueRef<SOAuthorizationCoordinator> m_soAuthorizationCoordinator;
#endif
diff --git a/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp b/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp
index dc0a70b8824afdc7ec3dd1f69f4d9b51942924f6..a4e90dc22fb278864c49c0636964e82f3d0d7193 100644
--- a/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp
+++ b/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp
@@ -27,9 +27,11 @@
#include "config.h"
#include "BackingStore.h"
+#include "DrawingAreaProxyCoordinatedGraphics.h"
#include "ShareableBitmap.h"
#include "UpdateInfo.h"
#include "WebPageProxy.h"
+#include "WebPageInspectorController.h"
#include <WebCore/BackingStoreBackendCairoImpl.h>
#include <WebCore/CairoUtilities.h>
#include <WebCore/GraphicsContextImplCairo.h>
@@ -62,6 +64,13 @@ std::unique_ptr<BackingStoreBackendCairo> BackingStore::createBackend()
return makeUnique<BackingStoreBackendCairoImpl>(m_size, m_deviceScaleFactor);
}
+cairo_surface_t* BackingStore::surface() const {
+ if (!m_backend)
+ return nullptr;
+
+ return m_backend->surface();
+}
+
void BackingStore::paint(cairo_t* context, const IntRect& rect)
{
ASSERT(m_backend);
diff --git a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp
index 411056d43ea764c42bce0403e6c69ddb8b24b04e..86d4e842699a230ce595088b62a29eabea5b6b90 100644
--- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp
+++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp
@@ -60,6 +60,8 @@ void GeoclueGeolocationProvider::start(UpdateNotifyFunction&& updateNotifyFuncti
m_isRunning = true;
m_cancellable = adoptGRef(g_cancellable_new());
if (!m_manager) {
+ g_cancellable_cancel(m_cancellable_start.get());
+ m_cancellable_start = adoptGRef(g_cancellable_new());
g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr,
"org.freedesktop.GeoClue2", "/org/freedesktop/GeoClue2/Manager", "org.freedesktop.GeoClue2.Manager", m_cancellable.get(),
[](GObject*, GAsyncResult* result, gpointer userData) {
@@ -91,6 +93,12 @@ void GeoclueGeolocationProvider::stop()
g_cancellable_cancel(m_cancellable.get());
m_cancellable = nullptr;
stopClient();
+ g_cancellable_cancel(m_cancellable_start.get());
+ m_cancellable_start = nullptr;
+ g_cancellable_cancel(m_cancellable_setup.get());
+ m_cancellable_setup = nullptr;
+ g_cancellable_cancel(m_cancellable_create.get());
+ m_cancellable_create = nullptr;
destroyManagerLater();
}
@@ -153,6 +161,8 @@ void GeoclueGeolocationProvider::createClient(const char* clientPath)
return;
}
+ g_cancellable_cancel(m_cancellable_create.get());
+ m_cancellable_create = adoptGRef(g_cancellable_new());
g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr,
"org.freedesktop.GeoClue2", clientPath, "org.freedesktop.GeoClue2.Client", m_cancellable.get(),
[](GObject*, GAsyncResult* result, gpointer userData) {
diff --git a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h
index 31d29091985f34a65134a2b0e7cb3ace1dae441d..571ceac8a4b291fa6e91eb8b17065c0aba908ac3 100644
--- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h
+++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h
@@ -71,6 +71,9 @@ private:
GRefPtr<GDBusProxy> m_manager;
GRefPtr<GDBusProxy> m_client;
GRefPtr<GCancellable> m_cancellable;
+ GRefPtr<GCancellable> m_cancellable_start;
+ GRefPtr<GCancellable> m_cancellable_setup;
+ GRefPtr<GCancellable> m_cancellable_create;
UpdateNotifyFunction m_updateNotifyFunction;
RunLoop::Timer<GeoclueGeolocationProvider> m_destroyManagerLaterTimer;
};
diff --git a/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..31a4e32d4cf8442049f0bea04c817a40b801c1f7
--- /dev/null
+++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorPlaywrightAgentClientGLib.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgent.h"
+#include "WebKitBrowserInspectorPrivate.h"
+#include "WebKitWebContextPrivate.h"
+#include "WebKitWebsiteDataManagerPrivate.h"
+#include "WebKitWebViewPrivate.h"
+#include "WebPageProxy.h"
+#include <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/StringView.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+static WebCore::SoupNetworkProxySettings parseRawProxySettings(const String& proxyServer, const char* const* ignoreHosts)
+{
+ WebCore::SoupNetworkProxySettings settings;
+ if (proxyServer.isEmpty())
+ return settings;
+
+ settings.mode = WebCore::SoupNetworkProxySettings::Mode::Custom;
+ settings.defaultProxyURL = proxyServer.utf8();
+ settings.ignoreHosts.reset(g_strdupv(const_cast<char**>(ignoreHosts)));
+ return settings;
+}
+
+static WebCore::SoupNetworkProxySettings parseProxySettings(const String& proxyServer, const String& proxyBypassList)
+{
+ Vector<const char*> ignoreHosts;
+ if (!proxyBypassList.isEmpty()) {
+ Vector<String> tokens = proxyBypassList.split(',');
+ Vector<CString> protectTokens;
+ for (String token : tokens) {
+ CString cstr = token.utf8();
+ ignoreHosts.append(cstr.data());
+ protectTokens.append(WTFMove(cstr));
+ }
+ }
+ ignoreHosts.append(nullptr);
+ return parseRawProxySettings(proxyServer, ignoreHosts.data());
+}
+
+InspectorPlaywrightAgentClientGlib::InspectorPlaywrightAgentClientGlib(const WTF::String& proxyURI, const char* const* ignoreHosts)
+ : m_proxySettings(parseRawProxySettings(proxyURI, ignoreHosts))
+{
+}
+
+RefPtr<WebPageProxy> InspectorPlaywrightAgentClientGlib::createPage(WTF::String& error, const BrowserContext& browserContext)
+{
+ auto sessionID = browserContext.dataStore->sessionID();
+ WebKitWebContext* context = m_idToContext.get(sessionID);
+ if (!context && !browserContext.dataStore->isPersistent()) {
+ ASSERT_NOT_REACHED();
+ error = "Context with provided id not found";
+ return nullptr;
+ }
+
+ RefPtr<WebPageProxy> page = webkitBrowserInspectorCreateNewPageInContext(context);
+ if (page == nullptr) {
+ error = "Failed to create new page in the context";
+ return nullptr;
+ }
+
+ if (context == nullptr && sessionID != page->sessionID()) {
+ ASSERT_NOT_REACHED();
+ error = " Failed to create new page in default context";
+ return nullptr;
+ }
+
+ return page;
+}
+
+void InspectorPlaywrightAgentClientGlib::closeBrowser()
+{
+ m_idToContext.clear();
+ webkitBrowserInspectorQuitApplication();
+ if (webkitWebContextExistingCount() > 1)
+ fprintf(stderr, "LEAK: %d contexts are still alive when closing browser\n", webkitWebContextExistingCount());
+}
+
+static PAL::SessionID sessionIDFromContext(WebKitWebContext* context)
+{
+ WebKitWebsiteDataManager* data_manager = webkit_web_context_get_website_data_manager(context);
+ WebsiteDataStore& websiteDataStore = webkitWebsiteDataManagerGetDataStore(data_manager);
+ return websiteDataStore.sessionID();
+}
+
+std::unique_ptr<BrowserContext> InspectorPlaywrightAgentClientGlib::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList)
+{
+ GRefPtr<WebKitWebsiteDataManager> data_manager = adoptGRef(webkit_website_data_manager_new_ephemeral());
+ GRefPtr<WebKitWebContext> context = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", data_manager.get(), "process-swap-on-cross-site-navigation-enabled", true, nullptr)));
+ if (!context) {
+ error = "Failed to create GLib ephemeral context";
+ return nullptr;
+ }
+ auto browserContext = std::make_unique<BrowserContext>();
+ browserContext->processPool = &webkitWebContextGetProcessPool(context.get());
+ browserContext->dataStore = &webkitWebsiteDataManagerGetDataStore(data_manager.get());
+ PAL::SessionID sessionID = sessionIDFromContext(context.get());
+ m_idToContext.set(sessionID, WTFMove(context));
+
+ if (!proxyServer.isEmpty()) {
+ WebCore::SoupNetworkProxySettings contextProxySettings = parseProxySettings(proxyServer, proxyBypassList);
+ browserContext->dataStore->setNetworkProxySettings(WTFMove(contextProxySettings));
+ } else {
+ browserContext->dataStore->setNetworkProxySettings(WebCore::SoupNetworkProxySettings(m_proxySettings));
+ }
+ return browserContext;
+}
+
+void InspectorPlaywrightAgentClientGlib::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
+{
+ m_idToContext.remove(sessionID);
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h
new file mode 100644
index 0000000000000000000000000000000000000000..8006336003a4512b4c63bc8272d4b3507bb63159
--- /dev/null
+++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgentClient.h"
+#include <WebCore/SoupNetworkProxySettings.h>
+#include "WebKitWebContext.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebKit {
+
+class InspectorPlaywrightAgentClientGlib : public InspectorPlaywrightAgentClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorPlaywrightAgentClientGlib(const WTF::String& proxyURI, const char* const* ignoreHosts);
+ ~InspectorPlaywrightAgentClientGlib() override = default;
+
+ RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
+ void closeBrowser() override;
+ std::unique_ptr<BrowserContext> createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) override;
+ void deleteBrowserContext(WTF::String& error, PAL::SessionID) override;
+
+private:
+ WebKitWebContext* findContext(WTF::String& error, PAL::SessionID);
+
+ HashMap<PAL::SessionID, GRefPtr<WebKitWebContext>> m_idToContext;
+ WebCore::SoupNetworkProxySettings m_proxySettings;
+};
+
+} // namespace API
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h
index 39aeff71fe05354cf63d3b3701d363642d63aca4..32e96cdd0bdbd8c5dcde43fdf60052ac13a226f7 100644
--- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h
+++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h
@@ -28,6 +28,7 @@
#include <wtf/Noncopyable.h>
typedef struct _cairo cairo_t;
+typedef struct _cairo_surface cairo_surface_t;
#if USE(GTK4)
typedef struct _GdkSnapshot GdkSnapshot;
@@ -56,6 +57,8 @@ public:
#else
virtual bool paint(cairo_t*, const WebCore::IntRect&) = 0;
#endif
+ virtual cairo_surface_t* surface() { return nullptr; }
+
virtual void realize() { };
virtual void unrealize() { };
virtual bool makeContextCurrent() { return false; }
diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.h b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.h
index 054e80bd900cf16d69801e8102ca989ff0563e1d..8245d7ed58008dbb6152e55e619e4331d30ae674 100644
--- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.h
+++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.h
@@ -52,6 +52,7 @@ private:
#else
bool paint(cairo_t*, const WebCore::IntRect&) override;
#endif
+ cairo_surface_t* surface() override { return m_surface.get(); }
RefPtr<cairo_surface_t> m_surface;
WebCore::XUniqueDamage m_damage;
diff --git a/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp b/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8a86cc348bc210b71bb463dcb3057f575ad7c1d3
--- /dev/null
+++ b/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorTargetProxy.h"
+
+#include "WebPageProxy.h"
+#include <WebCore/GtkUtilities.h>
+#include <gtk/gtk.h>
+
+namespace WebKit {
+
+void InspectorTargetProxy::platformActivate(String& error) const
+{
+ GtkWidget* parent = gtk_widget_get_toplevel(m_page.viewWidget());
+ if (WebCore::widgetIsOnscreenToplevelWindow(parent))
+ gtk_window_present(GTK_WINDOW(parent));
+ else
+ error = "The view is not on screen";
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e5e25acebabb76a05a77db02a99f1267bd99a3af
--- /dev/null
+++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DrawingAreaProxyCoordinatedGraphics.h"
+#include "WebPageInspectorEmulationAgent.h"
+#include "WebPageProxy.h"
+#include <WebCore/IntSize.h>
+#include <gtk/gtk.h>
+
+namespace WebKit {
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
+{
+ GtkWidget* viewWidget = m_page.viewWidget();
+ GtkWidget* window = gtk_widget_get_toplevel(viewWidget);
+ if (!window) {
+ callback("Cannot find parent window"_s);
+ return;
+ }
+ if (!GTK_IS_WINDOW(window)) {
+ callback("Toplevel is not a window"_s);
+ return;
+ }
+ GtkAllocation viewAllocation;
+ gtk_widget_get_allocation(viewWidget, &viewAllocation);
+ if (viewAllocation.width == width && viewAllocation.height == height) {
+ callback(String());
+ return;
+ }
+
+ GtkAllocation windowAllocation;
+ gtk_widget_get_allocation(window, &windowAllocation);
+
+ width += windowAllocation.width - viewAllocation.width;
+ height += windowAllocation.height - viewAllocation.height;
+
+ if (auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(m_page.drawingArea())) {
+ drawingArea->waitForSizeUpdate([callback = WTFMove(callback)]() {
+ callback(String());
+ });
+ } else {
+ callback("No backing store for window"_s);
+ }
+ gtk_window_resize(GTK_WINDOW(window), width, height);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d0f9827544994e450e24e3f7a427c35eeff94d67
--- /dev/null
+++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebPageInspectorInputAgent.h"
+
+#include "KeyBindingTranslator.h"
+#include "NativeWebKeyboardEvent.h"
+#include "WebPageProxy.h"
+#include <WebCore/PlatformKeyboardEvent.h>
+
+namespace WebKit {
+
+static Vector<String> commandsForKeyEvent(GdkEventType type, unsigned keyVal, unsigned state)
+{
+ ASSERT(type == GDK_KEY_PRESS || type == GDK_KEY_RELEASE);
+
+ GUniquePtr<GdkEvent> event(gdk_event_new(type));
+ event->key.keyval = keyVal;
+ event->key.time = GDK_CURRENT_TIME;
+ event->key.state = state;
+ // When synthesizing an event, an invalid hardware_keycode value can cause it to be badly processed by GTK+.
+ GUniqueOutPtr<GdkKeymapKey> keys;
+ int keysCount;
+ if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyVal, &keys.outPtr(), &keysCount) && keysCount)
+ event->key.hardware_keycode = keys.get()[0].keycode;
+ return KeyBindingTranslator().commandsForKeyEvent(&event->key);
+}
+
+static unsigned modifiersToEventState(OptionSet<WebEvent::Modifier> modifiers)
+{
+ unsigned state = 0;
+ if (modifiers.contains(WebEvent::Modifier::ControlKey))
+ state |= GDK_CONTROL_MASK;
+ if (modifiers.contains(WebEvent::Modifier::ShiftKey))
+ state |= GDK_SHIFT_MASK;
+ if (modifiers.contains(WebEvent::Modifier::AltKey))
+ state |= GDK_META_MASK;
+ if (modifiers.contains(WebEvent::Modifier::CapsLockKey))
+ state |= GDK_LOCK_MASK;
+ return state;
+}
+
+void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& macCommands, WallTime timestamp)
+{
+ Vector<String> commands;
+ const guint keyVal = WebCore::PlatformKeyboardEvent::gdkKeyCodeForWindowsKeyCode(windowsVirtualKeyCode);
+ if (keyVal) {
+ GdkEventType event = GDK_NOTHING;
+ switch (type)
+ {
+ case WebKeyboardEvent::KeyDown:
+ event = GDK_KEY_PRESS;
+ break;
+ case WebKeyboardEvent::KeyUp:
+ event = GDK_KEY_RELEASE;
+ break;
+ default:
+ fprintf(stderr, "Unsupported event type = %d\n", type);
+ break;
+ }
+ unsigned state = modifiersToEventState(modifiers);
+ commands = commandsForKeyEvent(event, keyVal, state);
+ }
+ NativeWebKeyboardEvent event(
+ type,
+ text,
+ unmodifiedText,
+ key,
+ code,
+ keyIdentifier,
+ windowsVirtualKeyCode,
+ nativeVirtualKeyCode,
+ isAutoRepeat,
+ isKeypad,
+ isSystemKey,
+ modifiers,
+ timestamp,
+ WTFMove(commands));
+ m_page.handleKeyboardEvent(event);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
index afcc45e9376d73a64d12a6ca7905fa72556c5aed..474de8a4dc0f3d8bdbfe9e386dba7c0e8095cf1d 100644
--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
@@ -435,6 +435,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
{
+ if (!event.nativeEvent())
+ return;
[m_contentView _didHandleKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled];
}
diff --git a/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h
new file mode 100644
index 0000000000000000000000000000000000000000..a16815a6759da61a6a61e3d79058228af887fd7c
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "InspectorPlaywrightAgentClient.h"
+#include <wtf/Forward.h>
+
+OBJC_PROTOCOL(_WKBrowserInspectorDelegate);
+
+namespace WebKit {
+
+class InspectorPlaywrightAgentClientMac : public InspectorPlaywrightAgentClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorPlaywrightAgentClientMac(_WKBrowserInspectorDelegate* delegate);
+ ~InspectorPlaywrightAgentClientMac() override = default;
+
+ RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
+ void closeBrowser() override;
+ std::unique_ptr<BrowserContext> createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) override;
+ void deleteBrowserContext(WTF::String& error, PAL::SessionID) override;
+
+private:
+ _WKBrowserInspectorDelegate* delegate_;
+};
+
+
+} // namespace API
diff --git a/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..8e588f7b8c8c29fb53dd37ea41d46f3d753077fd
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "InspectorPlaywrightAgentClientMac.h"
+
+#import <wtf/RefPtr.h>
+#import <wtf/text/WTFString.h>
+#import "WebPageProxy.h"
+#import "WebProcessPool.h"
+#import "WebsiteDataStore.h"
+#import "_WKBrowserInspector.h"
+#import "WKProcessPoolInternal.h"
+#import "WKWebsiteDataStoreInternal.h"
+#import "WKWebView.h"
+#import "WKWebViewInternal.h"
+
+namespace WebKit {
+
+InspectorPlaywrightAgentClientMac::InspectorPlaywrightAgentClientMac(_WKBrowserInspectorDelegate* delegate)
+ : delegate_(delegate)
+{
+}
+
+RefPtr<WebPageProxy> InspectorPlaywrightAgentClientMac::createPage(WTF::String& error, const BrowserContext& browserContext)
+{
+ auto sessionID = browserContext.dataStore->sessionID();
+ WKWebView *webView = [delegate_ createNewPage:sessionID.toUInt64()];
+ if (!webView) {
+ error = "Internal error: can't create page in given context"_s;
+ return nil;
+ }
+ return [webView _page].get();
+}
+
+void InspectorPlaywrightAgentClientMac::closeBrowser()
+{
+ [delegate_ quit];
+}
+
+std::unique_ptr<BrowserContext> InspectorPlaywrightAgentClientMac::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList)
+{
+ _WKBrowserContext* wkBrowserContext = [[delegate_ createBrowserContext:proxyServer WithBypassList:proxyBypassList] autorelease];
+ auto browserContext = std::make_unique<BrowserContext>();
+ browserContext->processPool = &static_cast<WebProcessPool&>([[wkBrowserContext processPool] _apiObject]);
+ browserContext->dataStore = &static_cast<WebsiteDataStore&>([[wkBrowserContext dataStore] _apiObject]);
+ return browserContext;
+}
+
+void InspectorPlaywrightAgentClientMac::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
+{
+ [delegate_ deleteBrowserContext:sessionID.toUInt64()];
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm b/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..721826c8c98fc85b68a4f45deaee69c1219a7254
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "InspectorTargetProxy.h"
+#import "WebPageProxy.h"
+
+#if PLATFORM(MAC)
+
+namespace WebKit {
+
+void InspectorTargetProxy::platformActivate(String& error) const
+{
+ NSWindow* window = m_page.platformWindow();
+ [window makeKeyAndOrderFront:nil];
+}
+
+} // namespace WebKit
+
+#endif
diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.h b/Source/WebKit/UIProcess/mac/PageClientImplMac.h
index 81a2c861c9ad71b83221d9a978e67e7379617a2c..8b070646433218dc41d7ce2fa85f5d8f71be436e 100644
--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.h
+++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.h
@@ -53,6 +53,8 @@ class PageClientImpl final : public PageClientImplCocoa
#endif
{
public:
+ static void setHeadless(bool headless);
+
PageClientImpl(NSView *, WKWebView *);
virtual ~PageClientImpl();
@@ -119,6 +121,7 @@ private:
WebCore::IntRect rootViewToScreen(const WebCore::IntRect&) override;
#if PLATFORM(MAC)
WebCore::IntRect rootViewToWindow(const WebCore::IntRect&) override;
+ int browserToolbarHeight() const override;
#endif
WebCore::IntPoint accessibilityScreenToRootView(const WebCore::IntPoint&) override;
WebCore::IntRect rootViewToAccessibilityScreen(const WebCore::IntRect&) override;
@@ -158,6 +161,9 @@ private:
void updateAcceleratedCompositingMode(const LayerTreeContext&) override;
void didFirstLayerFlush(const LayerTreeContext&) override;
+// Paywright begin
+ RetainPtr<CGImageRef> takeSnapshotForAutomation() override;
+// Paywright end
RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&) override;
void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&) override;
#if ENABLE(MAC_GESTURE_EVENTS)
@@ -212,6 +218,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 50469a524949a69e9419280ed2a4f8c2bc1e5f23..2bc6e32b486f4ae244a6ccb870a88de9cc17129e 100644
--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm
+++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm
@@ -81,6 +81,7 @@
#import <WebCore/TextUndoInsertionMarkupMac.h>
#import <WebCore/ValidationBubble.h>
#import <WebCore/WebCoreCALayerExtras.h>
+#import <WebCore/NotImplemented.h>
#import <pal/spi/mac/NSApplicationSPI.h>
#import <wtf/ProcessPrivilege.h>
#import <wtf/RetainPtr.h>
@@ -107,6 +108,13 @@ namespace WebKit {
using namespace WebCore;
+static bool _headless = false;
+
+// static
+void PageClientImpl::setHeadless(bool headless) {
+ _headless = headless;
+}
+
PageClientImpl::PageClientImpl(NSView *view, WKWebView *webView)
: PageClientImplCocoa(webView)
, m_view(view)
@@ -160,6 +168,9 @@ NSWindow *PageClientImpl::activeWindow() const
bool PageClientImpl::isViewWindowActive()
{
+ if (_headless)
+ return true;
+
ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
NSWindow *activeViewWindow = activeWindow();
return activeViewWindow.isKeyWindow || (activeViewWindow && [NSApp keyWindow] == activeViewWindow);
@@ -167,6 +178,9 @@ bool PageClientImpl::isViewWindowActive()
bool PageClientImpl::isViewFocused()
{
+ if (_headless)
+ return true;
+
// FIXME: This is called from the WebPageProxy constructor before we have a WebViewImpl.
// Once WebViewImpl and PageClient merge, this won't be a problem.
if (!m_impl)
@@ -190,6 +204,9 @@ void PageClientImpl::makeFirstResponder()
bool PageClientImpl::isViewVisible()
{
+ if (_headless)
+ return true;
+
NSView *activeView = this->activeView();
NSWindow *activeViewWindow = activeWindow();
@@ -273,7 +290,8 @@ void PageClientImpl::didRelaunchProcess()
void PageClientImpl::preferencesDidChange()
{
- m_impl->preferencesDidChange();
+ if (m_impl)
+ m_impl->preferencesDidChange();
}
void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip)
@@ -466,6 +484,15 @@ IntRect PageClientImpl::rootViewToWindow(const WebCore::IntRect& rect)
return enclosingIntRect(tempRect);
}
+int PageClientImpl::browserToolbarHeight() const
+{
+ // There are no controls in headless mode.
+ if (_headless)
+ return 0;
+
+ return 55;
+}
+
IntPoint PageClientImpl::accessibilityScreenToRootView(const IntPoint& point)
{
return screenToRootView(point);
@@ -478,11 +505,15 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
{
+ if (!event.nativeEvent())
+ return;
m_impl->doneWithKeyEvent(event.nativeEvent(), eventWasHandled);
}
RefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy& page)
{
+ if (_headless)
+ return nullptr;
return WebPopupMenuProxyMac::create(m_view, page);
}
@@ -602,6 +633,12 @@ CALayer *PageClientImpl::acceleratedCompositingRootLayer() const
return m_impl->acceleratedCompositingRootLayer();
}
+// Paywright begin
+RetainPtr<CGImageRef> PageClientImpl::takeSnapshotForAutomation() {
+ return m_impl->takeSnapshotForAutomation();
+}
+// Paywright begin
+
RefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot(Optional<WebCore::IntRect>&&)
{
return m_impl->takeViewSnapshot();
@@ -780,6 +817,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);
@@ -946,6 +990,9 @@ void PageClientImpl::didRestoreScrollPosition()
bool PageClientImpl::windowIsFrontWindowUnderMouse(const NativeWebMouseEvent& event)
{
+ // Simulated event.
+ if (!event.nativeEvent())
+ return false;
return m_impl->windowIsFrontWindowUnderMouse(event.nativeEvent());
}
diff --git a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h
index 0bb07e679f30e7b3682b3736b5372cbbb2d31ec8..cc0740c7d88d11d419cf2ca51cbc00b193531100 100644
--- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h
+++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h
@@ -62,6 +62,7 @@ private:
void show() override;
void showContextMenuWithItems(Vector<Ref<WebContextMenuItem>>&&) override;
void useContextMenuItems(Vector<Ref<WebContextMenuItem>>&&) override;
+ void hide() override;
void getContextMenuItem(const WebContextMenuItemData&, CompletionHandler<void(NSMenuItem *)>&&);
void getContextMenuFromItems(const Vector<WebContextMenuItemData>&, CompletionHandler<void(NSMenu *)>&&);
diff --git a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm
index 5ad887b13fb41224383e40014b48910cbe2e7dcd..b6a2b93f13bdc6be626bcbb9282ac26da1415049 100644
--- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm
+++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm
@@ -326,6 +326,12 @@ void WebContextMenuProxyMac::getShareMenuItem(CompletionHandler<void(NSMenuItem
}
#endif
+void WebContextMenuProxyMac::hide()
+{
+ if (m_menu)
+ [m_menu cancelTracking];
+}
+
void WebContextMenuProxyMac::show()
{
#if ENABLE(SERVICE_CONTROLS)
diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..6113f4cd60a5d72b8ead61176cb43200803478ed
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "WebPageInspectorEmulationAgent.h"
+
+#import "WebPageProxy.h"
+
+namespace WebKit {
+
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
+{
+ NSWindow* window = m_page.platformWindow();
+ NSRect windowRect = [window frame];
+ NSRect viewRect = window.contentLayoutRect;
+ windowRect.size.width += width - viewRect.size.width;
+ windowRect.size.height += height - viewRect.size.height;
+ [window setFrame:windowRect display:YES animate:NO];
+ callback(String());
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..726053d74b9283d734d8699daca0e5e7f8893eca
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "NativeWebMouseEvent.h"
+#import "WebPageInspectorInputAgent.h"
+#import "WebPageProxy.h"
+#import <WebCore/IntPoint.h>
+#import <WebCore/IntSize.h>
+#import "NativeWebKeyboardEvent.h"
+
+namespace WebKit {
+
+using namespace WebCore;
+
+void WebPageInspectorInputAgent::platformDispatchMouseEvent(const String& type, int x, int y, Optional<int>&& optionalModifiers, const String& button, Optional<int>&& optionalClickCount) {
+ IntPoint locationInWindow(x, y);
+
+ NSEventModifierFlags modifiers = 0;
+ if (optionalModifiers) {
+ int inputModifiers = *optionalModifiers;
+ if (inputModifiers & 1)
+ modifiers |= NSEventModifierFlagShift;
+ if (inputModifiers & 2)
+ modifiers |= NSEventModifierFlagControl;
+ if (inputModifiers & 4)
+ modifiers |= NSEventModifierFlagOption;
+ if (inputModifiers & 8)
+ modifiers |= NSEventModifierFlagCommand;
+ }
+ int clickCount = optionalClickCount ? *optionalClickCount : 0;
+
+ NSTimeInterval timestamp = [NSDate timeIntervalSinceReferenceDate];
+ NSWindow *window = m_page.platformWindow();
+ NSInteger windowNumber = window.windowNumber;
+
+ NSEventType downEventType = (NSEventType)0;
+ NSEventType dragEventType = (NSEventType)0;
+ NSEventType upEventType = (NSEventType)0;
+
+ if (!button || button == "none") {
+ downEventType = NSEventTypeMouseMoved;
+ dragEventType = NSEventTypeMouseMoved;
+ upEventType = NSEventTypeMouseMoved;
+ } else if (button == "left") {
+ downEventType = NSEventTypeLeftMouseDown;
+ dragEventType = NSEventTypeLeftMouseDragged;
+ upEventType = NSEventTypeLeftMouseUp;
+ } else if (button == "middle") {
+ downEventType = NSEventTypeOtherMouseDown;
+ dragEventType = NSEventTypeLeftMouseDragged;
+ upEventType = NSEventTypeOtherMouseUp;
+ } else if (button == "right") {
+ downEventType = NSEventTypeRightMouseDown;
+ upEventType = NSEventTypeRightMouseUp;
+ }
+
+ NSInteger eventNumber = 0;
+
+ NSEvent* event = nil;
+ if (type == "move") {
+ event = [NSEvent mouseEventWithType:dragEventType location:locationInWindow modifierFlags:modifiers timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:eventNumber clickCount:clickCount pressure:0.0f];
+ } else if (type == "down") {
+ event = [NSEvent mouseEventWithType:downEventType location:locationInWindow modifierFlags:modifiers timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:eventNumber clickCount:clickCount pressure:WebCore::ForceAtClick];
+ } else if (type == "up") {
+ event = [NSEvent mouseEventWithType:upEventType location:locationInWindow modifierFlags:modifiers timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:eventNumber clickCount:clickCount pressure:0.0f];
+ }
+
+ if (event) {
+ NativeWebMouseEvent nativeEvent(event, nil, [window contentView]);
+ m_page.handleMouseEvent(nativeEvent);
+ }
+}
+
+void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& commands, WallTime timestamp)
+{
+ Vector<WebCore::KeypressCommand> macCommands;
+ for (const String& command : commands) {
+ m_page.registerKeypressCommandName(command);
+ macCommands.append(WebCore::KeypressCommand(command.utf8().data()));
+ }
+ if (text.length() > 0 && macCommands.size() == 0)
+ macCommands.append(WebCore::KeypressCommand("insertText:", text));
+ NativeWebKeyboardEvent event(
+ type,
+ text,
+ unmodifiedText,
+ key,
+ code,
+ keyIdentifier,
+ windowsVirtualKeyCode,
+ nativeVirtualKeyCode,
+ isAutoRepeat,
+ isKeypad,
+ isSystemKey,
+ modifiers,
+ timestamp,
+ WTFMove(macCommands));
+ m_page.handleKeyboardEvent(event);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dd7fe0604188bb025f361f1c44685e38bbf935ca
--- /dev/null
+++ b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorPlaywrightAgentClientWin.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "APIPageConfiguration.h"
+#include "APIProcessPoolConfiguration.h"
+#include "InspectorPlaywrightAgent.h"
+#include "WebPageProxy.h"
+#include "WebsiteDataStore.h"
+#include "WebPreferences.h"
+#include "WebProcessPool.h"
+#include "WebView.h"
+#include "WKAPICast.h"
+#include <WebCore/CurlProxySettings.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/StringView.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+InspectorPlaywrightAgentClientWin::InspectorPlaywrightAgentClientWin(ConfigureDataStoreCallback configureDataStore, CreatePageCallback createPage, QuitCallback quit)
+ : m_configureDataStore(configureDataStore)
+ , m_createPage(createPage)
+ , m_quit(quit)
+{
+}
+
+RefPtr<WebPageProxy> InspectorPlaywrightAgentClientWin::createPage(WTF::String& error, const BrowserContext& context)
+{
+ auto conf = API::PageConfiguration::create();
+ conf->setProcessPool(context.processPool.get());
+ conf->setWebsiteDataStore(context.dataStore.get());
+ return toImpl(m_createPage(toAPI(&conf.get())));
+}
+
+void InspectorPlaywrightAgentClientWin::closeBrowser()
+{
+ m_quit();
+}
+
+std::unique_ptr<BrowserContext> InspectorPlaywrightAgentClientWin::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList)
+{
+ auto config = API::ProcessPoolConfiguration::create();
+ auto browserContext = std::make_unique<BrowserContext>();
+ browserContext->processPool = WebKit::WebProcessPool::create(config);
+ browserContext->dataStore = WebKit::WebsiteDataStore::createNonPersistent();
+ m_configureDataStore(toAPI(browserContext->dataStore.get()));
+ if (!proxyServer.isEmpty()) {
+ URL proxyURL = URL(URL(), proxyServer);
+ WebCore::CurlProxySettings settings(WTFMove(proxyURL), String(proxyBypassList));
+ browserContext->dataStore->setNetworkProxySettings(WTFMove(settings));
+ }
+ PAL::SessionID sessionID = browserContext->dataStore->sessionID();
+ return browserContext;
+}
+
+void InspectorPlaywrightAgentClientWin::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
+{
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.h b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.h
new file mode 100644
index 0000000000000000000000000000000000000000..df18883b2b7d22d73540cb084d3dd5291231097d
--- /dev/null
+++ b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgentClient.h"
+#include <WebKit/WKInspector.h>
+#include <wtf/Forward.h>
+#include <wtf/text/StringHash.h>
+
+typedef void (*ConfigureDataStoreCallback)(WKWebsiteDataStoreRef dataStore);
+typedef WKPageRef (*CreatePageCallback)(WKPageConfigurationRef configuration);
+typedef void (*QuitCallback)();
+
+namespace WebKit {
+
+class InspectorPlaywrightAgentClientWin : public InspectorPlaywrightAgentClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorPlaywrightAgentClientWin(ConfigureDataStoreCallback, CreatePageCallback, QuitCallback);
+ ~InspectorPlaywrightAgentClientWin() override = default;
+
+ RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
+ void closeBrowser() override;
+ std::unique_ptr<BrowserContext> createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) override;
+ void deleteBrowserContext(WTF::String& error, PAL::SessionID) override;
+
+private:
+ ConfigureDataStoreCallback m_configureDataStore;
+ CreatePageCallback m_createPage;
+ QuitCallback m_quit;
+};
+
+} // namespace API
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/win/InspectorTargetProxyWin.cpp b/Source/WebKit/UIProcess/win/InspectorTargetProxyWin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..135a60361fa8fbf907382625e7c8dd4ea64ceb94
--- /dev/null
+++ b/Source/WebKit/UIProcess/win/InspectorTargetProxyWin.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorTargetProxy.h"
+#include "WebPageProxy.h"
+
+namespace WebKit {
+
+void InspectorTargetProxy::platformActivate(String& error) const
+{
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp
index 3dcd0ec35c92e37239208a8f5d4f461fbeaac3ce..84ba07c57f2abac1bd0ca5d0af2e7366ad036892 100644
--- a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp
+++ b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp
@@ -112,5 +112,11 @@ WebContextMenuProxyWin::~WebContextMenuProxyWin()
::DestroyMenu(m_menu);
}
+void WebContextMenuProxyWin::hide()
+{
+ if (m_menu)
+ ::EndMenu();
+}
+
} // namespace WebKit
#endif // ENABLE(CONTEXT_MENUS)
diff --git a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h
index 0c80d970c3f9a987faf620081c909f6c7021970d..1467e5481f7417913c0d12a1cb492d02b2a7d1b7 100644
--- a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h
+++ b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h
@@ -47,6 +47,7 @@ public:
private:
WebContextMenuProxyWin(WebPageProxy&, ContextMenuContextData&&, const UserData&);
void showContextMenuWithItems(Vector<Ref<WebContextMenuItem>>&&) override;
+ void hide() override;
HMENU m_menu;
};
diff --git a/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp b/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..62b841fe1d0de2296e1c61e328cff564f5aa1c0f
--- /dev/null
+++ b/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebPageInspectorEmulationAgent.h"
+#include "WebPageProxy.h"
+
+namespace WebKit {
+
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
+{
+ HWND viewHwnd = m_page.viewWidget();
+ HWND windowHwnd = GetAncestor(viewHwnd, GA_ROOT);
+ RECT viewRect;
+ RECT windowRect;
+
+ if (!windowHwnd || !GetWindowRect(windowHwnd, &windowRect)) {
+ callback("Could not retrieve window size");
+ return;
+ }
+ if (!GetWindowRect(viewHwnd, &viewRect)) {
+ callback("Could retrieve view size");
+ return;
+ }
+
+ width += windowRect.right - windowRect.left - viewRect.right + viewRect.left;
+ height += windowRect.bottom - windowRect.top - viewRect.bottom + viewRect.top;
+
+ if (!SetWindowPos(windowHwnd, 0, 0, 0, width, height, SWP_NOCOPYBITS | SWP_NOSENDCHANGING | SWP_NOMOVE)) {
+ callback("Could not resize window");
+ return;
+ }
+ callback(String());
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/win/WebPageInspectorInputAgentWin.cpp b/Source/WebKit/UIProcess/win/WebPageInspectorInputAgentWin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5cf8a010e9809e6a95741cdb7c2cbeb445ab638b
--- /dev/null
+++ b/Source/WebKit/UIProcess/win/WebPageInspectorInputAgentWin.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "WebPageInspectorInputAgent.h"
+
+#include "NativeWebKeyboardEvent.h"
+#include "WebPageProxy.h"
+#include <WebCore/PlatformKeyboardEvent.h>
+
+namespace WebKit {
+
+void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& macCommands, WallTime timestamp)
+{
+ NativeWebKeyboardEvent event(
+ type,
+ text,
+ unmodifiedText,
+ key,
+ code,
+ keyIdentifier,
+ windowsVirtualKeyCode,
+ nativeVirtualKeyCode,
+ isAutoRepeat,
+ isKeypad,
+ isSystemKey,
+ modifiers,
+ timestamp);
+ m_page.handleKeyboardEvent(event);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7453194ca6f032ba86a4c67f5bf12688ab6ec1be
--- /dev/null
+++ b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorTargetProxy.h"
+
+#include "WebPageProxy.h"
+#include <wpe/wpe.h>
+
+namespace WebKit {
+
+void InspectorTargetProxy::platformActivate(String& error) const
+{
+ struct wpe_view_backend* backend = m_page.viewBackend();
+ wpe_view_backend_add_activity_state(backend, wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5dc76aa302cb574307059e66a1b73730efe920da
--- /dev/null
+++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebPageInspectorEmulationAgent.h"
+
+#include "WebPageProxy.h"
+#include <wpe/wpe.h>
+
+namespace WebKit {
+
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
+{
+ struct wpe_view_backend* backend = m_page.viewBackend();
+ wpe_view_backend_dispatch_set_size(backend, width, height);
+ callback(String());
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c3d7cacea987ba2b094d5022c670705ef6ced129
--- /dev/null
+++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebPageInspectorInputAgent.h"
+
+#include "NativeWebKeyboardEvent.h"
+#include "WebPageProxy.h"
+#include <WebCore/PlatformKeyboardEvent.h>
+#include <wpe/wpe.h>
+
+namespace WebKit {
+
+void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& macCommands, WallTime timestamp)
+{
+ NativeWebKeyboardEvent event(
+ type,
+ text,
+ unmodifiedText,
+ key,
+ code,
+ keyIdentifier,
+ windowsVirtualKeyCode,
+ nativeVirtualKeyCode,
+ isAutoRepeat,
+ isKeypad,
+ isSystemKey,
+ modifiers,
+ timestamp);
+ m_page.handleKeyboardEvent(event);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
index 4665ccb7bc6af7a7a08915fde46726d967f5fcb4..00fd2b38391938fdfc5885ef57f9fccb4ebb0c09 100644
--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj
+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
@@ -1803,6 +1803,18 @@
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 /* InspectorPlaywrightAgentClientMac.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */; };
+ D71A94342370E07A002C4D9E /* InspectorPlaywrightAgentClient.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */; };
+ D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */; };
+ D71A94422371F67E002C4D9E /* WebPageInspectorEmulationAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */; };
+ D71A94432371F67E002C4D9E /* WebPageInspectorInputAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */; };
+ D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94492372290B002C4D9E /* _WKBrowserInspector.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */; };
+ D76D6888238DBD81008D314B /* InspectorDialogAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D76D6887238DBD80008D314B /* InspectorDialogAgent.h */; };
+ D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */; };
+ D79902B2236E9404005D6F7E /* InspectorTargetProxyMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */; };
+ D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */; };
+ D7EB04E72372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */; };
DF462E0F23F22F5500EFF35F /* WKHTTPCookieStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
DF462E1223F338BE00EFF35F /* WKContentWorldPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
DF84CEE4249AA24D009096F6 /* WKPDFHUDView.mm in Sources */ = {isa = PBXBuildFile; fileRef = DF84CEE2249AA21F009096F6 /* WKPDFHUDView.mm */; };
@@ -1860,6 +1872,9 @@
E5BEF6822130C48000F31111 /* WebDataListSuggestionsDropdownIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = E5BEF6802130C47F00F31111 /* WebDataListSuggestionsDropdownIOS.h */; };
E5CB07DC20E1678F0022C183 /* WKFormColorControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E5CB07DA20E1678F0022C183 /* WKFormColorControl.h */; };
ED82A7F2128C6FAF004477B3 /* WKBundlePageOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A22F0FF1289FCD90085E74F /* WKBundlePageOverlay.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F303B849249A8D640031DE5C /* ScreencastEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */; };
+ F33C7AC7249AD79C0018BE41 /* libwebrtc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */; };
+ F3867F0A24607D4E008F0F31 /* InspectorScreencastAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */; };
F409BA181E6E64BC009DA28E /* WKDragDestinationAction.h in Headers */ = {isa = PBXBuildFile; fileRef = F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */; settings = {ATTRIBUTES = (Private, ); }; };
F42D634122A0EFDF00D2FB3A /* WebAutocorrectionData.h in Headers */ = {isa = PBXBuildFile; fileRef = F42D633F22A0EFD300D2FB3A /* WebAutocorrectionData.h */; };
F430E9422247335F005FE053 /* WebsiteMetaViewportPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = F430E941224732A9005FE053 /* WebsiteMetaViewportPolicy.h */; };
@@ -5327,6 +5342,19 @@
D3B9484311FF4B6500032B39 /* WebPopupMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPopupMenu.h; sourceTree = "<group>"; };
D3B9484411FF4B6500032B39 /* WebSearchPopupMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSearchPopupMenu.cpp; sourceTree = "<group>"; };
D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSearchPopupMenu.h; sourceTree = "<group>"; };
+ D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBrowserInspector.h; sourceTree = "<group>"; };
+ D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorPlaywrightAgentClientMac.h; sourceTree = "<group>"; };
+ D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorPlaywrightAgentClient.h; sourceTree = "<group>"; };
+ D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteInspectorPipe.h; sourceTree = "<group>"; };
+ D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorEmulationAgent.h; sourceTree = "<group>"; };
+ D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorInputAgent.h; sourceTree = "<group>"; };
+ D71A94492372290B002C4D9E /* _WKBrowserInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKBrowserInspector.h; sourceTree = "<group>"; };
+ D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrowserInspectorPipe.h; sourceTree = "<group>"; };
+ D76D6887238DBD80008D314B /* InspectorDialogAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDialogAgent.h; sourceTree = "<group>"; };
+ D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorEmulationAgentMac.mm; sourceTree = "<group>"; };
+ D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorTargetProxyMac.mm; sourceTree = "<group>"; };
+ D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorInputAgentMac.mm; sourceTree = "<group>"; };
+ D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorPlaywrightAgentClientMac.mm; sourceTree = "<group>"; };
DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKHTTPCookieStorePrivate.h; sourceTree = "<group>"; };
DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContentWorldPrivate.h; sourceTree = "<group>"; };
DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebWheelEvent.h; sourceTree = "<group>"; };
@@ -5438,6 +5466,14 @@
ECA680D31E6904B500731D20 /* ExtraPrivateSymbolsForTAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtraPrivateSymbolsForTAPI.h; sourceTree = "<group>"; };
ECBFC1DB1E6A4D66000300C7 /* ExtraPublicSymbolsForTAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtraPublicSymbolsForTAPI.h; sourceTree = "<group>"; };
F036978715F4BF0500C3A80E /* WebColorPicker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebColorPicker.cpp; sourceTree = "<group>"; };
+ F303B847249A8D3A0031DE5C /* ScreencastEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScreencastEncoder.cpp; sourceTree = "<group>"; };
+ F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreencastEncoder.h; sourceTree = "<group>"; };
+ F31E2DA424C76E4B004B2775 /* WebMFileWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebMFileWriter.cpp; sourceTree = "<group>"; };
+ F31E2DA524C76E4C004B2775 /* WebMFileWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebMFileWriter.h; sourceTree = "<group>"; };
+ F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; path = libwebrtc.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+ F3867F0324607D2B008F0F31 /* InspectorScreencastAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorScreencastAgent.cpp; sourceTree = "<group>"; };
+ F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorScreencastAgent.h; sourceTree = "<group>"; };
+ F3970344249BD4CE003E1A22 /* ScreencastEncoderMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScreencastEncoderMac.mm; sourceTree = "<group>"; };
F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDragDestinationAction.h; sourceTree = "<group>"; };
F40D1B68220BDC0F00B49A01 /* WebAutocorrectionContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebAutocorrectionContext.h; path = ios/WebAutocorrectionContext.h; sourceTree = "<group>"; };
F41056612130699A0092281D /* APIAttachmentCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = APIAttachmentCocoa.mm; sourceTree = "<group>"; };
@@ -5537,6 +5573,7 @@
3766F9EF189A1244003CF19B /* QuartzCore.framework in Frameworks */,
37694525184FC6B600CDE21F /* Security.framework in Frameworks */,
37BEC4DD1948FC6A008B4286 /* WebCore.framework in Frameworks */,
+ F33C7AC7249AD79C0018BE41 /* libwebrtc.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -7279,6 +7316,7 @@
37C4C08318149C2A003688B9 /* Cocoa */ = {
isa = PBXGroup;
children = (
+ D71A94492372290B002C4D9E /* _WKBrowserInspector.h */,
1A43E826188F38E2009E4D30 /* Deprecated */,
37A5E01218BBF937000A081E /* _WKActivatedElementInfo.h */,
37A5E01118BBF937000A081E /* _WKActivatedElementInfo.mm */,
@@ -8257,6 +8295,7 @@
isa = PBXGroup;
children = (
57A9FF15252C6AEF006A2040 /* libWTF.a */,
+ F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */,
5750F32A2032D4E500389347 /* LocalAuthentication.framework */,
570DAAB0230273D200E8FC04 /* NearField.framework */,
);
@@ -8664,6 +8703,12 @@
children = (
9197940423DBC4BB00257892 /* InspectorBrowserAgent.cpp */,
9197940323DBC4BB00257892 /* InspectorBrowserAgent.h */,
+ F3867F0324607D2B008F0F31 /* InspectorScreencastAgent.cpp */,
+ F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */,
+ F303B847249A8D3A0031DE5C /* ScreencastEncoder.cpp */,
+ F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */,
+ F31E2DA424C76E4B004B2775 /* WebMFileWriter.cpp */,
+ F31E2DA524C76E4C004B2775 /* WebMFileWriter.h */,
);
path = Agents;
sourceTree = "<group>";
@@ -8672,6 +8717,7 @@
isa = PBXGroup;
children = (
A5D3504D1D78F0D2005124A9 /* RemoteWebInspectorProxyMac.mm */,
+ F3970344249BD4CE003E1A22 /* ScreencastEncoderMac.mm */,
1CA8B935127C774E00576C2B /* WebInspectorProxyMac.mm */,
994BADF11F7D77EA00B571E7 /* WKInspectorViewController.h */,
994BADF21F7D77EB00B571E7 /* WKInspectorViewController.mm */,
@@ -9099,6 +9145,12 @@
BC032DC310F438260058C15A /* UIProcess */ = {
isa = PBXGroup;
children = (
+ D76D6887238DBD80008D314B /* InspectorDialogAgent.h */,
+ D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */,
+ D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */,
+ D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */,
+ D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */,
+ D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */,
BC032DC410F4387C0058C15A /* API */,
512F588D12A8836F00629530 /* Authentication */,
9955A6E81C79809000EB6A93 /* Automation */,
@@ -9380,6 +9432,7 @@
BC0C376610F807660076D7CB /* C */ = {
isa = PBXGroup;
children = (
+ D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */,
5123CF18133D25E60056F800 /* cg */,
6EE849C41368D9040038D481 /* mac */,
BCB63477116BF10600603215 /* WebKit2_C.h */,
@@ -9975,6 +10028,11 @@
BCCF085C113F3B7500C650C5 /* mac */ = {
isa = PBXGroup;
children = (
+ D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */,
+ D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */,
+ D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */,
+ D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */,
+ D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */,
B878B613133428DC006888E9 /* CorrectionPanel.h */,
B878B614133428DC006888E9 /* CorrectionPanel.mm */,
C1817362205844A900DFDA65 /* DisplayLink.cpp */,
@@ -10767,6 +10825,7 @@
991F492F23A812C60054642B /* _WKInspectorDebuggableInfo.h in Headers */,
99036AE223A949CF0000B06A /* _WKInspectorDebuggableInfoInternal.h in Headers */,
9197940C23DBC50300257892 /* _WKInspectorDelegate.h in Headers */,
+ D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */,
5CAFDE472130846A00B1F7E1 /* _WKInspectorInternal.h in Headers */,
9979CA58237F49F10039EC05 /* _WKInspectorPrivate.h in Headers */,
99996A9F25004BCC004F7559 /* _WKInspectorPrivateForTesting.h in Headers */,
@@ -11009,6 +11068,7 @@
1A14F8E21D74C834006CBEC6 /* FrameInfoData.h in Headers */,
1AE00D611831792100087DD7 /* FrameLoadState.h in Headers */,
5C121E842410208D00486F9B /* FrameTreeNodeData.h in Headers */,
+ F303B849249A8D640031DE5C /* ScreencastEncoder.h in Headers */,
2D4AF0892044C3C4006C8817 /* FrontBoardServicesSPI.h in Headers */,
CD78E1151DB7D7ED0014A2DE /* FullscreenClient.h in Headers */,
CD19D2EA2046406F0017074A /* FullscreenTouchSecheuristic.h in Headers */,
@@ -11021,6 +11081,7 @@
BC06F43A12DBCCFB002D78DE /* GeolocationPermissionRequestProxy.h in Headers */,
2DA944A41884E4F000ED86DB /* GestureTypes.h in Headers */,
2DA049B8180CCD0A00AAFA9E /* GraphicsLayerCARemote.h in Headers */,
+ D71A94342370E07A002C4D9E /* InspectorPlaywrightAgentClient.h in Headers */,
C0CE72AD1247E78D00BC0EC4 /* HandleMessage.h in Headers */,
1AC75A1B1B3368270056745B /* HangDetectionDisabler.h in Headers */,
57AC8F50217FEED90055438C /* HidConnection.h in Headers */,
@@ -11152,8 +11213,10 @@
413075AC1DE85F370039EC69 /* NetworkRTCMonitor.h in Headers */,
41DC45961E3D6E2200B11F51 /* NetworkRTCProvider.h in Headers */,
5C20CBA01BB1ECD800895BB1 /* NetworkSession.h in Headers */,
+ D71A94422371F67E002C4D9E /* WebPageInspectorEmulationAgent.h in Headers */,
532159551DBAE7290054AA3C /* NetworkSessionCocoa.h in Headers */,
417915B92257046F00D6F97E /* NetworkSocketChannel.h in Headers */,
+ D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */,
570DAAC22303730300E8FC04 /* NfcConnection.h in Headers */,
570DAAAE23026F5C00E8FC04 /* NfcService.h in Headers */,
31A2EC5614899C0900810D71 /* NotificationPermissionRequest.h in Headers */,
@@ -11235,6 +11298,7 @@
BC1A7C581136E19C00FB7167 /* ProcessLauncher.h in Headers */,
463FD4821EB94EC000A2982C /* ProcessTerminationReason.h in Headers */,
86E67A251910B9D100004AB7 /* ProcessThrottler.h in Headers */,
+ D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */,
83048AE61ACA45DC0082C832 /* ProcessThrottlerClient.h in Headers */,
A1E688701F6E2BAB007006A6 /* QuarantineSPI.h in Headers */,
1A0C227E2451130A00ED614D /* QuickLookThumbnailingSoftLink.h in Headers */,
@@ -11537,6 +11601,7 @@
A543E30D215C8A9000279CD9 /* WebPageInspectorTargetController.h in Headers */,
A543E307215AD13700279CD9 /* WebPageInspectorTargetFrontendChannel.h in Headers */,
C0CE72A11247E71D00BC0EC4 /* WebPageMessages.h in Headers */,
+ F3867F0A24607D4E008F0F31 /* InspectorScreencastAgent.h in Headers */,
2D5C9D0619C81D8F00B3C5C1 /* WebPageOverlay.h in Headers */,
46C392292316EC4D008EED9B /* WebPageProxyIdentifier.h in Headers */,
BCBD3915125BB1A800D2C29F /* WebPageProxyMessages.h in Headers */,
@@ -11664,6 +11729,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 */,
@@ -11716,6 +11782,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 */,
@@ -11865,6 +11932,7 @@
1AB8A1F818400BB800E9AE69 /* WKPageContextMenuClient.h in Headers */,
8372DB251A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h in Headers */,
1AB8A1F418400B8F00E9AE69 /* WKPageFindClient.h in Headers */,
+ D71A94322370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h in Headers */,
1AB8A1F618400B9D00E9AE69 /* WKPageFindMatchesClient.h in Headers */,
1AB8A1F018400B0000E9AE69 /* WKPageFormClient.h in Headers */,
BC7B633712A45ABA00D174A4 /* WKPageGroup.h in Headers */,
@@ -12999,6 +13067,7 @@
C1A152D724E5A29A00978C8B /* HandleXPCEndpointMessages.mm in Sources */,
2749F6442146561B008380BF /* InjectedBundleNodeHandle.cpp in Sources */,
2749F6452146561E008380BF /* InjectedBundleRangeHandle.cpp in Sources */,
+ D79902B2236E9404005D6F7E /* InspectorTargetProxyMac.mm in Sources */,
9BF5EC642541145600984E77 /* JSIPCBinding.cpp in Sources */,
2D913441212CF9F000128AFD /* JSNPMethod.cpp in Sources */,
2D913442212CF9F000128AFD /* JSNPObject.cpp in Sources */,
@@ -13014,6 +13083,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 */,
@@ -13037,6 +13107,7 @@
1A2D8439127F65D5001EB962 /* NPObjectMessageReceiverMessageReceiver.cpp in Sources */,
2D92A792212B6AD400F493FD /* NPObjectProxy.cpp in Sources */,
2D92A793212B6AD400F493FD /* NPRemoteObjectMap.cpp in Sources */,
+ D7EB04E72372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm in Sources */,
2D913447212CF9F000128AFD /* NPRuntimeObjectMap.cpp in Sources */,
2D913448212CF9F000128AFD /* NPRuntimeUtilities.cpp in Sources */,
2D92A794212B6AD400F493FD /* NPVariantData.cpp in Sources */,
@@ -13324,6 +13395,7 @@
2D92A78C212B6AB100F493FD /* WebMouseEvent.cpp in Sources */,
31BA924D148831260062EDB5 /* WebNotificationManagerMessageReceiver.cpp in Sources */,
2DF6FE52212E110900469030 /* WebPage.cpp in Sources */,
+ D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */,
C0CE72A01247E71D00BC0EC4 /* WebPageMessageReceiver.cpp in Sources */,
BCBD3914125BB1A800D2C29F /* WebPageProxyMessageReceiver.cpp in Sources */,
7CE9CE101FA0767A000177DE /* WebPageUpdatePreferences.cpp in Sources */,
diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
index 69dea7493e2683c5417ebc9fa647b687ea710b83..427c4ddd5c3b6743ff686790e9076700e3705c3a 100644
--- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
+++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
@@ -223,6 +223,11 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou
}
#endif
+ if (m_emulateOfflineState) {
+ scheduleInternallyFailedLoad(resourceLoader);
+ return;
+ }
+
if (!tryLoadingUsingURLSchemeHandler(resourceLoader, trackingParameters)) {
WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be scheduled with the NetworkProcess");
@@ -770,7 +775,7 @@ void WebLoaderStrategy::didFinishPreconnection(uint64_t preconnectionIdentifier,
bool WebLoaderStrategy::isOnLine() const
{
- return m_isOnLine;
+ return m_emulateOfflineState ? false : m_isOnLine;
}
void WebLoaderStrategy::addOnlineStateChangeListener(Function<void(bool)>&& listener)
@@ -790,6 +795,11 @@ void WebLoaderStrategy::isResourceLoadFinished(CachedResource& resource, Complet
void WebLoaderStrategy::setOnLineState(bool isOnLine)
{
+ if (m_emulateOfflineState) {
+ m_isOnLine = isOnLine;
+ return;
+ }
+
if (m_isOnLine == isOnLine)
return;
@@ -798,6 +808,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 9d9884183ec93daeb3ab63218960172a050e0ffb..65ae20cbeaf74d4954590b76ae63a4b2a9c1b506 100644
--- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h
+++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h
@@ -88,6 +88,7 @@ public:
bool isOnLine() const final;
void addOnlineStateChangeListener(Function<void(bool)>&&) final;
void setOnLineState(bool);
+ void setEmulateOfflineState(bool) final;
static uint64_t generateLoadIdentifier();
@@ -130,6 +131,7 @@ private:
HashMap<unsigned long, PreconnectCompletionHandler> m_preconnectCompletionHandlers;
Vector<Function<void(bool)>> m_onlineStateChangeListeners;
bool m_isOnLine { true };
+ bool m_emulateOfflineState { false };
};
} // namespace WebKit
diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
index a7a76950d45e43f241ffbd2f31aac15708519116..2ddb5afe1435ad38c2b02f43f296937fc6099ad4 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
@@ -390,6 +390,8 @@ void WebChromeClient::setResizable(bool resizable)
void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, unsigned columnNumber, const String& sourceID)
{
+ if (level == MessageLevel::Error)
+ m_page.send(Messages::WebPageProxy::LogToStderr(message));
// Notify the bundle client.
m_page.injectedBundleUIClient().willAddMessageToConsole(&m_page, source, level, message, lineNumber, columnNumber, sourceID);
}
@@ -809,6 +811,13 @@ std::unique_ptr<DateTimeChooser> WebChromeClient::createDateTimeChooser(DateTime
#endif
+#if ENABLE(ORIENTATION_EVENTS) && !PLATFORM(IOS_FAMILY)
+int WebChromeClient::deviceOrientation() const {
+ // Only overrides are supported for non-iOS platforms.
+ return 0;
+}
+#endif
+
void WebChromeClient::runOpenPanel(Frame& frame, FileChooser& fileChooser)
{
if (m_page.activeOpenPanelResultListener())
diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
index 975fd89020395b49e192575b7a24789c68cdf8a7..3a4422d1d583caa5d653a9b5d201bcbd437d0f1a 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
@@ -1559,13 +1559,6 @@ void WebFrameLoaderClient::transitionToCommittedForNewPage()
if (webPage->scrollPinningBehavior() != DoNotPin)
view->setScrollPinningBehavior(webPage->scrollPinningBehavior());
-#if USE(COORDINATED_GRAPHICS)
- if (shouldUseFixedLayout) {
- view->setDelegatesScrolling(shouldUseFixedLayout);
- view->setPaintsEntireContents(shouldUseFixedLayout);
- return;
- }
-#endif
}
void WebFrameLoaderClient::didRestoreFromBackForwardCache()
diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
index 4f1a1ff1e4476cd8b272eb14100015943296eb19..c77cce25000a35040996ff36e2fca207d59cb6b7 100644
--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
+++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
@@ -36,7 +36,9 @@
#include "WebPageCreationParameters.h"
#include "WebPreferencesKeys.h"
#include <WebCore/Frame.h>
+#include <WebCore/FrameView.h>
#include <WebCore/GraphicsContext.h>
+#include <WebCore/InspectorController.h>
#include <WebCore/Page.h>
#include <WebCore/PageOverlayController.h>
#include <WebCore/Settings.h>
@@ -122,6 +124,16 @@ void DrawingAreaCoordinatedGraphics::scroll(const IntRect& scrollRect, const Int
ASSERT(m_scrollRect.isEmpty());
ASSERT(m_scrollOffset.isEmpty());
ASSERT(m_dirtyRegion.isEmpty());
+// Playwright begin
+#if !PLATFORM(WIN)
+ if (m_webPage.mainFrameView() && m_webPage.mainFrameView()->useFixedLayout()) {
+ IntRect visibleRect;
+ visibleRect.move(-scrollDelta.width(), -scrollDelta.height());
+ m_layerTreeHost->scrollNonCompositedContents(visibleRect);
+ return;
+ }
+#endif
+// Playwright end
m_layerTreeHost->scrollNonCompositedContents(scrollRect);
return;
}
@@ -247,6 +259,7 @@ void DrawingAreaCoordinatedGraphics::updatePreferences(const WebPreferencesStore
settings.setAcceleratedCompositingEnabled(false);
}
#endif
+
settings.setForceCompositingMode(store.getBoolValueForKey(WebPreferencesKey::forceCompositingModeKey()));
// Fixed position elements need to be composited and create stacking contexts
// in order to be scrolled by the ScrollingCoordinator.
@@ -616,6 +629,11 @@ void DrawingAreaCoordinatedGraphics::enterAcceleratedCompositingMode(GraphicsLay
m_scrollOffset = IntSize();
m_displayTimer.stop();
m_isWaitingForDidUpdate = false;
+// Playwright begin
+#if PLATFORM(WIN)
+ didChangeAcceleratedCompositingMode(true);
+#endif
+// Playwright end
}
void DrawingAreaCoordinatedGraphics::exitAcceleratedCompositingMode()
@@ -665,6 +683,11 @@ void DrawingAreaCoordinatedGraphics::exitAcceleratedCompositingMode()
// UI process, we still need to let it know about the new contents, so send an Update message.
send(Messages::DrawingAreaProxy::Update(m_backingStoreStateID, updateInfo));
}
+// Playwright begin
+#if PLATFORM(WIN)
+ didChangeAcceleratedCompositingMode(false);
+#endif
+// Playwright end
}
void DrawingAreaCoordinatedGraphics::scheduleDisplay()
diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp
index 8685e23d0d468601c459954775fe6f565b0ce7ac..f9d49292837bf390b81eadeaebe2d4d599bc236c 100644
--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp
+++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp
@@ -166,8 +166,16 @@ void LayerTreeHost::setViewOverlayRootLayer(GraphicsLayer* viewOverlayRootLayer)
void LayerTreeHost::scrollNonCompositedContents(const IntRect& rect)
{
auto* frameView = m_webPage.mainFrameView();
+
+// Playwright begin
+#if PLATFORM(WIN)
if (!frameView || !frameView->delegatesScrolling())
+ return
+#else
+ if (!frameView)
return;
+#endif
+// Playwright end
m_viewportController.didScroll(rect.location());
if (m_isDiscardable)
diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp
index 28e2c6d10fa08265d8edb7449565ee527f9826ed..044e7a5a9f3fb74fbfb7cdae33df4439d1b2938a 100644
--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp
+++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp
@@ -29,6 +29,7 @@
#if USE(GRAPHICS_LAYER_TEXTURE_MAPPER)
+#include "DrawingArea.h"
#include "WebPage.h"
#include <GLES2/gl2.h>
#include <WebCore/Document.h>
diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp
index 97429e9769d2accf3d99949e2f6ca8a4e8acece9..eda4008b60b4f28958e246ae9aea773b4407769e 100644
--- a/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp
+++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp
@@ -27,6 +27,7 @@
#include "DrawingArea.h"
#include "DrawingAreaMessages.h"
+#include "DrawingAreaProxyMessages.h"
#include "WebPage.h"
#include "WebPageCreationParameters.h"
#include "WebProcess.h"
@@ -89,6 +90,13 @@ RefPtr<WebCore::DisplayRefreshMonitor> DrawingArea::createDisplayRefreshMonitor(
}
#endif
+#if PLATFORM(WIN)
+void DrawingArea::didChangeAcceleratedCompositingMode(bool enabled)
+{
+ send(Messages::DrawingAreaProxy::DidChangeAcceleratedCompositingMode(enabled));
+}
+#endif
+
void DrawingArea::removeMessageReceiverIfNeeded()
{
if (m_hasRemovedMessageReceiver)
diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.h b/Source/WebKit/WebProcess/WebPage/DrawingArea.h
index e1c230af001c04e9ad5c525a31b5c912e2eac3bd..9c1a2473fe463830718412f62506a14ceff63e10 100644
--- a/Source/WebKit/WebProcess/WebPage/DrawingArea.h
+++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.h
@@ -143,6 +143,9 @@ public:
virtual void didChangeViewportAttributes(WebCore::ViewportAttributes&&) = 0;
virtual void deviceOrPageScaleFactorChanged() = 0;
#endif
+#if PLATFORM(WIN)
+ void didChangeAcceleratedCompositingMode(bool enabled);
+#endif
virtual void adoptLayersFromDrawingArea(DrawingArea&) { }
virtual void adoptDisplayRefreshMonitorsFromDrawingArea(DrawingArea&) { }
diff --git a/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.cpp b/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.cpp
index b2d54a627b94583bda3518c4e7c3364481b605a4..d407e32b6a7b8b27925c49391e86d42c9b3dfa8b 100644
--- a/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.cpp
+++ b/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.cpp
@@ -47,6 +47,14 @@ void WebDocumentLoader::detachFromFrame()
DocumentLoader::detachFromFrame();
}
+void WebDocumentLoader::replacedByFragmentNavigation(Frame& frame)
+{
+ ASSERT(!this->frame());
+ // Notify WebPageProxy that the navigation has been converted into same page navigation.
+ if (m_navigationID)
+ WebFrame::fromCoreFrame(frame)->documentLoaderDetached(m_navigationID);
+}
+
void WebDocumentLoader::setNavigationID(uint64_t navigationID)
{
ASSERT(navigationID);
diff --git a/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.h b/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.h
index f127d64d005ab7b93875591b94a5899205e91579..df0de26e4dc449a0fbf93e7037444df4e5365822 100644
--- a/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.h
+++ b/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.h
@@ -43,7 +43,10 @@ public:
private:
WebDocumentLoader(const WebCore::ResourceRequest&, const WebCore::SubstituteData&);
+ uint64_t loaderIDForInspector() override { return navigationID(); }
+
void detachFromFrame() override;
+ void replacedByFragmentNavigation(WebCore::Frame&) override;
uint64_t m_navigationID;
};
diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
index b148ce85829bb4b4f60e648a928b7a334281632e..e715473c457a0f926e8d4bd3c432faa1357d7b85 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
@@ -805,6 +805,9 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters)
m_page->setCanUseCredentialStorage(parameters.canUseCredentialStorage);
+ if (parameters.shouldPauseInInspectorWhenShown)
+ m_page->inspectorController().pauseWhenShown();
+
updateThrottleState();
}
@@ -1593,6 +1596,22 @@ void WebPage::platformDidReceiveLoadParameters(const LoadParameters& loadParamet
}
#endif
+void WebPage::loadRequestInFrameForInspector(LoadParameters&& loadParameters, WebCore::FrameIdentifier frameID)
+{
+ WebFrame* frame = WebProcess::singleton().webFrame(frameID);
+ if (!frame) {
+ send(Messages::WebPageProxy::DidDestroyNavigation(loadParameters.navigationID));
+ return;
+ }
+
+ // FIXME: use m_pendingNavigationID instead?
+ m_pendingFrameNavigationID = loadParameters.navigationID;
+
+ FrameLoadRequest frameLoadRequest { *frame->coreFrame(), loadParameters.request };
+ frame->coreFrame()->loader().load(WTFMove(frameLoadRequest));
+ ASSERT(!m_pendingFrameNavigationID);
+}
+
void WebPage::loadRequest(LoadParameters&& loadParameters)
{
#if ENABLE(APP_BOUND_DOMAINS)
@@ -1803,17 +1822,13 @@ void WebPage::setSize(const WebCore::IntSize& viewSize)
view->resize(viewSize);
m_drawingArea->setNeedsDisplay();
-#if USE(COORDINATED_GRAPHICS)
if (view->useFixedLayout())
sendViewportAttributesChanged(m_page->viewportArguments());
-#endif
}
-#if USE(COORDINATED_GRAPHICS)
void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArguments)
{
- FrameView* view = m_page->mainFrame().view();
- ASSERT(view && view->useFixedLayout());
+ ASSERT(m_page->mainFrame().view() && m_page->mainFrame().view()->useFixedLayout());
// Viewport properties have no impact on zero sized fixed viewports.
if (m_viewSize.isEmpty())
@@ -1830,20 +1845,18 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg
ViewportAttributes attr = computeViewportAttributes(viewportArguments, minimumLayoutFallbackWidth, deviceWidth, deviceHeight, 1, m_viewSize);
- // If no layout was done yet set contentFixedOrigin to (0,0).
- IntPoint contentFixedOrigin = view->didFirstLayout() ? view->fixedVisibleContentRect().location() : IntPoint();
-
- // Put the width and height to the viewport width and height. In css units however.
- // Use FloatSize to avoid truncated values during scale.
- FloatSize contentFixedSize = m_viewSize;
-
- contentFixedSize.scale(1 / attr.initialScale);
- view->setFixedVisibleContentRect(IntRect(contentFixedOrigin, roundedIntSize(contentFixedSize)));
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+ FrameView* view = m_page->mainFrame().view();
+ // CSS viewport descriptors might be applied to already affected viewport size
+ // if the page enables/disables stylesheets, so need to keep initial viewport size.
+ view->setInitialViewportSize(roundedIntSize(m_viewSize));
+#endif
attr.initialScale = m_page->viewportArguments().zoom; // Resets auto (-1) if no value was set by user.
// This also takes care of the relayout.
setFixedLayoutSize(roundedIntSize(attr.layoutSize));
+ scaleView(deviceWidth / attr.layoutSize.width());
#if USE(COORDINATED_GRAPHICS)
m_drawingArea->didChangeViewportAttributes(WTFMove(attr));
@@ -1851,7 +1864,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg
send(Messages::WebPageProxy::DidChangeViewportProperties(attr));
#endif
}
-#endif
void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
{
@@ -2150,6 +2162,7 @@ void WebPage::scaleView(double scale)
}
m_page->setViewScaleFactor(scale);
+ send(Messages::WebPageProxy::ViewScaleFactorDidChange(scale));
scalePage(pageScale, scrollPositionAtNewScale);
}
@@ -2254,17 +2267,13 @@ void WebPage::viewportPropertiesDidChange(const ViewportArguments& viewportArgum
viewportConfigurationChanged();
#endif
-#if USE(COORDINATED_GRAPHICS)
FrameView* view = m_page->mainFrame().view();
if (view && view->useFixedLayout())
sendViewportAttributesChanged(viewportArguments);
+#if USE(COORDINATED_GRAPHICS)
else
m_drawingArea->didChangeViewportAttributes(ViewportAttributes());
#endif
-
-#if !PLATFORM(IOS_FAMILY) && !USE(COORDINATED_GRAPHICS)
- UNUSED_PARAM(viewportArguments);
-#endif
}
void WebPage::listenForLayoutMilestones(OptionSet<WebCore::LayoutMilestone> milestones)
@@ -3092,6 +3101,104 @@ void WebPage::touchEvent(const WebTouchEvent& touchEvent)
send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
}
+
+void WebPage::fakeTouchTap(const WebCore::IntPoint& position, uint8_t modifiers, CompletionHandler<void()>&& completionHandler)
+{
+ SetForScope<bool> userIsInteractingChange { m_userIsInteracting, true };
+
+ bool handled = false;
+
+ uint32_t id = 0;
+ float radiusX = 1.0;
+ float radiusY = 1.0;
+ float rotationAngle = 0.0;
+ float force = 1.0;
+ const WebCore::IntSize radius(radiusX,radiusY);
+ const WebCore::IntPoint screenPosition = position;
+ OptionSet<WebEvent::Modifier> eventModifiers;
+ eventModifiers = eventModifiers.fromRaw(modifiers);
+
+ {
+ Vector<WebPlatformTouchPoint> touchPoints;
+ WebPlatformTouchPoint::TouchPointState state = WebPlatformTouchPoint::TouchPointState::TouchPressed;
+ touchPoints.append(WebPlatformTouchPoint(id, state, screenPosition, position, radius, rotationAngle, force));
+
+ WebTouchEvent touchEvent(WebEvent::TouchStart, WTFMove(touchPoints), eventModifiers, WallTime::now());
+
+ CurrentEvent currentEvent(touchEvent);
+ handled = handleTouchEvent(touchEvent, m_page.get());
+ }
+ {
+ Vector<WebPlatformTouchPoint> touchPoints;
+ WebPlatformTouchPoint::TouchPointState state = WebPlatformTouchPoint::TouchPointState::TouchReleased;
+ touchPoints.append(WebPlatformTouchPoint(id, state, screenPosition, position, radius, rotationAngle, force));
+
+ WebTouchEvent touchEvent(WebEvent::TouchEnd, WTFMove(touchPoints), eventModifiers, WallTime::now());
+
+ CurrentEvent currentEvent(touchEvent);
+ handled = handleTouchEvent(touchEvent, m_page.get()) || handled;
+ }
+ if (!handled) {
+ FloatPoint adjustedPoint;
+ Node* nodeRespondingToClick = m_page->mainFrame().nodeRespondingToClickEvents(position, adjustedPoint);
+ Frame* frameRespondingToClick = nodeRespondingToClick ? nodeRespondingToClick->document().frame() : nullptr;
+ IntPoint adjustedIntPoint = roundedIntPoint(adjustedPoint);
+ if (!frameRespondingToClick) {
+ completionHandler();
+ return;
+ }
+ bool shiftKey = eventModifiers.contains(WebEvent::Modifier::ShiftKey);
+ bool ctrlKey = eventModifiers.contains(WebEvent::Modifier::ControlKey);
+ bool altKey = eventModifiers.contains(WebEvent::Modifier::AltKey);
+ bool metaKey = eventModifiers.contains(WebEvent::Modifier::MetaKey);
+ double force = 0.0;
+ SyntheticClickType syntheticClickType = SyntheticClickType::OneFingerTap;
+
+ m_page->mainFrame().eventHandler().mouseMoved(PlatformMouseEvent(
+ adjustedIntPoint,
+ adjustedIntPoint,
+ MouseButton::NoButton,
+ PlatformEvent::Type::MouseMoved,
+ 0,
+ shiftKey,
+ ctrlKey,
+ altKey,
+ metaKey,
+ WallTime::now(),
+ force,
+ syntheticClickType
+ ));
+ m_page->mainFrame().eventHandler().handleMousePressEvent(PlatformMouseEvent(
+ adjustedIntPoint,
+ adjustedIntPoint,
+ MouseButton::LeftButton,
+ PlatformEvent::Type::MousePressed,
+ 1,
+ shiftKey,
+ ctrlKey,
+ altKey,
+ metaKey,
+ WallTime::now(),
+ force,
+ syntheticClickType
+ ));
+ m_page->mainFrame().eventHandler().handleMouseReleaseEvent(PlatformMouseEvent(
+ adjustedIntPoint,
+ adjustedIntPoint,
+ MouseButton::LeftButton,
+ PlatformEvent::Type::MouseReleased,
+ 1,
+ shiftKey,
+ ctrlKey,
+ altKey,
+ metaKey,
+ WallTime::now(),
+ force,
+ syntheticClickType
+ ));
+ }
+ completionHandler();
+}
#endif
void WebPage::cancelPointer(WebCore::PointerID pointerId, const WebCore::IntPoint& documentPoint)
@@ -3168,6 +3275,11 @@ void WebPage::sendMessageToTargetBackend(const String& targetId, const String& m
m_inspectorTargetController->sendMessageToTargetBackend(targetId, message);
}
+void WebPage::resumeInspectorIfPausedInNewWindow()
+{
+ m_page->inspectorController().resumeIfPausedInNewWindow();
+}
+
void WebPage::insertNewlineInQuotedContent()
{
Frame& frame = m_page->focusController().focusedOrMainFrame();
@@ -3403,6 +3515,7 @@ void WebPage::didCompletePageTransition()
void WebPage::show()
{
send(Messages::WebPageProxy::ShowPage());
+ m_page->inspectorController().didShowNewWindow();
}
void WebPage::setIsTakingSnapshotsForApplicationSuspension(bool isTakingSnapshotsForApplicationSuspension)
@@ -6512,6 +6625,9 @@ Ref<DocumentLoader> WebPage::createDocumentLoader(Frame& frame, const ResourceRe
WebsitePoliciesData::applyToDocumentLoader(WTFMove(*m_pendingWebsitePolicies), documentLoader);
m_pendingWebsitePolicies = WTF::nullopt;
}
+ } else if (m_pendingFrameNavigationID) {
+ documentLoader->setNavigationID(m_pendingFrameNavigationID);
+ m_pendingFrameNavigationID = 0;
}
return documentLoader;
diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h
index f05fc8063c7f10d3a988b7026997aed294d1f3f9..d9c9b4f800622d4fc3c48d4188d863fc10f0af13 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.h
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h
@@ -1189,6 +1189,7 @@ public:
void connectInspector(const String& targetId, Inspector::FrontendChannel::ConnectionType);
void disconnectInspector(const String& targetId);
void sendMessageToTargetBackend(const String& targetId, const String& message);
+ void resumeInspectorIfPausedInNewWindow();
void insertNewlineInQuotedContent();
@@ -1474,6 +1475,7 @@ private:
// Actions
void tryClose(CompletionHandler<void(bool)>&&);
void platformDidReceiveLoadParameters(const LoadParameters&);
+ void loadRequestInFrameForInspector(LoadParameters&&, WebCore::FrameIdentifier);
void loadRequest(LoadParameters&&);
NO_RETURN void loadRequestWaitingForProcessLaunch(LoadParameters&&, URL&&, WebPageProxyIdentifier, bool);
void loadData(LoadParameters&&);
@@ -1509,6 +1511,7 @@ private:
void updatePotentialTapSecurityOrigin(const WebTouchEvent&, bool wasHandled);
#elif ENABLE(TOUCH_EVENTS)
void touchEvent(const WebTouchEvent&);
+ void fakeTouchTap(const WebCore::IntPoint& position, uint8_t modifiers, CompletionHandler<void()>&& completionHandler);
#endif
void cancelPointer(WebCore::PointerID, const WebCore::IntPoint&);
@@ -1626,9 +1629,7 @@ private:
void countStringMatches(const String&, OptionSet<FindOptions>, uint32_t maxMatchCount);
void replaceMatches(const Vector<uint32_t>& matchIndices, const String& replacementText, bool selectionOnly, CallbackID);
-#if USE(COORDINATED_GRAPHICS)
void sendViewportAttributesChanged(const WebCore::ViewportArguments&);
-#endif
void didChangeSelectedIndexForActivePopupMenu(int32_t newIndex);
void setTextForActivePopupMenu(int32_t index);
@@ -2107,6 +2108,7 @@ private:
UserActivity m_userActivity;
uint64_t m_pendingNavigationID { 0 };
+ uint64_t m_pendingFrameNavigationID { 0 };
Optional<WebsitePoliciesData> m_pendingWebsitePolicies;
bool m_mainFrameProgressCompleted { false };
diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
index 3a7d1af25f5aa67ed522e05326d48a9bce48fd0b..cd86b8df97b42c6830124daef31a2d2e83234314 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
@@ -132,6 +132,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType
ConnectInspector(String targetId, Inspector::FrontendChannel::ConnectionType connectionType)
DisconnectInspector(String targetId)
SendMessageToTargetBackend(String targetId, String message)
+ ResumeInspectorIfPausedInNewWindow();
#if ENABLE(REMOTE_INSPECTOR)
SetIndicating(bool indicating);
@@ -143,6 +144,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType
#endif
#if !ENABLE(IOS_TOUCH_EVENTS) && ENABLE(TOUCH_EVENTS)
TouchEvent(WebKit::WebTouchEvent event)
+ FakeTouchTap(WebCore::IntPoint position, uint8_t modifiers) -> () Async
#endif
CancelPointer(WebCore::PointerID pointerId, WebCore::IntPoint documentPoint)
@@ -177,6 +179,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType
LoadURLInFrame(URL url, String referrer, WebCore::FrameIdentifier frameID)
LoadDataInFrame(IPC::DataReference data, String MIMEType, String encodingName, URL baseURL, WebCore::FrameIdentifier frameID)
LoadRequest(struct WebKit::LoadParameters loadParameters)
+ LoadRequestInFrameForInspector(struct WebKit::LoadParameters loadParameters, WebCore::FrameIdentifier frameID)
LoadRequestWaitingForProcessLaunch(struct WebKit::LoadParameters loadParameters, URL resourceDirectoryURL, WebKit::WebPageProxyIdentifier pageID, bool checkAssumedReadAccessToResourceURL)
LoadData(struct WebKit::LoadParameters loadParameters)
LoadAlternateHTML(struct WebKit::LoadParameters loadParameters)
diff --git a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm
index a1729f5c6205d16d7fa998a6536a84c8fa480454..a23b742a0f5ef084f116b2e2c61e84605f63a2a7 100644
--- a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm
+++ b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm
@@ -832,21 +832,37 @@ String WebPage::platformUserAgent(const URL&) const
bool WebPage::hoverSupportedByPrimaryPointingDevice() const
{
+#if ENABLE(TOUCH_EVENTS)
+ return !screenIsTouchPrimaryInputDevice();
+#else
return true;
+#endif
}
bool WebPage::hoverSupportedByAnyAvailablePointingDevice() const
{
+#if ENABLE(TOUCH_EVENTS)
+ return !screenHasTouchDevice();
+#else
return true;
+#endif
}
Optional<PointerCharacteristics> WebPage::pointerCharacteristicsOfPrimaryPointingDevice() const
{
+#if ENABLE(TOUCH_EVENTS)
+ if (screenIsTouchPrimaryInputDevice())
+ return PointerCharacteristics::Coarse;
+#endif
return PointerCharacteristics::Fine;
}
OptionSet<PointerCharacteristics> WebPage::pointerCharacteristicsOfAllAvailablePointingDevices() const
{
+#if ENABLE(TOUCH_EVENTS)
+ if (screenHasTouchDevice())
+ return PointerCharacteristics::Coarse;
+#endif
return PointerCharacteristics::Fine;
}
diff --git a/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp b/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp
index fbfc1fd3ece09dc3dfd9300dc1d67f045942053b..08a671959b8483760771a790ad6793eb124a9495 100644
--- a/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp
+++ b/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp
@@ -43,6 +43,7 @@
#include <WebCore/NotImplemented.h>
#include <WebCore/Page.h>
#include <WebCore/PlatformKeyboardEvent.h>
+#include <WebCore/PlatformScreen.h>
#include <WebCore/PointerCharacteristics.h>
#include <WebCore/Settings.h>
#include <WebCore/SharedBuffer.h>
@@ -118,21 +119,37 @@ String WebPage::platformUserAgent(const URL&) const
bool WebPage::hoverSupportedByPrimaryPointingDevice() const
{
+#if ENABLE(TOUCH_EVENTS)
+ return !screenIsTouchPrimaryInputDevice();
+#else
return true;
+#endif
}
bool WebPage::hoverSupportedByAnyAvailablePointingDevice() const
{
+#if ENABLE(TOUCH_EVENTS)
+ return !screenHasTouchDevice();
+#else
return true;
+#endif
}
Optional<PointerCharacteristics> WebPage::pointerCharacteristicsOfPrimaryPointingDevice() const
{
+#if ENABLE(TOUCH_EVENTS)
+ if (screenIsTouchPrimaryInputDevice())
+ return PointerCharacteristics::Coarse;
+#endif
return PointerCharacteristics::Fine;
}
OptionSet<PointerCharacteristics> WebPage::pointerCharacteristicsOfAllAvailablePointingDevices() const
{
+#if ENABLE(TOUCH_EVENTS)
+ if (screenHasTouchDevice())
+ return PointerCharacteristics::Coarse;
+#endif
return PointerCharacteristics::Fine;
}
diff --git a/Source/WebKit/WebProcess/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp
index dfa57c655ada7cf97189b757c59aa901950aa9e8..56832e0190d11e0894a4c537b3ff3806adf4e473 100644
--- a/Source/WebKit/WebProcess/WebProcess.cpp
+++ b/Source/WebKit/WebProcess/WebProcess.cpp
@@ -81,6 +81,7 @@
#include "WebsiteData.h"
#include "WebsiteDataStoreParameters.h"
#include "WebsiteDataType.h"
+#include <JavaScriptCore/IdentifiersFactory.h>
#include <JavaScriptCore/JSLock.h>
#include <JavaScriptCore/MemoryStatistics.h>
#include <JavaScriptCore/WasmFaultSignalHandler.h>
@@ -298,6 +299,8 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter
platformInitializeProcess(parameters);
updateCPULimit();
+
+ Inspector::IdentifiersFactory::initializeWithProcessID(parameters.processIdentifier->toUInt64());
}
void WebProcess::initializeConnection(IPC::Connection* connection)
diff --git a/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in b/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in
index 3c3fbaab081e5775e9c6e40e571e56521c8de843..25ca899fc5fb6be42aceec515fcabbec7753a586 100644
--- a/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in
+++ b/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in
@@ -1218,14 +1218,19 @@
#include <WebKitAdditions/WebContentSandboxAdditionsMac.sb>
#endif
-(when (defined? 'mach-bootstrap)
- (allow mach-bootstrap
- (apply-message-filter
- (allow xpc-message-send (with telemetry))
- (allow xpc-message-send (with telemetry) (message-number 206))
- )
- )
-)
+;;; Playwright: This requires an entitlement
+;;; that only exists in builds signed by Apple.
+;;; It looks like we can disable it for now
+;;; without side effects
+;;;
+;;; (when (defined? 'mach-bootstrap)
+;;; (allow mach-bootstrap
+;;; (apply-message-filter
+;;; (allow xpc-message-send (with telemetry))
+;;; (allow xpc-message-send (with telemetry) (message-number 206))
+;;; )
+;;; )
+;;; )
(when (defined? 'mach-kernel-endpoint)
(allow mach-kernel-endpoint
diff --git a/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp b/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp
index 89bc159df35910abe133c68d71057cdfe1995cbb..aba8e9110a3ec4c59e9888b148e1e908d477cbe4 100644
--- a/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp
+++ b/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp
@@ -42,7 +42,9 @@ public:
bool platformInitialize() override
{
if (SetProcessDpiAwarenessContextPtr())
- SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
+ // Playwright begin
+ SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_UNAWARE);
+ // Playwright end
else
SetProcessDPIAware();
return true;
diff --git a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
index 5e6fe8a0b8b8ddecbf80dbe3f5bae1318b086c67..d0818be5694661726f762aaadfb7aaecc255c167 100644
--- a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
+++ b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
@@ -4227,7 +4227,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 b60e326f10bf5ce3ca6fa3f40b1aa8e0979d4237..e16971854b698923c4ae41de41674f555372863a 100644
--- a/Source/WebKitLegacy/mac/WebView/WebView.mm
+++ b/Source/WebKitLegacy/mac/WebView/WebView.mm
@@ -4188,7 +4188,7 @@ IGNORE_WARNINGS_END
}
#endif // PLATFORM(IOS_FAMILY)
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(IOS_TOUCH_EVENTS)
- (NSArray *)_touchEventRegions
{
@@ -4230,7 +4230,7 @@ IGNORE_WARNINGS_END
}).autorelease();
}
-#endif // ENABLE(TOUCH_EVENTS)
+#endif // ENABLE(IOS_TOUCH_EVENTS)
// For backwards compatibility with the WebBackForwardList API, we honor both
// a per-WebView and a per-preferences setting for whether to use the back/forward cache.
diff --git a/Source/cmake/FindLibVPX.cmake b/Source/cmake/FindLibVPX.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..dd6a53e2d57318489b7e49dd7373706d5d9dc387
--- /dev/null
+++ b/Source/cmake/FindLibVPX.cmake
@@ -0,0 +1,25 @@
+# Find LibVPX
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_LIBVPX REQUIRED vpx)
+
+find_path(LIBVPX_INCLUDE_DIRS
+ NAMES vpx/vp8.h
+ HINTS ${PC_LIBVPX_INCLUDEDIR}
+ ${PC_LIBVPX_INCLUDE_DIRS}
+)
+
+find_library(LIBVPX_LIBRARIES
+ NAMES vpx
+ HINTS ${PC_LIBVPX_LIBDIR}
+ ${PC_LIBVPX_LIBRARY_DIRS}
+)
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibVPX REQUIRED_VARS LIBVPX_INCLUDE_DIRS LIBVPX_LIBRARIES
+ VERSION_VAR PC_LIBVPX_VERSION)
+
+mark_as_advanced(
+ LIBVPX_INCLUDE_DIRS
+ LIBVPX_LIBRARIES
+)
diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake
index 2800be7b8392590f42b06b7d9b9633977aa350df..ad9efe97fdbcac92a66631e704e6ffe8d6737f75 100644
--- a/Source/cmake/OptionsGTK.cmake
+++ b/Source/cmake/OptionsGTK.cmake
@@ -6,6 +6,8 @@ WEBKIT_OPTION_DEFINE(USE_GTK4 "Whether to enable usage of GTK4 instead of GTK3."
SET_PROJECT_VERSION(2 31 0)
+set(ENABLE_WEBKIT_LEGACY OFF)
+
if (USE_GTK4)
set(WEBKITGTK_API_VERSION 5.0)
set(GTK_MINIMUM_VERSION 3.98.5)
@@ -55,6 +57,10 @@ find_package(EGL)
find_package(OpenGL)
find_package(OpenGLES2)
+# Playwright begin
+find_package(LibVPX REQUIRED)
+# Playwright end
+
include(GStreamerDefinitions)
SET_AND_EXPOSE_TO_BUILD(USE_ATK TRUE)
@@ -148,7 +154,7 @@ endif ()
# without approval from a GTK reviewer. There must be strong reason to support
# changing the value of the option.
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DRAG_SUPPORT PUBLIC ON)
-WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC OFF)
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPELLCHECK PUBLIC ON)
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_EVENTS PUBLIC ON)
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_CRYPTO PUBLIC ON)
@@ -189,6 +195,12 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHAREABLE_RESOURCE PRIVATE ON)
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_API_STATISTICS PRIVATE ON)
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_RTC PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
+# Playwright
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_APPLICATION_MANIFEST PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TRAILING_WORD PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON)
+
include(GStreamerDependencies)
# Finalize the value for all options. Do not attempt to use an option before
diff --git a/Source/cmake/OptionsWPE.cmake b/Source/cmake/OptionsWPE.cmake
index 5fbf72fe95cb148667207b39381bf90b377ad6b2..b544291ae00f9cecf2fa48d639a6449800519d52 100644
--- a/Source/cmake/OptionsWPE.cmake
+++ b/Source/cmake/OptionsWPE.cmake
@@ -3,6 +3,7 @@ include(VersioningUtils)
SET_PROJECT_VERSION(2 31 0)
set(WPE_API_VERSION 1.0)
+set(ENABLE_WEBKIT_LEGACY OFF)
CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(WEBKIT 15 0 12)
@@ -79,13 +80,20 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBGL2 PRIVATE OFF)
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_RTC PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBXR PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
+# Playwright
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_APPLICATION_MANIFEST PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TRAILING_WORD PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DARK_MODE_CSS PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON)
+
# Public options specific to the WPE port. Do not add any options here unless
# there is a strong reason we should support changing the value of the option,
# and the option is not relevant to any other WebKit ports.
WEBKIT_OPTION_DEFINE(ENABLE_GTKDOC "Whether or not to use generate gtkdoc." PUBLIC OFF)
WEBKIT_OPTION_DEFINE(USE_OPENJPEG "Whether to enable support for JPEG2000 images." PUBLIC ON)
WEBKIT_OPTION_DEFINE(USE_WOFF2 "Whether to enable support for WOFF2 Web Fonts." PUBLIC ON)
-WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC ${ENABLE_DEVELOPER_MODE})
+WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC OFF)
WEBKIT_OPTION_DEFINE(USE_SYSTEMD "Whether to enable journald logging" PUBLIC ON)
# Private options specific to the WPE port.
diff --git a/Source/cmake/OptionsWin.cmake b/Source/cmake/OptionsWin.cmake
index f8f5e6734c691cade89a3416073689d057c5b39e..79136da42497ec7a88b44bd8098f65a7829c5980 100644
--- a/Source/cmake/OptionsWin.cmake
+++ b/Source/cmake/OptionsWin.cmake
@@ -7,8 +7,9 @@ add_definitions(-D_WINDOWS -DWINVER=0x601 -D_WIN32_WINNT=0x601)
add_definitions(-DNOMINMAX)
add_definitions(-DUNICODE -D_UNICODE)
+set(ENABLE_WEBKIT_LEGACY OFF)
+
if ((NOT DEFINED ENABLE_WEBKIT_LEGACY) OR ENABLE_WEBKIT_LEGACY)
- set(ENABLE_WEBKIT_LEGACY ON)
set(ENABLE_WEBKIT OFF)
endif ()
@@ -86,6 +87,13 @@ if (${WTF_PLATFORM_WIN_CAIRO})
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBDRIVER PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_CRYPTO PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
+ # Playwright
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_CONIC_GRADIENTS PRIVATE ON)
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TRAILING_WORD PRIVATE ON)
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DARK_MODE_CSS PRIVATE ON)
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON)
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_EVENTS PRIVATE ON)
+
# FIXME: Implement plugin process on Modern WebKit. https://bugs.webkit.org/show_bug.cgi?id=185313
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETSCAPE_PLUGIN_API PRIVATE OFF)
else ()
diff --git a/Source/cmake/OptionsWinCairo.cmake b/Source/cmake/OptionsWinCairo.cmake
index bc7059b8640dc89efaa7bba164f41aaac4f658a0..49601573cd49e176866c7f13ae0bcb76bf8b6503 100644
--- a/Source/cmake/OptionsWinCairo.cmake
+++ b/Source/cmake/OptionsWinCairo.cmake
@@ -32,15 +32,36 @@ if (OpenJPEG_FOUND)
endif ()
find_package(WOFF2 1.0.2 COMPONENTS dec)
-if (WOFF2_FOUND)
- SET_AND_EXPOSE_TO_BUILD(USE_WOFF2 ON)
-endif ()
+SET_AND_EXPOSE_TO_BUILD(USE_WOFF2 ON)
find_package(WebP COMPONENTS demux)
if (WebP_FOUND)
SET_AND_EXPOSE_TO_BUILD(USE_WEBP ON)
endif ()
+# Playwright begin
+if (NOT LIBVPX_PACKAGE_PATH)
+ set(LIBVPX_PACKAGE_PATH "C:\\vcpkg\\packages\\libvpx_x64-windows")
+endif()
+file(TO_CMAKE_PATH "${LIBVPX_PACKAGE_PATH}" LIBVPX_PACKAGE_PATH)
+message(STATUS "Using LIBVPX_PACKAGE_PATH = ${LIBVPX_PACKAGE_PATH}")
+
+find_library(LIBVPX_CUSTOM_LIBRARY vpxmd.lib
+ HINTS ${LIBVPX_PACKAGE_PATH}/lib
+ REQIRED
+ NO_DEFAULT_PATH
+)
+message(STATUS "Found LIBVPX_CUSTOM_LIBRARY = ${LIBVPX_CUSTOM_LIBRARY}")
+
+find_path(LIBVPX_CUSTOM_INCLUDE_DIR
+ NAMES vpx/vp8.h
+ HINTS ${LIBVPX_PACKAGE_PATH}/include
+ REQUIRED
+ NO_DEFAULT_PATH
+)
+message(STATUS "Found LIBVPX_CUSTOM_INCLUDE_DIR = ${LIBVPX_CUSTOM_INCLUDE_DIR}")
+# Playwright end
+
# TODO: Add a check for HAVE_RSA_PSS for support of CryptoAlgorithmRSA_PSS
# https://bugs.webkit.org/show_bug.cgi?id=206635
diff --git a/Tools/MiniBrowser/gtk/BrowserTab.c b/Tools/MiniBrowser/gtk/BrowserTab.c
index 3845eabba3e964f9e11bb0ffcb8726fd4ea96fc4..2e0e3929907d4760eb681c743984d4c83273880d 100644
--- a/Tools/MiniBrowser/gtk/BrowserTab.c
+++ b/Tools/MiniBrowser/gtk/BrowserTab.c
@@ -160,6 +160,11 @@ static void loadChanged(WebKitWebView *webView, WebKitLoadEvent loadEvent, Brows
#endif
}
+static gboolean loadFailed()
+{
+ return TRUE;
+}
+
static GtkWidget *createInfoBarQuestionMessage(const char *title, const char *text)
{
GtkWidget *dialog = gtk_info_bar_new_with_buttons("No", GTK_RESPONSE_NO, "Yes", GTK_RESPONSE_YES, NULL);
@@ -623,6 +628,7 @@ static void browserTabConstructed(GObject *gObject)
g_signal_connect(tab->webView, "notify::is-loading", G_CALLBACK(isLoadingChanged), tab);
g_signal_connect(tab->webView, "decide-policy", G_CALLBACK(decidePolicy), tab);
g_signal_connect(tab->webView, "load-changed", G_CALLBACK(loadChanged), tab);
+ g_signal_connect(tab->webView, "load-failed", G_CALLBACK(loadFailed), tab);
g_signal_connect(tab->webView, "load-failed-with-tls-errors", G_CALLBACK(loadFailedWithTLSerrors), tab);
g_signal_connect(tab->webView, "permission-request", G_CALLBACK(decidePermissionRequest), tab);
g_signal_connect(tab->webView, "run-color-chooser", G_CALLBACK(runColorChooserCallback), tab);
@@ -668,6 +674,9 @@ static char *getInternalURI(const char *uri)
if (g_str_has_prefix(uri, "about:") && !g_str_equal(uri, "about:blank"))
return g_strconcat(BROWSER_ABOUT_SCHEME, uri + strlen ("about"), NULL);
+ if (!g_str_has_prefix(uri, "http://") && !g_str_has_prefix(uri, "https://") && !g_str_has_prefix(uri, "file://"))
+ return g_strconcat("http://", uri, NULL);
+
return g_strdup(uri);
}
diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.c b/Tools/MiniBrowser/gtk/BrowserWindow.c
index d77f77b12700bf585e515214ac6006f15966f676..575af598557f44a9f4872b36544b5347c1e18173 100644
--- a/Tools/MiniBrowser/gtk/BrowserWindow.c
+++ b/Tools/MiniBrowser/gtk/BrowserWindow.c
@@ -1334,6 +1334,12 @@ static gboolean browserWindowDeleteEvent(GtkWidget *widget, GdkEventAny* event)
}
#endif
+static void zeroPreferredSize(GtkWidget* widget, gint* minimumSize, gint* naturalSize)
+{
+ *minimumSize = 10;
+ *naturalSize = 10;
+}
+
static void browser_window_class_init(BrowserWindowClass *klass)
{
GObjectClass *gobjectClass = G_OBJECT_CLASS(klass);
@@ -1347,6 +1353,14 @@ static void browser_window_class_init(BrowserWindowClass *klass)
GtkWidgetClass *widgetClass = GTK_WIDGET_CLASS(klass);
widgetClass->delete_event = browserWindowDeleteEvent;
#endif
+
+// Playwrigth begin
+ // Override preferred (which is minimum :-) size to 0 so that we can
+ // emulate arbitrary resolution.
+ GtkWidgetClass* browserWidgetClass = GTK_WIDGET_CLASS(klass);
+ browserWidgetClass->get_preferred_width = zeroPreferredSize;
+ browserWidgetClass->get_preferred_height = zeroPreferredSize;
+// Playwrigth end
}
/* Public API. */
diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.h b/Tools/MiniBrowser/gtk/BrowserWindow.h
index 62629b4c1c25ae82bd797b39bbf9de0331f8eed2..5de7900a29b0e629f1ac404bbb0dc5b4e605294d 100644
--- a/Tools/MiniBrowser/gtk/BrowserWindow.h
+++ b/Tools/MiniBrowser/gtk/BrowserWindow.h
@@ -37,7 +37,7 @@ G_BEGIN_DECLS
#define BROWSER_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), BROWSER_TYPE_WINDOW))
#define BROWSER_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), BROWSER_TYPE_WINDOW))
#define BROWSER_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), BROWSER_TYPE_WINDOW, BrowserWindowClass))
-#define BROWSER_DEFAULT_URL "http://www.webkitgtk.org/"
+#define BROWSER_DEFAULT_URL "about:blank"
#define BROWSER_ABOUT_SCHEME "minibrowser-about"
typedef struct _BrowserWindow BrowserWindow;
diff --git a/Tools/MiniBrowser/gtk/main.c b/Tools/MiniBrowser/gtk/main.c
index dc53db0c258b0401e0a2dca43e0380f1074ce024..1eed53ed934952e921a69c9f62bcd34f380f9935 100644
--- a/Tools/MiniBrowser/gtk/main.c
+++ b/Tools/MiniBrowser/gtk/main.c
@@ -52,7 +52,12 @@ static const char *cookiesPolicy;
static const char *proxy;
static gboolean darkMode;
static gboolean enableITP;
+static gboolean inspectorPipe;
+static gboolean headless;
+static gboolean noStartupWindow;
+static const char *userDataDir;
static gboolean printVersion;
+static GtkApplication *browserApplication = NULL;
typedef enum {
MINI_BROWSER_ERROR_INVALID_ABOUT_PATH
@@ -144,6 +149,10 @@ static const GOptionEntry commandLineOptions[] =
{ "content-filter", 0, 0, G_OPTION_ARG_FILENAME, &contentFilter, "JSON with content filtering rules", "FILE" },
{ "enable-itp", 0, 0, G_OPTION_ARG_NONE, &enableITP, "Enable Intelligent Tracking Prevention (ITP)", NULL },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WebKitGTK version", NULL },
+ { "inspector-pipe", 0, 0, G_OPTION_ARG_NONE, &inspectorPipe, "Open pipe connection to the remote inspector", NULL },
+ { "user-data-dir", 0, 0, G_OPTION_ARG_STRING, &userDataDir, "Default profile persistence folder location", NULL },
+ { "headless", 0, 0, G_OPTION_ARG_NONE, &headless, "Noop headless operation", NULL },
+ { "no-startup-window", 0, 0, G_OPTION_ARG_NONE, &noStartupWindow, "Do not open default page", NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL…]" },
{ 0, 0, 0, 0, 0, 0, 0 }
};
@@ -584,6 +593,48 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul
g_main_loop_quit(data->mainLoop);
}
+static WebKitWebContext *persistentWebContext = NULL;
+
+static WebKitWebView *createNewPage(WebKitBrowserInspector *browser_inspector, WebKitWebContext *context)
+{
+ if (context == NULL)
+ context = persistentWebContext;
+
+ WebKitWebView *newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", context,
+ "is-ephemeral", webkit_web_context_is_ephemeral(context),
+ "is-controlled-by-automation", TRUE,
+ NULL));
+ GtkWidget *newWindow = browser_window_new(NULL, context);
+ gtk_window_set_application(GTK_WINDOW(newWindow), browserApplication);
+ browser_window_append_view(BROWSER_WINDOW(newWindow), newWebView);
+ gtk_widget_grab_focus(GTK_WIDGET(newWebView));
+ gtk_widget_show(GTK_WIDGET(newWindow));
+ webkit_web_view_load_uri(newWebView, "about:blank");
+ return newWebView;
+}
+
+static void quitBroserApplication(WebKitBrowserInspector* browser_inspector)
+{
+ g_application_release(G_APPLICATION(browserApplication));
+}
+
+static void keepApplicationAliveUntilQuit(GApplication *application)
+{
+ // Reference the application, it will be released in quitBroserApplication.
+ g_application_hold(application);
+ WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default();
+ g_signal_connect(browserInspector, "quit-application", G_CALLBACK(quitBroserApplication), NULL);
+}
+
+static void configureBrowserInspectorPipe()
+{
+ WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default();
+ g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL);
+
+ webkit_browser_inspector_initialize_pipe(proxy, ignoreHosts);
+}
+
static void startup(GApplication *application)
{
const char *actionAccels[] = {
@@ -614,10 +665,22 @@ static void startup(GApplication *application)
static void activate(GApplication *application, WebKitSettings *webkitSettings)
{
+ if (inspectorPipe)
+ configureBrowserInspectorPipe();
+
+ if (noStartupWindow) {
+ keepApplicationAliveUntilQuit(application);
+ g_clear_object(&webkitSettings);
+ return;
+ }
+
WebKitWebsiteDataManager *manager;
- if (privateMode || automationMode)
+ if (userDataDir) {
+ manager = webkit_website_data_manager_new("base-data-directory", userDataDir, "base-cache-directory", userDataDir, NULL);
+ cookiesFile = g_build_filename(userDataDir, "cookies.txt", NULL);
+ } else if (inspectorPipe || privateMode || automationMode) {
manager = webkit_website_data_manager_new_ephemeral();
- else {
+ } else {
char *dataDirectory = g_build_filename(g_get_user_data_dir(), "webkitgtk-" WEBKITGTK_API_VERSION_STRING, "MiniBrowser", NULL);
char *cacheDirectory = g_build_filename(g_get_user_cache_dir(), "webkitgtk-" WEBKITGTK_API_VERSION_STRING, "MiniBrowser", NULL);
manager = webkit_website_data_manager_new("base-data-directory", dataDirectory, "base-cache-directory", cacheDirectory, NULL);
@@ -641,6 +704,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings)
"use-system-appearance-for-scrollbars", FALSE,
#endif
NULL);
+ persistentWebContext = webContext;
g_object_unref(manager);
if (cookiesPolicy) {
@@ -716,9 +780,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings)
WebKitWebView *webView = createBrowserTab(mainWindow, webkitSettings, userContentManager, defaultWebsitePolicies);
if (!i)
firstTab = GTK_WIDGET(webView);
- gchar *url = argumentToURL(uriArguments[i]);
- webkit_web_view_load_uri(webView, url);
- g_free(url);
+ webkit_web_view_load_uri(webView, uriArguments[i]);
}
} else {
WebKitWebView *webView = createBrowserTab(mainWindow, webkitSettings, userContentManager, defaultWebsitePolicies);
@@ -791,9 +853,11 @@ int main(int argc, char *argv[])
}
GtkApplication *application = gtk_application_new(NULL, G_APPLICATION_FLAGS_NONE);
+ browserApplication = application;
g_signal_connect(application, "startup", G_CALLBACK(startup), NULL);
g_signal_connect(application, "activate", G_CALLBACK(activate), webkitSettings);
g_application_run(G_APPLICATION(application), 0, NULL);
+ browserApplication = NULL;
g_object_unref(application);
return 0;
diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp
index 2ab04ce061cffbfcbbc4e64c6683996b672abbce..2d105be12aa764a538132c8a7cf19b4ea8ec5099 100644
--- a/Tools/MiniBrowser/wpe/main.cpp
+++ b/Tools/MiniBrowser/wpe/main.cpp
@@ -40,6 +40,9 @@ static gboolean headlessMode;
static gboolean privateMode;
static gboolean automationMode;
static gboolean ignoreTLSErrors;
+static gboolean inspectorPipe;
+static gboolean noStartupWindow;
+static const char* userDataDir;
static const char* contentFilter;
static const char* cookiesFile;
static const char* cookiesPolicy;
@@ -63,6 +66,9 @@ static const GOptionEntry commandLineOptions[] =
{ "bg-color", 0, 0, G_OPTION_ARG_STRING, &bgColor, "Window background color. Default: white", "COLOR" },
{ "enable-itp", 0, 0, G_OPTION_ARG_NONE, &enableITP, "Enable Intelligent Tracking Prevention (ITP)", nullptr },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WPE version", nullptr },
+ { "inspector-pipe", 'v', 0, G_OPTION_ARG_NONE, &inspectorPipe, "Expose remote debugging protocol over pipe", nullptr },
+ { "user-data-dir", 0, 0, G_OPTION_ARG_STRING, &userDataDir, "Default profile persistence folder location", "FILE" },
+ { "no-startup-window", 0, 0, G_OPTION_ARG_NONE, &noStartupWindow, "Do not open default page", nullptr },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, nullptr, "[URL]" },
{ nullptr, 0, 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr }
};
@@ -147,13 +153,34 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul
g_main_loop_quit(data->mainLoop);
}
+static gboolean webViewLoadFailed()
+{
+ return TRUE;
+}
+
static void webViewClose(WebKitWebView* webView, gpointer)
{
// Hash table key delete func takes care of unref'ing the view
g_hash_table_remove(openViews, webView);
}
-static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer)
+static gboolean scriptDialog(WebKitWebView*, WebKitScriptDialog* dialog, gpointer)
+{
+ if (inspectorPipe)
+ webkit_script_dialog_ref(dialog);
+ return TRUE;
+}
+
+static gboolean scriptDialogHandled(WebKitWebView*, WebKitScriptDialog* dialog, gpointer)
+{
+ if (inspectorPipe)
+ webkit_script_dialog_unref(dialog);
+ return TRUE;
+}
+
+static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer);
+
+static WebKitWebView* createWebViewImpl(WebKitWebView* webView, WebKitWebContext *webContext)
{
auto backend = createViewBackend(1280, 720);
struct wpe_view_backend* wpeBackend = backend->backend();
@@ -165,17 +192,66 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi
delete static_cast<WPEToolingBackends::ViewBackend*>(data);
}, backend.release());
- auto* newWebView = webkit_web_view_new_with_related_view(viewBackend, webView);
- webkit_web_view_set_settings(newWebView, webkit_web_view_get_settings(webView));
+// Playwright begin
+ if (headlessMode) {
+ webkit_web_view_backend_set_screenshot_callback(viewBackend,
+ [](gpointer data) {
+ return static_cast<WPEToolingBackends::HeadlessViewBackend*>(data)->snapshot();
+ });
+ }
+// Playwright end
+ WebKitWebView* newWebView;
+ if (webView) {
+ newWebView = webkit_web_view_new_with_related_view(viewBackend, webView);
+ } else {
+ newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "backend", viewBackend,
+ "web-context", webContext,
+ nullptr));
+ }
g_signal_connect(newWebView, "create", G_CALLBACK(createWebView), nullptr);
g_signal_connect(newWebView, "close", G_CALLBACK(webViewClose), nullptr);
g_hash_table_add(openViews, newWebView);
+ g_signal_connect(newWebView, "load-failed", G_CALLBACK(webViewLoadFailed), nullptr);
+ g_signal_connect(newWebView, "script-dialog", G_CALLBACK(scriptDialog), nullptr);
+ g_signal_connect(newWebView, "script-dialog-handled", G_CALLBACK(scriptDialogHandled), nullptr);
+ g_signal_connect(newWebView, "create", G_CALLBACK(createWebView), nullptr);
return newWebView;
}
+static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer)
+{
+ return createWebViewImpl(webView, nullptr);
+}
+
+static WebKitWebContext *persistentWebContext = NULL;
+
+static WebKitWebView* createNewPage(WebKitBrowserInspector*, WebKitWebContext *webContext)
+{
+ if (!webContext)
+ webContext = persistentWebContext;
+ WebKitWebView* webView = createWebViewImpl(nullptr, webContext);
+ webkit_web_view_load_uri(webView, "about:blank");
+ return webView;
+}
+
+static void quitBroserApplication(WebKitBrowserInspector* browser_inspector, gpointer data)
+{
+ GMainLoop* mainLoop = static_cast<GMainLoop*>(data);
+ g_main_loop_quit(mainLoop);
+}
+
+static void configureBrowserInspector(GMainLoop* mainLoop)
+{
+ WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default();
+ g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL);
+ g_signal_connect(browserInspector, "quit-application", G_CALLBACK(quitBroserApplication), mainLoop);
+ webkit_browser_inspector_initialize_pipe(proxy, ignoreHosts);
+}
+
int main(int argc, char *argv[])
{
#if ENABLE_DEVELOPER_MODE
@@ -207,6 +283,16 @@ int main(int argc, char *argv[])
}
auto* loop = g_main_loop_new(nullptr, FALSE);
+ if (inspectorPipe)
+ configureBrowserInspector(loop);
+
+ openViews = g_hash_table_new_full(nullptr, nullptr, g_object_unref, nullptr);
+
+ if (noStartupWindow) {
+ g_main_loop_run(loop);
+ g_main_loop_unref(loop);
+ return 0;
+ }
auto backend = createViewBackend(1280, 720);
struct wpe_view_backend* wpeBackend = backend->backend();
@@ -216,7 +302,15 @@ int main(int argc, char *argv[])
return 1;
}
- auto* manager = (privateMode || automationMode) ? webkit_website_data_manager_new_ephemeral() : webkit_website_data_manager_new(nullptr);
+ WebKitWebsiteDataManager *manager;
+ if (userDataDir) {
+ manager = webkit_website_data_manager_new("base-data-directory", userDataDir, "base-cache-directory", userDataDir, NULL);
+ cookiesFile = g_build_filename(userDataDir, "cookies.txt", NULL);
+ } else if (inspectorPipe || privateMode || automationMode) {
+ manager = webkit_website_data_manager_new_ephemeral();
+ } else {
+ manager = webkit_website_data_manager_new(NULL);
+ }
webkit_website_data_manager_set_itp_enabled(manager, enableITP);
if (proxy) {
@@ -228,7 +322,8 @@ int main(int argc, char *argv[])
if (ignoreTLSErrors)
webkit_website_data_manager_set_tls_errors_policy(manager, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
- auto* webContext = webkit_web_context_new_with_website_data_manager(manager);
+ WebKitWebContext *webContext = WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, "process-swap-on-cross-site-navigation-enabled", TRUE, NULL));
+ persistentWebContext = webContext;
g_object_unref(manager);
if (cookiesPolicy) {
@@ -287,7 +382,14 @@ int main(int argc, char *argv[])
auto* viewBackend = webkit_web_view_backend_new(wpeBackend, [](gpointer data) {
delete static_cast<WPEToolingBackends::ViewBackend*>(data);
}, backend.release());
-
+// Playwright begin
+ if (headlessMode) {
+ webkit_web_view_backend_set_screenshot_callback(viewBackend,
+ [](gpointer data) {
+ return static_cast<WPEToolingBackends::HeadlessViewBackend*>(data)->snapshot();
+ });
+ }
+// Playwright end
auto* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
"backend", viewBackend,
"web-context", webContext,
@@ -304,8 +406,6 @@ int main(int argc, char *argv[])
backendPtr->setAccessibleChild(ATK_OBJECT(accessible));
#endif
- openViews = g_hash_table_new_full(nullptr, nullptr, g_object_unref, nullptr);
-
webkit_web_context_set_automation_allowed(webContext, automationMode);
g_signal_connect(webContext, "automation-started", G_CALLBACK(automationStartedCallback), webView);
g_signal_connect(webView, "permission-request", G_CALLBACK(decidePermissionRequest), nullptr);
@@ -318,16 +418,9 @@ int main(int argc, char *argv[])
webkit_web_view_set_background_color(webView, &color);
if (uriArguments) {
- const char* uri = uriArguments[0];
- if (g_str_equal(uri, "about:gpu"))
- uri = "webkit://gpu";
-
- GFile* file = g_file_new_for_commandline_arg(uri);
- char* url = g_file_get_uri(file);
- g_object_unref(file);
- webkit_web_view_load_uri(webView, url);
- g_free(url);
- } else if (automationMode)
+ // Playwright: avoid weird url transformation like http://trac.webkit.org/r240840
+ webkit_web_view_load_uri(webView, uriArguments[0]);
+ } else if (automationMode || inspectorPipe)
webkit_web_view_load_uri(webView, "about:blank");
else
webkit_web_view_load_uri(webView, "https://wpewebkit.org");
@@ -337,8 +430,7 @@ int main(int argc, char *argv[])
g_hash_table_destroy(openViews);
- if (privateMode || automationMode)
- g_object_unref(webContext);
+ g_object_unref(webContext);
g_main_loop_unref(loop);
return 0;
diff --git a/Tools/PlatformWin.cmake b/Tools/PlatformWin.cmake
index ef4407cfc114e602d98ed81724da504f453e258f..448dd483715162baba484f756fbcc1d72de4ba0c 100644
--- a/Tools/PlatformWin.cmake
+++ b/Tools/PlatformWin.cmake
@@ -12,4 +12,5 @@ endif ()
if (ENABLE_WEBKIT)
add_subdirectory(WebKitTestRunner)
+ add_subdirectory(Playwright/win)
endif ()
diff --git a/Tools/Scripts/build-webkit b/Tools/Scripts/build-webkit
index ddc2a96ac68cd51d5f4efeca78a118db91709aa2..57a78f54e72d264daa27faa53ac2a30cab98dd82 100755
--- a/Tools/Scripts/build-webkit
+++ b/Tools/Scripts/build-webkit
@@ -247,7 +247,7 @@ if (isAppleCocoaWebKit()) {
push @projects, ("Source/WebKit");
if (!isEmbeddedWebKit()) {
- push @projects, ("Tools/MiniBrowser");
+ push @projects, ("Tools/Playwright");
# WebInspectorUI must come after JavaScriptCore and WebCore but before WebKit and WebKit2
my $webKitIndex = first { $projects[$_] eq "Source/WebKitLegacy" } 0..$#projects;
diff --git a/Tools/WebKitTestRunner/PlatformGTK.cmake b/Tools/WebKitTestRunner/PlatformGTK.cmake
index 6f8366b63e43eca6b95b67bb47fee9e7a1970cf9..cc8299dfa4380b833e79a870779a222059579d3b 100644
--- a/Tools/WebKitTestRunner/PlatformGTK.cmake
+++ b/Tools/WebKitTestRunner/PlatformGTK.cmake
@@ -26,6 +26,7 @@ list(APPEND WebKitTestRunner_LIBRARIES
${GLIB_LIBRARIES}
Cairo::Cairo
GTK::GTK
+ stdc++fs
)
list(APPEND WebKitTestRunnerInjectedBundle_LIBRARIES
diff --git a/Tools/WebKitTestRunner/PlatformWPE.cmake b/Tools/WebKitTestRunner/PlatformWPE.cmake
index 775b41868718ea6734efc9082f8161eee2e0015e..68a720c0cb01d534653a259536c481683873680d 100644
--- a/Tools/WebKitTestRunner/PlatformWPE.cmake
+++ b/Tools/WebKitTestRunner/PlatformWPE.cmake
@@ -31,6 +31,7 @@ list(APPEND WebKitTestRunner_LIBRARIES
${WPEBACKEND_FDO_LIBRARIES}
Cairo::Cairo
WPEToolingBackends
+ stdc++fs
)
list(APPEND WebKitTestRunnerInjectedBundle_LIBRARIES
diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp
index a8b15401e2092abdb807a24dd590c450b1a1fa44..91395a373a91f7313b09665a74da4f6ba46c2461 100644
--- a/Tools/WebKitTestRunner/TestController.cpp
+++ b/Tools/WebKitTestRunner/TestController.cpp
@@ -731,7 +731,8 @@ void TestController::createWebViewWithOptions(const TestOptions& options)
0, // didResignInputElementStrongPasswordAppearance
0, // requestStorageAccessConfirm
shouldAllowDeviceOrientationAndMotionAccess,
- runWebAuthenticationPanel
+ runWebAuthenticationPanel,
+ 0 // handleJavaScriptDialog
};
WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient.base);
diff --git a/Tools/WebKitTestRunner/mac/EventSenderProxy.mm b/Tools/WebKitTestRunner/mac/EventSenderProxy.mm
index 10272884084d2c10208cfa0714f1b10c5efc0a0b..fca38337665e206b40fc3f620c408b249d696701 100644
--- a/Tools/WebKitTestRunner/mac/EventSenderProxy.mm
+++ b/Tools/WebKitTestRunner/mac/EventSenderProxy.mm
@@ -873,4 +873,51 @@ void EventSenderProxy::mouseScrollByWithWheelAndMomentumPhases(int x, int y, int
}
}
+#if ENABLE(TOUCH_EVENTS)
+void EventSenderProxy::addTouchPoint(int, int)
+{
+}
+
+void EventSenderProxy::updateTouchPoint(int, int, int)
+{
+}
+
+void EventSenderProxy::touchStart()
+{
+}
+
+void EventSenderProxy::touchMove()
+{
+}
+
+void EventSenderProxy::touchEnd()
+{
+}
+
+void EventSenderProxy::touchCancel()
+{
+}
+
+void EventSenderProxy::clearTouchPoints()
+{
+}
+
+void EventSenderProxy::releaseTouchPoint(int)
+{
+}
+
+void EventSenderProxy::cancelTouchPoint(int)
+{
+}
+
+void EventSenderProxy::setTouchPointRadius(int, int)
+{
+}
+
+void EventSenderProxy::setTouchModifier(WKEventModifiers, bool)
+{
+}
+#endif // ENABLE(TOUCH_EVENTS)
+
+
} // namespace WTR
diff --git a/Tools/win/DLLLauncher/DLLLauncherMain.cpp b/Tools/win/DLLLauncher/DLLLauncherMain.cpp
index 39238ac08dbcab92fb1d053928938a96f154c9b1..64bc9f1458254322dca9005b5e2d2b19bb901386 100644
--- a/Tools/win/DLLLauncher/DLLLauncherMain.cpp
+++ b/Tools/win/DLLLauncher/DLLLauncherMain.cpp
@@ -96,11 +96,9 @@ static bool prependPath(const wstring& directoryToPrepend)
static int fatalError(const wstring& programName, const wstring& message)
{
wstring caption = programName + L" can't open.";
-#if USE_CONSOLE_ENTRY_POINT
+// Playwright begin
fwprintf(stderr, L"%s\n%s\n", caption.c_str(), message.c_str());
-#else
- ::MessageBoxW(0, message.c_str(), caption.c_str(), MB_ICONERROR);
-#endif
+// Playwright end
return 1;
}
diff --git a/Tools/wpe/backends/HeadlessViewBackend.cpp b/Tools/wpe/backends/HeadlessViewBackend.cpp
index c09b6f39f894943f11b7a453428fab7d6f6e68fb..bc21acb648562ee0380811599b08f7d26c3e706a 100644
--- a/Tools/wpe/backends/HeadlessViewBackend.cpp
+++ b/Tools/wpe/backends/HeadlessViewBackend.cpp
@@ -145,27 +145,24 @@ void HeadlessViewBackend::updateSnapshot(struct wpe_fdo_shm_exported_buffer* exp
return;
}
- uint32_t bufferStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width);
- uint8_t* buffer = new uint8_t[bufferStride * m_height];
- memset(buffer, 0, bufferStride * m_height);
+ uint32_t width = std::max(0, wl_shm_buffer_get_width(shmBuffer));
+ uint32_t height = std::max(0, wl_shm_buffer_get_height(shmBuffer));
+ if (!width || !height) {
+ fprintf(stderr, "HeadlessViewBackend::updateSnapshot shmBuffer is empty: %ux%u\n", width, height);
+ return;
+ }
+ uint32_t bufferStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
+ uint32_t stride = std::max(0, wl_shm_buffer_get_stride(shmBuffer));
+ if (bufferStride != stride) {
+ fprintf(stderr, "bufferStride != stride: %u != %u\n", bufferStride, stride);
+ return;
+ }
+ uint8_t* buffer = new uint8_t[bufferStride * height];
{
- uint32_t width = std::min<uint32_t>(m_width, std::max(0, wl_shm_buffer_get_width(shmBuffer)));
- uint32_t height = std::min<uint32_t>(m_height, std::max(0, wl_shm_buffer_get_height(shmBuffer)));
- uint32_t stride = std::max(0, wl_shm_buffer_get_stride(shmBuffer));
-
wl_shm_buffer_begin_access(shmBuffer);
auto* data = static_cast<uint8_t*>(wl_shm_buffer_get_data(shmBuffer));
-
- for (uint32_t y = 0; y < height; ++y) {
- for (uint32_t x = 0; x < width; ++x) {
- buffer[bufferStride * y + 4 * x + 0] = data[stride * y + 4 * x + 0];
- buffer[bufferStride * y + 4 * x + 1] = data[stride * y + 4 * x + 1];
- buffer[bufferStride * y + 4 * x + 2] = data[stride * y + 4 * x + 2];
- buffer[bufferStride * y + 4 * x + 3] = data[stride * y + 4 * x + 3];
- }
- }
-
+ memcpy(buffer, data, bufferStride * height);
wl_shm_buffer_end_access(shmBuffer);
}
@@ -173,7 +170,7 @@ void HeadlessViewBackend::updateSnapshot(struct wpe_fdo_shm_exported_buffer* exp
cairo_surface_destroy(m_snapshot);
m_snapshot = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32,
- m_width, m_height, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width));
+ width, height, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width));
static cairo_user_data_key_t bufferKey;
cairo_surface_set_user_data(m_snapshot, &bufferKey, buffer,