playwright/browser_patches/webkit/patches/bootstrap.diff

19338 lines
839 KiB
Diff
Raw Normal View History

2019-11-19 05:18:28 +03:00
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index 990ae99086de90c6d175ddaaf5b6ec56b154814c..bd9d2f21ee9492784760331968046517daf04880 100644
2019-11-19 05:18:28 +03:00
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -1157,18 +1157,22 @@ set(JavaScriptCore_INSPECTOR_DOMAINS
2019-11-19 05:18:28 +03:00
${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
2019-11-19 05:18:28 +03:00
${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMStorage.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Database.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Debugger.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Browser.json
2019-11-19 05:18:28 +03:00
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Emulation.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/GenericTypes.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Heap.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Input.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Inspector.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/LayerTree.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Network.json
${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
2019-11-19 05:18:28 +03:00
diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make
index e9d804d9e8be5c345ef47219e0e996d319bbf907..9a73a9d88e1b2825458d40d33500d23c67d4d08b 100644
2019-11-19 05:18:28 +03:00
--- a/Source/JavaScriptCore/DerivedSources.make
+++ b/Source/JavaScriptCore/DerivedSources.make
@@ -244,18 +244,22 @@ INSPECTOR_DOMAINS := \
2019-11-19 05:18:28 +03:00
$(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 \
2019-11-19 05:18:28 +03:00
$(JavaScriptCore)/inspector/protocol/DOMStorage.json \
$(JavaScriptCore)/inspector/protocol/Database.json \
$(JavaScriptCore)/inspector/protocol/Debugger.json \
$(JavaScriptCore)/inspector/protocol/Browser.json \
2019-11-19 05:18:28 +03:00
+ $(JavaScriptCore)/inspector/protocol/Emulation.json \
$(JavaScriptCore)/inspector/protocol/GenericTypes.json \
$(JavaScriptCore)/inspector/protocol/Heap.json \
+ $(JavaScriptCore)/inspector/protocol/Input.json \
$(JavaScriptCore)/inspector/protocol/Inspector.json \
$(JavaScriptCore)/inspector/protocol/LayerTree.json \
$(JavaScriptCore)/inspector/protocol/Network.json \
$(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 \
diff --git a/Source/JavaScriptCore/bindings/ScriptValue.cpp b/Source/JavaScriptCore/bindings/ScriptValue.cpp
index dece6ac51e3a85b1e094e405effc6203887ddfd4..9bf7519d894eceb06b40d754c4fb7940399eba84 100644
--- a/Source/JavaScriptCore/bindings/ScriptValue.cpp
+++ b/Source/JavaScriptCore/bindings/ScriptValue.cpp
@@ -81,7 +81,10 @@ static RefPtr<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(), WTFMove(inspectorValue));
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 cc849f051fa40518a9d1a03429bc2b4dbcfb3102..11b05346f6098fa23f51ba9abc1af0e0e60a626c 100644
--- a/Source/JavaScriptCore/inspector/InjectedScript.cpp
+++ b/Source/JavaScriptCore/inspector/InjectedScript.cpp
@@ -287,9 +287,13 @@ 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;
RefPtr<JSON::Object> resultObject;
- bool castSucceeded = toInspectorValue(globalObject(), callResult.value())->asObject(resultObject);
+ bool castSucceeded = toInspectorValue(globalObject(), callResultValue)->asObject(resultObject);
ASSERT_UNUSED(castSucceeded, castSucceeded);
return BindingTraits<Protocol::Runtime::RemoteObject>::runtimeCast(resultObject);
diff --git a/Source/JavaScriptCore/inspector/InjectedScriptSource.js b/Source/JavaScriptCore/inspector/InjectedScriptSource.js
index cd593a24af4fe24ba59577b73b26947765edcc32..1f7a04d72065dbd60761c1a72f3254f953d3b9a9 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;
}
2019-11-19 05:18:28 +03:00
diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
index 038cb646d31706905deff8935040d63c0afd00f9..2fca7b043f15a8cce3819cc827912fb719a345db 100644
2019-11-19 05:18:28 +03:00
--- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
+++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
@@ -102,7 +102,7 @@ void BackendDispatcher::registerDispatcherForDomain(const String& domain, Supple
m_dispatchers.set(domain, dispatcher);
}
-void BackendDispatcher::dispatch(const String& message)
+BackendDispatcher::DispatchResult BackendDispatcher::dispatch(const String& message, Mode mode, Interceptor&& interceptor)
2019-11-19 05:18:28 +03:00
{
Ref<BackendDispatcher> protect(*this);
@@ -120,29 +120,32 @@ void BackendDispatcher::dispatch(const String& message)
2019-11-19 05:18:28 +03:00
if (!JSON::Value::parseJSON(message, parsedMessage)) {
reportProtocolError(ParseError, "Message must be in JSON format"_s);
sendPendingErrors();
- return;
+ return DispatchResult::Finished;
}
if (!parsedMessage->asObject(messageObject)) {
reportProtocolError(InvalidRequest, "Message must be a JSONified object"_s);
sendPendingErrors();
- return;
+ return DispatchResult::Finished;
}
RefPtr<JSON::Value> requestIdValue;
if (!messageObject->getValue("id"_s, requestIdValue)) {
reportProtocolError(InvalidRequest, "'id' property was not found"_s);
sendPendingErrors();
- return;
+ return DispatchResult::Finished;
}
if (!requestIdValue->asInteger(requestId)) {
reportProtocolError(InvalidRequest, "The type of 'id' property must be integer"_s);
sendPendingErrors();
- return;
+ return DispatchResult::Finished;
}
}
+ if (interceptor && interceptor(messageObject) == DispatchResult::Finished)
+ return DispatchResult::Finished;
+
{
// We could be called re-entrantly from a nested run loop, so restore the previous id.
SetForScope<Optional<long>> scopedRequestId(m_currentRequestId, requestId);
@@ -151,29 +154,31 @@ void BackendDispatcher::dispatch(const String& message)
2019-11-19 05:18:28 +03:00
if (!messageObject->getValue("method"_s, methodValue)) {
reportProtocolError(InvalidRequest, "'method' property wasn't found"_s);
sendPendingErrors();
- return;
+ return DispatchResult::Finished;
}
String methodString;
if (!methodValue->asString(methodString)) {
reportProtocolError(InvalidRequest, "The type of 'method' property must be string"_s);
sendPendingErrors();
- return;
+ return DispatchResult::Finished;
}
Vector<String> domainAndMethod = methodString.splitAllowingEmptyEntries('.');
if (domainAndMethod.size() != 2 || !domainAndMethod[0].length() || !domainAndMethod[1].length()) {
reportProtocolError(InvalidRequest, "The 'method' property was formatted incorrectly. It should be 'Domain.method'"_s);
sendPendingErrors();
- return;
+ return DispatchResult::Finished;
}
String domain = domainAndMethod[0];
SupplementalBackendDispatcher* domainDispatcher = m_dispatchers.get(domain);
if (!domainDispatcher) {
+ if (mode == Mode::ContinueIfDomainIsMissing)
+ return DispatchResult::Continue;
reportProtocolError(MethodNotFound, "'" + domain + "' domain was not found");
sendPendingErrors();
- return;
+ return DispatchResult::Finished;
}
String method = domainAndMethod[1];
@@ -182,6 +187,7 @@ void BackendDispatcher::dispatch(const String& message)
2019-11-19 05:18:28 +03:00
if (m_protocolErrors.size())
sendPendingErrors();
}
+ return DispatchResult::Finished;
}
// FIXME: remove this function when legacy InspectorObject symbols are no longer needed <http://webkit.org/b/179847>.
diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
index 95d9d81188e735e8f1b70cc0deee2682cb6714f0..4c67ce34302f74e0d07f64ae53a4eaf18df6669a 100644
2019-11-19 05:18:28 +03:00
--- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
+++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
@@ -82,7 +82,11 @@ public:
2019-11-19 05:18:28 +03:00
};
void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*);
- void dispatch(const String& message);
+
+ enum class DispatchResult { Finished, Continue };
+ enum class Mode { FailIfDomainIsMissing, ContinueIfDomainIsMissing };
+ using Interceptor = WTF::Function<DispatchResult(const RefPtr<JSON::Object>&)>;
+ DispatchResult dispatch(const String& message, Mode mode = Mode::FailIfDomainIsMissing, Interceptor&& interceptor = Interceptor());
2019-11-19 05:18:28 +03:00
// 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;
}
2020-02-12 22:38:38 +03:00
diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.cpp b/Source/JavaScriptCore/inspector/InspectorTarget.cpp
index 0cc2127c9c12c2d82dea9550bad73f4ffb99ba24..8ca65cc042d435cbc0e05dcc5c5dfc958eb24f5a 100644
2020-02-12 22:38:38 +03:00
--- 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()
2020-02-12 22:38:38 +03:00
void InspectorTarget::setResumeCallback(WTF::Function<void()>&& callback)
{
- ASSERT(!m_resumeCallback);
m_resumeCallback = WTFMove(callback);
}
2019-11-19 05:18:28 +03:00
diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.h b/Source/JavaScriptCore/inspector/InspectorTarget.h
index 4b95964db4d902b4b7f4b0b4c40afea51654ff2f..966a5927702b65edb343369decafda7fc83eaec7 100644
2019-11-19 05:18:28 +03:00
--- a/Source/JavaScriptCore/inspector/InspectorTarget.h
+++ b/Source/JavaScriptCore/inspector/InspectorTarget.h
@@ -56,8 +56,12 @@ public:
2019-11-19 05:18:28 +03:00
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"; }
2019-12-17 03:58:04 +03:00
+ virtual void close(String& error, bool /* runBeforeUnload */) { error = "Target cannot be closed"; }
2019-11-19 05:18:28 +03:00
private:
+ virtual void willResume() { }
+
WTF::Function<void()> m_resumeCallback;
bool m_isPaused { false };
};
2019-11-19 05:18:28 +03:00
diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
index 8fcb5a1e55750d325a84824d86c49cfe6fb04268..ed2525df326bfe649793701a112eefa30952e375 100644
2019-11-19 05:18:28 +03:00
--- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
+++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
@@ -87,6 +87,28 @@ void InspectorTargetAgent::sendMessageToTarget(ErrorString& errorString, const S
2019-11-19 05:18:28 +03:00
target->sendMessageToTargetBackend(message);
}
+void InspectorTargetAgent::activate(ErrorString& errorString, const String& targetId)
+{
+ InspectorTarget* target = m_targets.get(targetId);
+ if (!target) {
+ errorString = "Missing target for given targetId"_s;
+ return;
+ }
+
+ target->activate(errorString);
+}
+
+void InspectorTargetAgent::close(ErrorString& errorString, const String& targetId, const bool* runBeforeUnload)
2019-11-19 05:18:28 +03:00
+{
+ InspectorTarget* target = m_targets.get(targetId);
+ if (!target) {
+ errorString = "Missing target for given targetId"_s;
+ return;
+ }
+
+ target->close(errorString, runBeforeUnload && *runBeforeUnload);
2019-11-19 05:18:28 +03:00
+}
+
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 +166,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 +191,18 @@ void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID,
2019-11-19 05:18:28 +03:00
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 1eb7abb2fa21d7a8ec0833160f53e5c523ec4317..7709bcc2ec69aab0589ca1b954db1fb241bb583b 100644
2019-11-19 05:18:28 +03:00
--- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h
+++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h
@@ -52,15 +52,21 @@ public:
void setPauseOnStart(ErrorString&, bool pauseOnStart) override;
void resume(ErrorString&, const String& targetId) override;
2019-11-19 05:18:28 +03:00
void sendMessageToTarget(ErrorString&, const String& targetId, const String& message) final;
+ void activate(ErrorString&, const String& targetId) override;
+ void close(ErrorString&, const String& targetId, const bool* runBeforeUnload) override;
2019-11-19 05:18:28 +03:00
// Target lifecycle.
void targetCreated(InspectorTarget&);
void targetDestroyed(InspectorTarget&);
+ void targetCrashed(InspectorTarget&);
2019-11-19 05:18:28 +03:00
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;
2019-11-19 05:18:28 +03:00
diff --git a/Source/JavaScriptCore/inspector/protocol/DOM.json b/Source/JavaScriptCore/inspector/protocol/DOM.json
index 38cb48bedf2b168149ff79423b7fafc1e63ce8b3..e3d044934f5a0dc2331534439daa53116019548f 100644
2019-11-19 05:18:28 +03:00
--- 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": [
@@ -481,7 +501,9 @@
"name": "resolveNode",
"description": "Resolves JavaScript node object for given node id.",
"parameters": [
- { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to resolve." },
+ { "name": "nodeId", "$ref": "NodeId", "optional": true, "description": "Id of the node to resolve." },
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "Source element handle." },
+ { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Specifies in which execution context to adopt to." },
{ "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }
],
"returns": [
@@ -542,6 +564,45 @@
2019-11-19 05:18:28 +03:00
"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." }
+ ]
+ },
+ {
2019-11-19 05:18:28 +03:00
+ "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." }
2019-11-19 05:18:28 +03:00
+ ],
+ "returns": [
+ {
+ "name": "quads", "type": "array", "items": { "$ref": "Quad" }, "description": "Quads that describe node layout relative to viewport."
2019-11-19 05:18:28 +03:00
+ }
+ ]
+ },
+ {
+ "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" }
2019-11-19 05:18:28 +03:00
+ ]
}
],
"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."}
+ ]
+ }
+ ]
+}
2019-11-19 05:18:28 +03:00
diff --git a/Source/JavaScriptCore/inspector/protocol/Emulation.json b/Source/JavaScriptCore/inspector/protocol/Emulation.json
new file mode 100644
index 0000000000000000000000000000000000000000..3f28f8e41b39c517369c8ca69415486a75657489
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Emulation.json
@@ -0,0 +1,51 @@
2019-11-19 05:18:28 +03:00
+{
+ "domain": "Emulation",
+ "availability": ["web"],
+ "commands": [
+ {
+ "name": "setDeviceMetricsOverride",
+ "description": "Overrides device metrics with provided values.",
+ "async": true,
2019-11-19 05:18:28 +03:00
+ "parameters": [
+ { "name": "width", "type": "integer" },
+ { "name": "height", "type": "integer" },
2020-01-03 09:38:17 +03:00
+ { "name": "deviceScaleFactor", "type": "number" },
+ { "name": "fixedLayout", "type": "boolean" }
2019-11-19 05:18:28 +03:00
+ ]
+ },
+ {
+ "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."
2019-11-19 05:18:28 +03:00
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/Input.json b/Source/JavaScriptCore/inspector/protocol/Input.json
new file mode 100644
index 0000000000000000000000000000000000000000..34909cce9f6d8d7c74be4c96e40f80cadb2f931d
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Input.json
@@ -0,0 +1,165 @@
2019-11-19 05:18:28 +03:00
+{
+ "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"
+ }
2019-11-19 05:18:28 +03:00
+ }
+ ]
+ },
+ {
+ "name": "dispatchMouseEvent",
+ "description": "Dispatches a mouse event to the page.",
+ "async": true,
+ "parameters": [
+ {
+ "name": "type",
+ "description": "Type of the mouse event.",
+ "type": "string",
+ "enum": [ "move", "down", "up", "wheel"]
+ },
+ {
+ "name": "x",
+ "description": "X coordinate of the event relative to the main frame's viewport in CSS pixels.",
+ "type": "integer"
+ },
+ {
+ "name": "y",
+ "description": "Y coordinate of the event relative to the main frame's viewport in CSS pixels. 0 refers to\nthe top of the viewport and Y increases as it proceeds towards the bottom of the viewport.",
+ "type": "integer"
+ },
+ {
+ "name": "modifiers",
+ "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8\n(default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "button",
+ "description": "Mouse button (default: \"none\").",
+ "optional": true,
+ "type": "string",
+ "enum": [
+ "none",
+ "left",
+ "middle",
+ "right",
+ "back",
+ "forward"
+ ]
+ },
+ {
+ "name": "buttons",
+ "description": "A number indicating which buttons are pressed on the mouse when a mouse event is triggered.\nLeft=1, Right=2, Middle=4, Back=8, Forward=16, None=0.",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "clickCount",
+ "description": "Number of times the mouse button was clicked (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "deltaX",
+ "description": "X delta in CSS pixels for mouse wheel event (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "deltaY",
+ "description": "Y delta in CSS pixels for mouse wheel event (default: 0).",
+ "optional": true,
+ "type": "integer"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/Network.json b/Source/JavaScriptCore/inspector/protocol/Network.json
index 777a54166ed6664561b3f8249a6abb4ac59d0480..e738f34f65fa8137a16bf7b66bc237b85b2f5208 100644
--- a/Source/JavaScriptCore/inspector/protocol/Network.json
+++ b/Source/JavaScriptCore/inspector/protocol/Network.json
@@ -231,7 +231,8 @@
"name": "setInterceptionEnabled",
"description": "Enable interception of network requests.",
"parameters": [
- { "name": "enabled", "type": "boolean" }
+ { "name": "enabled", "type": "boolean" },
+ { "name": "interceptRequests", "type": "boolean", "optional": true }
]
},
{
@@ -258,7 +259,18 @@
"name": "interceptContinue",
"description": "Continue an interception with no modifications.",
"parameters": [
- { "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network request or response to continue." }
+ { "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network request or response to continue." },
+ { "name": "method", "type": "string", "optional": true,"description": "HTTP request method." },
+ { "name": "headers", "$ref": "Headers", "optional": true, "description": "HTTP response headers. Pass through original values if unmodified." },
+ { "name": "postData", "type": "string", "optional": true, "description": "HTTP POST request data." }
+ ]
+ },
+ {
+ "name": "interceptAsError",
+ "description": "Abort the intercepted request with given reason.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network request." },
+ { "name": "reason", "type": "string", "description": "Deliver error reason for the request." }
]
},
{
@@ -266,13 +278,20 @@
"description": "Provide response content for an intercepted response.",
"parameters": [
{ "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network response to modify." },
- { "name": "content", "type": "string" },
- { "name": "base64Encoded", "type": "boolean", "description": "True, if content was sent as base64." },
+ { "name": "content", "type": "string", "optional": true },
+ { "name": "base64Encoded", "type": "boolean", "optional": true, "description": "True, if content was sent as base64." },
{ "name": "mimeType", "type": "string", "optional": true, "description": "MIME Type for the data." },
{ "name": "status", "type": "integer", "optional": true, "description": "HTTP response status code. Pass through original values if unmodified." },
{ "name": "statusText", "type": "string", "optional": true, "description": "HTTP response status text. Pass through original values if unmodified." },
{ "name": "headers", "$ref": "Headers", "optional": true, "description": "HTTP response headers. Pass through original values if unmodified." }
]
+ },
+ {
+ "name": "setEmulateOfflineState",
+ "description": "Emulate offline state overriding the actual state.",
+ "parameters": [
+ { "name": "offline", "type": "boolean", "description": "True to emulate offline." }
+ ]
}
],
"events": [
@@ -356,6 +375,14 @@
{ "name": "response", "$ref": "Response", "description": "Original response content that would proceed if this is continued." }
]
},
+ {
+ "name": "requestIntercepted",
+ "description": "Fired when HTTP request has been intercepted. The frontend must response with <code>Network.interceptContinue</code> or <code>Network.interceptWithRespons</code>` to continue this response.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Identifier for this intercepted network. Corresponds with an earlier <code>Network.requestWillBeSent</code>." },
+ { "name": "request", "$ref": "Request", "description": "Original request content that would proceed if this is continued." }
+ ]
+ },
{
"name": "webSocketWillSendHandshakeRequest",
"description": "Fired when WebSocket is about to initiate handshake.",
2019-11-19 05:18:28 +03:00
diff --git a/Source/JavaScriptCore/inspector/protocol/Page.json b/Source/JavaScriptCore/inspector/protocol/Page.json
index 78980810141a9e9b65b93e6cebe80daff9a52dc1..4818c82fff8b19e060e129275ef5f95f1db2fcb0 100644
2019-11-19 05:18:28 +03:00
--- a/Source/JavaScriptCore/inspector/protocol/Page.json
+++ b/Source/JavaScriptCore/inspector/protocol/Page.json
@@ -109,6 +109,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": [
@@ -128,11 +163,21 @@
{ "name": "revalidateAllResources", "type": "boolean", "optional": true, "description": "If true, all cached subresources will be revalidated when the main resource loads. Otherwise, only expired cached subresources will be revalidated (the default behavior for most WebKit clients)." }
]
},
+ {
+ "name": "goBack",
+ "description": "Goes back in the history."
+ },
+ {
+ "name": "goForward",
+ "description": "Goes forward in the history."
+ },
{
2019-11-19 05:18:28 +03:00
"name": "navigate",
"description": "Navigates current page to the given URL.",
"parameters": [
- { "name": "url", "type": "string", "description": "URL to navigate the page to." }
+ { "name": "url", "type": "string", "description": "URL to navigate the page to." },
+ { "name": "frameId", "$ref": "Network.FrameId", "optional": true, "description": "Id of the frame to navigate."},
+ { "name": "referrer", "type": "string", "optional": true, "description": "Referrer URL." }
2019-11-19 05:18:28 +03:00
]
},
{
@@ -252,6 +297,20 @@
2019-12-20 02:07:19 +03:00
{ "name": "appearance", "$ref": "Appearance", "description": "Appearance name to force. Empty string disables the override." }
]
},
+ {
+ "name": "setTimeZone",
+ "description": "Enables time zone emulation.",
+ "parameters": [
+ { "name": "timeZone", "type": "string", "optional": true }
+ ]
+ },
+ {
2019-12-20 02:07:19 +03:00
+ "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.",
@@ -282,19 +341,85 @@
"returns": [
{ "name": "data", "type": "string", "description": "Base64-encoded web archive." }
]
+ },
+ {
+ "name": "insertText",
+ "description": "Insert text into the current selection of the page.",
+ "parameters": [
+ { "name": "text", "type": "string", "description": "Text to insert." }
+ ]
+ },
+ {
+ "name": "accessibilitySnapshot",
+ "description": "Serializes and returns all of the accessibility nodes of the page.",
+ "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": "setScreenSizeOverride",
+ "description": "Overrides screen size with provided values.",
+ "parameters": [
+ { "name": "width", "type": "integer" },
+ { "name": "height", "type": "integer" }
+ ]
+ },
+ {
+ "name": "setOrientationOverride",
+ "description": "Overrides window.orientation with provided value.",
+ "parameters": [
+ { "name": "angle", "type": "integer", "optional": true }
+ ]
}
],
"events": [
{
"name": "domContentEventFired",
"parameters": [
- { "name": "timestamp", "type": "number" }
+ { "name": "timestamp", "type": "number" },
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired DOMContentLoaded event." }
]
},
{
"name": "loadEventFired",
"parameters": [
- { "name": "timestamp", "type": "number" }
+ { "name": "timestamp", "type": "number" },
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired load event." }
]
},
{
@@ -304,6 +429,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.",
@@ -340,12 +473,50 @@
{ "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has cleared its scheduled navigation." }
]
},
+ {
+ "name": "navigatedWithinDocument",
+ "description": "Fired when same-document navigation happens, e.g. due to history API usage or anchor navigation.",
+ "parameters": [
+ {
+ "name": "frameId",
+ "description": "Id of the frame.",
+ "$ref": "Network.FrameId"
+ },
+ {
+ "name": "url",
+ "description": "Frame's new url.",
+ "type": "string"
+ }
+ ]
+ },
{
"name": "defaultAppearanceDidChange",
"description": "Fired when page's default appearance changes, even if there is a forced appearance.",
"parameters": [
{ "name": "appearance", "$ref": "Appearance", "description": "Name of the appearance that is active (not considering any forced appearance.)" }
]
+ },
+ {
+ "name": "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..7b632af490e3f643129d89fdd58497e0aed87c7c
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Playwright.json
@@ -0,0 +1,220 @@
+{
+ "domain": "Playwright",
+ "availability": ["web"],
+ "types": [
+ {
+ "id": "ContextID",
+ "type": "string",
+ "description": "Id of Browser context."
+ },
+ {
+ "id": "PageProxyID",
+ "type": "string",
+ "description": "Id of WebPageProxy."
+ },
+ {
+ "id": "PageProxyInfo",
+ "type": "object",
+ "description": "Tab info object",
+ "properties": [
+ { "name": "pageProxyId", "$ref": "PageProxyID" },
+ { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." },
+ { "name": "openerId", "$ref": "PageProxyID", "optional": true, "description": "Unique identifier of the opening page. Only set for pages created by window.open()." }
+ ]
+ },
+ {
+ "id": "CookieSameSitePolicy",
+ "type": "string",
+ "enum": ["None", "Lax", "Strict"],
+ "description": "Same-Site policy of a cookie."
+ },
+ {
+ "id": "Cookie",
+ "type": "object",
+ "description": "Cookie object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Cookie name." },
+ { "name": "value", "type": "string", "description": "Cookie value." },
+ { "name": "domain", "type": "string", "description": "Cookie domain." },
+ { "name": "path", "type": "string", "description": "Cookie path." },
+ { "name": "expires", "type": "number", "description": "Cookie expires." },
+ { "name": "httpOnly", "type": "boolean", "description": "True if cookie is http-only." },
+ { "name": "secure", "type": "boolean", "description": "True if cookie is secure." },
+ { "name": "session", "type": "boolean", "description": "True if cookie is session cookie." },
+ { "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." }
+ ]
+ },
+ {
+ "id": "SetCookieParam",
+ "type": "object",
+ "description": "Cookie object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Cookie name." },
+ { "name": "value", "type": "string", "description": "Cookie value." },
+ { "name": "domain", "type": "string", "description": "Cookie domain." },
+ { "name": "path", "type": "string", "description": "Cookie path." },
+ { "name": "expires", "type": "number", "optional": true, "description": "Cookie expires." },
+ { "name": "httpOnly", "type": "boolean", "optional": true, "description": "True if cookie is http-only." },
+ { "name": "secure", "type": "boolean", "optional": true, "description": "True if cookie is secure." },
+ { "name": "session", "type": "boolean", "optional": true, "description": "True if cookie is session cookie." },
+ { "name": "sameSite", "$ref": "CookieSameSitePolicy", "optional": true, "description": "Cookie Same-Site policy." }
+ ]
+ },
+ {
+ "id": "Geolocation",
+ "type": "object",
+ "description": "Geolocation",
+ "properties": [
+ { "name": "timestamp", "type": "number", "description": "Mock latitude" },
+ { "name": "latitude", "type": "number", "description": "Mock latitude" },
+ { "name": "longitude", "type": "number", "description": "Mock longitude" },
+ { "name": "accuracy", "type": "number", "description": "Mock accuracy" }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "close",
+ "async": true,
+ "description": "Close browser."
+ },
+ {
+ "name": "createContext",
+ "description": "Creates new ephemeral browser context.",
+ "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.",
2019-11-19 05:18:28 +03:00
+ "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": "pageProxyInfo", "$ref": "PageProxyInfo" }
2019-11-19 05:18:28 +03:00
+ ]
+ },
+ {
+ "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": "downloadCreated",
+ "parameters": [
+ { "name": "uuid", "type": "string" },
+ { "name": "url", "type": "string" },
+ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." },
+ { "name": "browserContextId", "$ref": "ContextID" }
+ ]
+ },
+ {
+ "name": "downloadFinished",
+ "parameters": [
+ { "name": "uuid", "type": "string" },
+ { "name": "error", "type": "string" }
+ ]
+ }
+ ]
+}
2019-11-19 05:18:28 +03:00
diff --git a/Source/JavaScriptCore/inspector/protocol/Target.json b/Source/JavaScriptCore/inspector/protocol/Target.json
index 52920cded24a9c6b0ef6fb4e518664955db4f9fa..bbbabc4e7259088b9404e8cc07eecd6f45077da0 100644
2019-11-19 05:18:28 +03:00
--- a/Source/JavaScriptCore/inspector/protocol/Target.json
+++ b/Source/JavaScriptCore/inspector/protocol/Target.json
@@ -10,7 +10,7 @@
2019-11-19 05:18:28 +03:00
"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." },
2019-11-19 05:18:28 +03:00
+ { "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." }
2019-11-19 05:18:28 +03:00
]
}
@@ -37,6 +37,21 @@
2019-11-19 05:18:28 +03:00
{ "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 }
2019-11-19 05:18:28 +03:00
+ ]
}
],
"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 9e2bee913d37c79fedbb918176a43022b84fa45b..ad8926d773144114dad3842fa0fe239155a15d9e 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",
@@ -32,7 +32,8 @@
"name": "workerCreated",
"parameters": [
{ "name": "workerId", "type": "string" },
- { "name": "url", "type": "string" }
+ { "name": "url", "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 77a28d3bf5d94df1a73f4dfcb5d4a43d3e29383c..b84f1fcb0c52b1e70161e37e30892ee19976a8a1 100644
--- a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
+++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
@@ -40,6 +40,7 @@
#include <unicode/udatpg.h>
#include <unicode/uenum.h>
#include <unicode/ufieldpositer.h>
+#include <wtf/DateMath.h>
#include <wtf/text/StringBuilder.h>
namespace JSC {
@@ -108,6 +109,10 @@ void IntlDateTimeFormat::setBoundFormat(VM& vm, JSBoundFunction* format)
static String defaultTimeZone()
{
+ String tz = WTF::timeZoneForAutomation();
+ if (!tz.isEmpty())
+ return tz;
+
// 6.4.3 DefaultTimeZone () (ECMA-402 2.0)
// The DefaultTimeZone abstract operation returns a String value representing the valid (6.4.1) and canonicalized (6.4.2) time zone name for the host environments current time zone.
diff --git a/Source/WTF/wtf/DateMath.cpp b/Source/WTF/wtf/DateMath.cpp
index 1999737341553001d5246b8190e9ea11d615a158..540ed892bca8110f8013477da7bd9b459a17e60d 100644
--- a/Source/WTF/wtf/DateMath.cpp
+++ b/Source/WTF/wtf/DateMath.cpp
@@ -77,11 +77,16 @@
#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/MathExtras.h>
+#include <wtf/NeverDestroyed.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/ThreadSpecific.h>
#include <wtf/text/StringBuilder.h>
+#include <wtf/unicode/UTF8Conversion.h>
#if OS(WINDOWS)
#include <windows.h>
@@ -107,6 +112,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" };
@@ -333,6 +350,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
@@ -1034,4 +1059,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 cfd5d75cfdcaac5b51dae96045903d812c033b8a..9fca8b41989737608274a2cca8fb78be04d40b0b 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 06b096fc9430eda6c410206bb4d19a1bd6c3636d..bc597102c661b81f35b111cc516f5e7b1bfc5526 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)
diff --git a/Source/WTF/wtf/PlatformHave.h b/Source/WTF/wtf/PlatformHave.h
index 166a135d7e04db3a95a4315ca03669248eb4b750..fdb45ee793c52d0306ba2150d65d4c228f9064a3 100644
--- a/Source/WTF/wtf/PlatformHave.h
+++ b/Source/WTF/wtf/PlatformHave.h
@@ -383,7 +383,7 @@
#define HAVE_NSHTTPCOOKIESTORAGE__INITWITHIDENTIFIER_WITH_INACCURATE_NULLABILITY 1
#endif
-#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || PLATFORM(IOS) || PLATFORM(MACCATALYST)
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || PLATFORM(IOS) || PLATFORM(MACCATALYST) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)
#define HAVE_OS_DARK_MODE_SUPPORT 1
#endif
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;
}
2019-12-24 00:12:56 +03:00
diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt
index ffc61b4865520dfa77eda4ba4d09762d62eeb316..c16f0947fae07c2b6f376f50e3d54e6e49f31eaf 100644
2019-12-24 00:12:56 +03:00
--- a/Source/WebCore/SourcesCocoa.txt
+++ b/Source/WebCore/SourcesCocoa.txt
@@ -651,7 +651,7 @@ WHLSLStandardLibraryFunctionMap.cpp
2019-12-24 00:12:56 +03:00
#endif
-#if ENABLE_IOS_TOUCH_EVENTS
+#if ENABLE_TOUCH_EVENTS
JSTouch.cpp
JSTouchEvent.cpp
diff --git a/Source/WebCore/WebCore.order b/Source/WebCore/WebCore.order
index 34f1a72596fb89c8b647fff3348cca3d959c014c..ab6e42c4da2a8a77f66ce532a3a12bb9ee991207 100644
--- a/Source/WebCore/WebCore.order
+++ b/Source/WebCore/WebCore.order
@@ -3094,7 +3094,6 @@ __ZN7WebCore14DocumentLoader23stopLoadingSubresourcesEv
__ZN7WebCore14DocumentLoader18stopLoadingPlugInsEv
__ZN7WebCore14DocumentLoader15detachFromFrameEv
__ZN7WebCore20ApplicationCacheHost22setDOMApplicationCacheEPNS_19DOMApplicationCacheE
-__ZN7WebCore24InspectorInstrumentation27loaderDetachedFromFrameImplEPNS_19InstrumentingAgentsEPNS_14DocumentLoaderE
__ZN7WebCore14DocumentLoaderD0Ev
__ZN7WebCore14DocumentLoaderD2Ev
__ZN7WebCore14DocumentLoader17clearMainResourceEv
2019-12-24 00:12:56 +03:00
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 5979ec326e5bea0c552d25dfc33341f5055ce4a1..82dc578471c6c891cc00a4aa5ca771095c720997 100644
2019-12-24 00:12:56 +03:00
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -5033,6 +5033,14 @@
2019-12-24 00:12:56 +03:00
EDE3A5000C7A430600956A37 /* ColorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = EDE3A4FF0C7A430600956A37 /* ColorMac.h */; settings = {ATTRIBUTES = (Private, ); }; };
EDEC98030AED7E170059137F /* WebCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EDEC98020AED7E170059137F /* WebCorePrefix.h */; };
EFCC6C8F20FE914400A2321B /* CanvasActivityRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16923AD660C0011CE47 /* Touch.cpp */; };
+ F050E16D23AD66630011CE47 /* TouchList.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16B23AD66620011CE47 /* TouchList.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E16E23AD66630011CE47 /* TouchList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16C23AD66630011CE47 /* TouchList.cpp */; };
+ F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16F23AD669E0011CE47 /* TouchEvent.cpp */; };
+ F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17023AD669F0011CE47 /* TouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E17423AD6A800011CE47 /* DocumentTouch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E17323AD6A800011CE47 /* DocumentTouch.cpp */; };
+ F050E17823AD70C50011CE47 /* PlatformTouchPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
F12171F516A8CED2000053CA /* WebVTTElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F12171F316A8BC63000053CA /* WebVTTElement.cpp */; };
F12171F616A8CF0B000053CA /* WebVTTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = F12171F416A8BC63000053CA /* WebVTTElement.h */; };
F32BDCD92363AACA0073B6AE /* UserGestureEmulationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = F32BDCD72363AACA0073B6AE /* UserGestureEmulationScope.h */; };
@@ -15613,6 +15621,14 @@
2019-12-24 00:12:56 +03:00
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>"; };
@@ -20850,7 +20866,12 @@
2019-12-24 00:12:56 +03:00
2D2E34A921A4E191004598B5 /* EditableImageReference.h */,
1AF326770D78B9440068F0C4 /* EditorClient.h */,
93C09A800B064F00005ABD4D /* EventHandler.cpp */,
+ F050E16F23AD669E0011CE47 /* TouchEvent.cpp */,
+ F050E17023AD669F0011CE47 /* TouchEvent.h */,
93C09A520B064DB3005ABD4D /* EventHandler.h */,
+ F050E16923AD660C0011CE47 /* Touch.cpp */,
+ F050E16C23AD66630011CE47 /* TouchList.cpp */,
+ F050E16B23AD66620011CE47 /* TouchList.h */,
E0FEF371B27C53EAC1C1FBEE /* EventSource.cpp */,
E0FEF371B17C53EAC1C1FBEE /* EventSource.h */,
E0FEF371B07C53EAC1C1FBEE /* EventSource.idl */,
@@ -26100,7 +26121,9 @@
2019-12-24 00:12:56 +03:00
B2C3D9EC0D006C1D00EF6F26 /* text */,
E1EE8B6B2412B2A700E794D6 /* xr */,
2019-12-24 00:12:56 +03:00
DFDB912CF8E88A6DA1AD264F /* AbortableTaskQueue.h */,
+ F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */,
49AE2D94134EE5F90072920A /* CalculationValue.cpp */,
+ F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */,
49AE2D95134EE5F90072920A /* CalculationValue.h */,
C330A22113EC196B0000B45B /* ColorChooser.h */,
C37CDEBC149EF2030042090D /* ColorChooserClient.h */,
@@ -28443,6 +28466,7 @@
2019-12-24 00:12:56 +03:00
BCCFBAE70B5152ED0001F1D7 /* DocumentParser.h */,
AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */,
AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */,
+ F050E17323AD6A800011CE47 /* DocumentTouch.cpp */,
6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */,
6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */,
6BDB5DC5227CA0EB00919770 /* DocumentStorageAccess.idl */,
@@ -29327,6 +29351,7 @@
2019-12-24 00:12:56 +03:00
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 */,
@@ -31190,6 +31215,7 @@
2019-12-24 00:12:56 +03:00
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 */,
@@ -33108,9 +33134,11 @@
2019-12-24 00:12:56 +03:00
A7DBF8DE1276919C006B6008 /* TextCheckingHelper.h in Headers */,
B2C3DA3A0D006C1D00EF6F26 /* TextCodec.h in Headers */,
26E98A10130A9FCA008EB7B2 /* TextCodecASCIIFastPath.h in Headers */,
+ F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */,
B2C3DA3C0D006C1D00EF6F26 /* TextCodecICU.h in Headers */,
B2C3DA3E0D006C1D00EF6F26 /* TextCodecLatin1.h in Headers */,
57EF5E601D20C83900171E60 /* TextCodecReplacement.h in Headers */,
+ F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */,
B2C3DA400D006C1D00EF6F26 /* TextCodecUserDefined.h in Headers */,
B2C3DA420D006C1D00EF6F26 /* TextCodecUTF16.h in Headers */,
9343CB8212F25E510033C5EE /* TextCodecUTF8.h in Headers */,
@@ -34011,6 +34039,7 @@
2019-12-24 00:12:56 +03:00
CDDE02ED18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm in Sources */,
CDDE02F018B5651300CF7FF1 /* CDMSessionAVStreamSession.mm in Sources */,
CDE5959D1BF2757100A1CBE8 /* CDMSessionMediaSourceAVFObjC.mm in Sources */,
+ F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */,
A14090FB1AA51E1D0091191A /* ContentFilterUnblockHandlerCocoa.mm in Sources */,
07AFF4231EFB144900B545B3 /* CoreAudioCaptureSourceIOS.mm in Sources */,
46C696CC1E7205FC00597937 /* CPUMonitor.cpp in Sources */,
@@ -34085,6 +34114,7 @@
2019-12-24 00:12:56 +03:00
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 */,
@@ -34174,6 +34204,7 @@
2019-12-24 00:12:56 +03:00
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 */,
@@ -34706,6 +34737,7 @@
2019-12-24 00:12:56 +03:00
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 d36fc1207a2a795ea82942bdee26bcfd99bddf44..f809b7b464e02c6c1c329cc306e12af31d0ab2ce 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"
@@ -3254,10 +3255,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/css/MediaQueryEvaluator.cpp b/Source/WebCore/css/MediaQueryEvaluator.cpp
index 8118b7ab3c50b3ced8120fc106dce9c73141afe4..2aea3ba07eae2a23b6364074d253356165757549 100644
--- a/Source/WebCore/css/MediaQueryEvaluator.cpp
+++ b/Source/WebCore/css/MediaQueryEvaluator.cpp
@@ -388,7 +388,7 @@ static bool deviceAspectRatioEvaluate(CSSValue* value, const CSSToLengthConversi
if (!value)
return true;
- auto size = screenRect(frame.mainFrame().view()).size();
+ auto size = frame.page()->screenSize();
bool result = compareAspectRatioValue(value, size.width(), size.height(), op);
LOG_WITH_STREAM(MediaQueries, stream << " deviceAspectRatioEvaluate: " << op << " " << aspectRatioValueAsString(value) << " actual screen size " << size << ": " << result);
return result;
@@ -506,7 +506,7 @@ static bool deviceHeightEvaluate(CSSValue* value, const CSSToLengthConversionDat
if (!value)
return true;
int length;
- auto height = screenRect(frame.mainFrame().view()).height();
+ auto height = frame.page()->screenSize().height();
if (!computeLength(value, !frame.document()->inQuirksMode(), conversionData, length))
return false;
@@ -521,8 +521,10 @@ static bool deviceWidthEvaluate(CSSValue* value, const CSSToLengthConversionData
// assume if we have a device, assume non-zero
if (!value)
return true;
+ if (!frame.mainFrame().view())
+ return false;
int length;
- auto width = screenRect(frame.mainFrame().view()).width();
+ auto width = frame.page()->screenSize().width();
if (!computeLength(value, !frame.document()->inQuirksMode(), conversionData, length))
return false;
diff --git a/Source/WebCore/dom/UserGestureIndicator.cpp b/Source/WebCore/dom/UserGestureIndicator.cpp
index dfec93b644f72a51bad0bebf396da61c57f6e428..353833a7614a55566862c196bafc598a475536a1 100644
--- a/Source/WebCore/dom/UserGestureIndicator.cpp
+++ b/Source/WebCore/dom/UserGestureIndicator.cpp
@@ -56,8 +56,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 4e41fd3f807e8f34bfef3f63f0ba6119a619821e..1f7be602cb2134f8867bf95afe0c9337bce57055 100644
--- a/Source/WebCore/html/FileInputType.cpp
+++ b/Source/WebCore/html/FileInputType.cpp
@@ -36,6 +36,7 @@
#include "HTMLNames.h"
#include "Icon.h"
#include "InputTypeNames.h"
+#include "InspectorInstrumentation.h"
#include "LocalizedStrings.h"
#include "RenderFileUploadControl.h"
#include "RuntimeEnabledFeatures.h"
@@ -205,6 +206,11 @@ void FileInputType::handleDOMActivateEvent(Event& event)
if (input.isDisabledFormControl())
return;
+ bool intercept = false;
+ InspectorInstrumentation::runOpenPanel(input.document().frame(), element(), &intercept);
+ if (intercept)
+ return;
+
if (!UserGestureIndicator::processingUserGesture())
return;
diff --git a/Source/WebCore/inspector/InspectorController.cpp b/Source/WebCore/inspector/InspectorController.cpp
index 7d50ddc7a38a3723e4ee7d66ca97c8acb37c726a..bcab1fb5bc6a26174dc6a57e233fe6e9b8c2161c 100644
--- a/Source/WebCore/inspector/InspectorController.cpp
+++ b/Source/WebCore/inspector/InspectorController.cpp
@@ -366,8 +366,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);
}
@@ -510,4 +510,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
2020-02-27 03:21:43 +03:00
index cd4497c9cdf7e3dc7fe89ffdbf188d47f2aaa00d..8cadb40ac6cd04fa3921866a6c4d3142518cb0c3 100644
--- a/Source/WebCore/inspector/InspectorController.h
+++ b/Source/WebCore/inspector/InspectorController.h
@@ -100,6 +100,10 @@ public:
WEBCORE_EXPORT void willComposite(Frame&);
WEBCORE_EXPORT void didComposite(Frame&);
2020-02-27 03:21:43 +03:00
+ 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);
@@ -149,6 +153,7 @@ private:
bool m_isAutomaticInspection { false };
bool m_pauseAfterInitialization = { false };
bool m_didCreateLazyAgents { false };
+ bool m_pauseWhenShown { false };
};
} // namespace WebCore
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp
index 7a386a72edb985898758c3701bfe120de945255e..94f18ca6aa11ebdcfea63153a16b9cedbc8260a8 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebCore/inspector/InspectorInstrumentation.cpp
+++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp
@@ -628,6 +628,12 @@ void InspectorInstrumentation::didFailLoadingImpl(InstrumentingAgents& instrumen
consoleAgent->didFailLoading(identifier, error); // This should come AFTER resource notification, front-end relies on this.
}
2019-12-17 03:22:36 +03:00
+void InspectorInstrumentation::didReceiveMainResourceErrorImpl(InstrumentingAgents& instrumentingAgents, Frame& frame, const ResourceError&)
+{
+ if (auto* pageRuntimeAgent = instrumentingAgents.pageRuntimeAgent())
+ pageRuntimeAgent->didReceiveMainResourceError(frame);
+}
+
void InspectorInstrumentation::willLoadXHRSynchronouslyImpl(InstrumentingAgents& instrumentingAgents)
{
if (InspectorNetworkAgent* networkAgent = instrumentingAgents.inspectorNetworkAgent())
@@ -660,20 +666,17 @@ void InspectorInstrumentation::didReceiveScriptResponseImpl(InstrumentingAgents&
void InspectorInstrumentation::domContentLoadedEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
{
- if (!frame.isMainFrame())
- return;
-
if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
- pageAgent->domContentEventFired();
+ pageAgent->domContentEventFired(frame);
}
void InspectorInstrumentation::loadEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame* frame)
{
- if (!frame || !frame->isMainFrame())
+ if (!frame)
return;
if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
- pageAgent->loadEventFired();
+ pageAgent->loadEventFired(*frame);
}
void InspectorInstrumentation::frameDetachedFromParentImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
@@ -751,12 +754,6 @@ void InspectorInstrumentation::frameDocumentUpdatedImpl(InstrumentingAgents& ins
pageDOMDebuggerAgent->frameDocumentUpdated(frame);
}
-void InspectorInstrumentation::loaderDetachedFromFrameImpl(InstrumentingAgents& instrumentingAgents, DocumentLoader& loader)
-{
- if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.inspectorPageAgent())
- inspectorPageAgent->loaderDetachedFromFrame(loader);
-}
-
void InspectorInstrumentation::frameStartedLoadingImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
{
if (frame.isMainFrame()) {
@@ -793,6 +790,12 @@ void InspectorInstrumentation::frameClearedScheduledNavigationImpl(Instrumenting
2019-11-19 05:18:28 +03:00
inspectorPageAgent->frameClearedScheduledNavigation(frame);
}
+void InspectorInstrumentation::didNavigateWithinPageImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
+{
+ if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.inspectorPageAgent())
+ inspectorPageAgent->didNavigateWithinPage(frame);
+}
+
void InspectorInstrumentation::defaultAppearanceDidChangeImpl(InstrumentingAgents& instrumentingAgents, bool useDarkAppearance)
{
if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.inspectorPageAgent())
@@ -1295,6 +1298,43 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents& ins
layerTreeAgent->renderLayerDestroyed(renderLayer);
}
+void InspectorInstrumentation::runOpenPanelImpl(InstrumentingAgents& instrumentingAgents, HTMLInputElement* element, bool* intercept)
+{
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
+ pageAgent->runOpenPanel(element, intercept);
+}
+
+void InspectorInstrumentation::frameAttachedImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) {
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
+ pageAgent->frameAttached(frame);
+}
+
+bool InspectorInstrumentation::shouldBypassCSPImpl(InstrumentingAgents& instrumentingAgents)
+{
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
+ return pageAgent->shouldBypassCSP();
+ return false;
+}
+
+void InspectorInstrumentation::willCheckNewWindowPolicyImpl(InstrumentingAgents& instrumentingAgents, const URL& url)
+{
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
+ pageAgent->willCheckNewWindowPolicy(url);
+}
+
+void InspectorInstrumentation::didCheckNewWindowPolicyImpl(InstrumentingAgents& instrumentingAgents, bool allowed)
+{
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
+ pageAgent->didCheckNewWindowPolicy(allowed);
+}
+
+bool InspectorInstrumentation::interceptRequestImpl(InstrumentingAgents& instrumentingAgents, ResourceLoader& loader, Function<void(bool handled)>&& handler)
+{
+ if (InspectorNetworkAgent* networkAgent = instrumentingAgents.inspectorNetworkAgent())
+ return networkAgent->interceptRequest(loader, WTFMove(handler));
+ return false;
+}
+
InstrumentingAgents& InspectorInstrumentation::instrumentingAgentsForWorkerGlobalScope(WorkerGlobalScope& workerGlobalScope)
{
return workerGlobalScope.inspectorController().m_instrumentingAgents;
@@ -1306,6 +1346,13 @@ InstrumentingAgents& InspectorInstrumentation::instrumentingAgentsForPage(Page&
return page.inspectorController().m_instrumentingAgents.get();
}
+void InspectorInstrumentation::maybeOverrideDefaultObjectInclusion(Page& page, AccessibilityObjectInclusion& inclusion) {
+ if (InspectorPageAgent* pageAgent = InspectorInstrumentation::instrumentingAgentsForPage(page).inspectorPageAgent()) {
+ if (pageAgent->doingAccessibilitySnapshot())
+ inclusion = AccessibilityObjectInclusion::DefaultBehavior;
+ }
+}
+
InstrumentingAgents* InspectorInstrumentation::instrumentingAgentsForContext(ScriptExecutionContext& context)
{
if (is<Document>(context))
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h
index 21f88d13d7684d8970a8d7f8b7b1bb3237a9e73b..b120aace1b59eda7e4a582fe2a5db70080e75cf3 100644
2019-11-19 05:18:28 +03:00
--- 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"
@@ -45,11 +46,13 @@
#include "HitTestResult.h"
#include "InspectorInstrumentationPublic.h"
#include "Page.h"
+#include "ResourceLoader.h"
#include "StorageArea.h"
#include "WebAnimation.h"
#include <JavaScriptCore/ConsoleMessage.h>
#include <initializer_list>
#include <wtf/CompletionHandler.h>
+#include <wtf/Function.h>
#include <wtf/MemoryPressureHandler.h>
#include <wtf/RefPtr.h>
@@ -77,6 +80,7 @@ class DOMWrapperWorld;
class Document;
class DocumentLoader;
class EventListener;
+class HTMLInputElement;
class HTTPHeaderMap;
class InspectorTimelineAgent;
class InstrumentingAgents;
@@ -198,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(WorkerGlobalScope&, unsigned long identifier, ResourceRequest&);
static void didReceiveResourceResponse(WorkerGlobalScope&, unsigned long identifier, const ResourceResponse&);
@@ -224,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&);
2019-11-19 05:18:28 +03:00
static void frameStoppedLoading(Frame&);
static void frameScheduledNavigation(Frame&, Seconds delay);
static void frameClearedScheduledNavigation(Frame&);
+ static void didNavigateWithinPage(Frame&);
static void defaultAppearanceDidChange(Page&, bool useDarkAppearance);
static void willDestroyCachedResource(CachedResource&);
@@ -318,6 +323,13 @@ 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 bool interceptRequest(ResourceLoader&, Function<void(bool handled)>&&);
+
static void frontendCreated();
static void frontendDeleted();
static bool hasFrontends() { return InspectorInstrumentationPublic::hasFrontends(); }
@@ -333,6 +345,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&);
@@ -419,6 +433,7 @@ private:
static void didReceiveDataImpl(InstrumentingAgents&, unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
static void didFinishLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, const NetworkLoadMetrics&, ResourceLoader*);
static void didFailLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, const ResourceError&);
+ static void didReceiveMainResourceErrorImpl(InstrumentingAgents&, Frame&, const ResourceError&);
static void willLoadXHRSynchronouslyImpl(InstrumentingAgents&);
static void didLoadXHRSynchronouslyImpl(InstrumentingAgents&);
static void scriptImportedImpl(InstrumentingAgents&, unsigned long identifier, const String& sourceString);
@@ -429,11 +444,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&);
2019-11-19 05:18:28 +03:00
static void frameStoppedLoadingImpl(InstrumentingAgents&, Frame&);
static void frameScheduledNavigationImpl(InstrumentingAgents&, Frame&, Seconds delay);
static void frameClearedScheduledNavigationImpl(InstrumentingAgents&, Frame&);
+ static void didNavigateWithinPageImpl(InstrumentingAgents&, Frame&);
static void defaultAppearanceDidChangeImpl(InstrumentingAgents&, bool useDarkAppearance);
static void willDestroyCachedResourceImpl(CachedResource&);
@@ -519,6 +534,13 @@ 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 bool interceptRequestImpl(InstrumentingAgents&, ResourceLoader&, Function<void(bool handled)>&&);
+
static InstrumentingAgents& instrumentingAgentsForPage(Page&);
static InstrumentingAgents& instrumentingAgentsForWorkerGlobalScope(WorkerGlobalScope&);
@@ -1107,6 +1129,13 @@ inline void InspectorInstrumentation::didFailLoading(Frame* frame, DocumentLoade
didFailLoadingImpl(*instrumentingAgents, identifier, loader, error);
}
+inline void InspectorInstrumentation::didReceiveMainResourceError(Frame& frame, const ResourceError& error)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+ didReceiveMainResourceErrorImpl(*instrumentingAgents, frame, error);
+}
+
inline void InspectorInstrumentation::didFailLoading(WorkerGlobalScope& workerGlobalScope, unsigned long identifier, const ResourceError& error)
{
didFailLoadingImpl(instrumentingAgentsForWorkerGlobalScope(workerGlobalScope), identifier, nullptr, error);
@@ -1202,13 +1231,6 @@ inline void InspectorInstrumentation::frameDocumentUpdated(Frame& frame)
frameDocumentUpdatedImpl(*instrumentingAgents, frame);
}
-inline void InspectorInstrumentation::loaderDetachedFromFrame(Frame& frame, DocumentLoader& loader)
-{
- FAST_RETURN_IF_NO_FRONTENDS(void());
- if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
- loaderDetachedFromFrameImpl(*instrumentingAgents, loader);
-}
-
inline void InspectorInstrumentation::frameStartedLoading(Frame& frame)
{
FAST_RETURN_IF_NO_FRONTENDS(void());
@@ -1237,6 +1259,13 @@ inline void InspectorInstrumentation::frameClearedScheduledNavigation(Frame& fra
2019-11-19 05:18:28 +03:00
frameClearedScheduledNavigationImpl(*instrumentingAgents, frame);
}
+inline void InspectorInstrumentation::didNavigateWithinPage(Frame& frame)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+ didNavigateWithinPageImpl(*instrumentingAgents, frame);
+}
+
inline void InspectorInstrumentation::defaultAppearanceDidChange(Page& page, bool useDarkAppearance)
{
FAST_RETURN_IF_NO_FRONTENDS(void());
@@ -1687,6 +1716,50 @@ inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const Ren
renderLayerDestroyedImpl(*instrumentingAgents, renderLayer);
}
+inline void InspectorInstrumentation::runOpenPanel(Frame* frame, HTMLInputElement* element, bool* intercept)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(*frame))
+ runOpenPanelImpl(*instrumentingAgents, element, intercept);
+}
+
+inline void InspectorInstrumentation::frameAttached(Frame* frame)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+ frameAttachedImpl(*instrumentingAgents, *frame);
+}
+
+inline bool InspectorInstrumentation::shouldBypassCSP(ScriptExecutionContext* context)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(false);
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+ return shouldBypassCSPImpl(*instrumentingAgents);
+ return false;
+}
+
+inline void InspectorInstrumentation::willCheckNewWindowPolicy(Frame& frame, const URL& url)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+ willCheckNewWindowPolicyImpl(*instrumentingAgents, url);
+}
+
+inline void InspectorInstrumentation::didCheckNewWindowPolicy(Frame& frame, bool allowed)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+ didCheckNewWindowPolicyImpl(*instrumentingAgents, allowed);
+}
+
+inline bool InspectorInstrumentation::interceptRequest(ResourceLoader& loader, Function<void(bool handled)>&& handler)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(false);
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(loader.frame()))
+ return interceptRequestImpl(*instrumentingAgents, loader, WTFMove(handler));
+ return false;
+}
+
inline InstrumentingAgents* InspectorInstrumentation::instrumentingAgentsForContext(ScriptExecutionContext* context)
{
return context ? instrumentingAgentsForContext(*context) : nullptr;
diff --git a/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp b/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp
index 954aaf121a9fa507d83bc10ae37de1f128f7dcfc..9f16be3dbcf4857742ec2ab131e2b2f962a2a47c 100644
--- a/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp
+++ b/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp
@@ -30,6 +30,11 @@
namespace WebCore {
+bool InspectorInstrumentationWebKit::interceptRequestInternal(ResourceLoader& loader, Function<void(bool handled)>&& handler)
+{
+ return InspectorInstrumentation::interceptRequest(loader, WTFMove(handler));
+}
+
bool InspectorInstrumentationWebKit::shouldInterceptResponseInternal(const Frame& frame, const ResourceResponse& response)
{
return InspectorInstrumentation::shouldInterceptResponse(frame, response);
diff --git a/Source/WebCore/inspector/InspectorInstrumentationWebKit.h b/Source/WebCore/inspector/InspectorInstrumentationWebKit.h
index b67e89b80b4e7a8586cac81ade5d58a1bcb0d431..c468bc0981d1fb13272b28095f9f7584840b5861 100644
--- a/Source/WebCore/inspector/InspectorInstrumentationWebKit.h
+++ b/Source/WebCore/inspector/InspectorInstrumentationWebKit.h
@@ -27,6 +27,7 @@
#include "InspectorInstrumentationPublic.h"
#include <wtf/CompletionHandler.h>
+#include <wtf/Function.h>
namespace WebCore {
@@ -36,14 +37,22 @@ class SharedBuffer;
class WEBCORE_EXPORT InspectorInstrumentationWebKit {
public:
+ static bool interceptRequest(ResourceLoader&, Function<void(bool handled)>&&);
static bool shouldInterceptResponse(const Frame*, const ResourceResponse&);
static void interceptResponse(const Frame*, const ResourceResponse&, unsigned long identifier, CompletionHandler<void(const ResourceResponse&, RefPtr<SharedBuffer>)>&&);
private:
+ static bool interceptRequestInternal(ResourceLoader&, Function<void(bool handled)>&&);
static bool shouldInterceptResponseInternal(const Frame&, const ResourceResponse&);
static void interceptResponseInternal(const Frame&, const ResourceResponse&, unsigned long identifier, CompletionHandler<void(const ResourceResponse&, RefPtr<SharedBuffer>)>&&);
};
+inline bool InspectorInstrumentationWebKit::interceptRequest(ResourceLoader& loader, Function<void(bool handled)>&& handler)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(false);
+ return interceptRequestInternal(loader, WTFMove(handler));
+}
+
inline bool InspectorInstrumentationWebKit::shouldInterceptResponse(const Frame* frame, const ResourceResponse& response)
{
FAST_RETURN_IF_NO_FRONTENDS(false);
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp
index 684d4be5d00dbddfc9935990f765bd8e6f1dbbba..c8c2d2fe25a899ec7160a497fedda5e37699114b 100644
2019-11-19 05:18:28 +03:00
--- 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"
2019-11-19 05:18:28 +03:00
#include "FrameTree.h"
#include "FrameView.h"
#include "FullscreenManager.h"
+#include "FloatQuad.h"
#include "HTMLElement.h"
#include "HTMLFrameOwnerElement.h"
+#include "HTMLInputElement.h"
2019-11-19 05:18:28 +03:00
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
@@ -93,11 +97,14 @@
2019-11-19 05:18:28 +03:00
#include "Page.h"
#include "Pasteboard.h"
#include "PseudoElement.h"
+#include "RenderLayer.h"
2019-11-19 05:18:28 +03:00
+#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(const JSON::Object* colorObject)
+// static
+Color InspectorDOMAgent::parseColor(const JSON::Object* colorObject)
{
if (!colorObject)
return Color::transparent;
@@ -157,7 +165,7 @@ static Color parseConfigColor(const String& fieldName, const JSON::Object* confi
RefPtr<JSON::Object> colorObject;
configObject->getObject(fieldName, colorObject);
- return parseColor(colorObject.get());
+ return InspectorDOMAgent::parseColor(colorObject.get());
}
static bool parseQuad(const JSON::Array& quadArray, FloatQuad* quad)
@@ -438,6 +446,20 @@ Node* InspectorDOMAgent::assertNode(ErrorString& errorString, int nodeId)
return node;
}
+Node* InspectorDOMAgent::assertNode(ErrorString& errorString, const int* nodeId, const String* objectId)
+{
+ Node* node = nullptr;
+ if (nodeId) {
+ node = assertNode(errorString, *nodeId);
+ } else if (objectId) {
+ node = nodeForObjectId(*objectId);
+ if (!node)
+ errorString = "Missing node for given objectId"_s;
+ } else
+ errorString = "Either nodeId or objectId must be specified"_s;
+ return node;
+}
+
Document* InspectorDOMAgent::assertDocument(ErrorString& errorString, int nodeId)
{
Node* node = assertNode(errorString, nodeId);
@@ -1329,16 +1351,7 @@ void InspectorDOMAgent::highlightSelector(ErrorString& errorString, const JSON::
void InspectorDOMAgent::highlightNode(ErrorString& errorString, const JSON::Object& highlightInspectorObject, const int* nodeId, const String* objectId)
{
- Node* node = nullptr;
- if (nodeId)
- node = assertNode(errorString, *nodeId);
- else if (objectId) {
- node = nodeForObjectId(*objectId);
- if (!node)
- errorString = "Missing node for given objectId"_s;
- } else
- errorString = "Either nodeId or objectId must be specified"_s;
-
+ Node* node = assertNode(errorString, nodeId, objectId);
if (!node)
return;
@@ -1486,18 +1499,147 @@ void InspectorDOMAgent::setInspectedNode(ErrorString& errorString, int nodeId)
2019-11-19 05:18:28 +03:00
m_suppressEventListenerChangedEvent = false;
}
-void InspectorDOMAgent::resolveNode(ErrorString& errorString, int nodeId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result)
+static FloatPoint contentsToRootView(FrameView& containingView, const FloatPoint& point)
{
- String objectGroupName = objectGroup ? *objectGroup : emptyString();
- Node* node = assertNode(errorString, nodeId);
+ return containingView.convertToRootView(point - toFloatSize(containingView.documentScrollPositionRelativeToViewOrigin()));
+}
+
+static void frameQuadToViewport(FrameView& containingView, FloatQuad& quad, 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));
2019-11-19 05:18:28 +03:00
+}
+
+static RefPtr<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 RefPtr<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;
+}
+
+void InspectorDOMAgent::describeNode(ErrorString& errorString, const String& objectId, Optional<String>& contentFrameId, Optional<String>& ownerFrameId)
+{
+ Node* node = nodeForObjectId(objectId);
+ if (!node) {
+ errorString = "Node not found"_s;
+ return;
+ }
+
+ auto* pageAgent = m_instrumentingAgents.inspectorPageAgent();
+ if (!pageAgent) {
+ errorString = "Page agent must be enabled"_s;
+ return;
+ }
+
+ String frameId = pageAgent->frameId(node->document().frame());
+ if (!frameId.isEmpty())
+ ownerFrameId = frameId;
+
+ if (is<HTMLFrameOwnerElement>(*node)) {
+ const auto& frameOwner = downcast<HTMLFrameOwnerElement>(*node);
+ String frameId = pageAgent->frameId(frameOwner.contentFrame());
+ if (!frameId.isEmpty())
+ contentFrameId = frameId;
+ }
+}
+
+void InspectorDOMAgent::scrollIntoViewIfNeeded(ErrorString& errorString, const String& objectId, const JSON::Object* rect)
+{
+ Node* node = nodeForObjectId(objectId);
+ if (!node) {
+ errorString = "Node not found"_s;
+ return;
+ }
+ node->document().updateLayoutIgnorePendingStylesheets();
+ if (!node->isConnected()) {
+ errorString = "Node is detached from document"_s;
+ return;
+ }
+ RenderObject* renderer = node->renderer();
+ if (!renderer) {
+ errorString = "Node does not have a layout object"_s;
+ return;
+ }
+ bool insideFixed;
+ LayoutRect absoluteBounds = renderer->absoluteBoundingBoxRect(true, &insideFixed);
+ if (rect) {
+ double x = 0.0;
+ double y = 0.0;
+ double width = 0.0;
+ double height = 0.0;
+ if (!rect->getDouble("x", x) || !rect->getDouble("y", y) || !rect->getDouble("width", width) || !rect->getDouble("height", height)) {
+ errorString = "Malformed rect"_s;
+ return;
+ }
+ 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 });
+}
+
+void InspectorDOMAgent::getContentQuads(ErrorString& errorString, const String& objectId, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::Quad>>& contentQuads)
2019-11-19 05:18:28 +03:00
+{
+ Node* node = nodeForObjectId(objectId);
+ if (!node) {
+ errorString = "Node not found"_s;
2019-11-19 05:18:28 +03:00
+ return;
+ }
+ RenderObject* renderer = node->renderer();
+ if (!renderer) {
+ errorString = "Node doesn't have renderer"_s;
2019-11-19 05:18:28 +03:00
+ return;
+ }
+
+ // Ensure quads are up to date.
+ renderer->document().updateLayoutIgnorePendingStylesheets();
+
2019-11-19 05:18:28 +03:00
+ Frame* containingFrame = renderer->document().frame();
+ FrameView* containingView = containingFrame ? containingFrame->view() : nullptr;
+ if (!containingView) {
+ errorString = "Internal error: no containing view"_s;
2019-11-19 05:18:28 +03:00
+ return;
+ }
+ Vector<FloatQuad> quads;
+ renderer->absoluteQuads(quads);
+ for (auto& quad : quads)
+ frameQuadToViewport(*containingView, quad, m_inspectedPage.pageScaleFactor());
+ contentQuads = buildArrayOfQuads(quads);
2019-11-19 05:18:28 +03:00
+}
+
+void InspectorDOMAgent::resolveNode(ErrorString& errorString, const int* nodeId, const String* objectId, const int* contextId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result)
+{
+ Node* node = assertNode(errorString, nodeId, objectId);
if (!node)
return;
- RefPtr<Inspector::Protocol::Runtime::RemoteObject> object = resolveNode(node, objectGroupName);
- if (!object) {
+ String objectGroupName = objectGroup ? *objectGroup : emptyString();
+ result = resolveNode(node, objectGroupName, contextId);
+ if (!result) {
errorString = "Missing injected script for given nodeId"_s;
return;
}
- result = object;
}
void InspectorDOMAgent::getAttributes(ErrorString& errorString, int nodeId, RefPtr<JSON::ArrayOf<String>>& result)
@@ -2662,7 +2804,7 @@ void InspectorDOMAgent::pushNodeByPathToFrontend(ErrorString& errorString, const
errorString = "Missing node for given path"_s;
}
-RefPtr<Inspector::Protocol::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
+RefPtr<Inspector::Protocol::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup, const int* contextId)
2019-11-19 05:18:28 +03:00
{
Document* document = &node->document();
if (auto* templateHost = document->templateDocumentHost())
@@ -2671,12 +2813,16 @@ RefPtr<Inspector::Protocol::Runtime::RemoteObject> InspectorDOMAgent::resolveNod
if (!frame)
return nullptr;
- auto& state = *mainWorldExecState(frame);
- auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state);
+ InjectedScript injectedScript;
+ if (contextId) {
+ injectedScript = m_injectedScriptManager.injectedScriptForId(*contextId);
+ } else {
+ injectedScript = m_injectedScriptManager.injectedScriptFor(mainWorldExecState(frame));
+ }
if (injectedScript.hasNoValue())
return nullptr;
- return injectedScript.wrapObject(nodeAsScriptValue(state, node), objectGroup);
+ return injectedScript.wrapObject(nodeAsScriptValue(*injectedScript.globalObject(), node), objectGroup);
}
Node* InspectorDOMAgent::scriptValueAsNode(JSC::JSValue value)
@@ -2697,4 +2843,46 @@ void InspectorDOMAgent::setAllowEditingUserAgentShadowTrees(ErrorString&, bool a
m_allowEditingUserAgentShadowTrees = allow;
}
+void InspectorDOMAgent::setInputFiles(ErrorString& errorString, const String& objectId, const JSON::Array& files) {
+ InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
+ if (injectedScript.hasNoValue()) {
+ errorString = "Can not find element's context for given id"_s;
+ return;
+ }
+ Node* node = scriptValueAsNode(injectedScript.findObjectById(objectId));
+ if (!node) {
+ errorString = "Can not find element for given id"_s;
+ return;
+ }
+ if (node->nodeType() != Node::ELEMENT_NODE || node->nodeName() != "INPUT") {
+ errorString = "Not an input node"_s;
+ return;
+ }
+ HTMLInputElement* element = static_cast<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;
+ if (!item->asObject(obj)) {
+ errorString = "Invalid file payload format"_s;
+ return;
+ }
+ String name;
+ String type;
+ String data;
+ if (!obj->getString("name", name) || !obj->getString("type", type) || !obj->getString("data", data)) {
+ errorString = "Invalid file payload format"_s;
+ return;
+ }
+ Vector<uint8_t> buffer;
+ if (!base64Decode(data, buffer)) {
+ errorString = "Unable to decode given content"_s;
+ return;
+ }
+ fileObjects.append(File::create(Blob::create(SharedBuffer::create(WTFMove(buffer)), type), name));
+ }
+ RefPtr<FileList> fileList = FileList::create(WTFMove(fileObjects));
+ element->setFiles(WTFMove(fileList));
+}
+
} // namespace WebCore
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.h b/Source/WebCore/inspector/agents/InspectorDOMAgent.h
index 7df0e83eb53d75c41c554f1401235ba21719414c..ae6f961a7b7fe63ece60e34210bf333bedef2eee 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebCore/inspector/agents/InspectorDOMAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.h
@@ -54,6 +54,7 @@ namespace WebCore {
class AXCoreObject;
class CharacterData;
+class Color;
class DOMEditor;
class Document;
class Element;
@@ -88,6 +89,7 @@ public:
static String toErrorString(Exception&&);
static String documentURLString(Document*);
+ static Color parseColor(const JSON::Object*);
// We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently.
// We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics.
@@ -129,7 +131,7 @@ public:
void performSearch(ErrorString&, const String& query, const JSON::Array* nodeIds, const bool* caseSensitive, String* searchId, int* resultCount) override;
void getSearchResults(ErrorString&, const String& searchId, int fromIndex, int toIndex, RefPtr<JSON::ArrayOf<int>>&) override;
void discardSearchResults(ErrorString&, const String& searchId) override;
- void resolveNode(ErrorString&, int nodeId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result) override;
+ void resolveNode(ErrorString&, const int* nodeId, const String* objectId, const int* contextId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result) override;
void getAttributes(ErrorString&, int nodeId, RefPtr<JSON::ArrayOf<String>>& result) override;
void setInspectModeEnabled(ErrorString&, bool enabled, const JSON::Object* highlightConfig, const bool* showRulers) override;
void requestNode(ErrorString&, const String& objectId, int* nodeId) override;
@@ -148,6 +150,10 @@ public:
2019-11-19 05:18:28 +03:00
void focus(ErrorString&, int nodeId) override;
void setInspectedNode(ErrorString&, int nodeId) override;
void setAllowEditingUserAgentShadowTrees(ErrorString&, bool allow) final;
+ void describeNode(ErrorString&, const String& objectId, Optional<String>& contentFrameId, Optional<String>& ownerFrameId) override;
+ void scrollIntoViewIfNeeded(ErrorString&, const String& objectId, const JSON::Object* rect) override;
+ void getContentQuads(ErrorString&, const String& objectId, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::Quad>>&) override;
+ void setInputFiles(ErrorString&, const String& objectId, const JSON::Array& files) override;
2019-11-19 05:18:28 +03:00
// InspectorInstrumentation
int identifierForNode(Node&);
@@ -185,7 +191,7 @@ public:
Node* nodeForId(int nodeId);
int boundNodeId(const Node*);
- RefPtr<Inspector::Protocol::Runtime::RemoteObject> resolveNode(Node*, const String& objectGroup);
+ RefPtr<Inspector::Protocol::Runtime::RemoteObject> resolveNode(Node*, const String& objectGroup, const int* contextId);
bool handleMousePress();
void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags);
void inspect(Node*);
@@ -196,12 +202,15 @@ public:
void reset();
Node* assertNode(ErrorString&, int nodeId);
+ Node* assertNode(ErrorString&, const int* nodeId, const String* objectId);
Element* assertElement(ErrorString&, int nodeId);
Document* assertDocument(ErrorString&, int nodeId);
bool hasBreakpointForEventListener(EventTarget&, const AtomString& eventType, EventListener&, bool capture);
int idForEventListener(EventTarget&, const AtomString& eventType, EventListener&, bool capture);
+ Node* nodeForObjectId(const String& objectId);
+
private:
#if ENABLE(VIDEO)
void mediaMetricsTimerFired();
@@ -228,9 +237,8 @@ private:
Ref<Inspector::Protocol::DOM::EventListener> buildObjectForEventListener(const RegisteredEventListener&, int identifier, EventTarget&, const AtomString& eventType, bool disabled, bool hasBreakpoint);
RefPtr<Inspector::Protocol::DOM::AccessibilityProperties> buildObjectForAccessibilityProperties(Node*);
void processAccessibilityChildren(AXCoreObject&, JSON::ArrayOf<int>&);
-
+
Node* nodeForPath(const String& path);
- Node* nodeForObjectId(const String& objectId);
void discardBindings();
diff --git a/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h b/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h
index b578660fbb3ce176e4e0aeb5a22021dc880e47f0..a7c968bc9f88c7d26e1887bb53106b4af2464753 100644
--- a/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h
@@ -40,6 +40,7 @@ class DOMStorageFrontendDispatcher;
namespace WebCore {
+class Color;
class Frame;
class Page;
class SecurityOrigin;
diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp
index ee9edb30dd7b3461c4d491dfaf7929011d498bc9..53872c5dc1487e08cdc2a14ef0738ad0499cb1b6 100644
--- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp
@@ -44,6 +44,7 @@
#include "DocumentLoader.h"
#include "DocumentThreadableLoader.h"
#include "Frame.h"
+#include "FormData.h"
#include "FrameLoader.h"
#include "HTTPHeaderMap.h"
#include "HTTPHeaderNames.h"
@@ -56,6 +57,7 @@
#include "MIMETypeRegistry.h"
#include "MemoryCache.h"
#include "NetworkResourcesData.h"
+#include "NetworkStateNotifier.h"
#include "Page.h"
#include "PlatformStrategies.h"
#include "ProgressTracker.h"
@@ -99,6 +101,11 @@ using namespace Inspector;
namespace {
+String inspectorInitiatorPrefix()
+{
+ return "InspectorPageAgent.navigate referrer:"_s;
+}
+
class InspectorThreadableLoaderClient final : public ThreadableLoaderClient {
WTF_MAKE_NONCOPYABLE(InspectorThreadableLoaderClient);
public:
@@ -453,6 +460,13 @@ void InspectorNetworkAgent::willSendRequest(unsigned long identifier, DocumentLo
for (auto& entry : m_extraRequestHeaders)
request.setHTTPHeaderField(entry.key, entry.value);
+ if (request.initiatorIdentifier().startsWith(inspectorInitiatorPrefix())) {
+ String referrer = request.initiatorIdentifier().substring(inspectorInitiatorPrefix().length());
+ if (!referrer.isEmpty())
+ request.setHTTPReferrer(referrer);
+ request.setInitiatorIdentifier(String());
+ }
+
auto protocolResourceType = InspectorPageAgent::resourceTypeJSON(type);
Document* document = loader && loader->frame() ? loader->frame()->document() : nullptr;
@@ -841,6 +855,7 @@ void InspectorNetworkAgent::disable(ErrorString&)
m_resourcesData->clear();
m_extraRequestHeaders.clear();
+ continuePendingRequests();
continuePendingResponses();
setResourceCachingDisabled(false);
@@ -864,6 +879,16 @@ bool InspectorNetworkAgent::shouldIntercept(URL url)
return false;
}
+void InspectorNetworkAgent::continuePendingRequests()
+{
+ for (auto& pendingRequest : m_pendingInterceptRequests.values()) {
+ ResourceLoader* loader = pendingRequest->m_loader.get();
+ if (loader->identifier())
+ pendingRequest->m_callback(false);
+ }
+ m_pendingInterceptRequests.clear();
+}
+
void InspectorNetworkAgent::continuePendingResponses()
{
for (auto& pendingInterceptResponse : m_pendingInterceptResponses.values())
@@ -1020,17 +1045,15 @@ void InspectorNetworkAgent::resolveWebSocket(ErrorString& errorString, const Str
result = injectedScript.wrapObject(webSocketAsScriptValue(state, webSocket), objectGroupName);
}
-void InspectorNetworkAgent::setInterceptionEnabled(ErrorString& errorString, bool enabled)
+void InspectorNetworkAgent::setInterceptionEnabled(ErrorString&, bool enabled, const bool* interceptRequests)
{
- if (m_interceptionEnabled == enabled) {
- errorString = m_interceptionEnabled ? "Interception already enabled"_s : "Interception already disabled"_s;
- return;
- }
-
m_interceptionEnabled = enabled;
+ m_interceptRequests = interceptRequests && *interceptRequests;
if (!m_interceptionEnabled)
continuePendingResponses();
+ if (!m_interceptionEnabled || !m_interceptRequests)
+ continuePendingRequests();
}
void InspectorNetworkAgent::addInterception(ErrorString& errorString, const String& url, const bool* optionalCaseSensitive, const bool* optionalIsRegex, const String* networkStageString)
@@ -1112,19 +1135,133 @@ void InspectorNetworkAgent::interceptResponse(const ResourceResponse& response,
m_frontendDispatcher->responseIntercepted(requestId, buildObjectForResourceResponse(response, nullptr));
}
-void InspectorNetworkAgent::interceptContinue(ErrorString& errorString, const String& requestId)
-{
+bool InspectorNetworkAgent::interceptRequest(ResourceLoader& loader, Function<void(bool handled)>&& handler) {
+ if (!m_interceptionEnabled || !m_interceptRequests)
+ return false;
+ String requestId = IdentifiersFactory::requestId(loader.identifier());
+ auto pendingRequest = makeUnique<PendingInterceptRequest>();
+ pendingRequest->m_loader = &loader;
+ pendingRequest->m_callback = WTFMove(handler);
+ m_pendingInterceptRequests.set(requestId, WTFMove(pendingRequest));
+ m_frontendDispatcher->requestIntercepted(requestId, buildObjectForResourceRequest(loader.request()));
+ return true;
+}
+
+void InspectorNetworkAgent::interceptContinue(ErrorString& errorString, const String& requestId, const String* method, const JSON::Object* headers, const String* postData)
+{
+ auto pendingRequest = m_pendingInterceptRequests.take(requestId);
+ if (pendingRequest) {
+ ResourceLoader* loader = pendingRequest->m_loader.get();
+ if (!loader->identifier()) {
+ // Do not throw upon continue of canceled requests.
+ return;
+ }
+ // Safe to const cast at this point, we are only adjusting the method / headers / post.
+ ResourceRequest* request = const_cast<ResourceRequest*>(&loader->request());
+ if (method)
+ request->setHTTPMethod(*method);
+ if (headers) {
+ HTTPHeaderMap explicitHeaders;
+ for (auto& header : *headers) {
+ String headerValue;
+ if (header.value->asString(headerValue))
+ explicitHeaders.add(header.key, headerValue);
+ }
+ request->setHTTPHeaderFields(WTFMove(explicitHeaders));
+ }
+ if (postData) {
+ Vector<uint8_t> buffer;
+ if (!base64Decode(*postData, buffer)) {
+ errorString = "Unable to decode given postData"_s;
+ return;
+ }
+ Ref<FormData> data = FormData::create(buffer);
+ request->setHTTPBody(WTFMove(data));
+ }
+ pendingRequest->m_callback(false);
+ return;
+ }
+
auto pendingInterceptResponse = m_pendingInterceptResponses.take(requestId);
- if (!pendingInterceptResponse) {
- errorString = "Missing pending intercept response for given requestId"_s;
+ if (pendingInterceptResponse) {
+ pendingInterceptResponse->respondWithOriginalResponse();
return;
}
- pendingInterceptResponse->respondWithOriginalResponse();
+ errorString = "Missing pending intercept response for given requestId"_s;
}
-void InspectorNetworkAgent::interceptWithResponse(ErrorString& errorString, const String& requestId, const String& content, bool base64Encoded, const String* mimeType, const int* status, const String* statusText, const JSON::Object* headers)
+void InspectorNetworkAgent::interceptAsError(ErrorString& errorString, const String& requestId, const String& reason)
{
+ auto pendingRequest = m_pendingInterceptRequests.take(requestId);
+ if (pendingRequest) {
+ ResourceLoader* loader = pendingRequest->m_loader.get();
+ if (!loader->identifier()) {
+ errorString = "Unable to abort request, it has already been processed"_s;
+ return;
+ }
+ ResourceError error(errorDomainWebKitInternal, 0, loader->url(), "Request intercepted"_s, ResourceError::Type::General);
+ if (reason == "AccessControl")
+ error = ResourceError(errorDomainWebKitInternal, 0, loader->url(), "Access denied"_s, ResourceError::Type::AccessControl);
+ else if (reason == "Cancellation")
+ error = ResourceError(errorDomainWebKitInternal, 0, loader->url(), "Request canceled"_s, ResourceError::Type::Cancellation);
+ else if (reason == "Timeout")
+ error = ResourceError(errorDomainWebKitInternal, 0, loader->url(), "Request timed out"_s, ResourceError::Type::Timeout);
+ loader->didFail(error);
+ pendingRequest->m_callback(true);
+ return;
+ }
+
+ errorString = "Missing pending intercept response for given requestId"_s;
+}
+
+void InspectorNetworkAgent::interceptWithResponse(ErrorString& errorString, const String& requestId, const String* content, const bool* base64Encoded, const String* mimeType, const int* status, const String* statusText, const JSON::Object* headers)
+{
+ auto pendingRequest = m_pendingInterceptRequests.take(requestId);
+ if (pendingRequest && status && statusText && mimeType && headers) {
+ RefPtr<ResourceLoader> loader = pendingRequest->m_loader.get();
+ if (!loader->identifier()) {
+ errorString = "Unable to fulfill request, it has already been processed"_s;
+ return;
+ }
+ RefPtr<SharedBuffer> data;
+ if (base64Encoded && *base64Encoded && content) {
+ Vector<uint8_t> buffer;
+ if (!base64Decode(*content, buffer)) {
+ errorString = "Unable to decode given content"_s;
+ return;
+ }
+ data = SharedBuffer::create(WTFMove(buffer));
+ } else if (content) {
+ data = SharedBuffer::create(content->utf8().data(), content->utf8().length());
+ }
+
+ ResourceResponse response(pendingRequest->m_loader->url(), *mimeType, data->size(), String());
+ response.setSource(ResourceResponse::Source::InspectorOverride);
+ response.setHTTPStatusCode(*status);
+ response.setHTTPStatusText(*statusText);
+ HTTPHeaderMap explicitHeaders;
+ for (auto& header : *headers) {
+ String headerValue;
+ if (header.value->asString(headerValue))
+ explicitHeaders.add(header.key, headerValue);
+ }
+ response.setHTTPHeaderFields(WTFMove(explicitHeaders));
+ response.setHTTPHeaderField(HTTPHeaderName::ContentType, response.mimeType());
+ if (response.isRedirection()) {
+ loader->setRequest(loader->request().redirectedRequest(response, false));
+ pendingRequest->m_callback(false);
+ } else {
+ loader->didReceiveResponse(response, [loader, data = data.releaseNonNull()]() mutable {
+ if (data->size())
+ loader->didReceiveBuffer(WTFMove(data), data->size(), DataPayloadWholeResource);
+ loader->didFinishLoading(NetworkLoadMetrics());
+ });
+ pendingRequest->m_callback(true);
+ }
+ return;
+ }
+
auto pendingInterceptResponse = m_pendingInterceptResponses.take(requestId);
if (!pendingInterceptResponse) {
errorString = "Missing pending intercept response for given requestId"_s;
@@ -1152,20 +1289,26 @@ void InspectorNetworkAgent::interceptWithResponse(ErrorString& errorString, cons
}
RefPtr<SharedBuffer> overrideData;
- if (base64Encoded) {
+ if (base64Encoded && *base64Encoded && content) {
Vector<uint8_t> buffer;
- if (!base64Decode(content, buffer)) {
+ if (!base64Decode(*content, buffer)) {
errorString = "Unable to decode given content"_s;
pendingInterceptResponse->respondWithOriginalResponse();
return;
}
overrideData = SharedBuffer::create(WTFMove(buffer));
- } else
- overrideData = SharedBuffer::create(content.utf8().data(), content.utf8().length());
+ } else if (content) {
+ overrideData = SharedBuffer::create(content->utf8().data(), content->utf8().length());
+ }
pendingInterceptResponse->respond(overrideResponse, overrideData);
}
+void InspectorNetworkAgent::setEmulateOfflineState(ErrorString&, bool offline)
+{
+ platformStrategies()->loaderStrategy()->setEmulateOfflineState(offline);
+}
+
bool InspectorNetworkAgent::shouldTreatAsText(const String& mimeType)
{
return startsWithLettersIgnoringASCIICase(mimeType, "text/")
@@ -1295,6 +1438,11 @@ void InspectorNetworkAgent::searchInRequest(ErrorString& errorString, const Stri
results = ContentSearchUtilities::searchInTextByLines(resourceData->content(), query, caseSensitive, isRegex);
}
+String InspectorNetworkAgent::createInitiatorIdentifierForInspectorNavigation(const String& referrer)
+{
+ return inspectorInitiatorPrefix() + referrer;
+}
+
void InspectorNetworkAgent::mainFrameNavigated(DocumentLoader& loader)
{
m_resourcesData->clear(loaderIdentifier(&loader));
diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
index b038a1879c043aa17dae97425693f29be42e3258..d60716b837663004675ffd90bceede4c3a6e98c6 100644
--- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
@@ -87,11 +87,13 @@ public:
void loadResource(const String& frameId, const String& url, Ref<LoadResourceCallback>&&) final;
void getSerializedCertificate(ErrorString&, const String& requestId, String* serializedCertificate) final;
void resolveWebSocket(ErrorString&, const String& requestId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>&) final;
- void setInterceptionEnabled(ErrorString&, bool enabled) final;
+ void setInterceptionEnabled(ErrorString&, bool enabled, const bool* interceptRequests) final;
void addInterception(ErrorString&, const String& url, const bool* caseSensitive, const bool* isRegex, const String* networkStageString) final;
void removeInterception(ErrorString&, const String& url, const bool* caseSensitive, const bool* isRegex, const String* networkStageString) final;
- void interceptContinue(ErrorString&, const String& requestId) final;
- void interceptWithResponse(ErrorString&, const String& requestId, const String& content, bool base64Encoded, const String* mimeType, const int* status, const String* statusText, const JSON::Object* headers) final;
+ void interceptContinue(ErrorString&, const String& requestId, const String* method, const JSON::Object* headers, const String* postData) final;
+ void interceptAsError(ErrorString&, const String& requestId, const String& reason) final;
+ void interceptWithResponse(ErrorString&, const String& requestId, const String* content, const bool* base64Encoded, const String* mimeType, const int* status, const String* statusText, const JSON::Object* headers) final;
+ void setEmulateOfflineState(ErrorString&, bool offline) final;
// InspectorInstrumentation
void willRecalculateStyle();
@@ -121,10 +123,13 @@ public:
bool willInterceptRequest(const ResourceRequest&);
bool shouldInterceptResponse(const ResourceResponse&);
void interceptResponse(const ResourceResponse&, unsigned long identifier, CompletionHandler<void(const ResourceResponse&, RefPtr<SharedBuffer>)>&&);
+ bool interceptRequest(ResourceLoader& loader, Function<void(bool handled)>&&);
void searchOtherRequests(const JSC::Yarr::RegularExpression&, RefPtr<JSON::ArrayOf<Inspector::Protocol::Page::SearchResult>>&);
void searchInRequest(ErrorString&, const String& requestId, const String& query, bool caseSensitive, bool isRegex, RefPtr<JSON::ArrayOf<Inspector::Protocol::GenericTypes::SearchMatch>>&);
+ static String createInitiatorIdentifierForInspectorNavigation(const String& referrer);
+
protected:
InspectorNetworkAgent(WebAgentContext&);
@@ -141,6 +146,7 @@ private:
void willSendRequest(unsigned long identifier, DocumentLoader*, ResourceRequest&, const ResourceResponse& redirectResponse, InspectorPageAgent::ResourceType);
bool shouldIntercept(URL);
+ void continuePendingRequests();
void continuePendingResponses();
WebSocket* webSocketForRequestId(const String& requestId);
@@ -191,6 +197,15 @@ private:
bool m_responded { false };
};
+ class PendingInterceptRequest {
+ WTF_MAKE_NONCOPYABLE(PendingInterceptRequest);
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
+ PendingInterceptRequest() = default;
+ RefPtr<ResourceLoader> m_loader;
+ CompletionHandler<void(bool handled)> m_callback;
+ };
+
std::unique_ptr<Inspector::NetworkFrontendDispatcher> m_frontendDispatcher;
RefPtr<Inspector::NetworkBackendDispatcher> m_backendDispatcher;
Inspector::InjectedScriptManager& m_injectedScriptManager;
@@ -214,6 +229,7 @@ private:
};
Vector<Intercept> m_intercepts;
HashMap<String, std::unique_ptr<PendingInterceptResponse>> m_pendingInterceptResponses;
+ HashMap<String, std::unique_ptr<PendingInterceptRequest>> m_pendingInterceptRequests;
// FIXME: InspectorNetworkAgent should not be aware of style recalculation.
RefPtr<Inspector::Protocol::Network::Initiator> m_styleRecalculationInitiator;
@@ -222,6 +238,7 @@ private:
bool m_enabled { false };
bool m_loadingXHRSynchronously { false };
bool m_interceptionEnabled { false };
+ bool m_interceptRequests { false };
};
} // namespace WebCore
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
index 0e2e3c2bcc2fe167c246a5f55c4de3b52282a516..848df344e9a3b4b00883db8010be0de39844f3cc 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
@@ -32,6 +32,8 @@
#include "config.h"
#include "InspectorPageAgent.h"
+#include "AXObjectCache.h"
+#include "BackForwardController.h"
#include "CachedResource.h"
#include "CachedResourceLoader.h"
#include "Cookie.h"
@@ -40,12 +42,15 @@
#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"
@@ -56,19 +61,29 @@
#include "MIMETypeRegistry.h"
#include "MemoryCache.h"
#include "Page.h"
+#include "PageRuntimeAgent.h"
#include "RenderObject.h"
#include "RenderTheme.h"
2019-12-20 02:07:19 +03:00
+#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 <platform/ProcessIdentifier.h>
+#include <wtf/DateMath.h>
#include <wtf/ListHashSet.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/Ref.h>
+#include <wtf/RefPtr.h>
#include <wtf/Stopwatch.h>
#include <wtf/text/Base64.h>
#include <wtf/text/StringBuilder.h>
@@ -81,7 +96,6 @@
#include "LegacyWebArchive.h"
#endif
-
namespace WebCore {
using namespace Inspector;
@@ -100,6 +114,11 @@ using namespace Inspector;
macro(WebRTCEncryptionEnabled) \
macro(WebSecurityEnabled)
+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) {
@@ -340,6 +359,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)
{
@@ -373,11 +393,20 @@ void InspectorPageAgent::enable(ErrorString& errorString)
#if HAVE(OS_DARK_MODE_SUPPORT)
defaultAppearanceDidChange(m_inspectedPage.defaultUseDarkAppearance());
#endif
+
+ if (!createdUserWorlds().isEmpty()) {
+ Vector<DOMWrapperWorld*> worlds;
+ for (const auto& world : createdUserWorlds().values())
+ worlds.append(world.ptr());
+ ensureUserWorldsExistInAllFrames(worlds);
+ }
}
void InspectorPageAgent::disable(ErrorString&)
{
m_instrumentingAgents.setInspectorPageAgent(nullptr);
+ m_interceptFileChooserDialog = false;
+ m_bypassCSP = false;
ErrorString unused;
setShowPaintRects(unused, false);
@@ -415,14 +444,35 @@ void InspectorPageAgent::reload(ErrorString&, const bool* optionalReloadFromOrig
2019-11-19 05:18:28 +03:00
m_inspectedPage.mainFrame().loader().reload(reloadOptions);
}
-void InspectorPageAgent::navigate(ErrorString&, const String& url)
+void InspectorPageAgent::goBack(ErrorString& errorString)
+{
+ if (!m_inspectedPage.backForward().goBack())
+ errorString = "Failed to go back"_s;
+}
+
+void InspectorPageAgent::goForward(ErrorString& errorString)
+{
+ if (!m_inspectedPage.backForward().goForward())
+ errorString = "Failed to go forward"_s;
+}
+
+void InspectorPageAgent::navigate(ErrorString& errorString, const String& url, const String* frameId, const String* referrer)
2019-11-19 05:18:28 +03:00
{
UserGestureIndicator indicator { ProcessingUserGesture };
- Frame& frame = m_inspectedPage.mainFrame();
+ Frame* frame = frameId ? assertFrame(errorString, *frameId) : &m_inspectedPage.mainFrame();
+ if (!frame)
+ return;
- ResourceRequest resourceRequest { frame.document()->completeURL(url) };
- FrameLoadRequest frameLoadRequest { *frame.document(), frame.document()->securityOrigin(), WTFMove(resourceRequest), "_self"_s, LockHistory::No, LockBackForwardList::No, ReferrerPolicy::EmptyString, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown };
- frame.loader().changeLocation(WTFMove(frameLoadRequest));
+ ResourceRequest resourceRequest { frame->document()->completeURL(url) };
+ if (!resourceRequest.url().isValid()) {
+ errorString = "Cannot navigate to invalid URL"_s;
+ return;
+ }
+
+ if (referrer)
+ resourceRequest.setInitiatorIdentifier(InspectorNetworkAgent::createInitiatorIdentifierForInspectorNavigation(*referrer));
+ FrameLoadRequest frameLoadRequest { *frame->document(), frame->document()->securityOrigin(), WTFMove(resourceRequest), "_self"_s, LockHistory::No, LockBackForwardList::No, ReferrerPolicy::EmptyString, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown };
2019-11-19 05:18:28 +03:00
+ frame->loader().changeLocation(WTFMove(frameLoadRequest));
}
void InspectorPageAgent::overrideUserAgent(ErrorString&, const String* value)
@@ -747,15 +797,16 @@ void InspectorPageAgent::setShowPaintRects(ErrorString&, bool show)
m_overlay->setShowPaintRects(show);
}
-void InspectorPageAgent::domContentEventFired()
+void InspectorPageAgent::domContentEventFired(Frame& frame)
{
- m_isFirstLayoutAfterOnLoad = true;
- m_frontendDispatcher->domContentEventFired(timestamp());
+ if (frame.isMainFrame())
+ m_isFirstLayoutAfterOnLoad = true;
+ m_frontendDispatcher->domContentEventFired(timestamp(), frameId(&frame));
}
-void InspectorPageAgent::loadEventFired()
+void InspectorPageAgent::loadEventFired(Frame& frame)
{
- m_frontendDispatcher->loadEventFired(timestamp());
+ m_frontendDispatcher->loadEventFired(timestamp(), frameId(&frame));
}
void InspectorPageAgent::frameNavigated(Frame& frame)
@@ -763,13 +814,18 @@ void InspectorPageAgent::frameNavigated(Frame& frame)
m_frontendDispatcher->frameNavigated(buildObjectForFrame(&frame));
}
+static String globalIDForFrame(Frame& frame)
+{
+ return makeString(Process::identifier().toUInt64(), ".", frame.loader().client().frameID()->toUInt64());
+}
+
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 String& frameId)
@@ -781,20 +837,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(ErrorString& errorString, const String& frameId)
@@ -805,11 +859,6 @@ Frame* InspectorPageAgent::assertFrame(ErrorString& errorString, const String& f
return frame;
}
-void InspectorPageAgent::loaderDetachedFromFrame(DocumentLoader& loader)
-{
- m_loaderToIdentifier.remove(&loader);
-}
-
void InspectorPageAgent::frameStartedLoading(Frame& frame)
{
m_frontendDispatcher->frameStartedLoading(frameId(&frame));
@@ -830,6 +879,12 @@ void InspectorPageAgent::frameClearedScheduledNavigation(Frame& frame)
2019-11-19 05:18:28 +03:00
m_frontendDispatcher->frameClearedScheduledNavigation(frameId(&frame));
}
+void InspectorPageAgent::didNavigateWithinPage(Frame& frame)
+{
2019-11-19 05:18:28 +03:00
+ String url = frame.document()->url().string();
+ m_frontendDispatcher->navigatedWithinDocument(frameId(&frame), url);
+}
+
void InspectorPageAgent::defaultAppearanceDidChange(bool useDarkAppearance)
2019-11-19 05:18:28 +03:00
{
m_frontendDispatcher->defaultAppearanceDidChange(useDarkAppearance ? Inspector::Protocol::Page::Appearance::Dark : Inspector::Protocol::Page::Appearance::Light);
@@ -887,6 +942,48 @@ void InspectorPageAgent::didRecalculateStyle()
m_overlay->update();
}
+void InspectorPageAgent::runOpenPanel(HTMLInputElement* element, bool* intercept)
+{
+ if (m_interceptFileChooserDialog) {
+ *intercept = true;
+ } else {
+ return;
+ }
+ Document& document = element->document();
+ auto* frame = document.frame();
+ if (!frame)
+ return;
+
+ auto& state = *mainWorldExecState(frame);
+ auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state);
+ if (injectedScript.hasNoValue())
+ return;
+
+ m_frontendDispatcher->fileChooserOpened(frameId(frame), injectedScript.wrapObject(InspectorDOMAgent::nodeAsScriptValue(state, element), WTF::String()));
+}
+
+void InspectorPageAgent::frameAttached(Frame& frame)
+{
+ Frame* parent = frame.tree().parent();
+ String parentFrameId = frameId(parent);
+ m_frontendDispatcher->frameAttached(frameId(&frame), parent ? &parentFrameId : nullptr);
+}
+
+bool InspectorPageAgent::shouldBypassCSP()
+{
+ return m_bypassCSP;
+}
+
+void InspectorPageAgent::willCheckNewWindowPolicy(const URL& url)
+{
+ m_frontendDispatcher->willRequestOpenWindow(url.string());
+}
+
+void InspectorPageAgent::didCheckNewWindowPolicy(bool allowed)
+{
+ m_frontendDispatcher->didRequestOpenWindow(allowed);
+}
+
Ref<Inspector::Protocol::Page::Frame> InspectorPageAgent::buildObjectForFrame(Frame* frame)
{
ASSERT_ARG(frame, frame);
@@ -1030,6 +1127,29 @@ void InspectorPageAgent::snapshotRect(ErrorString& errorString, int x, int y, in
2019-12-20 02:07:19 +03:00
*outDataURL = snapshot->toDataURL("image/png"_s, WTF::nullopt, PreserveResolution::Yes);
}
+void InspectorPageAgent::setTimeZone(ErrorString& errorString, const String* timeZone)
+{
+ if (!timeZone) {
+ WTF::setTimeZoneForAutomation(String());
+ return;
+ }
+ bool success = WTF::setTimeZoneForAutomation(*timeZone);
+ if (!success)
+ errorString = "Invalid time zone " + *timeZone;
+}
+
+void InspectorPageAgent::setTouchEmulationEnabled(ErrorString& errorString, bool enabled)
+{
2019-12-20 02:07:19 +03:00
+#if ENABLE(TOUCH_EVENTS)
+ RuntimeEnabledFeatures::sharedFeatures().setTouchEventsEnabled(enabled);
+ UNUSED_PARAM(errorString);
+#else
+ UNUSED_PARAM(enabled);
+ errorString = "Not supported"_s;
+#endif
+}
+
+
void InspectorPageAgent::archive(ErrorString& errorString, String* data)
{
#if ENABLE(WEB_ARCHIVE) && USE(CF)
@@ -1047,4 +1167,538 @@ void InspectorPageAgent::archive(ErrorString& errorString, String* data)
#endif
}
+void InspectorPageAgent::insertText(ErrorString&, const String& text)
+{
+ UserGestureIndicator indicator { ProcessingUserGesture };
+ Document* focusedDocument = m_inspectedPage.focusController().focusedOrMainFrame().document();
+ TypingCommand::insertText(*focusedDocument, text, 0);
+}
+
+static String roleFromObject(RefPtr<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 RefPtr<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()) {
+ RefPtr<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(children);
+ }
+ return axNode;
+}
+
+
+void InspectorPageAgent::accessibilitySnapshot(ErrorString& errorString, const String* objectId, RefPtr<Inspector::Protocol::Page::AXNode>& out_axNode)
+{
+ if (!WebCore::AXObjectCache::accessibilityEnabled())
+ WebCore::AXObjectCache::enableAccessibility();
+ auto document = makeRefPtr(m_inspectedPage.mainFrame().document());
+ if (!document) {
+ errorString = "No document for main frame"_s;
+ return;
+ }
+ AXObjectCache* axObjectCache = document->axObjectCache();
+ if (!axObjectCache) {
+ errorString = "No AXObjectCache for main document"_s;
+ return;
+ }
+ AXCoreObject* axObject = axObjectCache->rootObject();
+ if (!axObject) {
+ errorString = "No AXObject for main document"_s;
+ return;
+ }
+
+ Node* node = nullptr;
+ if (objectId) {
+ InspectorDOMAgent* domAgent = m_instrumentingAgents.inspectorDOMAgent();
+ ASSERT(domAgent);
+ node = domAgent->nodeForObjectId(*objectId);
+ if (!node) {
+ errorString = "No Node for objectId"_s;
+ return;
+ }
+ }
+
+ m_doingAccessibilitySnapshot = true;
+ out_axNode = snapshotForAXObject(makeRefPtr(axObject), node);
+ m_doingAccessibilitySnapshot = false;
+}
+
+void InspectorPageAgent::setInterceptFileChooserDialog(ErrorString&, bool enabled)
+{
+ m_interceptFileChooserDialog = enabled;
+}
+
+void InspectorPageAgent::setDefaultBackgroundColorOverride(ErrorString& errorString, const JSON::Object* color)
+{
+ FrameView* view = m_inspectedPage.mainFrame().view();
+ if (!view) {
+ errorString = "Internal error: No frame view to set color two"_s;
+ return;
+ }
+ if (!color) {
+ view->updateBackgroundRecursively(Optional<Color>());
+ return;
+ }
+ view->updateBackgroundRecursively(InspectorDOMAgent::parseColor(color));
+}
+
+void InspectorPageAgent::createUserWorld(ErrorString& errorString, const String& name)
+{
+ if (createdUserWorlds().contains(name)) {
+ errorString = "World with the given name already exists"_s;
+ return;
+ }
+
+ Ref<DOMWrapperWorld> world = ScriptController::createWorld(name, ScriptController::WorldType::User);
+ ensureUserWorldsExistInAllFrames({world.ptr()});
+ createdUserWorlds().set(name, WTFMove(world));
+}
+
+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();
+ }
+}
+
+void InspectorPageAgent::setBypassCSP(ErrorString&, bool enabled)
+{
+ m_bypassCSP = enabled;
+}
+
+void InspectorPageAgent::crash(ErrorString&)
+{
+ CRASH();
+}
+
+void InspectorPageAgent::setScreenSizeOverride(ErrorString&, int width, int height)
+{
+ Optional<FloatSize> size;
+ if (width && height)
+ size = FloatSize(width, height);
+ m_inspectedPage.setOverrideScreenSize(size);
+}
+
+void InspectorPageAgent::setOrientationOverride(Inspector::ErrorString&, const int* angle)
+{
+ Optional<int> orientation;
+ if (angle)
+ orientation = *angle;
+ m_inspectedPage.setOverrideOrientation(orientation);
+}
+
} // namespace WebCore
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.h b/Source/WebCore/inspector/agents/InspectorPageAgent.h
index 6c75829502336b0806db2531e78186d2c559e44c..7b3c952fb5c8e60620d605bd2b9b4989554ae91c 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebCore/inspector/agents/InspectorPageAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorPageAgent.h
@@ -40,11 +40,16 @@
#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;
@@ -97,7 +102,9 @@ public:
2019-11-19 05:18:28 +03:00
void enable(ErrorString&) override;
void disable(ErrorString&) override;
void reload(ErrorString&, const bool* optionalReloadFromOrigin, const bool* optionalRevalidateAllResources) override;
- void navigate(ErrorString&, const String& url) override;
+ void goBack(ErrorString&) override;
+ void goForward(ErrorString&) override;
+ void navigate(ErrorString&, const String& url, const String* frameId, const String* referrer) override;
2019-11-19 05:18:28 +03:00
void overrideUserAgent(ErrorString&, const String* value) override;
void overrideSetting(ErrorString&, const String& setting, const bool* value) override;
void getCookies(ErrorString&, RefPtr<JSON::ArrayOf<Inspector::Protocol::Page::Cookie>>& cookies) override;
@@ -112,20 +119,31 @@ public:
2019-12-20 02:07:19 +03:00
void setShowPaintRects(ErrorString&, bool show) override;
void setEmulatedMedia(ErrorString&, const String&) override;
void setForcedAppearance(ErrorString&, const String&) override;
+ void setTimeZone(ErrorString&, const String*) override;
2019-12-20 02:07:19 +03:00
+ void setTouchEmulationEnabled(ErrorString&, bool) override;
void snapshotNode(ErrorString&, int nodeId, String* outDataURL) override;
- void snapshotRect(ErrorString&, int x, int y, int width, int height, const String& coordinateSystem, String* outDataURL) override;
+ void snapshotRect(ErrorString&, int x, int y, int width, int height, const String& coordinateSystem, String* outDataURL) override;
void archive(ErrorString&, String* data) override;
+ void insertText(ErrorString&, const String& text) override;
+ void accessibilitySnapshot(ErrorString&, const String* objectId, RefPtr<Inspector::Protocol::Page::AXNode>& out_axNode) override;
+ void setInterceptFileChooserDialog(ErrorString&, bool enabled) override;
+ void setDefaultBackgroundColorOverride(ErrorString&, const JSON::Object*) override;
+ void createUserWorld(ErrorString&, const String&) override;
+ void setBypassCSP(ErrorString&, bool) override;
+ void crash(ErrorString&) override;
+ void setScreenSizeOverride(ErrorString&, int width, int height) override;
+ void setOrientationOverride(Inspector::ErrorString&, const int* angle) override;
// InspectorInstrumentation
- void domContentEventFired();
- void loadEventFired();
+ void domContentEventFired(Frame&);
+ void loadEventFired(Frame&);
void frameNavigated(Frame&);
void frameDetached(Frame&);
- void loaderDetachedFromFrame(DocumentLoader&);
void frameStartedLoading(Frame&);
2019-11-19 05:18:28 +03:00
void frameStoppedLoading(Frame&);
void frameScheduledNavigation(Frame&, Seconds delay);
void frameClearedScheduledNavigation(Frame&);
+ void didNavigateWithinPage(Frame&);
void defaultAppearanceDidChange(bool useDarkAppearance);
void applyUserAgentOverride(String&);
void applyEmulatedMedia(String&);
@@ -134,6 +152,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 String& frameId);
WEBCORE_EXPORT String frameId(Frame*);
@@ -142,6 +166,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);
@@ -153,18 +178,20 @@ 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_forcedAppearance;
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 5b7d17a424be41789f73e795736defb8fdf4ed1b..ee571acbf3a4c34cd7039ddd04febe36164a7346 100644
--- a/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp
@@ -160,7 +160,11 @@ void InspectorWorkerAgent::connectToWorkerInspectorProxy(WorkerInspectorProxy* p
m_connectedProxies.set(proxy->identifier(), proxy);
- m_frontendDispatcher->workerCreated(proxy->identifier(), proxy->url());
+ ASSERT(is<Document>(proxy->scriptExecutionContext()));
+ Document& document = downcast<Document>(*proxy->scriptExecutionContext());
+ auto* pageAgent = m_instrumentingAgents.inspectorPageAgent();
+ m_frontendDispatcher->workerCreated(proxy->identifier(), proxy->url(),
+ 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 cc0b0526f19f806ce621521d0771cc5f30d43840..6b54fa315ac22af78f2bf1befef204ca48308200 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 "PageScriptDebugServer.h"
@@ -70,8 +71,11 @@ bool PageDebuggerAgent::enabled() const
void PageDebuggerAgent::evaluateOnCallFrame(ErrorString& errorString, const String& callFrameId, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, const bool* emulateUserGesture, RefPtr<Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown, Optional<int>& savedResultIndex)
{
+ 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);
+ UserGestureEmulationScope userGestureScope(m_inspectedPage, shouldEmulateUserGesture, document);
WebDebuggerAgent::evaluateOnCallFrame(errorString, callFrameId, expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, saveResult, emulateUserGesture, result, wasThrown, savedResultIndex);
}
diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
index 63336051bb0050d6a55eb5543b0349eb964bbb7a..eecfb5a50196c6d9ca353e9b7aedbd4d6feb690c 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"
@@ -106,6 +108,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(ErrorString& errorString, const int* executionContextId)
{
if (!executionContextId) {
@@ -194,13 +205,21 @@ void PageRuntimeAgent::notifyContextCreated(const String& frameId, JSC::JSGlobal
void PageRuntimeAgent::evaluate(ErrorString& errorString, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, const bool* emulateUserGesture, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown, Optional<int>& savedResultIndex)
{
- UserGestureEmulationScope userGestureScope(m_inspectedPage, asBool(emulateUserGesture));
+ InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId);
+ if (!errorString.isEmpty())
+ return;
+ JSC::JSGlobalObject* globalObject = injectedScript.globalObject();
+ Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr;
+ UserGestureEmulationScope userGestureScope(m_inspectedPage, asBool(emulateUserGesture), document);
InspectorRuntimeAgent::evaluate(errorString, expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, executionContextId, returnByValue, generatePreview, saveResult, emulateUserGesture, result, wasThrown, savedResultIndex);
}
void PageRuntimeAgent::callFunctionOn(ErrorString& errorString, const String& objectId, const String& expression, const JSON::Array* optionalArguments, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* emulateUserGesture, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown)
{
- UserGestureEmulationScope userGestureScope(m_inspectedPage, asBool(emulateUserGesture));
+ InjectedScript injectedScript = injectedScriptManager().injectedScriptForObjectId(objectId);
+ JSC::JSGlobalObject* globalObject = injectedScript.globalObject();
+ Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr;
+ UserGestureEmulationScope userGestureScope(m_inspectedPage, asBool(emulateUserGesture), document);
InspectorRuntimeAgent::callFunctionOn(errorString, objectId, expression, optionalArguments, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, emulateUserGesture, result, wasThrown);
}
diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
index 2af3739b7fe7c16faa7d8d2797ce6d010215398d..80bfde6120874e16fb173f707fd0bd8a3e5067a0 100644
--- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
+++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
@@ -63,6 +63,7 @@ public:
// InspectorInstrumentation
void frameNavigated(Frame&);
void didClearWindowObjectInWorld(Frame&, DOMWrapperWorld&);
+ void didReceiveMainResourceError(Frame&);
private:
Inspector::InjectedScript injectedScriptForEval(ErrorString&, const int* executionContextId) override;
@@ -73,7 +74,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 796513c20c701cd8511e72c0b5c646612392f21b..c6a7473f063f1e94f82bcb53dd769b88c6801760 100644
--- a/Source/WebCore/loader/DocumentLoader.cpp
+++ b/Source/WebCore/loader/DocumentLoader.cpp
@@ -1294,8 +1294,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 cc9d1c1bc0c5ede7c81c1ad1a05d358a4760d074..07af1a43029f6e3d74e43d3b0b26ea40dc7224ac 100644
--- a/Source/WebCore/loader/DocumentLoader.h
+++ b/Source/WebCore/loader/DocumentLoader.h
@@ -163,9 +163,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; }
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp
index c86fb76fc57d702b5432f74e8a331b6a1ad2ab77..d7a59d0ca6143ff65a61d881be6c66200bc38643 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebCore/loader/FrameLoader.cpp
+++ b/Source/WebCore/loader/FrameLoader.cpp
@@ -1183,6 +1183,7 @@ void FrameLoader::loadInSameDocument(const URL& url, SerializedScriptValue* stat
2019-11-19 05:18:28 +03:00
}
m_client->dispatchDidNavigateWithinPage();
2019-11-19 05:18:28 +03:00
+ InspectorInstrumentation::didNavigateWithinPage(m_frame);
m_frame.document()->statePopped(stateObject ? Ref<SerializedScriptValue> { *stateObject } : SerializedScriptValue::nullValue());
m_client->dispatchDidPopStateWithinPage();
@@ -1365,6 +1366,8 @@ void FrameLoader::loadURL(FrameLoadRequest&& frameLoadRequest, const String& ref
ASSERT(newLoadType != FrameLoadType::Same);
+ request.setInitiatorIdentifier(frameLoadRequest.resourceRequest().initiatorIdentifier());
+
// The search for a target frame is done earlier in the case of form submission.
Frame* targetFrame = isFormSubmission ? nullptr : findFrameForNavigation(effectiveFrameName);
if (targetFrame && targetFrame != &m_frame) {
@@ -1497,6 +1500,7 @@ void FrameLoader::load(FrameLoadRequest&& request)
void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, NavigationAction&& action, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, const String& downloadAttribute, 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()));
@@ -1601,6 +1605,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 };
@@ -3146,6 +3152,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)
@@ -3910,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)
@@ -3921,13 +3926,13 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
{
- if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.windowProxy().existingJSWindowProxy(world))
- return;
+ if (m_frame.windowProxy().existingJSWindowProxy(world)) {
+ if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
+ m_client->dispatchDidClearWindowObjectInWorld(world);
- m_client->dispatchDidClearWindowObjectInWorld(world);
-
- if (Page* page = m_frame.page())
- page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
+ if (Page* page = m_frame.page())
+ page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
+ }
InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
}
diff --git a/Source/WebCore/loader/LoaderStrategy.h b/Source/WebCore/loader/LoaderStrategy.h
index 579d9038f317d45d27c84a27e3f21cff0ae8fddf..9dc41a6ff78b85e229927409b309e01adce2f27a 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 c8f4a214aa63a9c0292cf3023a9e55c744ff9eef..8563d0c93e94ed97498c1d33dc827b06157a0026 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>
@@ -257,26 +258,32 @@ void PolicyChecker::checkNewWindowPolicy(NavigationAction&& navigationAction, Re
auto blobURLLifetimeExtension = extendBlobURLLifetimeIfNecessary(request);
+ InspectorInstrumentation::willCheckNewWindowPolicy(m_frame, request.url());
auto requestIdentifier = PolicyCheckIdentifier::create();
m_frame.loader().client().dispatchDecidePolicyForNewWindowAction(navigationAction, request, formState.get(), frameName, requestIdentifier, [frame = 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, { }, { }, ShouldContinue::No);
+ }
switch (policyAction) {
case PolicyAction::Download:
frame->loader().client().startDownload(request);
FALLTHROUGH;
case PolicyAction::Ignore:
+ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false);
function({ }, nullptr, { }, { }, ShouldContinue::No);
return;
case PolicyAction::StopAllLoads:
ASSERT_NOT_REACHED();
+ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false);
function({ }, nullptr, { }, { }, ShouldContinue::No);
return;
case PolicyAction::Use:
+ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), true);
function(request, makeWeakPtr(formState.get()), frameName, navigationAction, ShouldContinue::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 4949fea85dc0178ec18984348c9e41cde3a948c6..974b1ffdc7433a86346eb73f83e41ba126dd66e8 100644
--- a/Source/WebCore/page/ChromeClient.h
+++ b/Source/WebCore/page/ChromeClient.h
@@ -270,7 +270,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 5c24edc97732f1369da26b597944c3a9188560d0..79c7b66d0a035b40b08a202c70e616627979fbad 100644
--- a/Source/WebCore/page/EventHandler.cpp
+++ b/Source/WebCore/page/EventHandler.cpp
@@ -812,9 +812,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;
@@ -853,8 +851,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
@@ -876,8 +872,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)
@@ -898,7 +896,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);
@@ -915,6 +915,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
@@ -946,6 +948,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())
@@ -1037,7 +1041,6 @@ void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResul
m_frame.selection().setSelectionByMouseIfDifferent(newSelection, m_frame.selection().granularity(),
FrameSelection::AdjustEndpointsAtBidiBoundary);
}
-#endif // ENABLE(DRAG_SUPPORT)
void EventHandler::lostMouseCapture()
{
@@ -1085,9 +1088,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;
@@ -2042,10 +2043,8 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& platformMouseE
return true;
swallowEvent = !dispatchMouseEvent(eventNames().mousemoveEvent, mouseEvent.targetNode(), false, 0, platformMouseEvent, true);
-#if ENABLE(DRAG_SUPPORT)
if (!swallowEvent)
swallowEvent = handleMouseDraggedEvent(mouseEvent);
-#endif
return swallowEvent;
}
diff --git a/Source/WebCore/page/EventHandler.h b/Source/WebCore/page/EventHandler.h
index adb15dbb4c53f8d1c4957a646eff30fe8c9cc659..a596843b0779b912688c2c029cc073e636bf1470 100644
--- a/Source/WebCore/page/EventHandler.h
+++ b/Source/WebCore/page/EventHandler.h
@@ -132,9 +132,7 @@ public:
WEBCORE_EXPORT VisiblePosition selectionExtentRespectingEditingBoundary(const VisibleSelection&, const LayoutPoint&, Node*);
-#if ENABLE(DRAG_SUPPORT)
void updateSelectionForMouseDrag();
-#endif
#if ENABLE(PAN_SCROLLING)
void didPanScrollStart();
@@ -359,10 +357,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&);
@@ -456,10 +452,8 @@ private:
void defaultTabEventHandler(KeyboardEvent&);
void defaultArrowEventHandler(FocusDirection, KeyboardEvent&);
-#if ENABLE(DRAG_SUPPORT)
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.
@@ -467,9 +461,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);
@@ -520,10 +515,7 @@ private:
enum SelectionInitiationState { HaveNotStartedSelection, PlacedCaret, ExtendedSelection };
SelectionInitiationState m_selectionInitiationState { HaveNotStartedSelection };
-#if ENABLE(DRAG_SUPPORT)
LayoutPoint m_dragStartPosition;
-#endif
-
Timer m_hoverTimer;
Timer m_cursorUpdateTimer;
diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp
index e6271d7e86023bce03193752805f21ee96d235fa..37841e631f6837bb49dc82cc4213598cb2a862c2 100644
--- a/Source/WebCore/page/Frame.cpp
+++ b/Source/WebCore/page/Frame.cpp
@@ -184,6 +184,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)
@@ -322,7 +323,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)
diff --git a/Source/WebCore/page/FrameSnapshotting.cpp b/Source/WebCore/page/FrameSnapshotting.cpp
index 73587787f88a6ad4e4baffb0beb0b87e7782916f..88492f501e6ec9e38455dbe6fd27537bf0ee6970 100644
--- a/Source/WebCore/page/FrameSnapshotting.cpp
+++ b/Source/WebCore/page/FrameSnapshotting.cpp
@@ -114,7 +114,12 @@ std::unique_ptr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRe
std::unique_ptr<ImageBuffer> 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 @@ std::unique_ptr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRe
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 f59baa8c4ab3e130a7c4d67fffb8dc178c8cc84c..2004d521e6a5e4fcce447451fe74bc2f9d32a679 100644
--- a/Source/WebCore/page/FrameView.cpp
+++ b/Source/WebCore/page/FrameView.cpp
@@ -2987,7 +2987,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);
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp
index 9c58b06f4c471130ce4815f11d14cb78f81b49a0..3d624733c36f09518b12095d91e67a2ae67879e2 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebCore/page/History.cpp
+++ b/Source/WebCore/page/History.cpp
@@ -259,6 +259,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 232fd43079726422402ae646c4fa803eb5604568..2d06753c2c85c245e6a3a38385ca2efdd1f6097f 100644
--- a/Source/WebCore/page/Page.cpp
+++ b/Source/WebCore/page/Page.cpp
@@ -87,6 +87,7 @@
#include "PerformanceLoggingClient.h"
#include "PerformanceMonitor.h"
#include "PlatformMediaSessionManager.h"
+#include "PlatformScreen.h"
#include "PlatformStrategies.h"
#include "PlugInClient.h"
#include "PluginData.h"
@@ -428,6 +429,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 0c2244aa22e4742b1b57b9f47d1649519735226d..5f090a00532862204dd1bb203965424807e292af 100644
--- a/Source/WebCore/page/Page.h
+++ b/Source/WebCore/page/Page.h
@@ -187,6 +187,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();
@@ -720,6 +723,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
@@ -1010,6 +1018,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/Screen.cpp b/Source/WebCore/page/Screen.cpp
index a9d228ca404918860c40651994db78a1e76db5ca..1fc3c345308dfed8384d1c02334f2030e879383d 100644
--- a/Source/WebCore/page/Screen.cpp
+++ b/Source/WebCore/page/Screen.cpp
@@ -32,6 +32,7 @@
#include "FloatRect.h"
#include "Frame.h"
#include "FrameView.h"
+#include "Page.h"
#include "PlatformScreen.h"
#include "ResourceLoadObserver.h"
#include "RuntimeEnabledFeatures.h"
@@ -53,7 +54,7 @@ unsigned Screen::height() const
return 0;
if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled())
ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::Height);
- long height = static_cast<long>(screenRect(frame->view()).height());
+ long height = static_cast<long>(frame->page()->screenSize().height());
return static_cast<unsigned>(height);
}
@@ -64,7 +65,7 @@ unsigned Screen::width() const
return 0;
if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled())
ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::Width);
- long width = static_cast<long>(screenRect(frame->view()).width());
+ long width = static_cast<long>(frame->page()->screenSize().width());
return static_cast<unsigned>(width);
}
diff --git a/Source/WebCore/page/SocketProvider.cpp b/Source/WebCore/page/SocketProvider.cpp
index 803ac83155ff4df1becf75cd4710f6fbf7bbc32a..54fb28427e8b2b7da2ea3204673414f8e1bd24d7 100644
--- a/Source/WebCore/page/SocketProvider.cpp
+++ b/Source/WebCore/page/SocketProvider.cpp
@@ -33,7 +33,11 @@ namespace WebCore {
Ref<SocketStreamHandle> SocketProvider::createSocketStreamHandle(const URL& url, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, const StorageSessionProvider* provider)
{
+#if OS(WINDOWS)
+ return SocketStreamHandleImpl::create(url, false, client, sessionID, credentialPartition, { }, provider);
+#else
return SocketStreamHandleImpl::create(url, client, sessionID, credentialPartition, { }, provider);
+#endif
}
RefPtr<ThreadableWebSocketChannel> SocketProvider::createWebSocketChannel(Document&, WebSocketChannelClient&)
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
index ad6f5209c52e0842d93be267f8f5e99551dfe07c..0fcf4fe9877ba8a89a8dfb321e120f7954c6f69b 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
+++ b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
@@ -298,6 +298,8 @@ bool ContentSecurityPolicy::protocolMatchesSelf(const URL& url) const
template<typename 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)
@@ -311,6 +313,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) {
@@ -327,6 +331,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)...)) {
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebCore/platform/PlatformKeyboardEvent.h b/Source/WebCore/platform/PlatformKeyboardEvent.h
index f423a4a1d5399326fc48fe4d4a8a8fb9d4df861e..b4b60162d8b0d34113df052b04a1695d481d266e 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebCore/platform/PlatformKeyboardEvent.h
+++ b/Source/WebCore/platform/PlatformKeyboardEvent.h
@@ -138,6 +138,7 @@ namespace WebCore {
2019-11-19 05:18:28 +03:00
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 {
2019-11-19 05:18:28 +03:00
static String keyCodeForHardwareKeyCode(unsigned);
static String keyIdentifierForWPEKeyCode(unsigned);
static int windowsKeyCodeForWPEKeyCode(unsigned);
+ static unsigned WPEKeyCodeForWindowsKeyCode(int);
static String singleCharacterString(unsigned);
#endif
2019-12-24 00:12:56 +03:00
diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h
index 45fac029bd36be8b87b93335793d38265905c18c..316c63ab26b6060def42b69e02f56a748adeb79d 100644
2019-12-24 00:12:56 +03:00
--- a/Source/WebCore/platform/ScrollableArea.h
+++ b/Source/WebCore/platform/ScrollableArea.h
@@ -110,7 +110,7 @@ public:
2019-12-24 00:12:56 +03:00
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/opengl/GraphicsContextGLOpenGLBase.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp
index 445c7d78a4a1a8cdb0e08a859d3912e5cc62b6c6..93a8006dd5237018b573b976d0bbe28f02b8254f 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) || (PLATFORM(COCOA) && USE(OPENGL_ES)))
+#if !PLATFORM(WIN) && ENABLE(GRAPHICS_CONTEXT_GL) && (USE(OPENGL) || (PLATFORM(COCOA) && USE(OPENGL_ES)))
#if PLATFORM(IOS_FAMILY)
#include "GraphicsContextGLOpenGLESIOS.h"
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
index 269008b9053c8d8b6787cf22f13b44b46dace333..d3ba16947bc8964a7cfe746cabbf99d32a673cef 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
+++ b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
@@ -36,8 +36,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 {
@@ -1293,6 +1295,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/libwpe/PlatformKeyboardEventLibWPE.cpp b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp
index a34dc220bbb9a92b40dfb463e8724e81ac745b2c..8ecedd5dae88469366a619b96960598c1232a32d 100644
2019-11-19 05:18:28 +03:00
--- 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)
2019-11-19 05:18:28 +03:00
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/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/curl/CurlStream.cpp b/Source/WebCore/platform/network/curl/CurlStream.cpp
index 26dc7bef4b74bc6b4e2e526dec6523c3ad6d3643..c783aa5a7984f3966312e5e0ffd76f93ed6208f8 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)
{
@@ -49,6 +49,9 @@ CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, UR
m_curlHandle->setUrl(urlForConnection);
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 3b6dea9ed2552d81aaf7e694a5f922e96dbf94d6..6b5bd9b9782b0fb55341e76fc3cff8625f7a30a8 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/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/WebKit/NetworkProcess/NetworkProcess.cpp b/Source/WebKit/NetworkProcess/NetworkProcess.cpp
index fc05cff928d150dc5083081fea4be915ea2233f9..69786c2d48ffc18b0d8729d49389434161de08a3 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"
@@ -595,6 +594,41 @@ void NetworkProcess::destroySession(PAL::SessionID sessionID)
webIDBServer->close();
}
+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 ed5e11fcb061f6ecb3bfbd87ce83ef257563310c..bdfa56cc28c87a4f91df384e8bebb6dc997687bc 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.h
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.h
@@ -75,6 +75,7 @@ class SessionID;
namespace WebCore {
class CertificateInfo;
+struct Cookie;
class CurlProxySettings;
class DownloadID;
class ProtectionSpace;
@@ -203,6 +204,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 dfd6244249ccfb08dacc07bb6b157638c8ae0a4b..f8697eb4a7162da4acf29972401f503357c72d48 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
@@ -81,6 +81,11 @@ messages -> NetworkProcess LegacyReceiver {
PreconnectTo(PAL::SessionID sessionID, URL url, String userAgent, enum:uint8_t WebCore::StoredCredentialsPolicy storedCredentialsPolicy, enum:bool 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 46342935377111aebb2847dca80dde5b4972f270..9d6756747082c6044c13e5df1f65db9554fa5655 100644
--- a/Source/WebKit/NetworkProcess/NetworkSession.h
+++ b/Source/WebKit/NetworkProcess/NetworkSession.h
@@ -137,6 +137,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); }
@@ -167,6 +170,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 d1fa427d82884fc43569d1bf0df7d728921502fc..59790afe7f4deedc69b3f020e23f2b50a38595cf 100644
--- a/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
+++ b/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
@@ -43,7 +43,11 @@ 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)
+#if OS(WINDOWS)
+ , m_impl(SocketStreamHandleImpl::create(url, networkProcess.networkSession(sessionID)->ignoreCertificateErrors(), *this, sessionID, credentialPartition, WTFMove(auditData), NetworkStorageSessionProvider::create(networkProcess, sessionID).ptr()))
+#else
, m_impl(SocketStreamHandleImpl::create(url, *this, sessionID, credentialPartition, WTFMove(auditData), NetworkStorageSessionProvider::create(networkProcess, sessionID).ptr()))
+#endif
{
}
diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
index 9b0104d46e55ac8d4b2bba1c9c2e9a631cbae0cb..5eeeabb53e0039aa12789ecf490db0319a356d23 100644
--- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
+++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
@@ -654,7 +654,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)
diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp
index 977a403be8dc962a9ccfa6428bc1d3e7c4682f86..53753443288519bd229aed3a848aa3bca53ad496 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>
@@ -38,6 +42,7 @@
#include <WebCore/ResourceError.h>
#include <WebCore/SameSiteInfo.h>
#include <WebCore/SynchronousLoaderClient.h>
+#include <wtf/FileSystem.h>
namespace WebKit {
@@ -71,6 +76,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();
}
@@ -177,7 +184,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));
}
@@ -186,6 +198,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));
}
@@ -199,6 +217,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);
}
@@ -235,6 +260,18 @@ void NetworkDataTaskCurl::invokeDidReceiveResponse()
break;
case PolicyAction::Ignore:
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;
@@ -312,6 +349,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();
diff --git a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
index 1de5ad90f434b50025dcb97dfaa01694c39f8a13..0bace7ed07af493570ef11d29ad29be590bccea1 100644
--- a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
+++ b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
@@ -434,6 +434,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 = SoupNetworkSession::checkTLSErrors(url, certificate, tlsErrors);
if (!error)
return true;
diff --git a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
index 407361f036e79891767d807fbb63c9044b260a70..24773d8f349d441e2b6b1981baa5af170a96b384 100644
--- a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
+++ b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
@@ -106,6 +106,11 @@ static gboolean webSocketAcceptCertificateCallback(GTlsConnection*, GTlsCertific
return !SoupNetworkSession::checkTLSErrors(soupURIToURL(soup_message_get_uri(soupMessage)), certificate, errors);
}
+static gboolean webSocketAcceptCertificateCallbackIgnoreTLSErrors(GTlsConnection*, GTlsCertificate* certificate, GTlsCertificateFlags errors, SoupMessage* soupMessage)
+{
+ return TRUE;
+}
+
static void webSocketMessageNetworkEventCallback(SoupMessage* soupMessage, GSocketClientEvent event, GIOStream* connection)
{
if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING)
@@ -114,6 +119,14 @@ static void webSocketMessageNetworkEventCallback(SoupMessage* soupMessage, GSock
g_signal_connect(connection, "accept-certificate", G_CALLBACK(webSocketAcceptCertificateCallback), soupMessage);
}
+static void webSocketMessageNetworkEventCallbackIgnoreTLSErrors(SoupMessage* soupMessage, GSocketClientEvent event, GIOStream* connection)
+{
+ if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING)
+ return;
+
+ 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();
@@ -122,8 +135,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), nullptr);
+ if (request.url().protocolIs("wss")) {
+ if (ignoreCertificateErrors())
+ g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallbackIgnoreTLSErrors), nullptr);
+ else
+ g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallback), nullptr);
+ }
return makeUnique<WebSocketTask>(channel, soupSession(), soupMessage.get(), protocol);
}
diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake
index 1ad03e9ce3b4a94bf761eaf8ecc2fb1b7a39a221..a7646e30d99da5fa840e5e3f57b6c1b37876f38a 100644
--- a/Source/WebKit/PlatformWPE.cmake
+++ b/Source/WebKit/PlatformWPE.cmake
@@ -254,6 +254,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"
diff --git a/Source/WebKit/PlatformWin.cmake b/Source/WebKit/PlatformWin.cmake
index fe60361f605ad72bda67f0178a4ebec35250aff4..d609d7f4d8c791caf7ef5107c34bc2f8e1db3abd 100644
--- a/Source/WebKit/PlatformWin.cmake
+++ b/Source/WebKit/PlatformWin.cmake
@@ -59,8 +59,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
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/Shared/API/c/wpe/WebKit.h b/Source/WebKit/Shared/API/c/wpe/WebKit.h
index 898e30b370db8176e886fbbde0cd960e38a64818..74945e06fac0eb14936578de6a599a123364a63a 100644
2019-11-19 05:18:28 +03:00
--- 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 f08c19fb95ec8c8cca8f4ca2aa4049885637febf..c09e35e1b4fbf95b31f8d890bf09231055e4373a 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/Shared/NativeWebKeyboardEvent.h
+++ b/Source/WebKit/Shared/NativeWebKeyboardEvent.h
@@ -34,6 +34,7 @@
#if USE(APPKIT)
#include <wtf/RetainPtr.h>
OBJC_CLASS NSView;
+OBJC_CLASS NSEvent;
namespace WebCore {
struct CompositionUnderline;
@@ -67,18 +68,34 @@ 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&);
2019-11-19 05:18:28 +03:00
enum class HandledByInputMethod : bool { No, Yes };
NativeWebKeyboardEvent(GdkEvent*, const String&, HandledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&, Vector<String>&& commands);
2019-11-19 05:18:28 +03:00
+ 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 0fa557e9faa34ba81a7a4f7da5e32f30cbfad5d2..4f06afeb895fb1231d87e4304a4b588cd326944c 100644
--- a/Source/WebKit/Shared/NativeWebMouseEvent.h
+++ b/Source/WebKit/Shared/NativeWebMouseEvent.h
@@ -70,6 +70,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 fd320ec94e4802a4c954a7ae0d6c650192fbcc6b..a3b5ef8f7c722a466b0f218bd62289439c8d588f 100644
--- a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
+++ b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
@@ -1491,6 +1491,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)
@@ -1519,6 +1522,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;
}
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/Shared/WebEvent.h b/Source/WebKit/Shared/WebEvent.h
index a5f5fd1796d3cc5d064e6c7ff6067b43679f52ab..04914136a3f15ee6d7688c8d2aaf78453da56cd2 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/Shared/WebEvent.h
+++ b/Source/WebKit/Shared/WebEvent.h
@@ -37,6 +37,7 @@
2019-11-19 05:18:28 +03:00
#include <WebCore/IntSize.h>
#include <WebCore/KeypressCommand.h>
#include <wtf/OptionSet.h>
+#include <wtf/RefCounted.h>
#include <wtf/WallTime.h>
#include <wtf/text/WTFString.h>
@@ -252,14 +253,18 @@ public:
#if USE(APPKIT)
2019-11-19 05:18:28 +03:00
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);
2019-11-19 05:18:28 +03:00
#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);
2019-11-19 05:18:28 +03:00
+ 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; }
@@ -301,7 +306,7 @@ private:
2019-11-19 05:18:28 +03:00
int32_t m_nativeVirtualKeyCode;
int32_t m_macCharCode;
#if USE(APPKIT) || USE(UIKIT_KEYBOARD_ADDITIONS) || PLATFORM(GTK) || USE(LIBWPE)
2019-11-19 05:18:28 +03:00
- bool m_handledByInputMethod;
+ bool m_handledByInputMethod = false;
#endif
#if PLATFORM(GTK) || USE(LIBWPE)
Optional<Vector<WebCore::CompositionUnderline>> m_preeditUnderlines;
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/Shared/WebKeyboardEvent.cpp b/Source/WebKit/Shared/WebKeyboardEvent.cpp
index cccb560418f32fad40587ac083b95f398eb1399d..f6b0aee44e5f12055dd14ad0636d780d2d4ece5d 100644
2019-11-19 05:18:28 +03:00
--- 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&
2019-11-19 05:18:28 +03:00
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/WebPageCreationParameters.cpp b/Source/WebKit/Shared/WebPageCreationParameters.cpp
index e8c70eb9d2a74123095fc50990e3041e7ed9ad50..f8a20ec561aa25b9b214c94edce6d68d9b726e0c 100644
--- a/Source/WebKit/Shared/WebPageCreationParameters.cpp
+++ b/Source/WebKit/Shared/WebPageCreationParameters.cpp
@@ -147,6 +147,8 @@ void WebPageCreationParameters::encode(IPC::Encoder& encoder) const
encoder << shouldRenderCanvasInGPUProcess;
encoder << needsInAppBrowserPrivacyQuirks;
+ encoder << shouldPauseInInspectorWhenShown;
+
#if PLATFORM(GTK)
encoder << themeName;
#endif
@@ -470,6 +472,9 @@ Optional<WebPageCreationParameters> WebPageCreationParameters::decode(IPC::Decod
if (!decoder.decode(parameters.needsInAppBrowserPrivacyQuirks))
return WTF::nullopt;
+ if (!decoder.decode(parameters.shouldPauseInInspectorWhenShown))
+ return WTF::nullopt;
+
#if PLATFORM(GTK)
if (!decoder.decode(parameters.themeName))
return WTF::nullopt;
diff --git a/Source/WebKit/Shared/WebPageCreationParameters.h b/Source/WebKit/Shared/WebPageCreationParameters.h
index 800e1a753a6310ecc5185e9badeefec3d0b54cfa..c8e9aaecae9ed965f0cb34fe5df4eebea1e85b2f 100644
--- a/Source/WebKit/Shared/WebPageCreationParameters.h
+++ b/Source/WebKit/Shared/WebPageCreationParameters.h
@@ -217,6 +217,8 @@ struct WebPageCreationParameters {
bool shouldRenderCanvasInGPUProcess { false };
bool needsInAppBrowserPrivacyQuirks { false };
+ bool shouldPauseInInspectorWhenShown { false };
+
#if PLATFORM(GTK)
String themeName;
#endif
diff --git a/Source/WebKit/Shared/WebPreferences.yaml b/Source/WebKit/Shared/WebPreferences.yaml
index f5448376a37eeb4028399d17347492b431330e56..195bcee9bed77dc23558a5091c155a11dfe42d19 100644
--- a/Source/WebKit/Shared/WebPreferences.yaml
+++ b/Source/WebKit/Shared/WebPreferences.yaml
@@ -317,7 +317,7 @@ MediaControlsScaleWithPageZoom:
InspectorStartsAttached:
type: bool
- defaultValue: true
+ defaultValue: false
webcoreBinding: none
ShowsToolTipOverTruncatedText:
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
index 2357f3d58415fae78e48b0f8a25bddad85c786bf..f3941a74922f5a0a3bf59a11cd4c42fbfd33d0af 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
+++ b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
@@ -40,7 +40,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(GdkEvent* event, const String& te
2019-11-19 05:18:28 +03:00
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(const NativeWebKeyboardEvent& event)
- : WebKeyboardEvent(WebEventFactory::createWebKeyboardEvent(event.nativeEvent(), event.text(), event.handledByInputMethod(), Optional<Vector<WebCore::CompositionUnderline>>(event.preeditUnderlines()), Optional<EditingRange>(event.preeditSelectionRange()), Vector<String>(event.commands())))
2019-11-19 05:18:28 +03:00
+ : WebKeyboardEvent(event)
, m_nativeEvent(gdk_event_copy(event.nativeEvent()))
{
}
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
index 58e37fe3827cdb08d36ef0c85b8d4a968dee001a..429d245ea99fdee1b598a5caf51de8ce4b47fb02 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
+++ b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
@@ -38,8 +38,8 @@ NativeWebMouseEvent::NativeWebMouseEvent(GdkEvent* event, int eventClickCount, O
2019-11-19 05:18:28 +03:00
}
NativeWebMouseEvent::NativeWebMouseEvent(const NativeWebMouseEvent& event)
- : WebMouseEvent(WebEventFactory::createWebMouseEvent(event.nativeEvent(), event.clickCount(), WebCore::IntPoint(event.deltaX(), event.deltaY())))
2019-11-19 05:18:28 +03:00
- , m_nativeEvent(gdk_event_copy(event.nativeEvent()))
+ : WebMouseEvent(event)
+ , m_nativeEvent(event.nativeEvent() ? gdk_event_copy(event.nativeEvent()) : nullptr)
{
}
2019-12-24 00:12:56 +03:00
diff --git a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
index 7b5eb372880d8662544334cd4697276d543de45b..ba06ecbb2cf5088a4c8c0824b50cb7797605dc57 100644
--- a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
+++ b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "WebEvent.h"
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
#include "WebCoreArgumentCoders.h"
@@ -79,4 +79,4 @@ Optional<WebPlatformTouchPoint> WebPlatformTouchPoint::decode(IPC::Decoder& deco
} // namespace WebKit
-#endif // ENABLE(TOUCH_EVENTS)
+#endif // ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
diff --git a/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp b/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp
index 45a56eb3b0fda13c3b78d57594a0092e4e1866f6..5e29e15813be6abe82790e6a98d3947e7a6fae44 100644
--- a/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp
+++ b/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "WebEvent.h"
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
#include "ArgumentCoders.h"
#include "WebCoreArgumentCoders.h"
@@ -71,4 +71,4 @@ bool WebTouchEvent::decode(IPC::Decoder& decoder, WebTouchEvent& result)
} // namespace WebKit
-#endif // ENABLE(TOUCH_EVENTS)
+#endif // ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
diff --git a/Source/WebKit/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();
}
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt
index 47ccbed451c3d8ae5ab0c73e51b8599e50291580..77a24ba19ebc645cc44fac28be4686637094254d 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/Sources.txt
+++ b/Source/WebKit/Sources.txt
@@ -275,16 +275,21 @@ Shared/WebsiteData/WebsiteData.cpp
2019-11-19 05:18:28 +03:00
UIProcess/AuxiliaryProcessProxy.cpp
UIProcess/BackgroundProcessResponsivenessTimer.cpp
+UIProcess/BrowserInspectorController.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
2019-11-19 05:18:28 +03:00
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
@@ -321,6 +326,8 @@ UIProcess/WebOpenPanelResultListenerProxy.cpp
UIProcess/WebPageDiagnosticLoggingClient.cpp
2019-11-19 05:18:28 +03:00
UIProcess/WebPageGroup.cpp
UIProcess/WebPageInjectedBundleClient.cpp
+UIProcess/WebPageInspectorEmulationAgent.cpp
+UIProcess/WebPageInspectorInputAgent.cpp
UIProcess/WebPageProxy.cpp
UIProcess/WebPasteboardProxy.cpp
UIProcess/WebPreferences.cpp
diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt
index f9323fb9396098a98df96f6bd62d0162d6df8cc8..e170aa113bd8748b6783f9ba95ffa8668f8651dc 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/SourcesCocoa.txt
+++ b/Source/WebKit/SourcesCocoa.txt
@@ -248,6 +248,7 @@ UIProcess/API/Cocoa/_WKApplicationManifest.mm
2019-11-19 05:18:28 +03:00
UIProcess/API/Cocoa/_WKAttachment.mm
UIProcess/API/Cocoa/_WKAutomationSession.mm
UIProcess/API/Cocoa/_WKAutomationSessionConfiguration.mm
+UIProcess/API/Cocoa/_WKBrowserInspector.mm
UIProcess/API/Cocoa/_WKContentRuleListAction.mm
UIProcess/API/Cocoa/_WKContextMenuElementInfo.mm
UIProcess/API/Cocoa/_WKCustomHeaderFields.mm @no-unify
diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt
index eba34614fe0fdcee53c1edc4e940c41bbd24027c..17b592801937088d73ecd8842c48d55f57f0d8d2 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/SourcesGTK.txt
+++ b/Source/WebKit/SourcesGTK.txt
@@ -130,6 +130,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify
2019-11-19 05:18:28 +03:00
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
@@ -237,6 +238,7 @@ UIProcess/WebsiteData/unix/WebsiteDataStoreUnix.cpp
2019-11-19 05:18:28 +03:00
UIProcess/cairo/BackingStoreCairo.cpp @no-unify
+UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
2019-11-19 05:18:28 +03:00
UIProcess/glib/WebProcessPoolGLib.cpp
UIProcess/glib/WebProcessProxyGLib.cpp
UIProcess/glib/WebsiteDataStoreGLib.cpp @no-unify
@@ -250,6 +252,7 @@ UIProcess/gtk/AcceleratedBackingStoreX11.cpp @no-unify
UIProcess/gtk/DragAndDropHandler.cpp
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
2019-11-19 05:18:28 +03:00
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
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt
index 69a52e17a4a8932b5dfc5edfa72b922c18d43082..bc332745c8905414f1c8079c036dadf73902fde4 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/SourcesWPE.txt
+++ b/Source/WebKit/SourcesWPE.txt
@@ -118,6 +118,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify
2019-11-19 05:18:28 +03:00
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
@@ -193,7 +194,7 @@ UIProcess/Automation/wpe/WebAutomationSessionWPE.cpp
2019-11-19 05:18:28 +03:00
UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
UIProcess/geoclue/GeoclueGeolocationProvider.cpp
-
+UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
2019-11-19 05:18:28 +03:00
UIProcess/glib/WebProcessPoolGLib.cpp
UIProcess/glib/WebProcessProxyGLib.cpp
UIProcess/glib/WebsiteDataStoreGLib.cpp @no-unify
@@ -220,6 +221,10 @@ UIProcess/soup/WebProcessPoolSoup.cpp
2019-11-19 05:18:28 +03:00
UIProcess/wpe/WebPageProxyWPE.cpp
+UIProcess/wpe/InspectorTargetProxyWPE.cpp
2019-11-19 05:18:28 +03:00
+UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp
+UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
+
WebProcess/InjectedBundle/API/glib/DOM/DOMObjectCache.cpp @no-unify
WebProcess/InjectedBundle/API/glib/DOM/WebKitDOMDocument.cpp @no-unify
WebProcess/InjectedBundle/API/glib/DOM/WebKitDOMElement.cpp @no-unify
diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
index 72ccef564d1854290de793921e1f092804a6bec6..2ae46d68a1c7454e02800e87ba7eade58713b9e1 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 2a7e318e14f5cd4d136756ce31eb3a16f14055df..2657b4524eb49b76dc2c136837f2d2f5b2806434 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; }
@@ -141,6 +146,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 acf7d0404736335521d1b4aa9cf408a154315b83..c14d1bd945844df507ed91c17769b08a955282d0 100644
--- a/Source/WebKit/UIProcess/API/APIUIClient.h
+++ b/Source/WebKit/UIProcess/API/APIUIClient.h
@@ -97,6 +97,7 @@ public:
virtual void runJavaScriptAlert(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, 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/WKContext.cpp b/Source/WebKit/UIProcess/API/C/WKContext.cpp
index 6d278423685e030a7357ed3772504edcec94caf6..2551fc578be731511dfd4b1ac668b49c20763fec 100644
--- a/Source/WebKit/UIProcess/API/C/WKContext.cpp
+++ b/Source/WebKit/UIProcess/API/C/WKContext.cpp
@@ -436,6 +436,11 @@ WKWebsiteDataStoreRef WKContextGetWebsiteDataStore(WKContextRef)
return WKWebsiteDataStoreGetDefaultDataStore();
}
+void WKContextSetPrimaryDataStore(WKContextRef contextRef, WKWebsiteDataStoreRef dataStoreRef)
+{
+ WebKit::toImpl(contextRef)->setPrimaryDataStore(*WebKit::toImpl(dataStoreRef));
+}
+
WKApplicationCacheManagerRef WKContextGetApplicationCacheManager(WKContextRef context)
{
return reinterpret_cast<WKApplicationCacheManagerRef>(WKWebsiteDataStoreGetDefaultDataStore());
diff --git a/Source/WebKit/UIProcess/API/C/WKContext.h b/Source/WebKit/UIProcess/API/C/WKContext.h
index 08f54ff5057f8d04e26adfe2c0e3a472647935e7..8f3ae0f0346514cec926ea7babff40c22fd4097a 100644
--- a/Source/WebKit/UIProcess/API/C/WKContext.h
+++ b/Source/WebKit/UIProcess/API/C/WKContext.h
@@ -168,6 +168,7 @@ WK_EXPORT void WKContextStartMemorySampler(WKContextRef context, WKDoubleRef int
WK_EXPORT void WKContextStopMemorySampler(WKContextRef context);
WK_EXPORT WKWebsiteDataStoreRef WKContextGetWebsiteDataStore(WKContextRef context) WK_C_API_DEPRECATED_WITH_REPLACEMENT(WKWebsiteDataStoreGetDefaultDataStore);
+WK_EXPORT void WKContextSetPrimaryDataStore(WKContextRef context, WKWebsiteDataStoreRef dataStore);
WK_EXPORT WKApplicationCacheManagerRef WKContextGetApplicationCacheManager(WKContextRef context) WK_C_API_DEPRECATED_WITH_REPLACEMENT(WKWebsiteDataStoreGetDefaultDataStore);
WK_EXPORT WKCookieManagerRef WKContextGetCookieManager(WKContextRef context) WK_C_API_DEPRECATED;
diff --git a/Source/WebKit/UIProcess/API/C/WKInspector.cpp b/Source/WebKit/UIProcess/API/C/WKInspector.cpp
index 39327c5c9230591e4f52e4574c416e36687788f0..269dc87a6ab35481d2b45bea86fff893a9bddfb2 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(CreatePageCallback createPage, QuitCallback quit)
+{
+#if PLATFORM(WIN)
+ initializeBrowserInspectorPipe(makeUnique<InspectorPlaywrightAgentClientWin>(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..1f707641766b51e3bddcdde0c49ee8cfcd83db0b 100644
--- a/Source/WebKit/UIProcess/API/C/WKInspector.h
+++ b/Source/WebKit/UIProcess/API/C/WKInspector.h
@@ -66,6 +66,9 @@ WK_EXPORT void WKInspectorTogglePageProfiling(WKInspectorRef inspector);
WK_EXPORT bool WKInspectorIsElementSelectionActive(WKInspectorRef inspector);
WK_EXPORT void WKInspectorToggleElementSelection(WKInspectorRef inspector);
+typedef WKPageRef (*CreatePageCallback)(WKPageConfigurationRef configuration);
+typedef void (*QuitCallback)();
+WK_EXPORT void WKInspectorInitializeRemoteInspectorPipe(CreatePageCallback, QuitCallback);
#ifdef __cplusplus
}
#endif
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/API/C/WKPage.cpp b/Source/WebKit/UIProcess/API/C/WKPage.cpp
index 09cfac91da8a16ed68dd5dc552d0b1c630da48ba..1824506d94e6ec3c201b0d61f8947a749edbf988 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/UIProcess/API/C/WKPage.cpp
+++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp
@@ -1689,6 +1689,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)
@@ -1749,6 +1756,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient
2019-11-19 05:18:28 +03:00
{
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 1d2febfba8833912f72216aa53c8c20090ee2d8b..1b2c3d84b15b12f1a187c0b7622db43cbbcd5996 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);
@@ -1352,6 +1353,7 @@ typedef struct WKPageUIClientV14 {
// Version 14.
WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel;
+ WKPageHandleJavaScriptDialogCallback handleJavaScriptDialog;
} WKPageUIClientV14;
#ifdef __cplusplus
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm b/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm
index 032584571cb63dbe6b49a7953f6e8d6d7e83e375..766b1e0456a490eb60eeef01c8edd8577ab3fe1a 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm
@@ -47,6 +47,7 @@
#import "_WKDownloadDelegate.h"
#import "_WKDownloadInternal.h"
#import "_WKProcessPoolConfigurationInternal.h"
+#import "_WKWebsiteDataStoreInternal.h"
#import <WebCore/CertificateInfo.h>
#import <WebCore/HTTPCookieAcceptPolicyCocoa.h>
#import <WebCore/PluginData.h>
@@ -84,6 +85,18 @@ static WKProcessPool *sharedProcessPool;
return self;
}
+- (instancetype)_initWithConfiguration:(_WKProcessPoolConfiguration *)configuration AndDataStore:(WKWebsiteDataStore*)dataStore
+{
+ if (!(self = [super init]))
+ return nil;
+
+ API::Object::constructInWrapper<WebKit::WebProcessPool>(self, *configuration->_processPoolConfiguration);
+ _processPool->setPrimaryDataStore(*dataStore->_websiteDataStore);
+
+ return self;
+}
+
+
- (instancetype)init
{
return [self _initWithConfiguration:adoptNS([[_WKProcessPoolConfiguration alloc] init]).get()];
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h b/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h
index cc0f99cf9b1fb80dfd023c2200c66d87d494d6c4..96713376932923a342d0c973216c96925d18dbf0 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h
@@ -37,6 +37,7 @@
@interface WKProcessPool ()
- (instancetype)_initWithConfiguration:(_WKProcessPoolConfiguration *)configuration __attribute__((objc_method_family(init))) NS_DESIGNATED_INITIALIZER;
+- (instancetype)_initWithConfiguration:(_WKProcessPoolConfiguration *)configuration AndDataStore:(WKWebsiteDataStore *)dataStore __attribute__((objc_method_family(init))) NS_DESIGNATED_INITIALIZER;
@end
@interface WKProcessPool (WKPrivate)
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h
index cad87f3ef2ab93d93a74cec0c34b47c695de6bc6..66145a384638b97ee08516e56e1e86a83713c634 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h
@@ -123,6 +123,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;
+/*! @abstract Handle a JavaScript dialog.
+ @param webView The web view invoking the delegate method.
+ @param accept Whether to accept the dialog.
+ @param value Value to use for prompt dialog.
+ */
+- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(nullable NSString *)value;
+
#if TARGET_OS_IPHONE
/*! @abstract Allows your app to determine whether or not the given element should show a preview.
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h
index 726c4972aa0b32e0dc602e0ab2d71f6ae8ef93ae..c67f408797724cb6d68ed441c0ef1cccd33ca1e0 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h
@@ -24,7 +24,6 @@
*/
#import <WebKit/WKFoundation.h>
-
#import <WebKit/WKWebsiteDataRecord.h>
NS_ASSUME_NONNULL_BEGIN
@@ -78,6 +77,8 @@ WK_CLASS_AVAILABLE(macos(10.11), ios(9.0))
/*! @abstract Returns the cookie store representing HTTP cookies in this website data store. */
@property (nonatomic, readonly) WKHTTPCookieStore *httpCookieStore WK_API_AVAILABLE(macos(10.13), ios(11.0));
+- (uint64_t)sessionID;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
index a48e1b62026b77132df4f799027b77c56a91cfca..2bc058614f4c3773f54606522aaa1cbce43da80e 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
@@ -44,6 +44,7 @@
#import "_WKWebsiteDataStoreDelegate.h"
#import <WebCore/Credential.h>
#import <WebCore/RegistrationDatabase.h>
+#import <pal/SessionID.h>
#import <wtf/BlockPtr.h>
#import <wtf/URL.h>
#import <wtf/WeakObjCPtr.h>
@@ -184,6 +185,11 @@ static WallTime toSystemClockTime(NSDate *date)
});
}
+- (uint64_t) sessionID
+{
+ return _websiteDataStore->sessionID().toUInt64();
+}
+
static Vector<WebKit::WebsiteDataRecord> toWebsiteDataRecords(NSArray *dataRecords)
{
Vector<WebKit::WebsiteDataRecord> result;
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h
new file mode 100644
index 0000000000000000000000000000000000000000..b64d1a6d54ec15a99164294706543cee626d1050
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#import <WebKit/WKFoundation.h>
+#import <WebKit/WKProcessPool.h>
+#import <WebKit/WKWebsiteDataStore.h>
2019-11-19 05:18:28 +03:00
+#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
+
2019-11-19 05:18:28 +03:00
+@protocol _WKBrowserInspectorDelegate <NSObject>
+- (WKWebView *)createNewPage:(uint64_t)sessionID;
+- (_WKBrowserContext *)createBrowserContext;
+- (void)deleteBrowserContext:(uint64_t)sessionID;
2019-11-19 05:18:28 +03:00
+- (void)quit;
+@end
+
+WK_CLASS_AVAILABLE(macos(10.14.0))
2019-11-19 05:18:28 +03:00
+@interface _WKBrowserInspector : NSObject
++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless;
2019-11-19 05:18:28 +03:00
+@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
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "_WKBrowserInspector.h"
+
+#include "BrowserInspectorPipe.h"
+#include "InspectorPlaywrightAgentClientMac.h"
+#include "PageClientImplMac.h"
+#include "WebKit2Initialize.h"
2019-11-19 05:18:28 +03:00
+
+#import "WKWebView.h"
+
+using namespace WebKit;
+
+@implementation _WKBrowserInspector
+
++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless
2019-11-19 05:18:28 +03:00
+{
+#if ENABLE(REMOTE_INSPECTOR)
+ InitializeWebKit2();
+ PageClientImpl::setHeadless(headless);
+ initializeBrowserInspectorPipe(makeUnique<InspectorPlaywrightAgentClientMac>(delegate));
2019-11-19 05:18:28 +03:00
+#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 04922b10809ed4754279184a42169defa5f01ec8..a40edf790cded9f05943aa226db1e1e7e7211cb6 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 18dae1c505a2d068740d559cf0ad31ea172c7c07..cb58f6df7a99867b149be670fcd76ba76a90be59 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
@@ -261,6 +261,16 @@
return _processPoolConfiguration->processSwapsOnNavigation();
}
+- (void)setForceOverlayScrollbars:(BOOL)force
+{
+ _processPoolConfiguration->setForceOverlayScrollbars(force);
+}
+
+- (BOOL)forceOverlayScrollbars
+{
+ return _processPoolConfiguration->forceOverlayScrollbars();
+}
+
- (void)setPrewarmsProcessesAutomatically:(BOOL)prewarms
{
_processPoolConfiguration->setIsAutomaticProcessWarmingEnabled(prewarms);
2019-12-14 04:09:45 +03:00
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm
index 2bdb8b9e7256f22096ebaa5d51959aa52389ca0a..2141d9d17497861a6c711f99306de10992a93ce8 100644
2019-12-14 04:09:45 +03:00
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm
@@ -25,6 +25,7 @@
#import "config.h"
#import "_WKRemoteWebInspectorViewController.h"
+#import "WKWebViewPrivate.h"
#if PLATFORM(MAC)
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1884526cd6ce7d436af6596ab3a45b103031dba1
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "WebKitBrowserInspector.h"
+
+#include "BrowserInspectorPipe.h"
+#include "InspectorPlaywrightAgentClientGLib.h"
2019-11-19 05:18:28 +03:00
+#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,
+
+ LAST_SIGNAL
+};
+
+struct _WebKitBrowserInspectorPrivate {
+ int unused { 0 };
+};
+
+WEBKIT_DEFINE_TYPE(WebKitBrowserInspector, webkit_browser_inspector, G_TYPE_OBJECT)
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+static void webkit_browser_inspector_class_init(WebKitBrowserInspectorClass* findClass)
+{
+ GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass);
+
+ /**
+ * WebKitBrowserInspector::create-new-page:
+ * @inspector: the #WebKitBrowserInspector on which the signal is emitted
+ *
+ * Emitted when the inspector is requested to create a new page in the provided
+ * #WebKitWebContext.
+ *
+ * This signal is emitted when inspector receives 'Browser.createPage' command
+ * from its remote client. If the signla is not handled the command will fail.
+ *
+ * Returns: %WebKitWebView that contains created page.
+ */
+ signals[CREATE_NEW_PAGE] = g_signal_new(
+ "create-new-page",
+ G_TYPE_FROM_CLASS(gObjectClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitBrowserInspectorClass, create_new_page),
+ nullptr, nullptr,
+ g_cclosure_marshal_generic,
+#if PLATFORM(GTK)
+ GTK_TYPE_WIDGET,
+#else
+ WEBKIT_TYPE_WEB_VIEW,
+#endif
+ 1,
+ WEBKIT_TYPE_WEB_CONTEXT);
+}
+
+WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext* context)
+{
+ WebKitWebView* newWebView;
+ g_signal_emit(webkit_browser_inspector_get_default(), signals[CREATE_NEW_PAGE], 0, context, &newWebView);
+ if (!newWebView)
+ return nullptr;
+ return &webkitWebViewGetPage(newWebView);
+}
+
+static gpointer createWebKitBrowserInspector(gpointer)
+{
+ static GRefPtr<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(GMainLoop* mainLoop)
2019-11-19 05:18:28 +03:00
+{
+#if ENABLE(REMOTE_INSPECTOR)
+ WebKit::initializeBrowserInspectorPipe(makeUnique<WebKit::InspectorPlaywrightAgentClientGlib>(mainLoop));
2019-11-19 05:18:28 +03:00
+#endif
+}
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h
new file mode 100644
index 0000000000000000000000000000000000000000..1bff4e694f19264d1be418198b7921780e4f8309
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#pragma once
+
+#include "WebKitBrowserInspector.h"
+#include "WebPageProxy.h"
+
+WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext*);
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
index e7a479bfeb52e49fe7fedd16757beec4c67dce7f..9ec33c9807aac32429eb2dd54794c793ce744532 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
+++ b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
@@ -64,7 +64,8 @@ private:
void createNewPage(WebPageProxy& page, WebCore::WindowFeatures&& windowFeatures, Ref<API::NavigationAction>&& apiNavigationAction, CompletionHandler<void(RefPtr<WebPageProxy>&&)>&& completionHandler) final
{
WebKitNavigationAction navigationAction(WTFMove(apiNavigationAction));
- completionHandler(webkitWebViewCreateNewPage(m_webView, windowFeatures, &navigationAction));
+ WebPageProxy* newPage = webkitWebViewCreateNewPage(m_webView, windowFeatures, &navigationAction);
+ completionHandler(adoptRef(newPage));
}
void showPage(WebPageProxy*) final
@@ -91,6 +92,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; }
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
index c9e7ee782b908c3aee5c47d9f3c30c62f017efb9..de6e06525841ef1843388574303921a97fcfa714 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
+++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
@@ -119,9 +119,7 @@ enum {
PROP_LOCAL_STORAGE_DIRECTORY,
#endif
PROP_WEBSITE_DATA_MANAGER,
-#if PLATFORM(GTK)
PROP_PSON_ENABLED
-#endif
};
enum {
@@ -202,9 +200,7 @@ struct _WebKitWebContextPrivate {
RefPtr<WebProcessPool> processPool;
bool clientsDetached;
-#if PLATFORM(GTK)
bool psonEnabled;
-#endif
GRefPtr<WebKitFaviconDatabase> faviconDatabase;
GRefPtr<WebKitSecurityManager> securityManager;
@@ -329,11 +325,9 @@ 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;
-#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec);
}
@@ -354,11 +348,9 @@ 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;
-#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec);
}
@@ -375,9 +367,7 @@ static void webkitWebContextConstructed(GObject* object)
API::ProcessPoolConfiguration configuration;
configuration.setInjectedBundlePath(FileSystem::stringFromFileSystemRepresentation(bundleFilename.get()));
-#if PLATFORM(GTK)
configuration.setProcessSwapsOnNavigation(priv->psonEnabled);
-#endif
if (!priv->websiteDataManager)
priv->websiteDataManager = adoptGRef(webkit_website_data_manager_new("local-storage-directory", priv->localStorageDirectory.data(), nullptr));
@@ -385,6 +375,11 @@ static void webkitWebContextConstructed(GObject* object)
2019-11-19 05:18:28 +03:00
if (!webkit_website_data_manager_is_ephemeral(priv->websiteDataManager.get()))
WebKit::LegacyGlobalSettings::singleton().setHSTSStorageDirectory(FileSystem::stringFromFileSystemRepresentation(webkit_website_data_manager_get_hsts_cache_directory(priv->websiteDataManager.get())));
+ const gchar *singleprocess = g_getenv("MINIBROWSER_SINGLEPROCESS");
+ if (singleprocess && *singleprocess) {
+ // processModel is not set at this point, force single process.
+ configuration.setUsesSingleWebProcess(true);
+ }
priv->processPool = WebProcessPool::create(configuration);
priv->processPool->setPrimaryDataStore(webkitWebsiteDataManagerGetDataStore(priv->websiteDataManager.get()));
priv->processPool->setUserMessageHandler([webContext](UserMessage&& message, CompletionHandler<void(UserMessage&&)>&& completionHandler) {
@@ -496,7 +491,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:
*
@@ -519,7 +513,6 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass
_("Whether swap Web processes on cross-site navigations is enabled"),
FALSE,
static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
-#endif
/**
* WebKitWebContext::download-started:
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
index b743a0d340be03f5fcc5c9a56654c1574d6e794f..b97da974f05a23d7ce5c98d8f4b334920c2ec96a 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
+++ b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
@@ -131,6 +131,7 @@ enum {
CLOSE,
SCRIPT_DIALOG,
+ SCRIPT_DIALOG_HANDLED,
DECIDE_POLICY,
PERMISSION_REQUEST,
@@ -1536,6 +1537,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
@@ -2417,6 +2427,20 @@ 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;
+ 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 5ab7574c9378f52db87ce75157627c04e9b2e962..5322d725238f5989c04b045615a2de8163329fdf 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*);
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
index a68a30983f609d925b45ee16fbe34110b6cabe95..533f45fe6810509b8a0e1823087011a86510770a 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
+++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
@@ -230,6 +230,8 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool
{
if (wasEventHandled)
2019-11-19 05:18:28 +03:00
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..a51cfebc270ca5a91cd94645eeeb005ba9a67caf
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#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);
+
+ 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 (GMainLoop*);
2019-11-19 05:18:28 +03:00
+
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit/UIProcess/API/gtk/webkit2.h b/Source/WebKit/UIProcess/API/gtk/webkit2.h
index 930b17b6629e04d0dfa2222bbc3217877c6e1812..395462e5f01c195231e9296d1204167cded99ad3 100644
2019-11-19 05:18:28 +03:00
--- 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/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h
new file mode 100644
index 0000000000000000000000000000000000000000..6dffa4fa10a9a64f778a0a77c760c2e76b2f9968
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#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);
+
+ 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 (GMainLoop*);
+
2019-11-19 05:18:28 +03:00
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitScriptDialogWPE.cpp b/Source/WebKit/UIProcess/API/wpe/WebKitScriptDialogWPE.cpp
index 3ad6e613657557045ec07ce4bcdb3eea0d1e7dae..a53a4aa01bd692ba34bacb9f663c335cfd3821a7 100644
--- a/Source/WebKit/UIProcess/API/wpe/WebKitScriptDialogWPE.cpp
+++ b/Source/WebKit/UIProcess/API/wpe/WebKitScriptDialogWPE.cpp
@@ -22,14 +22,26 @@
#include "WebKitScriptDialogPrivate.h"
-void webkitScriptDialogAccept(WebKitScriptDialog*)
+void webkitScriptDialogAccept(WebKitScriptDialog* dialog)
{
+ if (!dialog->completionHandler)
+ return;
+ auto completionHandler = std::exchange(dialog->completionHandler, nullptr);
+ completionHandler(true, String());
}
-void webkitScriptDialogDismiss(WebKitScriptDialog*)
+void webkitScriptDialogDismiss(WebKitScriptDialog* dialog)
{
+ if (!dialog->completionHandler)
+ return;
+ auto completionHandler = std::exchange(dialog->completionHandler, nullptr);
+ completionHandler(false, String());
}
-void webkitScriptDialogSetUserInput(WebKitScriptDialog*, const String&)
+void webkitScriptDialogSetUserInput(WebKitScriptDialog* dialog, const String& value)
{
+ if (!dialog->completionHandler)
+ return;
+ auto completionHandler = std::exchange(dialog->completionHandler, nullptr);
+ completionHandler(true, value);
}
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/API/wpe/webkit.h b/Source/WebKit/UIProcess/API/wpe/webkit.h
index 02e258253e47fbf6594c20f743d0faeac8a4eefe..e051fdf396dc65717def6b36168b5538e3cb2f4d 100644
2019-11-19 05:18:28 +03:00
--- 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/BrowserInspectorController.cpp b/Source/WebKit/UIProcess/BrowserInspectorController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..74b702953a54425bb80090f60b0a321b402e68eb
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/BrowserInspectorController.cpp
@@ -0,0 +1,238 @@
+/*
+ * 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "BrowserInspectorController.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgent.h"
+#include "InspectorPlaywrightAgentClient.h"
2019-11-19 05:18:28 +03:00
+#include "WebPageInspectorController.h"
+#include "WebPageProxy.h"
+#include "WebProcessPool.h"
+#include "WebProcessProxy.h"
+#include <JavaScriptCore/InspectorBackendDispatcher.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+#include <JavaScriptCore/InspectorFrontendChannel.h>
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <JavaScriptCore/InspectorTarget.h>
+#include <wtf/Ref.h>
+#include <wtf/RefPtr.h>
+
+using namespace Inspector;
+
+namespace WebKit {
+
+static Vector<WebPageProxy*> allPages()
+{
+ ASSERT(isMainThread());
+ Vector<WebPageProxy*> result;
+ for (WebProcessPool* pool : WebProcessPool::allProcessPools()) {
+ for (auto& process : pool->processes()) {
+ result.appendRange(process->pages().begin(), process->pages().end());
+ }
+ }
+ return result;
+}
+
+class BrowserInspectorController::PageProxyChannel : public FrontendChannel {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ PageProxyChannel(FrontendChannel& frontendChannel, String pageProxyID, WebPageProxy& page)
+ : m_pageProxyID(pageProxyID)
+ , m_frontendChannel(frontendChannel)
+ , m_page(page)
+ {
+ }
+
+ ~PageProxyChannel() override = default;
+
+ void dispatchMessageFromFrontend(const String& message)
+ {
+ m_page.inspectorController().dispatchMessageFromFrontend(message);
+ }
+
+ 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;
+ if (!JSON::Value::parseJSON(message, parsedMessage))
+ return message;
+
+ RefPtr<JSON::Object> messageObject;
+ if (!parsedMessage->asObject(messageObject))
+ return message;
+
+ messageObject->setString("pageProxyId"_s, m_pageProxyID);
+ return messageObject->toJSONString();
+ }
+
+ String m_pageProxyID;
+ FrontendChannel& m_frontendChannel;
+ WebPageProxy& m_page;
+};
+
+BrowserInspectorController::BrowserInspectorController(std::unique_ptr<InspectorPlaywrightAgentClient> client)
2019-11-19 05:18:28 +03:00
+ : m_frontendChannel(nullptr)
+ , m_frontendRouter(FrontendRouter::create())
+ , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
+ , m_browserAgentClient(std::move(client))
+{
+ PageProxyIDMap* map = this;
+ auto browserAgent = makeUnique<InspectorPlaywrightAgent>(m_frontendRouter, m_backendDispatcher, m_browserAgentClient.get(), *map);
+ m_browserAgent = browserAgent.get();
+ m_agents.append(WTFMove(browserAgent));
2019-11-19 05:18:28 +03:00
+}
+
+BrowserInspectorController::~BrowserInspectorController()
+{
+ if (m_frontendChannel)
+ disconnectFrontend();
+}
2019-11-19 05:18:28 +03:00
+
+void BrowserInspectorController::connectFrontend(FrontendChannel& frontendChannel)
+{
+ ASSERT(!m_frontendChannel);
+ m_frontendChannel = &frontendChannel;
+ WebPageInspectorController::setObserver(this);
2019-11-19 05:18:28 +03:00
+
+ bool connectingFirstFrontend = !m_frontendRouter->hasFrontends();
+ m_frontendRouter->connectFrontend(frontendChannel);
+ if (connectingFirstFrontend)
+ m_agents.didCreateFrontendAndBackend(&m_frontendRouter.get(), &m_backendDispatcher.get());
+
+ connectToAllPages();
+}
+
+void BrowserInspectorController::disconnectFrontend()
+{
+ ASSERT(m_frontendChannel);
+ disconnectFromAllPages();
+
+ m_frontendRouter->disconnectFrontend(*m_frontendChannel);
+ if (!m_frontendRouter->hasFrontends())
+ m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectorDestroyed);
+
+ WebPageInspectorController::setObserver(nullptr);
2019-11-19 05:18:28 +03:00
+ m_frontendChannel = nullptr;
+}
+
+void BrowserInspectorController::dispatchMessageFromFrontend(const String& message)
+{
+ m_backendDispatcher->dispatch(message, BackendDispatcher::Mode::FailIfDomainIsMissing, [&](const RefPtr<JSON::Object>& messageObject) {
+ RefPtr<JSON::Value> pageProxyIDValue;
+ if (!messageObject->getValue("pageProxyId"_s, pageProxyIDValue))
+ return BackendDispatcher::DispatchResult::Continue;
+
+ String pageProxyID;
+ if (!pageProxyIDValue->asString(pageProxyID)) {
+ m_backendDispatcher->reportProtocolError(BackendDispatcher::InvalidRequest, "The type of 'pageProxyId' must be string"_s);
+ m_backendDispatcher->sendPendingErrors();
+ return BackendDispatcher::DispatchResult::Finished;
+ }
+
+
+ if (auto pageProxyChannel = m_pageProxyChannels.get(pageProxyID)) {
+ pageProxyChannel->dispatchMessageFromFrontend(message);
+ return BackendDispatcher::DispatchResult::Finished;
+ }
+
+ m_backendDispatcher->reportProtocolError(BackendDispatcher::InvalidRequest, "Cannot find page proxy with provided 'pageProxyId'"_s);
+ m_backendDispatcher->sendPendingErrors();
+ return BackendDispatcher::DispatchResult::Finished;
+ });
2019-11-19 05:18:28 +03:00
+}
+
+void BrowserInspectorController::connectToAllPages()
+{
+ for (auto* page : allPages())
+ connectToPage(*page);
2019-11-19 05:18:28 +03:00
+}
+
+void BrowserInspectorController::disconnectFromAllPages()
+{
+ for (auto it = m_pageProxyChannels.begin(); it != m_pageProxyChannels.end(); ++it)
+ it->value->disconnect();
+ m_pageProxyChannels.clear();
+}
+
+void BrowserInspectorController::connectToPage(WebPageProxy& page)
+{
+ String pageProxyID = InspectorPlaywrightAgent::toPageProxyIDProtocolString(page);
+ auto pageProxyChannel = makeUnique<PageProxyChannel>(*m_frontendChannel, pageProxyID, page);
+ page.inspectorController().connectFrontend(*pageProxyChannel);
+ // Always pause new targets if controlled remotely.
+ page.inspectorController().setPauseOnStart(true);
+ m_pageProxyChannels.set(pageProxyID, WTFMove(pageProxyChannel));
2019-11-19 05:18:28 +03:00
+}
+
+void BrowserInspectorController::didCreateInspectorController(WebPageProxy& page)
+{
+ ASSERT(m_frontendChannel);
+ // Auto-connect to all new pages.
+ connectToPage(page);
+ m_browserAgent->didCreateWebPageProxy(page);
+}
+
+void BrowserInspectorController::willDestroyInspectorController(WebPageProxy& page)
+{
+ m_browserAgent->willDestroyWebPageProxy(page);
+
+ String pageProxyID = InspectorPlaywrightAgent::toPageProxyIDProtocolString(page);
+ auto it = m_pageProxyChannels.find(pageProxyID);
+ ASSERT(it != m_pageProxyChannels.end());
+ it->value->disconnect();
+ m_pageProxyChannels.remove(it);
+}
+
+void BrowserInspectorController::didFailProvisionalLoad(WebPageProxy& page, uint64_t navigationID, const String& error)
+{
+ m_browserAgent->didFailProvisionalLoad(page, navigationID, error);
+}
+
+WebPageProxy* BrowserInspectorController::findPageProxy(const String& pageProxyID)
+{
+ if (auto* pageProxyChannel = m_pageProxyChannels.get(pageProxyID))
+ return &pageProxyChannel->page();
+
+ return nullptr;
+}
+
2019-11-19 05:18:28 +03:00
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/BrowserInspectorController.h b/Source/WebKit/UIProcess/BrowserInspectorController.h
new file mode 100644
index 0000000000000000000000000000000000000000..4516c31d02caabbb731f662e96436569daf3eaeb
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/BrowserInspectorController.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
2019-11-19 05:18:28 +03:00
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgent.h"
+#include "WebPageInspectorController.h"
2019-11-19 05:18:28 +03:00
+#include <JavaScriptCore/InspectorAgentRegistry.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+}
+
+namespace WebKit {
+
+class InspectorPlaywrightAgent;
+class InspectorPlaywrightAgentClient;
2019-11-19 05:18:28 +03:00
+
+class BrowserInspectorController : private WebPageInspectorControllerObserver, private PageProxyIDMap {
2019-11-19 05:18:28 +03:00
+ WTF_MAKE_NONCOPYABLE(BrowserInspectorController);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ BrowserInspectorController(std::unique_ptr<InspectorPlaywrightAgentClient> client);
2019-11-19 05:18:28 +03:00
+ ~BrowserInspectorController();
+
+ void connectFrontend(Inspector::FrontendChannel&);
+ void disconnectFrontend();
+ void dispatchMessageFromFrontend(const String& message);
+
+private:
+ class TargetHandler;
+ class PageProxyChannel;
+
+ // WebPageInspectorControllerObserver
+ void didCreateInspectorController(WebPageProxy&) override;
+ void willDestroyInspectorController(WebPageProxy&) override;
+ void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error) override;
+
+ // PageProxyIDMap
+ WebPageProxy* findPageProxy(const String& pageProxyID) override;
+
2019-11-19 05:18:28 +03:00
+ void connectToAllPages();
+ void disconnectFromAllPages();
+ void connectToPage(WebPageProxy&);
2019-11-19 05:18:28 +03:00
+
+ Inspector::FrontendChannel* m_frontendChannel { nullptr };
+ Ref<Inspector::FrontendRouter> m_frontendRouter;
+ Ref<Inspector::BackendDispatcher> m_backendDispatcher;
+ std::unique_ptr<InspectorPlaywrightAgentClient> m_browserAgentClient;
2019-11-19 05:18:28 +03:00
+ Inspector::AgentRegistry m_agents;
+ InspectorPlaywrightAgent* m_browserAgent { nullptr };
+ HashMap<String, std::unique_ptr<PageProxyChannel>> m_pageProxyChannels;
2019-11-19 05:18:28 +03:00
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e07123453ecab2611ff4918cec37ee6e744a23a6
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "BrowserInspectorPipe.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "BrowserInspectorController.h"
+#include "RemoteInspectorPipe.h"
+#include <wtf/NeverDestroyed.h>
+#include "InspectorPlaywrightAgentClient.h"
2019-11-19 05:18:28 +03:00
+
+namespace WebKit {
+
+void initializeBrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client)
2019-11-19 05:18:28 +03:00
+{
+ class BrowserInspectorPipe {
+ public:
+ BrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client)
2019-11-19 05:18:28 +03:00
+ : m_browserInspectorController(std::move(client))
+ , m_remoteInspectorPipe(m_browserInspectorController)
+ {
+ }
+
+ BrowserInspectorController m_browserInspectorController;
+ 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
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+namespace WebKit {
+
+class InspectorPlaywrightAgentClient;
2019-11-19 05:18:28 +03:00
+
+void initializeBrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client);
2019-11-19 05:18:28 +03:00
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
2020-03-11 20:56:20 +03:00
diff --git a/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm b/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm
index 40949c2f409cd42dca616c29649852ff222f2af5..b56ff05f55263e00bdccfda75249a767e965fe82 100644
--- a/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm
+++ b/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm
@@ -40,7 +40,7 @@ namespace WebKit {
PageClientImplCocoa::PageClientImplCocoa(WKWebView *webView)
: m_webView { webView }
#if USE(DICTATION_ALTERNATIVES)
- , m_alternativeTextUIController { makeUnique<AlternativeTextUIController>() }
+ , m_alternativeTextUIController { makeUnique<WebCore::AlternativeTextUIController>() }
#endif
{
}
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h
index 454c61ffdefecc476d1560c7c43f5b5d345f281d..6de7509037b7683ddd403ee247bdf2845ce4e87a 100644
2019-11-19 05:18:28 +03:00
--- 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>
2019-11-19 05:18:28 +03:00
@@ -39,6 +41,8 @@ class NavigationAction;
2019-11-19 05:18:28 +03:00
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
2019-11-19 05:18:28 +03:00
--- 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 206246741e96e5d454d2a41e66399980426ebfe1..6f21ff815e22fe3c419911a28a09f901184a5f63 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;
@@ -170,6 +171,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 216295e4568dfa4e80e9682ae88fc10685a7d7b3..085e568d7a80386c53a324f42c88be4849f3ed20 100644
--- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
+++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
@@ -102,6 +102,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:)];
@@ -339,6 +340,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 65cf4713050692ccbdb91b6733e89e2e93895f27..255067036cb163496595605904775437ed4b05a7 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
+++ b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
@@ -357,7 +357,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)
@@ -657,8 +657,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/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
index 6bbd1cabd27ae2847648a8c2edcf9acfcd556ff5..38d101b9a96986e40f6e9f0261fa429a3d516e2e 100644
--- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
+++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
@@ -37,6 +37,7 @@
#include "WebProcessProxy.h"
#include <WebCore/PlatformDisplay.h>
#include <WebCore/Region.h>
+#include <wtf/Vector.h>
#if PLATFORM(GTK)
#include <gtk/gtk.h>
@@ -119,6 +120,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 +138,11 @@ void DrawingAreaProxyCoordinatedGraphics::deviceScaleFactorDidChange()
backingStoreStateDidChange(RespondImmediately);
}
+void DrawingAreaProxyCoordinatedGraphics::waitForSizeUpdate(Function<void ()>&& callback)
+{
+ m_callbacks.append(WTFMove(callback));
+}
+
void DrawingAreaProxyCoordinatedGraphics::waitForBackingStoreUpdateOnNextPaint()
{
m_hasReceivedFirstUpdate = true;
diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h
index d7695088e7cfc4f638f157338754f9f157489749..ba114d47ac079661702e44f19853398f5c1d6b55 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/HashMap.h>
#include <wtf/RunLoop.h>
namespace WebCore {
@@ -49,6 +50,7 @@ public:
bool isInAcceleratedCompositingMode() const { return !m_layerTreeContext.isEmpty(); }
const LayerTreeContext& layerTreeContext() const { return m_layerTreeContext; }
+ void waitForSizeUpdate(Function<void ()>&&);
private:
// DrawingAreaProxy
@@ -126,6 +128,8 @@ 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;
diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp
index 592fa4c4d9a45eb1e9b95e0cdabc8d404b40018d..4b0fe2f5a562fbcd3250dc4749072ddfa7c7be4f 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;
@@ -62,7 +64,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, originatingPage);
}
DownloadProxy::~DownloadProxy()
@@ -178,7 +183,18 @@ void DownloadProxy::decideDestinationWithSuggestedFilenameAsync(DownloadID downl
{
if (!m_processPool)
return;
-
+
+ if (m_processPool->networkProcess() && 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);
+ }
+ m_processPool->networkProcess()->send(Messages::NetworkProcess::ContinueDecidePendingDownloadDestination(downloadID, destination, sandboxExtensionHandle, true), 0);
+ return;
+ }
+
m_processPool->downloadClient().decideDestinationWithSuggestedFilename(*this, ResourceResponseBase::sanitizeSuggestedFilename(suggestedFilename), [this, protectedThis = makeRef(*this), downloadID = downloadID] (AllowOverwrite allowOverwrite, String destination) {
SandboxExtension::Handle sandboxExtensionHandle;
if (!destination.isNull())
@@ -206,6 +222,8 @@ void DownloadProxy::didFinish()
return;
m_processPool->downloadClient().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);
@@ -227,6 +245,8 @@ void DownloadProxy::didFail(const ResourceError& error, const IPC::DataReference
m_resumeData = createData(resumeData);
m_processPool->downloadClient().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);
@@ -237,6 +257,8 @@ void DownloadProxy::didCancel(const IPC::DataReference& resumeData)
m_resumeData = createData(resumeData);
m_processPool->downloadClient().didCancel(*this);
+ if (auto* instrumentation = m_dataStore->downloadInstrumentation())
+ instrumentation->downloadFinished(m_uuid, "canceled"_s);
// 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 a0ccbe0663c3c126437704bcc8f91b4724ccca9f..5d52ca9048562410c686c6fb30a0fae654bbb6db 100644
--- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h
+++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h
@@ -141,6 +141,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 d5119266490ac9c3f0e9dcb09b6b105f4597a70f..8cb4aedfc6d0ff61fc57145585ee993ae75a07ed 100644
--- a/Source/WebKit/UIProcess/DrawingAreaProxy.h
+++ b/Source/WebKit/UIProcess/DrawingAreaProxy.h
@@ -72,6 +72,7 @@ public:
const WebCore::IntSize& size() const { return m_size; }
bool setSize(const WebCore::IntSize&, const WebCore::IntSize& scrollOffset = { });
+ void waitForSizeUpdate(Function<void ()>&&);
#if !PLATFORM(COCOA)
// The timeout we use when waiting for a DidUpdateGeometry message.
diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp
index 6928ca2fbfb6939062e3cd14bb7ba6f2fdc87f5f..c4645302296540a408aa88dabb64fd5e9a04f3f7 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)
{
@@ -83,6 +81,9 @@ void InspectorTargetProxy::disconnect()
void InspectorTargetProxy::sendMessageToTargetBackend(const String& message)
{
+ if (m_page.inspectorController().dispatchMessageToTargetBackend(message))
+ return;
+
if (m_provisionalPage) {
m_provisionalPage->send(Messages::WebPage::SendMessageToTargetBackend(identifier(), message));
return;
@@ -97,6 +98,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)
2019-11-19 05:18:28 +03:00
+{
+ if (m_type != Inspector::InspectorTargetType::Page)
+ return InspectorTarget::close(error, runBeforeUnload);
2019-11-19 05:18:28 +03:00
+
+ 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..7c44efa7cdb60642608fbbbbd4811f834f6f7545 100644
--- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
+++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
@@ -26,12 +26,18 @@
#include "config.h"
#include "WebPageInspectorController.h"
+#include "APINavigation.h"
#include "InspectorBrowserAgent.h"
+#include "InspectorDialogAgent.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 <JavaScriptCore/InspectorAgentBase.h>
#include <JavaScriptCore/InspectorBackendDispatcher.h>
#include <JavaScriptCore/InspectorBackendDispatchers.h>
@@ -48,27 +54,96 @@ static String getTargetID(const ProvisionalPageProxy& provisionalPage)
return WebPageInspectorTarget::toTargetID(provisionalPage.webPageID());
}
+WebPageInspectorControllerObserver* WebPageInspectorController::s_observer = nullptr;
+
+void WebPageInspectorController::setObserver(WebPageInspectorControllerObserver* observer)
2019-11-19 05:18:28 +03:00
+{
+ s_observer = observer;
2019-11-19 05:18:28 +03:00
+}
+
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));
+
+ 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)
2019-11-19 05:18:28 +03:00
+{
+ 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();
2019-11-19 05:18:28 +03:00
+}
+
+void WebPageInspectorController::didShowPage()
+{
+ if (m_frontendRouter->hasFrontends())
+ m_emulationAgent->didShowPage();
+}
+
+void WebPageInspectorController::didProcessAllPendingKeyboardEvents()
2019-11-19 05:18:28 +03:00
+{
+ if (m_frontendRouter->hasFrontends())
+ m_inputAgent->didProcessAllPendingKeyboardEvents();
+}
+
+void WebPageInspectorController::didProcessAllPendingMouseEvents()
+{
+ if (m_frontendRouter->hasFrontends())
+ m_inputAgent->didProcessAllPendingMouseEvents();
}
bool WebPageInspectorController::hasLocalFrontend() const
@@ -82,6 +157,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 +186,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 +212,8 @@ void WebPageInspectorController::disconnectAllFrontends()
// Disconnect any remaining remote frontends.
m_frontendRouter->disconnectAllFrontends();
+ m_pendingNavigations.clear();
2019-11-19 05:18:28 +03:00
+
m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
#if ENABLE(REMOTE_INSPECTOR)
@@ -136,6 +226,11 @@ void WebPageInspectorController::dispatchMessageFromFrontend(const String& messa
m_backendDispatcher->dispatch(message);
}
+bool WebPageInspectorController::dispatchMessageToTargetBackend(const String& message)
2019-11-19 05:18:28 +03:00
+{
+ return m_backendDispatcher->dispatch(message, BackendDispatcher::Mode::ContinueIfDomainIsMissing) == BackendDispatcher::DispatchResult::Finished;
2019-11-19 05:18:28 +03:00
+}
+
#if ENABLE(REMOTE_INSPECTOR)
void WebPageInspectorController::setIndicating(bool indicating)
{
@@ -150,6 +245,55 @@ void WebPageInspectorController::setIndicating(bool indicating)
}
#endif
+void WebPageInspectorController::navigate(WebCore::ResourceRequest&& request, WebFrameProxy* frame, NavigationHandler&& completionHandler)
2019-11-19 05:18:28 +03:00
+{
+ auto navigation = m_page.loadRequestForInspector(WTFMove(request), frame);
+ if (!navigation) {
+ completionHandler("Failed to navigate"_s, 0);
+ return;
+ }
+
+ m_pendingNavigations.set(navigation->navigationID(), WTFMove(completionHandler));
2019-11-19 05:18:28 +03:00
+}
+
+void WebPageInspectorController::didReceivePolicyDecision(WebCore::PolicyAction action, uint64_t navigationID)
2019-11-19 05:18:28 +03:00
+{
+ if (!m_frontendRouter->hasFrontends())
+ return;
+
+ if (!navigationID)
2019-11-19 05:18:28 +03:00
+ 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 +313,33 @@ void WebPageInspectorController::sendMessageToInspectorFrontend(const String& ta
m_targetAgent->sendMessageFromTargetToFrontend(targetId, message);
}
+void WebPageInspectorController::setPauseOnStart(bool shouldPause)
+{
+ ASSERT(m_frontendRouter->hasFrontends());
+ String errorString;
+ m_targetAgent->setPauseOnStart(errorString, 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 +359,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 +412,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 9ce5ef36b652fd56a843c1d12a4c3c3cf639282c..316ca01147d2dd2c53af4d4106bc0302db1326ff 100644
--- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
+++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
@@ -26,17 +26,26 @@
#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>
namespace Inspector {
class BackendDispatcher;
class FrontendChannel;
class FrontendRouter;
+class InspectorTarget;
+}
+
+namespace WebCore {
+class ResourceError;
+class ResourceRequest;
+enum class PolicyAction : uint8_t;
}
namespace WebKit {
@@ -44,6 +53,20 @@ namespace WebKit {
class InspectorBrowserAgent;
struct WebPageAgentContext;
+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;
+
+protected:
+ virtual ~WebPageInspectorControllerObserver() = default;
+};
+
class WebPageInspectorController {
WTF_MAKE_NONCOPYABLE(WebPageInspectorController);
WTF_MAKE_FAST_ALLOCATED;
@@ -51,7 +74,17 @@ public:
WebPageInspectorController(WebPageProxy&);
void init();
+ void didFinishAttachingToWebProcess();
+
+ static void setObserver(WebPageInspectorControllerObserver*);
+
void pageClosed();
+ bool pageCrashed(ProcessTerminationReason);
+
+ void didShowPage();
+
+ void didProcessAllPendingKeyboardEvents();
+ void didProcessAllPendingMouseEvents();
bool hasLocalFrontend() const;
@@ -60,15 +93,28 @@ public:
void disconnectAllFrontends();
void dispatchMessageFromFrontend(const String& message);
+ bool dispatchMessageToTargetBackend(const String&);
#if ENABLE(REMOTE_INSPECTOR)
void setIndicating(bool);
#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 +130,7 @@ private:
void createLazyAgents();
void addTarget(std::unique_ptr<InspectorTargetProxy>&&);
+ void adjustPageSettings();
Ref<Inspector::FrontendRouter> m_frontendRouter;
Ref<Inspector::BackendDispatcher> m_backendDispatcher;
@@ -92,11 +139,16 @@ private:
WebPageProxy& m_page;
Inspector::InspectorTargetAgent* m_targetAgent;
+ WebPageInspectorEmulationAgent* m_emulationAgent { nullptr };
+ WebPageInspectorInputAgent* m_inputAgent { nullptr };
HashMap<String, std::unique_ptr<InspectorTargetProxy>> m_targets;
InspectorBrowserAgent* m_enabledInspectorBrowserAgent;
bool m_didCreateLazyAgents { false };
+ HashMap<uint64_t, NavigationHandler> m_pendingNavigations;
+
+ static WebPageInspectorControllerObserver* s_observer;
};
} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/gtk/WebInspectorProxyGtk.cpp b/Source/WebKit/UIProcess/Inspector/gtk/WebInspectorProxyGtk.cpp
index 8ad92ed84c0a838a61e40626c4c209d2c693f1ea..78fca74948915d8e320065a5eb11e3578c1ac71c 100644
--- a/Source/WebKit/UIProcess/Inspector/gtk/WebInspectorProxyGtk.cpp
+++ b/Source/WebKit/UIProcess/Inspector/gtk/WebInspectorProxyGtk.cpp
@@ -332,7 +332,7 @@ bool WebInspectorProxy::platformIsFront()
return false;
}
-void WebInspectorProxy::platformSetForcedAppearance(InspectorFrontendClient::Appearance)
+void WebInspectorProxy::platformSetForcedAppearance(WebCore::InspectorFrontendClient::Appearance)
{
notImplemented();
}
diff --git a/Source/WebKit/UIProcess/InspectorDialogAgent.cpp b/Source/WebKit/UIProcess/InspectorDialogAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ca5965f9d682c0821a40f0d1d43e5cbeda1353a5
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorDialogAgent.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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()
+{
+ Inspector::ErrorString err;
+ disable(err);
+}
+
+void InspectorDialogAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
+{
+}
+
+void InspectorDialogAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
+{
+}
+
+void InspectorDialogAgent::enable(Inspector::ErrorString& errorString)
+{
+ if (m_page.inspectorDialogAgent()) {
+ errorString = "Dialog domain is already enabled."_s;
+ return;
+ }
+ m_page.setInspectorDialogAgent(this);
+}
+
+void InspectorDialogAgent::disable(Inspector::ErrorString&)
+{
+ if (m_page.inspectorDialogAgent() != this)
+ return;
+ m_page.setInspectorDialogAgent(nullptr);
+}
+
+void InspectorDialogAgent::handleJavaScriptDialog(Inspector::ErrorString& errorString, bool accept, const String* value)
+{
+ m_page.uiClient().handleJavaScriptDialog(m_page, accept, value ? *value : String());
+}
+
+void InspectorDialogAgent::javascriptDialogOpening(const String& type, const String& message, const String* defaultValue) {
+ m_frontendDispatcher->javascriptDialogOpening(type, message, defaultValue);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/InspectorDialogAgent.h b/Source/WebKit/UIProcess/InspectorDialogAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..f356c613945fd263889bc74166bef2b279ab4ca1
--- /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 {
2019-11-19 05:18:28 +03:00
+
+class NativeWebKeyboardEvent;
+class WebPageProxy;
+
+class InspectorDialogAgent : public Inspector::InspectorAgentBase, public Inspector::DialogBackendDispatcherHandler {
+ WTF_MAKE_NONCOPYABLE(InspectorDialogAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorDialogAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page);
+ ~InspectorDialogAgent() override;
+
+ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+ void enable(Inspector::ErrorString&) override;
+ void disable(Inspector::ErrorString&) override;
+ void handleJavaScriptDialog(Inspector::ErrorString& errorString, bool accept, const String* promptText) override;
2019-11-19 05:18:28 +03:00
+
+ void javascriptDialogOpening(const String& type, const String& message, const String* defaultValue = nullptr);
+
+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
2019-11-19 05:18:28 +03:00
new file mode 100644
index 0000000000000000000000000000000000000000..8133961d81a81bb82ed05e0d2c82150a61d410e3
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp
@@ -0,0 +1,601 @@
+/*
+ * 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "InspectorPlaywrightAgent.h"
2019-11-19 05:18:28 +03:00
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "APIPageConfiguration.h"
+#include "InspectorPlaywrightAgentClient.h"
+#include "InspectorTargetProxy.h"
+#include "NetworkProcessMessages.h"
+#include "NetworkProcessProxy.h"
+#include "WebGeolocationManagerProxy.h"
+#include "WebGeolocationPosition.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/ProcessIdentifier.h>
+#include <WebCore/ResourceRequest.h>
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <pal/SessionID.h>
+#include <stdlib.h>
+#include <wtf/HashMap.h>
+#include <wtf/HexNumber.h>
2019-11-19 05:18:28 +03:00
+
+
+using namespace Inspector;
2019-11-19 05:18:28 +03:00
+
+namespace WebKit {
+
+namespace {
+
+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();
+}
2019-11-19 05:18:28 +03:00
+
+Ref<Inspector::Protocol::Playwright::PageProxyInfo> buildPageProxyInfo(const WebPageProxy& page) {
+ auto result = Inspector::Protocol::Playwright::PageProxyInfo::create()
+ .setPageProxyId(InspectorPlaywrightAgent::toPageProxyIDProtocolString(page))
+ .setBrowserContextId(InspectorPlaywrightAgent::toBrowserContextIDProtocolString(page.sessionID()))
+ .release();
+ auto* opener = page.configuration().relatedPage();
+ if (opener)
+ result->setOpenerId(InspectorPlaywrightAgent::toPageProxyIDProtocolString(*opener));
+ return result;
+}
+
+} // namespace
+
+Vector<WebPageProxy*> BrowserContext::pages() const {
+ Vector<WebPageProxy*> pages;
+ for (auto& process : processPool->processes()) {
+ for (auto* page : process->pages())
+ pages.append(page);
+ }
+ return pages;
+}
+
+class InspectorPlaywrightAgent::BrowserContextDeletion {
+ WTF_MAKE_NONCOPYABLE(BrowserContextDeletion);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ BrowserContextDeletion(const BrowserContext& context, size_t numberOfPages, Ref<DeleteContextCallback>&& callback)
+ : m_browserContext(context)
+ , m_numberOfPages(numberOfPages)
+ , m_callback(WTFMove(callback)) { }
+
+ void willDestroyPage(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) {
+ Vector<WebPageProxy*> 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; }
+
+private:
+ BrowserContext m_browserContext;
+ size_t m_numberOfPages;
+ Ref<DeleteContextCallback> m_callback;
+};
+
+
+InspectorPlaywrightAgent::InspectorPlaywrightAgent(Inspector::FrontendRouter& frontendRouter, Inspector::BackendDispatcher& backendDispatcher, InspectorPlaywrightAgentClient* client, PageProxyIDMap& pageProxyIDMap)
+ : InspectorAgentBase("Playwright"_s)
+ , m_frontendDispatcher(makeUnique<PlaywrightFrontendDispatcher>(frontendRouter))
+ , m_backendDispatcher(PlaywrightBackendDispatcher::create(backendDispatcher, this))
+ , m_client(client)
+ , m_pageProxyIDMap(pageProxyIDMap)
+{
+}
+
+InspectorPlaywrightAgent::~InspectorPlaywrightAgent() = default;
+
+void InspectorPlaywrightAgent::didCreateWebPageProxy(const WebPageProxy& page)
+{
+ if (m_isConnected)
+ m_frontendDispatcher->pageProxyCreated(buildPageProxyInfo(page));
+}
+
+void InspectorPlaywrightAgent::willDestroyWebPageProxy(const WebPageProxy& page)
+{
+ if (!m_isConnected)
+ return;
+
+ m_frontendDispatcher->pageProxyDestroyed(toPageProxyIDProtocolString(page));
+
+ auto it = m_browserContextDeletions.find(page.sessionID());
+ if (it == m_browserContextDeletions.end())
+ return;
+
+ it->value->willDestroyPage(page);
+ if (it->value->isFinished())
+ m_browserContextDeletions.remove(it);
+}
+
+void InspectorPlaywrightAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
+{
+ m_isConnected = true;
+ for (auto& pool : WebProcessPool::allProcessPools()) {
+ auto* dataStore = pool->websiteDataStore();
+ if (dataStore)
+ dataStore->setDownloadInstrumentation(this);
+ }
+}
+
+void InspectorPlaywrightAgent::didFailProvisionalLoad(WebPageProxy& page, uint64_t navigationID, const String& error)
+{
+ if (!m_isConnected)
+ return;
+
+ m_frontendDispatcher->provisionalLoadFailed(toPageProxyIDProtocolString(page), String::number(navigationID), error);
+}
+
+void InspectorPlaywrightAgent::willDestroyFrontendAndBackend(DisconnectReason)
+{
+ m_isConnected = false;
+ for (auto& pool : WebProcessPool::allProcessPools()) {
+ auto* dataStore = pool->websiteDataStore();
+ if (dataStore) {
+ dataStore->setDownloadInstrumentation(nullptr);
+ dataStore->setDownloadForAutomation(Optional<bool>(), String());
+ }
+ }
+ for (auto& it : m_browserContexts)
+ it.value.dataStore->setDownloadInstrumentation(nullptr);
+ m_browserContextDeletions.clear();
+}
+
+void InspectorPlaywrightAgent::close(Ref<CloseCallback>&& callback)
+{
+ Vector<WebPageProxy*> pages;
+ for (auto& pool : WebProcessPool::allProcessPools()) {
+ for (auto& process : pool->processes()) {
+ for (auto* page : process->pages())
+ pages.append(page);
+ }
+ }
+ for (auto* page : pages)
+ page->closePage();
+
+ if (!WebProcessPool::allProcessPools().size()) {
+ m_client->closeBrowser();
+ callback->sendSuccess();
+ return;
+ }
+
+ WebProcessPool::allProcessPools().first()->syncLocalStorage([this, callback = WTFMove(callback)] () {
+ if (!callback->isActive())
+ return;
+
+ m_browserContexts.clear();
+ if (m_client == nullptr) {
+ callback->sendFailure("no platform delegate to close browser");
+ } else {
+ m_client->closeBrowser();
+ callback->sendSuccess();
+ }
+ });
+
+}
+
+void InspectorPlaywrightAgent::createContext(ErrorString& errorString, String* browserContextID)
+{
+ BrowserContext browserContext = m_client->createBrowserContext(errorString);
+ if (!errorString.isEmpty())
+ return;
+ browserContext.processPool->setPrimaryDataStore(*browserContext.dataStore);
+ browserContext.processPool->ensureNetworkProcess(browserContext.dataStore.get());
+ browserContext.dataStore->setDownloadInstrumentation(this);
+
+ PAL::SessionID sessionID = browserContext.dataStore->sessionID();
+ *browserContextID = toBrowserContextIDProtocolString(sessionID);
+ m_browserContexts.set(*browserContextID, browserContext);
+}
+
+void InspectorPlaywrightAgent::deleteContext(const String& browserContextID, Ref<DeleteContextCallback>&& callback)
+{
+ String errorString;
+ BrowserContext browserContext = lookupBrowserContext(errorString, &browserContextID);
+ if (!errorString.isEmpty()) {
+ callback->sendFailure(errorString);
+ return;
+ }
+
+ Vector<WebPageProxy*> pages = browserContext.pages();
+ PAL::SessionID sessionID = browserContext.dataStore->sessionID();
+ m_browserContexts.remove(browserContextID);
+ if (pages.isEmpty()) {
+ callback->sendSuccess();
+ } else {
+ m_browserContextDeletions.set(sessionID, makeUnique<BrowserContextDeletion>(browserContext, pages.size(), WTFMove(callback)));
+ for (auto* page : pages)
+ page->closePage();
+ }
+ m_client->deleteBrowserContext(errorString, sessionID);
+}
+
+void InspectorPlaywrightAgent::createPage(ErrorString& errorString, const String* browserContextID, String* pageProxyID)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return;
+ RefPtr<WebPageProxy> page = m_client->createPage(errorString, browserContext);
+ if (!page)
+ return;
+ *pageProxyID = 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)
+{
+ WebPageProxy* page = m_pageProxyIDMap.findPageProxy(pageProxyID);
+ if (!page) {
+ 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() != page) {
+ callback->sendFailure("Frame with specified is not from the specified page"_s);
+ return;
+ }
+ }
+
+ page->inspectorController().navigate(WTFMove(resourceRequest), frame, [callback = WTFMove(callback)](const String& error, uint64_t navigationID) {
+ if (!error.isEmpty()) {
+ callback->sendFailure(error);
+ return;
+ }
+
+ Optional<String> navigationIDString;
+ if (navigationID)
+ navigationIDString = String::number(navigationID);
+ callback->sendSuccess(navigationIDString);
+ });
+}
+
+void InspectorPlaywrightAgent::setIgnoreCertificateErrors(Inspector::ErrorString& errorString, const String* browserContextID, bool ignore)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return;
+
+ PAL::SessionID sessionID = browserContext.dataStore->sessionID();
+ NetworkProcessProxy* networkProcess = browserContext.processPool->networkProcess();
+ networkProcess->send(Messages::NetworkProcess::SetIgnoreCertificateErrors(sessionID, ignore), 0);
+}
+
+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.processPool->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, const JSON::Array& in_cookies, Ref<SetCookiesCallback>&& callback) {
+ String errorString;
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty()) {
+ callback->sendFailure(errorString);
+ return;
+ }
+
+ NetworkProcessProxy* networkProcess = browserContext.processPool->networkProcess();
+ PAL::SessionID sessionID = browserContext.dataStore->sessionID();
+
+ Vector<WebCore::Cookie> cookies;
+ for (unsigned i = 0; i < in_cookies.length(); ++i) {
+ RefPtr<JSON::Value> item = in_cookies.get(i);
+ RefPtr<JSON::Object> obj;
+ if (!item->asObject(obj)) {
+ errorString = "Invalid cookie payload format"_s;
+ return;
+ }
+
+ WebCore::Cookie cookie;
+ if (!obj->getString("name", cookie.name) ||
+ !obj->getString("value", cookie.value) ||
+ !obj->getString("domain", cookie.domain) ||
+ !obj->getString("path", cookie.path)) {
+ errorString = "Invalid file payload format"_s;
+ return;
+ }
+
+ double expires;
+ if (obj->getDouble("expires", expires) && expires != -1)
+ cookie.expires = expires;
+ obj->getBoolean("httpOnly", cookie.httpOnly);
+ obj->getBoolean("secure", cookie.secure);
+ obj->getBoolean("session", cookie.session);
+ String sameSite;
+ if (obj->getString("sameSite", sameSite)) {
+ if (sameSite == "None")
+ cookie.sameSite = WebCore::Cookie::SameSitePolicy::None;
+ if (sameSite == "Lax")
+ cookie.sameSite = WebCore::Cookie::SameSitePolicy::Lax;
+ if (sameSite == "Strict")
+ cookie.sameSite = WebCore::Cookie::SameSitePolicy::Strict;
+ }
+ cookies.append(WTFMove(cookie));
+ }
+
+ networkProcess->sendWithAsyncReply(Messages::NetworkProcess::SetCookies(sessionID, WTFMove(cookies)),
+ [callback = WTFMove(callback)](bool success) {
+ if (!callback->isActive())
+ return;
+
+ if (success)
+ callback->sendSuccess();
+ else
+ callback->sendFailure("Internal error: no network storage"_s);
+ callback->sendSuccess();
+ }, 0);
+}
+
+void 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.processPool->networkProcess();
+ PAL::SessionID sessionID = browserContext.dataStore->sessionID();
+ networkProcess->sendWithAsyncReply(Messages::NetworkProcess::DeleteAllCookies(sessionID),
+ [callback = WTFMove(callback)](bool success) {
+ if (!callback->isActive())
+ return;
+ if (success)
+ callback->sendSuccess();
+ else
+ callback->sendFailure("Internal error: no network storage"_s);
+ }, 0);
+}
+
+void InspectorPlaywrightAgent::setLanguages(Inspector::ErrorString& errorString, const JSON::Array& languages, const String* browserContextID)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return;
+
+ Vector<String> items;
+ for (const auto& value : languages) {
+ String language;
+ if (!value->asString(language)) {
+ errorString = "Language must be a string"_s;
+ return;
+ }
+ items.append(language);
+ }
+
+ browserContext.dataStore->setLanguagesForAutomation(WTFMove(items));
+}
+
+void InspectorPlaywrightAgent::setDownloadBehavior(Inspector::ErrorString& errorString, const String* behavior, const String* downloadPath, const String* browserContextID)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return;
+ Optional<bool> allow;
+ if (behavior && *behavior == "allow"_s)
+ allow = true;
+ if (behavior && *behavior == "deny"_s)
+ allow = false;
+ browserContext.dataStore->setDownloadForAutomation(allow, downloadPath ? *downloadPath : String());
+}
+
+void InspectorPlaywrightAgent::setGeolocationOverride(Inspector::ErrorString& errorString, const String* browserContextID, const JSON::Object* geolocation)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return;
+ auto* geoManager = browserContext.processPool->supplement<WebGeolocationManagerProxy>();
+ if (!geoManager) {
+ errorString = "Internal error: geolocation manager is not available."_s;
+ return;
+ }
+ if (geolocation) {
+ double timestamp = 0;
+ double latitude = 0;
+ double longitude = 0;
+ double accuracy = 0;
+ if (!geolocation->getDouble("timestamp"_s, timestamp) ||
+ !geolocation->getDouble("latitude"_s, latitude) ||
+ !geolocation->getDouble("longitude"_s, longitude) ||
+ !geolocation->getDouble("accuracy"_s, accuracy)) {
+ errorString = "Invalid geolocation format"_s;
+ return;
+ }
+ auto position = WebGeolocationPosition::create(WebCore::GeolocationPositionData(timestamp, latitude, longitude, accuracy));
+ geoManager->providerDidChangePosition(&position.get());
+ } else {
+ geoManager->providerDidFailToDeterminePosition("Position unavailable"_s);
+ }
+}
+
+void InspectorPlaywrightAgent::downloadCreated(const String& uuid, const WebCore::ResourceRequest& request, WebPageProxy* page)
+{
+ if (!m_isConnected)
+ return;
+ m_frontendDispatcher->downloadCreated(uuid, request.url().string(),
+ InspectorPlaywrightAgent::toPageProxyIDProtocolString(*page),
+ InspectorPlaywrightAgent::toBrowserContextIDProtocolString(page->sessionID()));
+}
+
+void InspectorPlaywrightAgent::downloadFinished(const String& uuid, const String& error)
+{
+ if (!m_isConnected)
+ return;
+ m_frontendDispatcher->downloadFinished(uuid, error);
+}
+
+String InspectorPlaywrightAgent::toBrowserContextIDProtocolString(const PAL::SessionID& sessionID)
+{
+ StringBuilder builder;
+ builder.append(hex(sessionID.toUInt64(), 16));
+ return builder.toString();
+}
+
+String InspectorPlaywrightAgent::toPageProxyIDProtocolString(const WebPageProxy& page)
+{
+ return makeString(page.identifier().toUInt64());
+}
+
+BrowserContext InspectorPlaywrightAgent::lookupBrowserContext(ErrorString& errorString, const String* browserContextID)
+{
+ if (!browserContextID) {
+ BrowserContext context;
+ if (!WebProcessPool::allProcessPools().size()) {
+ errorString = "Browser started with no default context"_s;
+ return context;
+ }
+ auto* pool = WebProcessPool::allProcessPools().first();
+ context.processPool = pool;
+ context.dataStore = pool->websiteDataStore();
+ return context;
+ }
+
+ BrowserContext browserContext = m_browserContexts.get(*browserContextID);
+ if (!browserContext.processPool)
+ errorString = "Could not find browser context for given id"_s;
+ return browserContext;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..f42806c4bd0e3d844aa7636ae198d59de6fc96db
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h
@@ -0,0 +1,121 @@
+/*
+ * 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/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+#include "WebProcessPool.h"
+#include <wtf/HashMap.h>
+#include <pal/SessionID.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/URL.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+class PlaywrightFrontendDispatcher;
+}
+
+namespace PAL {
+class SessionID;
+}
+
+namespace WebKit {
+
+class NetworkProcess;
+class WebFrameProxy;
+
+class PageProxyIDMap {
+public:
+ virtual WebPageProxy* findPageProxy(const String& pageProxyID) = 0;
+
+protected:
+ virtual ~PageProxyIDMap() = default;
+};
+
+class InspectorPlaywrightAgent final
+ : public Inspector::InspectorAgentBase
+ , public Inspector::PlaywrightBackendDispatcherHandler
+ , public DownloadInstrumentation {
+ WTF_MAKE_NONCOPYABLE(InspectorPlaywrightAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorPlaywrightAgent(Inspector::FrontendRouter&, Inspector::BackendDispatcher&, InspectorPlaywrightAgentClient*, PageProxyIDMap&);
+ ~InspectorPlaywrightAgent() override;
+
+ void didCreateWebPageProxy(const WebPageProxy&);
+ void willDestroyWebPageProxy(const WebPageProxy&);
+ void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error);
+
+ // InspectorAgentBase
+ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+ // PlaywrightDispatcherHandler
+ void close(Ref<CloseCallback>&&) override;
+ void createContext(Inspector::ErrorString&, String* browserContextID) override;
+ void deleteContext(const String& browserContextID, Ref<DeleteContextCallback>&& callback) override;
+ void createPage(Inspector::ErrorString&, const String* browserContextID, String* pageProxyID) override;
+ void navigate(const String& url, const String& pageProxyID, const String* frameId, const String* referrer, Ref<NavigateCallback>&&) override;
+ void setIgnoreCertificateErrors(Inspector::ErrorString&, const String* browserContextID, bool ignore) override;
+
+ void getAllCookies(const String* browserContextID, Ref<GetAllCookiesCallback>&&) override;
+ void setCookies(const String* browserContextID, const JSON::Array& in_cookies, Ref<SetCookiesCallback>&&) override;
+ void deleteAllCookies(const String* browserContextID, Ref<DeleteAllCookiesCallback>&&) override;
+
+ void setGeolocationOverride(Inspector::ErrorString&, const String* browserContextID, const JSON::Object* geolocation) override;
+ void setLanguages(Inspector::ErrorString&, const JSON::Array& languages, const String* browserContextID) override;
+ void setDownloadBehavior(Inspector::ErrorString&, const String* behavior, const String* downloadPath, const String* browserContextID) override;
+
+ static String toBrowserContextIDProtocolString(const PAL::SessionID&);
+ static String toPageProxyIDProtocolString(const WebPageProxy&);
+
+ // DownloadInstrumentation
+ void downloadCreated(const String& uuid, const WebCore::ResourceRequest&, WebPageProxy* page) override;
+ void downloadFinished(const String& uuid, const String& error) override;
+
+private:
+ class BrowserContextDeletion;
+ BrowserContext lookupBrowserContext(Inspector::ErrorString&, const String* browserContextID);
+ WebFrameProxy* frameForID(const String& frameID, String& error);
+
+ std::unique_ptr<Inspector::PlaywrightFrontendDispatcher> m_frontendDispatcher;
+ Ref<Inspector::PlaywrightBackendDispatcher> m_backendDispatcher;
+ InspectorPlaywrightAgentClient* m_client;
+ PageProxyIDMap& m_pageProxyIDMap;
+ HashMap<String, BrowserContext> m_browserContexts;
+ HashMap<PAL::SessionID, std::unique_ptr<BrowserContextDeletion>> m_browserContextDeletions;
+ bool m_isConnected { false };
+};
+
+} // namespace WebKit
2019-11-19 05:18:28 +03:00
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h b/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h
2019-11-19 05:18:28 +03:00
new file mode 100644
index 0000000000000000000000000000000000000000..d2f02082007b41b9e20dc6bb4751743835d60fce
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#pragma once
2019-11-19 05:18:28 +03:00
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include <pal/SessionID.h>
+#include <wtf/Forward.h>
+
2019-11-19 05:18:28 +03:00
+namespace WebKit {
+
+class WebsiteDataStore;
+class WebPageProxy;
+class WebProcessPool;
+
+struct BrowserContext {
+ Vector<WebPageProxy*> pages() const;
+ RefPtr<WebsiteDataStore> dataStore;
+ RefPtr<WebProcessPool> processPool;
+};
+
+class InspectorPlaywrightAgentClient {
+public:
+ virtual ~InspectorPlaywrightAgentClient() = default;
+ virtual RefPtr<WebKit::WebPageProxy> createPage(WTF::String& error, const BrowserContext& context) = 0;
+ virtual void closeBrowser() = 0;
+ virtual BrowserContext createBrowserContext(WTF::String& error) = 0;
+ virtual void deleteBrowserContext(WTF::String& error, PAL::SessionID) = 0;
+};
+
+} // namespace WebKit
2019-11-19 05:18:28 +03:00
+
+#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/RemoteInspectorPipe.cpp b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..45d8dc48601548951dc5c5ecd68958dbd47c89db
--- /dev/null
+++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "RemoteInspectorPipe.h"
2019-11-19 05:18:28 +03:00
+
+#if ENABLE(REMOTE_INSPECTOR)
2019-11-19 05:18:28 +03:00
+
+#include "BrowserInspectorController.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)
2019-11-19 05:18:28 +03:00
+{
+ 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;
2019-11-19 05:18:28 +03:00
+}
+
+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(BrowserInspectorController& browserInspectorController)
+ : m_remoteFrontendChannel(makeUnique<RemoteFrontendChannel>())
+ , m_browserInspectorController(browserInspectorController)
+{
+ start();
+}
+
+RemoteInspectorPipe::~RemoteInspectorPipe()
+{
+ stop();
+}
+
+bool RemoteInspectorPipe::start()
+{
+ WTF::RunLoop::initializeMainRunLoop();
+ if (m_receiverThread)
+ return true;
+
+#if PLATFORM(WIN)
+ readHandle = reinterpret_cast<HANDLE>(_get_osfhandle(readFD));
+ writeHandle = reinterpret_cast<HANDLE>(_get_osfhandle(writeFD));
+#endif
+
+ m_browserInspectorController.connectFrontend(*m_remoteFrontendChannel);
+ m_terminated = false;
+ m_receiverThread = Thread::create("Inspector pipe reader", [this] {
+ workerRun();
+ });
+ return true;
+}
+
+void RemoteInspectorPipe::stop()
+{
+ if (!m_receiverThread)
+ return;
+
+ m_browserInspectorController.disconnectFrontend();
+
+ m_terminated = true;
+ m_receiverThread->waitForCompletion();
+ m_receiverThread = nullptr;
+}
+
+void RemoteInspectorPipe::workerRun()
+{
+ const size_t bufSize = 256 * 1024;
+ auto buffer = makeUniqueArray<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_browserInspectorController.dispatchMessageFromFrontend(message);
+ });
+ }
+ ++end;
+ start = end;
+ }
+ if (start != 0 && start < line.size())
+ memmove(line.data(), line.data() + start, line.size() - start);
+ line.shrink(line.size() - start);
+ }
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.h b/Source/WebKit/UIProcess/RemoteInspectorPipe.h
new file mode 100644
index 0000000000000000000000000000000000000000..b1307da8b9ee02d63ef98d276473d65a1d8c3556
--- /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 {
2019-11-19 05:18:28 +03:00
+
+class BrowserInspectorController;
2019-11-19 05:18:28 +03:00
+
+class RemoteInspectorPipe {
+ WTF_MAKE_NONCOPYABLE(RemoteInspectorPipe);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ explicit RemoteInspectorPipe(BrowserInspectorController&);
+ ~RemoteInspectorPipe();
+
+private:
+ class RemoteFrontendChannel;
+
+ bool start();
+ void stop();
+
+ void workerRun();
+
+ RefPtr<Thread> m_receiverThread;
+ std::atomic<bool> m_terminated { false };
+ std::unique_ptr<Inspector::FrontendChannel> m_remoteFrontendChannel;
+ BrowserInspectorController& m_browserInspectorController;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp b/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
index 407402b237d4489176b369f4114adb478adb230c..5ab5c90f0faabb14837ccc7a4eb6d635c862c1ea 100644
--- a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
+++ b/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
@@ -35,6 +35,7 @@
#include "NfcService.h"
#include "WebPageProxy.h"
#include "WebPreferencesKeys.h"
+#include "WebProcessProxy.h"
#include <WebCore/AuthenticatorAssertionResponse.h>
#include <WebCore/AuthenticatorTransport.h>
#include <WebCore/PublicKeyCredentialCreationOptions.h>
2020-03-11 20:56:20 +03:00
diff --git a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h b/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h
index 047c632a86287c1c0b58c488c524eac29bec3614..f301edcd4fbf6ca41781fac99104dc97c13a619a 100644
2020-03-11 20:56:20 +03:00
--- 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/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);
}
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3983c25682b06bbbf9ae9fde95b5b9c349ae6abe
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "WebPageInspectorEmulationAgent.h"
+
+#include "APIPageConfiguration.h"
2019-11-19 05:18:28 +03:00
+#include "WebPageProxy.h"
+#include "WebPreferences.h"
+#include "PageClient.h"
2019-11-19 05:18:28 +03:00
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <WebCore/Credential.h>
2019-11-19 05:18:28 +03:00
+
+
+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();
2019-11-19 05:18:28 +03:00
+}
+
2020-01-03 09:38:17 +03:00
+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);
2020-01-03 09:38:17 +03:00
+ 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);
+ });
2019-11-19 05:18:28 +03:00
+}
+
+void WebPageInspectorEmulationAgent::setJavaScriptEnabled(ErrorString&, bool enabled)
+{
+ auto copy = m_page.preferences().copy();
+ copy->setJavaScriptEnabled(enabled);
+ m_page.setPreferences(copy);
+}
+
+void WebPageInspectorEmulationAgent::setAuthCredentials(Inspector::ErrorString&, const String* username, const String* password)
+{
+ if (username && password)
+ m_page.setAuthCredentialsForAutomation(WebCore::Credential(*username, *password, CredentialPersistencePermanent));
+ else
+ m_page.setAuthCredentialsForAutomation(Optional<WebCore::Credential>());
+}
+
+void WebPageInspectorEmulationAgent::setActiveAndFocused(Inspector::ErrorString&, const bool* active)
+{
+ Optional<bool> value;
+ if (active)
+ value = *active;
+ m_page.setActiveForAutomation(value);
+}
+
+void WebPageInspectorEmulationAgent::grantPermissions(Inspector::ErrorString& errorString, const String& origin, const JSON::Array& values)
+{
+ HashSet<String> set;
+ for (const auto& value : values) {
+ String name;
+ if (!value->asString(name)) {
+ errorString = "Permission must be a string"_s;
+ return;
+ }
+ set.add(name);
+ }
+ m_permissions.set(origin, WTFMove(set));
+ m_page.setPermissionsForAutomation(m_permissions);
+}
+
+void WebPageInspectorEmulationAgent::resetPermissions(Inspector::ErrorString&)
+{
+ m_permissions.clear();
+ m_page.setPermissionsForAutomation(m_permissions);
+}
+
+void WebPageInspectorEmulationAgent::didShowPage()
+{
+ for (auto& command : m_commandsToRunWhenShown)
+ command();
+ m_commandsToRunWhenShown.clear();
+}
+
2019-11-19 05:18:28 +03:00
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ae0ce152f06b8316dbfbbbb2efd1990a31687d0
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#pragma once
+
+#include <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+
+#include <wtf/Forward.h>
+#include <wtf/Function.h>
2019-11-19 05:18:28 +03:00
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
2019-11-19 05:18:28 +03:00
+
+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;
+
2020-01-03 09:38:17 +03:00
+ void setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref<SetDeviceMetricsOverrideCallback>&&) override;
+ void setJavaScriptEnabled(Inspector::ErrorString&, bool enabled) override;
+ void setAuthCredentials(Inspector::ErrorString&, const String*, const String*) override;
+ void setActiveAndFocused(Inspector::ErrorString&, const bool*) override;
+ void grantPermissions(Inspector::ErrorString&, const String& origin, const JSON::Array& permissions) override;
+ void resetPermissions(Inspector::ErrorString&) override;
2019-11-19 05:18:28 +03:00
+
+ void didShowPage();
+
2019-11-19 05:18:28 +03:00
+private:
+ void setSize(int width, int height, Ref<SetDeviceMetricsOverrideCallback>&& callback);
+ void platformSetSize(int width, int height, Function<void (const String& error)>&&);
2019-11-19 05:18:28 +03:00
+
+ Ref<Inspector::EmulationBackendDispatcher> m_backendDispatcher;
+ WebPageProxy& m_page;
+ Vector<Function<void()>> m_commandsToRunWhenShown;
+ HashMap<String, HashSet<String>> m_permissions;
2019-11-19 05:18:28 +03:00
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5043224bbd6378175c9ca7dce63fc5a233649878
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp
@@ -0,0 +1,253 @@
+/*
+ * 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "WebPageInspectorInputAgent.h"
+
+#include "NativeWebKeyboardEvent.h"
+#include "NativeWebMouseEvent.h"
+#include "WebPageProxy.h"
+#include <wtf/MathExtras.h>
2019-11-19 05:18:28 +03:00
+
+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> {
+};
2019-11-19 05:18:28 +03:00
+
+class WebPageInspectorInputAgent::MouseCallbacks : public CallbackList<Inspector::InputBackendDispatcherHandler::DispatchMouseEventCallback> {
2019-11-19 05:18:28 +03:00
+};
+
+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()
2019-11-19 05:18:28 +03:00
+{
+ m_mouseCallbacks->sendSuccess();
2019-11-19 05:18:28 +03:00
+}
+
+void WebPageInspectorInputAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
+{
+ m_keyboardCallbacks = makeUnique<KeyboardCallbacks>();
+ m_mouseCallbacks = makeUnique<MouseCallbacks>();
2019-11-19 05:18:28 +03:00
+}
+
+void WebPageInspectorInputAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
+{
+ m_keyboardCallbacks = nullptr;
+ m_mouseCallbacks = nullptr;
2019-11-19 05:18:28 +03:00
+}
+
+void WebPageInspectorInputAgent::dispatchKeyEvent(const String& type, const int* modifiers, const String* text, const String* unmodifiedText, const String* code, const String* key, const int* windowsVirtualKeyCode, const int* nativeVirtualKeyCode, const bool* autoRepeat, const bool* isKeypad, const bool* isSystemKey, const JSON::Array* commands, Ref<Inspector::InputBackendDispatcherHandler::DispatchKeyEventCallback>&& callback)
2019-11-19 05:18:28 +03:00
+{
+ WebKit::WebEvent::Type eventType;
+ if (type == "keyDown") {
+ eventType = WebKit::WebEvent::KeyDown;
+ } else if (type == "keyUp") {
+ eventType = WebKit::WebEvent::KeyUp;
2019-11-19 05:18:28 +03:00
+ } else {
+ callback->sendFailure("Unsupported event type.");
+ return;
+ }
+ OptionSet<WebEvent::Modifier> eventModifiers;
+ if (modifiers)
+ eventModifiers = eventModifiers.fromRaw(*modifiers);
+ String eventText;
+ if (text)
+ eventText = *text;
+ String eventUnmodifiedText;
+ if (unmodifiedText)
+ eventUnmodifiedText = *unmodifiedText;
+ String eventCode;
+ if (code)
+ eventCode = *code;
+ String eventKey;
+ if (key)
+ eventKey = *key;
+ 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);
+ }
+ }
+
+ bool eventIsAutoRepeat = false;
+ if (autoRepeat)
+ eventIsAutoRepeat = *autoRepeat;
+ bool eventIsKeypad = false;
+ if (isKeypad)
+ eventIsKeypad = *isKeypad;
+ bool eventIsSystemKey = false;
+ if (isSystemKey)
+ eventIsSystemKey = *isSystemKey;
2019-11-19 05:18:28 +03:00
+ WallTime timestamp = WallTime::now();
+
+ m_keyboardCallbacks->append(WTFMove(callback));
2019-11-19 05:18:28 +03:00
+ platformDispatchKeyEvent(
+ eventType,
+ eventText,
+ eventUnmodifiedText,
+ eventKey,
+ eventCode,
+ eventWindowsVirtualKeyCode,
+ eventNativeVirtualKeyCode,
+ eventIsAutoRepeat,
+ eventIsKeypad,
+ eventIsSystemKey,
+ eventModifiers,
+ eventCommands,
2019-11-19 05:18:28 +03:00
+ timestamp);
+}
+
+void WebPageInspectorInputAgent::dispatchMouseEvent(const String& type, int x, int y, const int* modifiers, const String* button, const int* buttons, const int* clickCount, const int* deltaX, const int* deltaY, Ref<DispatchMouseEventCallback>&& callback)
2019-11-19 05:18:28 +03:00
+{
+ 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;
2019-11-19 05:18:28 +03:00
+ 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;
2019-11-19 05:18:28 +03:00
+ else {
+ callback->sendFailure("Unsupported eventButton");
2019-11-19 05:18:28 +03:00
+ 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, modifiers, button, clickCount);
+#elif PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)
+ WallTime timestamp = WallTime::now();
2019-11-19 05:18:28 +03:00
+ NativeWebMouseEvent event(
+ eventType,
+ eventButton,
+ eventButtons,
+ {x, y},
2019-11-19 05:18:28 +03:00
+ WebCore::IntPoint(),
+ eventDeltaX,
+ eventDeltaY,
2019-11-19 05:18:28 +03:00
+ 0,
+ eventClickCount,
+ eventModifiers,
2019-11-19 05:18:28 +03:00
+ timestamp);
+ m_page.handleMouseEvent(event);
+#endif
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..76290475097e756e3d932d22be4d8c797be4aa0c
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#pragma once
+
+#include "WebEvent.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();
+
2019-11-19 05:18:28 +03:00
+ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+ // Protocol handler
+ void dispatchKeyEvent(const String& type, const int* modifiers, const String* text, const String* unmodifiedText, const String* code, const String* key, const int* windowsVirtualKeyCode, const int* nativeVirtualKeyCode, const bool* autoRepeat, const bool* isKeypad, const bool* isSystemKey, const JSON::Array*, Ref<DispatchKeyEventCallback>&& callback) override;
+ void dispatchMouseEvent(const String& type, int x, int y, const int* modifiers, const String* button, const int* buttons, const int* clickCount, const int* deltaX, const int* deltaY, Ref<DispatchMouseEventCallback>&& callback) override;
2019-11-19 05:18:28 +03:00
+
+private:
+ void platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& commands, WallTime timestamp);
2019-11-19 05:18:28 +03:00
+#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, const int* modifier, const String* button, const int* clickCount);
+#endif
2019-11-19 05:18:28 +03:00
+
+ 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;
2019-11-19 05:18:28 +03:00
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp
index d1bb07e76d278580bab729373f885e9c8b865d1e..f0e05ed34906f6413113b1e8194508a9676622fb 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp
@@ -938,6 +938,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason)
2019-11-19 05:18:28 +03:00
m_pageLoadState.didSwapWebProcesses();
if (reason != ProcessLaunchReason::InitialProcess)
m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
+ m_inspectorController->didFinishAttachingToWebProcess();
}
void WebPageProxy::didAttachToRunningProcess()
@@ -1280,6 +1281,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)
@@ -1735,6 +1751,31 @@ void WebPageProxy::setControlledByAutomation(bool controlled)
2019-11-19 05:18:28 +03:00
m_process->processPool().sendToNetworkingProcess(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation));
}
+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());
+}
2019-11-19 05:18:28 +03:00
+
void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
{
MESSAGE_CHECK(m_process, !targetId.isEmpty());
@@ -1877,6 +1918,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())
@@ -2836,7 +2896,7 @@ static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2019-12-24 00:12:56 +03:00
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();
@@ -2869,7 +2929,7 @@ void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent
2019-12-24 00:12:56 +03:00
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
@@ -3233,6 +3293,7 @@ void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, A
void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, RefPtr<API::WebsitePolicies>&& websitePolicies, Ref<PolicyDecisionSender>&& sender, WillContinueLoadInNewProcess willContinueLoadInNewProcess)
{
+ m_inspectorController->didReceivePolicyDecision(action, navigation ? navigation->navigationID() : 0);
if (!hasRunningProcess()) {
sender->send(PolicyDecision { sender->identifier(), isNavigatingToAppBoundDomain(), hasNavigatedAwayFromAppBoundDomain(), PolicyAction::Ignore, 0, DownloadID(), WTF::nullopt });
return;
@@ -3922,6 +3983,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;
@@ -4333,6 +4399,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)
@@ -4557,6 +4624,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,
@@ -5527,6 +5603,7 @@ void WebPageProxy::createNewPage(FrameInfoData&& originatingFrameInfoData, Optio
void WebPageProxy::showPage()
{
m_uiClient->showPage(this);
+ m_inspectorController->didShowPage();
}
void WebPageProxy::exitFullscreenImmediately()
@@ -5583,6 +5660,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));
}
@@ -5602,6 +5681,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));
}
@@ -5621,6 +5702,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));
}
@@ -5780,6 +5863,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();
@@ -6846,6 +6931,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
2019-11-19 05:18:28 +03:00
if (auto* automationSession = process().processPool().automationSession())
automationSession->mouseEventsFlushedForPage(*this);
didFinishProcessingAllPendingMouseEvents();
+ m_inspectorController->didProcessAllPendingMouseEvents();
2019-11-19 05:18:28 +03:00
}
break;
@@ -6872,7 +6958,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
2019-11-19 05:18:28 +03:00
case WebEvent::RawKeyDown:
case WebEvent::Char: {
LOG(KeyHandling, "WebPageProxy::didReceiveEvent: %s (queue empty %d)", webKeyboardEventTypeString(type), m_keyEventQueue.isEmpty());
-
MESSAGE_CHECK(m_process, !m_keyEventQueue.isEmpty());
NativeWebKeyboardEvent event = m_keyEventQueue.takeFirst();
@@ -6892,7 +6977,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
2019-11-19 05:18:28 +03:00
// 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);
@@ -6901,6 +6985,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
2019-11-19 05:18:28 +03:00
if (!canProcessMoreKeyEvents) {
if (auto* automationSession = process().processPool().automationSession())
automationSession->keyboardEventsFlushedForPage(*this);
+ m_inspectorController->didProcessAllPendingKeyboardEvents();
2019-11-19 05:18:28 +03:00
}
break;
}
@@ -7359,8 +7444,10 @@ static bool shouldReloadAfterProcessTermination(ProcessTerminationReason reason)
void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason)
{
RELEASE_LOG_IF_ALLOWED(Loading, "dispatchProcessDidTerminate: reason = %d", reason);
+ bool handledByClient = m_inspectorController->pageCrashed(reason);
+ if (handledByClient)
+ return;
- bool handledByClient = false;
if (m_loaderClient)
handledByClient = reason != ProcessTerminationReason::RequestedByClient && m_loaderClient->processDidCrash(*this);
else
@@ -7645,6 +7732,7 @@ void WebPageProxy::resetStateAfterProcessExited(ProcessTerminationReason termina
WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& process, DrawingAreaProxy& drawingArea, RefPtr<API::WebsitePolicies>&& websitePolicies)
{
+
WebPageCreationParameters parameters;
parameters.processDisplayName = configuration().processDisplayName();
@@ -7787,6 +7875,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc
parameters.shouldRenderCanvasInGPUProcess = preferences().renderCanvasInGPUProcessEnabled();
parameters.shouldCaptureDisplayInUIProcess = m_process->processPool().configuration().shouldCaptureDisplayInUIProcess();
+ parameters.shouldPauseInInspectorWhenShown = m_inspectorController->shouldPauseLoading();
+
#if PLATFORM(GTK)
parameters.themeName = pageClient().themeName();
#endif
@@ -7850,6 +7940,14 @@ void WebPageProxy::gamepadActivity(const Vector<GamepadData>& gamepadDatas, bool
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 = authenticationChallenge.copyRef()] (bool shouldAllowLegacyTLS) {
if (shouldAllowLegacyTLS)
@@ -7930,7 +8028,8 @@ void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID,
MESSAGE_CHECK(m_process, frame);
// FIXME: Geolocation should probably be using toString() as its string representation instead of databaseIdentifier().
- auto origin = API::SecurityOrigin::create(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)
@@ -7939,6 +8038,14 @@ void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID,
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
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h
index a5f328b63dc07344c172a8d5eb0d65248a745ca5..e8c2db3e5732d3e2eed2abd200530080a3fa93c8 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/UIProcess/WebPageProxy.h
+++ b/Source/WebKit/UIProcess/WebPageProxy.h
@@ -36,6 +36,7 @@
#include "FocusedElementInformation.h"
#include "GeolocationPermissionRequestManagerProxy.h"
#include "HiddenPageThrottlingAutoIncreasesCounter.h"
+#include "InspectorDialogAgent.h"
#include "LayerTreeContext.h"
#include "MessageSender.h"
#include "NotificationPermissionRequestManagerProxy.h"
@@ -488,6 +489,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();
@@ -561,6 +564,11 @@ public:
2019-11-19 05:18:28 +03:00
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);
2019-11-19 05:18:28 +03:00
+
void initializeWebPage();
void setDrawingArea(std::unique_ptr<DrawingAreaProxy>&&);
@@ -586,6 +594,7 @@ public:
void closePage();
void addPlatformLoadParameters(LoadParameters&);
+ RefPtr<API::Navigation> loadRequestForInspector(WebCore::ResourceRequest&&, WebFrameProxy*);
RefPtr<API::Navigation> loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, 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);
@@ -1068,6 +1077,7 @@ public:
#endif
void pageScaleFactorDidChange(double);
+ void viewScaleFactorDidChange(double);
void pluginScaleFactorDidChange(double);
void pluginZoomFactorDidChange(double);
@@ -2340,6 +2350,7 @@ private:
String m_overrideContentSecurityPolicy;
RefPtr<WebInspectorProxy> m_inspector;
+ InspectorDialogAgent* m_inspectorDialogAgent { nullptr };
#if ENABLE(FULLSCREEN_API)
std::unique_ptr<WebFullScreenManagerProxy> m_fullScreenManager;
@@ -2762,6 +2773,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 f33b2e34be8a5bcc1381fc101cb8b1c5d59a3c95..99e8a120099716278bb73192e641f78bb8b0fa96 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 {
FindStringCallback(bool found, WebKit::CallbackID callbackID)
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 8d2580a5c96fb53ce4f85dbb1b89d079ecbd6f2e..a77ae49b4cc2c7f811233cad5fb6b38a3064734e 100644
--- a/Source/WebKit/UIProcess/WebProcessPool.cpp
+++ b/Source/WebKit/UIProcess/WebProcessPool.cpp
@@ -1017,7 +1017,10 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa
#endif
parameters.cacheModel = LegacyGlobalSettings::singleton().cacheModel();
- parameters.languages = configuration().overrideLanguages().isEmpty() ? userPreferredLanguages() : configuration().overrideLanguages();
+ if (websiteDataStore && websiteDataStore->languagesForAutomation().size())
+ parameters.languages = websiteDataStore->languagesForAutomation();
+ else
+ parameters.languages = configuration().overrideLanguages().isEmpty() ? userPreferredLanguages() : configuration().overrideLanguages();
parameters.urlSchemesRegisteredAsEmptyDocument = copyToVector(m_schemesToRegisterAsEmptyDocument);
parameters.urlSchemesRegisteredAsSecure = copyToVector(LegacyGlobalSettings::singleton().schemesToRegisterAsSecure());
diff --git a/Source/WebKit/UIProcess/WebProcessPool.h b/Source/WebKit/UIProcess/WebProcessPool.h
index 36db1a04b0a523b3adbdf4d3b8ca8b1be651d8f0..fbbc6a4e17f3e755917ff6752dd10ae13741aae8 100644
--- a/Source/WebKit/UIProcess/WebProcessPool.h
+++ b/Source/WebKit/UIProcess/WebProcessPool.h
@@ -714,8 +714,8 @@ private:
HashMap<uint64_t, RefPtr<DictionaryCallback>> m_dictionaryCallbacks;
-#if USE(SOUP)
- bool m_ignoreTLSErrors { true };
+#if USE(SOUP) || PLATFORM(COCOA) || PLATFORM(WIN)
+ bool m_ignoreTLSErrors { false };
#endif
bool m_memoryCacheDisabled { false };
diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
index be5f17ff03bacc1e2522ee03f86fddf4767a278f..6780955d1cca37a224f9c2bcbf6faa538a72e30a 100644
--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
@@ -185,6 +185,8 @@ void WebsiteDataStore::registerProcess(WebProcessProxy& process)
{
ASSERT(process.pageCount() || process.provisionalPageCount());
m_processes.add(process);
+ if (m_languagesForAutomation.size())
+ process.send(Messages::WebProcess::UserPreferredLanguagesChanged(m_languagesForAutomation), 0);
}
void WebsiteDataStore::unregisterProcess(WebProcessProxy& process)
@@ -2376,4 +2378,17 @@ void WebsiteDataStore::setInAppBrowserPrivacyEnabled(bool enabled, CompletionHan
}
}
+void WebsiteDataStore::setLanguagesForAutomation(Vector<String>&& languages)
+{
+ m_languagesForAutomation = WTFMove(languages);
+ for (auto& process : processes())
+ process.send(Messages::WebProcess::UserPreferredLanguagesChanged(languages), 0);
+}
+
+void WebsiteDataStore::setDownloadForAutomation(Optional<bool> allow, const String& downloadPath)
+{
+ m_allowDownloadForAutomation = allow;
+ m_downloadPathForAutomation = downloadPath;
+}
+
}
diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
index e842313256ba31bdd8a750ca55b33abdab2c0092..6fa4e7ff97db4dd9565b4834de2257a6966ed56a 100644
--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
@@ -96,6 +96,13 @@ enum class StorageAccessPromptStatus;
struct PluginModuleInfo;
#endif
+class DownloadInstrumentation {
+public:
+ virtual void downloadCreated(const String& uuid, const WebCore::ResourceRequest&, WebPageProxy* page) = 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();
@@ -282,6 +289,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()>&&);
void hasAppBoundSession(CompletionHandler<void(bool)>&&) const;
void setInAppBrowserPrivacyEnabled(bool enabled, CompletionHandler<void()>&&);
@@ -372,6 +387,11 @@ private:
RefPtr<API::HTTPCookieStore> m_cookieStore;
+ 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/geoclue/GeoclueGeolocationProvider.cpp b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp
index 7ba39332bce6e28f0f4b2f7acf636f835c54f486..7c3d8125df147b6049075491b12cce1dc84bf514 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
2019-11-19 05:18:28 +03:00
new file mode 100644
index 0000000000000000000000000000000000000000..c16ef9d7c0ba6b4aca36b0aad68296505dbacb50
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "InspectorPlaywrightAgentClientGLib.h"
2019-11-19 05:18:28 +03:00
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgent.h"
2019-11-19 05:18:28 +03:00
+#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 {
+
+InspectorPlaywrightAgentClientGlib::InspectorPlaywrightAgentClientGlib(GMainLoop* mainLoop)
+ : m_mainLoop(mainLoop)
2019-11-19 05:18:28 +03:00
+{
+}
+
+RefPtr<WebPageProxy> InspectorPlaywrightAgentClientGlib::createPage(WTF::String& error, const BrowserContext& browserContext)
2019-11-19 05:18:28 +03:00
+{
+ 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;
2019-11-19 05:18:28 +03:00
+ }
+
2019-11-19 05:18:28 +03:00
+ RefPtr<WebPageProxy> page = webkitBrowserInspectorCreateNewPageInContext(context);
+ if (page == nullptr) {
2019-11-19 05:18:28 +03:00
+ 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;
+ }
+
2019-11-19 05:18:28 +03:00
+ return page;
+}
+
+void InspectorPlaywrightAgentClientGlib::closeBrowser()
2019-11-19 05:18:28 +03:00
+{
+ m_idToContext.clear();
+#if PLATFORM(GTK)
+ gtk_main_quit();
+#else
+ if (m_mainLoop)
+ g_main_loop_quit(m_mainLoop);
+#endif
2019-11-19 05:18:28 +03:00
+}
+
+static PAL::SessionID sessionIDFromContext(WebKitWebContext* context)
+{
+ WebKitWebsiteDataManager* data_manager = webkit_web_context_get_website_data_manager(context);
+ WebsiteDataStore& websiteDataStore = webkitWebsiteDataManagerGetDataStore(data_manager);
+ return websiteDataStore.sessionID();
+}
+
+BrowserContext InspectorPlaywrightAgentClientGlib::createBrowserContext(WTF::String& error)
2019-11-19 05:18:28 +03:00
+{
+ BrowserContext browserContext;
+ 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)));
2019-11-19 05:18:28 +03:00
+ if (!context) {
+ error = "Failed to create GLib ephemeral context";
+ return browserContext;
2019-11-19 05:18:28 +03:00
+ }
+ browserContext.processPool = &webkitWebContextGetProcessPool(context.get());
+ browserContext.dataStore = &webkitWebsiteDataManagerGetDataStore(data_manager.get());
2019-11-19 05:18:28 +03:00
+ PAL::SessionID sessionID = sessionIDFromContext(context.get());
+ m_idToContext.set(sessionID, WTFMove(context));
+ return browserContext;
2019-11-19 05:18:28 +03:00
+}
+
+void InspectorPlaywrightAgentClientGlib::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
2019-11-19 05:18:28 +03:00
+{
+ m_idToContext.remove(sessionID);
2019-11-19 05:18:28 +03:00
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h
2019-11-19 05:18:28 +03:00
new file mode 100644
index 0000000000000000000000000000000000000000..4cba2671042d3517e4b8f66e7b2bb780d57aa402
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgentClient.h"
2019-11-19 05:18:28 +03:00
+#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 {
2019-11-19 05:18:28 +03:00
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorPlaywrightAgentClientGlib(GMainLoop* mainLoop);
+ ~InspectorPlaywrightAgentClientGlib() override = default;
2019-11-19 05:18:28 +03:00
+
+ RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
+ void closeBrowser() override;
+ BrowserContext createBrowserContext(WTF::String& error) override;
+ void deleteBrowserContext(WTF::String& error, PAL::SessionID) override;
2019-11-19 05:18:28 +03:00
+
+private:
+ WebKitWebContext* findContext(WTF::String& error, PAL::SessionID);
2019-11-19 05:18:28 +03:00
+
+ HashMap<PAL::SessionID, GRefPtr<WebKitWebContext>> m_idToContext;
+ GMainLoop* m_mainLoop;
2019-11-19 05:18:28 +03:00
+};
+
+} // namespace API
+
+#endif // ENABLE(REMOTE_INSPECTOR)
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
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e5e25acebabb76a05a77db02a99f1267bd99a3af
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "DrawingAreaProxyCoordinatedGraphics.h"
2019-11-19 05:18:28 +03:00
+#include "WebPageInspectorEmulationAgent.h"
+#include "WebPageProxy.h"
+#include <WebCore/IntSize.h>
2019-11-19 05:18:28 +03:00
+#include <gtk/gtk.h>
+
+namespace WebKit {
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
2019-11-19 05:18:28 +03:00
+{
+ GtkWidget* viewWidget = m_page.viewWidget();
+ GtkWidget* window = gtk_widget_get_toplevel(viewWidget);
+ if (!window) {
+ callback("Cannot find parent window"_s);
2019-11-19 05:18:28 +03:00
+ return;
+ }
+ if (!GTK_IS_WINDOW(window)) {
+ callback("Toplevel is not a window"_s);
2019-11-19 05:18:28 +03:00
+ return;
+ }
+ GtkAllocation viewAllocation;
+ gtk_widget_get_allocation(viewWidget, &viewAllocation);
+ if (viewAllocation.width == width && viewAllocation.height == height) {
+ callback(String());
+ return;
+ }
2019-11-19 05:18:28 +03:00
+
+ 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);
+ }
2019-11-19 05:18:28 +03:00
+ 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..7ad3fe416c5c747eaad8c6948c3549a3984223ea
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#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, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& macCommands, WallTime timestamp)
2019-11-19 05:18:28 +03:00
+{
+ Vector<String> commands;
+ const guint keyVal = WebCore::PlatformKeyboardEvent::gdkKeyCodeForWindowsKeyCode(windowsVirtualKeyCode);
+ String keyIdentifier;
+ if (keyVal) {
+ GdkEventType event = GDK_NOTHING;
+ switch (type)
+ {
+ case WebKeyboardEvent::KeyDown:
+ event = GDK_KEY_PRESS;
+ break;
+ case WebKeyboardEvent::KeyUp:
+ event = GDK_KEY_RELEASE;
+ break;
+ default:
+ fprintf(stderr, "Unsupported event type = %d\n", type);
+ break;
+ }
+ unsigned state = modifiersToEventState(modifiers);
+ commands = commandsForKeyEvent(event, keyVal, state);
+ keyIdentifier = WebCore::PlatformKeyboardEvent::keyIdentifierForGdkKeyCode(keyVal);
+ }
+ NativeWebKeyboardEvent event(
+ type,
+ text,
+ unmodifiedText,
+ key,
+ code,
+ keyIdentifier,
+ windowsVirtualKeyCode,
+ nativeVirtualKeyCode,
+ isAutoRepeat,
+ isKeypad,
+ isSystemKey,
+ modifiers,
+ timestamp,
+ WTFMove(commands));
+ m_page.handleKeyboardEvent(event);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
index ae706e961e76289751bd8dbe4e7c830e32676347..ee1d6987f6f867eea47c0c77655f3c454702c822 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
@@ -456,6 +456,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
2019-11-19 05:18:28 +03:00
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
2019-11-19 05:18:28 +03:00
new file mode 100644
index 0000000000000000000000000000000000000000..b75c2ce5ce9e9da3a33bca41ab548ec7a2f819ed
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#pragma once
+
+#include "InspectorPlaywrightAgentClient.h"
2019-11-19 05:18:28 +03:00
+#include <wtf/Forward.h>
+
+OBJC_PROTOCOL(_WKBrowserInspectorDelegate);
+
+namespace WebKit {
+
+class InspectorPlaywrightAgentClientMac : public InspectorPlaywrightAgentClient {
2019-11-19 05:18:28 +03:00
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorPlaywrightAgentClientMac(_WKBrowserInspectorDelegate* delegate);
+ ~InspectorPlaywrightAgentClientMac() override = default;
2019-11-19 05:18:28 +03:00
+
+ RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
+ void closeBrowser() override;
+ BrowserContext createBrowserContext(WTF::String& error) override;
+ void deleteBrowserContext(WTF::String& error, PAL::SessionID) override;
2019-11-19 05:18:28 +03:00
+
+private:
2019-11-19 05:18:28 +03:00
+ _WKBrowserInspectorDelegate* delegate_;
+};
+
+
+} // namespace API
diff --git a/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm
2019-11-19 05:18:28 +03:00
new file mode 100644
index 0000000000000000000000000000000000000000..5db92c0580fd4f216ac86ede56eaac2eabec27da
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#import "config.h"
+#import "InspectorPlaywrightAgentClientMac.h"
2019-11-19 05:18:28 +03:00
+
+#import <wtf/RefPtr.h>
+#import <wtf/text/WTFString.h>
+#import "WebPageProxy.h"
+#import "WebProcessPool.h"
+#import "WebsiteDataStore.h"
2019-11-19 05:18:28 +03:00
+#import "_WKBrowserInspector.h"
+#import "WKProcessPoolInternal.h"
+#import "WKWebsiteDataStoreInternal.h"
2019-11-19 05:18:28 +03:00
+#import "WKWebView.h"
+#import "WKWebViewInternal.h"
+
+namespace WebKit {
+
+InspectorPlaywrightAgentClientMac::InspectorPlaywrightAgentClientMac(_WKBrowserInspectorDelegate* delegate)
2019-11-19 05:18:28 +03:00
+ : delegate_(delegate)
+{
+}
+
+RefPtr<WebPageProxy> InspectorPlaywrightAgentClientMac::createPage(WTF::String& error, const BrowserContext& browserContext)
2019-11-19 05:18:28 +03:00
+{
+ 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();
2019-11-19 05:18:28 +03:00
+}
+
+void InspectorPlaywrightAgentClientMac::closeBrowser()
2019-11-19 05:18:28 +03:00
+{
+ [delegate_ quit];
+}
+
+BrowserContext InspectorPlaywrightAgentClientMac::createBrowserContext(WTF::String& error)
2019-11-19 05:18:28 +03:00
+{
+ _WKBrowserContext* wkBrowserContext = [[delegate_ createBrowserContext] autorelease];
+ BrowserContext browserContext;
+ browserContext.processPool = &static_cast<WebProcessPool&>([[wkBrowserContext processPool] _apiObject]);
+ browserContext.dataStore = &static_cast<WebsiteDataStore&>([[wkBrowserContext dataStore] _apiObject]);
+ return browserContext;
2019-11-19 05:18:28 +03:00
+}
+
+void InspectorPlaywrightAgentClientMac::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
2019-11-19 05:18:28 +03:00
+{
+ [delegate_ deleteBrowserContext:sessionID.toUInt64()];
2019-11-19 05:18:28 +03:00
+}
+
+} // 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 f0cc38a489474fb9e964fefc91e837f6266d2c04..71caf1fd10757a34aa9ef21d88d7326a66bb3a47 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();
@@ -204,6 +206,10 @@ private:
2019-12-24 00:12:56 +03:00
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;
2019-11-19 05:18:28 +03:00
diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm
index 03192d76aefb19cac18fdd5c4c6de50a2f2585c5..02ea60cb127f68fc073e417856c8c3248df3397c 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm
+++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm
2019-12-24 00:12:56 +03:00
@@ -78,6 +78,7 @@
#import <WebCore/TextUndoInsertionMarkupMac.h>
#import <WebCore/ValidationBubble.h>
#import <WebCore/WebCoreCALayerExtras.h>
+#import <WebCore/NotImplemented.h>
#import <wtf/ProcessPrivilege.h>
#import <wtf/RetainPtr.h>
2019-12-24 00:12:56 +03:00
#import <wtf/text/CString.h>
@@ -103,6 +104,13 @@ namespace WebKit {
using namespace WebCore;
+static bool _headless = false;
+
+// static
+void PageClientImpl::setHeadless(bool headless) {
+ _headless = true;
+}
+
PageClientImpl::PageClientImpl(NSView *view, WKWebView *webView)
: PageClientImplCocoa(webView)
, m_view(view)
@@ -156,6 +164,9 @@ NSWindow *PageClientImpl::activeWindow() const
bool PageClientImpl::isViewWindowActive()
{
+ if (_headless)
+ return true;
+
ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
NSWindow *activeViewWindow = activeWindow();
return activeViewWindow.isKeyWindow || [NSApp keyWindow] == activeViewWindow;
@@ -163,6 +174,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)
@@ -186,6 +200,9 @@ void PageClientImpl::makeFirstResponder()
bool PageClientImpl::isViewVisible()
{
+ if (_headless)
+ return true;
+
NSView *activeView = this->activeView();
NSWindow *activeViewWindow = activeWindow();
@@ -269,7 +286,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)
@@ -447,6 +465,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
2019-11-19 05:18:28 +03:00
void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
{
+ if (!event.nativeEvent())
+ return;
m_impl->doneWithKeyEvent(event.nativeEvent(), eventWasHandled);
}
@@ -738,6 +758,13 @@ void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntR
2019-12-24 00:12:56 +03:00
#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);
@@ -904,6 +931,9 @@ void PageClientImpl::didRestoreScrollPosition()
2019-11-19 05:18:28 +03:00
bool PageClientImpl::windowIsFrontWindowUnderMouse(const NativeWebMouseEvent& event)
{
+ // Simulated event.
+ if (!event.nativeEvent())
+ return false;
return m_impl->windowIsFrontWindowUnderMouse(event.nativeEvent());
}
diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..6113f4cd60a5d72b8ead61176cb43200803478ed
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#import "config.h"
+#import "WebPageInspectorEmulationAgent.h"
2019-11-19 05:18:28 +03:00
+
+#import "WebPageProxy.h"
2019-11-19 05:18:28 +03:00
+
+namespace WebKit {
+
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
2019-11-19 05:18:28 +03:00
+{
+ 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());
2019-11-19 05:18:28 +03:00
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..30e6ae3bdc8c1695189885afae949071add54c4e
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#import "config.h"
+#import "NativeWebMouseEvent.h"
+#import "WebPageInspectorInputAgent.h"
+#import "WebPageProxy.h"
+#import <WebCore/IntPoint.h>
+#import <WebCore/IntSize.h>
+#import "NativeWebKeyboardEvent.h"
+#import <wtf/HexNumber.h>
2019-11-19 05:18:28 +03:00
+
+namespace WebKit {
+
+using namespace WebCore;
+
+void WebPageInspectorInputAgent::platformDispatchMouseEvent(const String& type, int x, int y, const int* optionalModifiers, const String* button, const int* optionalClickCount) {
+ IntPoint locationInWindow(x, y);
+
+ NSEventModifierFlags modifiers = 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, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& commands, WallTime timestamp)
2019-11-19 05:18:28 +03:00
+{
+ String keyIdentifier = key.length() == 1 ? makeString("U+", hex(toASCIIUpper(key.characterAt(0)), 4)) : key;
+ Vector<WebCore::KeypressCommand> macCommands;
+ for (const String& command : commands)
+ macCommands.append(WebCore::KeypressCommand(command.utf8().data()));
+ if (text.length() > 0 && macCommands.size() == 0)
+ macCommands.append(WebCore::KeypressCommand("insertText:", text));
+ NativeWebKeyboardEvent event(
+ type,
+ text,
+ unmodifiedText,
+ key,
+ code,
+ keyIdentifier,
+ windowsVirtualKeyCode,
+ nativeVirtualKeyCode,
+ isAutoRepeat,
+ isKeypad,
+ isSystemKey,
+ modifiers,
+ timestamp,
+ WTFMove(macCommands));
+ m_page.handleKeyboardEvent(event);
2019-11-19 05:18:28 +03:00
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..544442b75afcba6e121ab202ad32dcdfaf923e2e
--- /dev/null
+++ b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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 <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/StringView.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+InspectorPlaywrightAgentClientWin::InspectorPlaywrightAgentClientWin(CreatePageCallback createPage, QuitCallback quit)
+ : m_createPage(createPage)
+ , m_quit(quit)
+{
+}
+
+RefPtr<WebPageProxy> InspectorPlaywrightAgentClientWin::createPage(WTF::String& error, const BrowserContext& context)
+{
+ auto conf = API::PageConfiguration::create();
+ auto prefs = WebPreferences::create(String(), "WebKit2Automation.", "WebKit2Automation.");
+ conf->setProcessPool(context.processPool.get());
+ conf->setWebsiteDataStore(context.dataStore.get());
+ return toImpl(m_createPage(toAPI(&conf.get())));
+}
+
+void InspectorPlaywrightAgentClientWin::closeBrowser()
+{
+ m_quit();
+}
+
+BrowserContext InspectorPlaywrightAgentClientWin::createBrowserContext(WTF::String& error)
+{
+ auto config = API::ProcessPoolConfiguration::create();
+ BrowserContext browserContext;
+ browserContext.processPool = WebKit::WebProcessPool::create(config);
+ browserContext.dataStore = WebKit::WebsiteDataStore::createNonPersistent();
+ 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..2536fe399ef9a5916803954e1f4971a24b7ca4ec
--- /dev/null
+++ b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.h
@@ -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.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorPlaywrightAgentClient.h"
+#include <WebKit/WKInspector.h>
+#include <wtf/Forward.h>
+#include <wtf/text/StringHash.h>
+
+typedef WKPageRef (*CreatePageCallback)(WKPageConfigurationRef configuration);
+typedef void (*QuitCallback)();
+
+namespace WebKit {
+
+class InspectorPlaywrightAgentClientWin : public InspectorPlaywrightAgentClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorPlaywrightAgentClientWin(CreatePageCallback, QuitCallback);
+ ~InspectorPlaywrightAgentClientWin() override = default;
+
+ RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
+ void closeBrowser() override;
+ BrowserContext createBrowserContext(WTF::String& error) override;
+ void deleteBrowserContext(WTF::String& error, PAL::SessionID) override;
+
+private:
+ 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/WebPageInspectorEmulationAgentWin.cpp b/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..520d9714bac279a8b778c2c377af4411fba8d5d7
--- /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_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..a299240b1fea96694cb47fa11fc6a6411ffdaf70
--- /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, 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,
+ "",
+ windowsVirtualKeyCode,
+ nativeVirtualKeyCode,
+ isAutoRepeat,
+ isKeypad,
+ isSystemKey,
+ modifiers,
+ timestamp);
+ m_page.handleKeyboardEvent(event);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/win/WebProcessPoolWin.cpp b/Source/WebKit/UIProcess/win/WebProcessPoolWin.cpp
index 18f9e93932793b7c3e44e6346be0f13ed6dbf233..bd056b2ab34f0059d6477c955f51d71136f2a252 100644
--- a/Source/WebKit/UIProcess/win/WebProcessPoolWin.cpp
+++ b/Source/WebKit/UIProcess/win/WebProcessPoolWin.cpp
@@ -26,7 +26,6 @@
#include "config.h"
#include "WebProcessPool.h"
-
#include "WebProcessCreationParameters.h"
#include <WebCore/NotImplemented.h>
diff --git a/Source/WebKit/UIProcess/win/WebView.cpp b/Source/WebKit/UIProcess/win/WebView.cpp
index 4a96b5e998800bb7b1ca104f860e96dcf418d178..d04d3be8e814b6994a3cc390fa1b17a87a3b06b9 100644
--- a/Source/WebKit/UIProcess/win/WebView.cpp
+++ b/Source/WebKit/UIProcess/win/WebView.cpp
@@ -114,6 +114,8 @@ LRESULT WebView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
m_page->tryClose();
break;
case WM_DESTROY:
+ if (!m_page)
+ return ::DefWindowProc(hWnd, message, wParam, lParam);
m_isBeingDestroyed = true;
close();
break;
@@ -275,6 +277,10 @@ WebView::WebView(RECT rect, const API::PageConfiguration& configuration, HWND pa
WebView::~WebView()
{
+ // We must close the page here since page expects pageClient to outlive it. Even though page
+ // client is a weak-ref in the page, the expectations are that it is available at least until
+ // the page.close.
+ m_page->close();
// Tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD.
if (::IsWindow(m_toolTipWindow))
::DestroyWindow(m_toolTipWindow);
diff --git a/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp
2019-11-19 05:18:28 +03:00
new file mode 100644
index 0000000000000000000000000000000000000000..7453194ca6f032ba86a4c67f5bf12688ab6ec1be
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#include "config.h"
+#include "InspectorTargetProxy.h"
2019-11-19 05:18:28 +03:00
+
+#include "WebPageProxy.h"
+#include <wpe/wpe.h>
2019-11-19 05:18:28 +03:00
+
+namespace WebKit {
+
+void InspectorTargetProxy::platformActivate(String& error) const
2019-11-19 05:18:28 +03:00
+{
+ 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);
2019-11-19 05:18:28 +03:00
+}
+
+} // 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
2019-11-19 05:18:28 +03:00
--- /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.
+ */
2019-11-19 05:18:28 +03:00
+
+#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)
2019-11-19 05:18:28 +03:00
+{
+ struct wpe_view_backend* backend = m_page.viewBackend();
+ wpe_view_backend_dispatch_set_size(backend, width, height);
+ callback(String());
2019-11-19 05:18:28 +03:00
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..585fb151f302e4b376c705ed0d0974d518733605
2019-11-19 05:18:28 +03:00
--- /dev/null
+++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
2019-11-19 05:18:28 +03:00
+
+#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, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& macCommands, WallTime timestamp)
2019-11-19 05:18:28 +03:00
+{
+ unsigned keyCode = WebCore::PlatformKeyboardEvent::WPEKeyCodeForWindowsKeyCode(windowsVirtualKeyCode);
+ String keyIdentifier;
+ if (keyCode)
+ keyIdentifier = WebCore::PlatformKeyboardEvent::keyIdentifierForWPEKeyCode(keyCode);
+ NativeWebKeyboardEvent event(
+ type,
+ text,
+ unmodifiedText,
+ key,
+ code,
+ keyIdentifier,
+ windowsVirtualKeyCode,
+ nativeVirtualKeyCode,
+ isAutoRepeat,
+ isKeypad,
+ isSystemKey,
+ modifiers,
+ timestamp);
+ m_page.handleKeyboardEvent(event);
2019-11-19 05:18:28 +03:00
+}
+
2019-11-19 05:18:28 +03:00
+} // namespace WebKit
diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
index b4c6eddf1459e589191d8c1d0d0d407045b9a864..5989d245828c78f15d3a19a08796d53bc9a32328 100644
2019-11-19 05:18:28 +03:00
--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj
+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
@@ -1766,6 +1766,19 @@
2019-11-19 05:18:28 +03:00
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 */; };
2019-11-19 05:18:28 +03:00
+ D71A94382370F032002C4D9E /* BrowserInspectorController.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94372370F032002C4D9E /* BrowserInspectorController.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 */; };
2019-11-19 05:18:28 +03:00
+ D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */; };
+ D79902B2236E9404005D6F7E /* InspectorTargetProxyMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */; };
2019-11-19 05:18:28 +03:00
+ 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, ); }; };
2019-11-19 05:18:28 +03:00
E105FE5418D7B9DE008F57A8 /* EditingRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E105FE5318D7B9DE008F57A8 /* EditingRange.h */; };
@@ -5200,6 +5213,20 @@
2019-11-19 05:18:28 +03:00
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>"; };
2019-11-19 05:18:28 +03:00
+ D71A94372370F032002C4D9E /* BrowserInspectorController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrowserInspectorController.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>"; };
2019-11-19 05:18:28 +03:00
+ 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>"; };
2019-11-19 05:18:28 +03:00
+ 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>"; };
2019-11-19 05:18:28 +03:00
DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebWheelEvent.h; sourceTree = "<group>"; };
@@ -7125,6 +7152,7 @@
2019-11-19 05:18:28 +03:00
37C4C08318149C2A003688B9 /* Cocoa */ = {
isa = PBXGroup;
children = (
+ D71A94492372290B002C4D9E /* _WKBrowserInspector.h */,
1A43E826188F38E2009E4D30 /* Deprecated */,
37A5E01218BBF937000A081E /* _WKActivatedElementInfo.h */,
37A5E01118BBF937000A081E /* _WKActivatedElementInfo.mm */,
@@ -8830,6 +8858,13 @@
2019-11-19 05:18:28 +03:00
BC032DC310F438260058C15A /* UIProcess */ = {
isa = PBXGroup;
children = (
+ D76D6887238DBD80008D314B /* InspectorDialogAgent.h */,
2019-11-19 05:18:28 +03:00
+ D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */,
+ D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */,
+ D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */,
+ D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */,
+ D71A94372370F032002C4D9E /* BrowserInspectorController.h */,
+ D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */,
2019-11-19 05:18:28 +03:00
BC032DC410F4387C0058C15A /* API */,
512F588D12A8836F00629530 /* Authentication */,
9955A6E81C79809000EB6A93 /* Automation */,
@@ -9107,6 +9142,7 @@
2019-11-19 05:18:28 +03:00
BC0C376610F807660076D7CB /* C */ = {
isa = PBXGroup;
children = (
+ D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */,
5123CF18133D25E60056F800 /* cg */,
6EE849C41368D9040038D481 /* mac */,
BCB63477116BF10600603215 /* WebKit2_C.h */,
@@ -9709,6 +9745,11 @@
2019-11-19 05:18:28 +03:00
BCCF085C113F3B7500C650C5 /* mac */ = {
isa = PBXGroup;
children = (
+ D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */,
+ D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */,
2019-11-19 05:18:28 +03:00
+ D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */,
+ D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */,
+ D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */,
2019-11-19 05:18:28 +03:00
B878B613133428DC006888E9 /* CorrectionPanel.h */,
B878B614133428DC006888E9 /* CorrectionPanel.mm */,
C1817362205844A900DFDA65 /* DisplayLink.cpp */,
@@ -10462,6 +10503,7 @@
991F492F23A812C60054642B /* _WKInspectorDebuggableInfo.h in Headers */,
99036AE223A949CF0000B06A /* _WKInspectorDebuggableInfoInternal.h in Headers */,
9197940C23DBC50300257892 /* _WKInspectorDelegate.h in Headers */,
2019-11-19 05:18:28 +03:00
+ D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */,
5CAFDE472130846A00B1F7E1 /* _WKInspectorInternal.h in Headers */,
9979CA58237F49F10039EC05 /* _WKInspectorPrivate.h in Headers */,
2019-11-19 05:18:28 +03:00
A5C0F0AB2000658200536536 /* _WKInspectorWindow.h in Headers */,
@@ -10586,6 +10628,7 @@
2019-11-19 05:18:28 +03:00
7C89D2981A6753B2003A5FDE /* APIPageConfiguration.h in Headers */,
1AC1336C18565C7A00F3EC05 /* APIPageHandle.h in Headers */,
1AFDD3151891B54000153970 /* APIPolicyClient.h in Headers */,
+ D71A94382370F032002C4D9E /* BrowserInspectorController.h in Headers */,
7CE4D2201A4914CA00C7F152 /* APIProcessPoolConfiguration.h in Headers */,
49BCA19223A177660028A836 /* APIResourceLoadStatisticsFirstParty.h in Headers */,
49BCA19723A1930D0028A836 /* APIResourceLoadStatisticsThirdParty.h in Headers */,
@@ -10711,6 +10754,7 @@
2019-11-19 05:18:28 +03:00
BC06F43A12DBCCFB002D78DE /* GeolocationPermissionRequestProxy.h in Headers */,
2DA944A41884E4F000ED86DB /* GestureTypes.h in Headers */,
2DA049B8180CCD0A00AAFA9E /* GraphicsLayerCARemote.h in Headers */,
+ D71A94342370E07A002C4D9E /* InspectorPlaywrightAgentClient.h in Headers */,
2019-11-19 05:18:28 +03:00
C0CE72AD1247E78D00BC0EC4 /* HandleMessage.h in Headers */,
1AC75A1B1B3368270056745B /* HangDetectionDisabler.h in Headers */,
57AC8F50217FEED90055438C /* HidConnection.h in Headers */,
@@ -10838,8 +10882,10 @@
2019-11-19 05:18:28 +03:00
41DC45961E3D6E2200B11F51 /* NetworkRTCProvider.h in Headers */,
413075AB1DE85F330039EC69 /* NetworkRTCSocket.h in Headers */,
5C20CBA01BB1ECD800895BB1 /* NetworkSession.h in Headers */,
+ D71A94422371F67E002C4D9E /* WebPageInspectorEmulationAgent.h in Headers */,
532159551DBAE7290054AA3C /* NetworkSessionCocoa.h in Headers */,
417915B92257046F00D6F97E /* NetworkSocketChannel.h in Headers */,
+ D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */,
570DAAC22303730300E8FC04 /* NfcConnection.h in Headers */,
570DAAAE23026F5C00E8FC04 /* NfcService.h in Headers */,
31A2EC5614899C0900810D71 /* NotificationPermissionRequest.h in Headers */,
@@ -10923,6 +10969,7 @@
2019-11-19 05:18:28 +03:00
CD2865EE2255562000606AC7 /* ProcessTaskStateObserver.h in Headers */,
463FD4821EB94EC000A2982C /* ProcessTerminationReason.h in Headers */,
86E67A251910B9D100004AB7 /* ProcessThrottler.h in Headers */,
+ D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */,
83048AE61ACA45DC0082C832 /* ProcessThrottlerClient.h in Headers */,
A1E688701F6E2BAB007006A6 /* QuarantineSPI.h in Headers */,
57FD318222B3515E008D0E8B /* RedirectSOAuthorizationSession.h in Headers */,
@@ -11349,6 +11396,7 @@
2019-11-19 05:18:28 +03:00
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 */,
@@ -11401,6 +11449,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 */,
@@ -11551,6 +11600,7 @@
2019-11-19 05:18:28 +03:00
1AB8A1F818400BB800E9AE69 /* WKPageContextMenuClient.h in Headers */,
8372DB251A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h in Headers */,
1AB8A1F418400B8F00E9AE69 /* WKPageFindClient.h in Headers */,
+ D71A94322370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h in Headers */,
2019-11-19 05:18:28 +03:00
1AB8A1F618400B9D00E9AE69 /* WKPageFindMatchesClient.h in Headers */,
1AB8A1F018400B0000E9AE69 /* WKPageFormClient.h in Headers */,
BC7B633712A45ABA00D174A4 /* WKPageGroup.h in Headers */,
@@ -12598,6 +12648,7 @@
CDA93DB122F8BCF400490A69 /* FullscreenTouchSecheuristicParameters.cpp in Sources */,
2749F6442146561B008380BF /* InjectedBundleNodeHandle.cpp in Sources */,
2749F6452146561E008380BF /* InjectedBundleRangeHandle.cpp in Sources */,
+ D79902B2236E9404005D6F7E /* InspectorTargetProxyMac.mm in Sources */,
2D913441212CF9F000128AFD /* JSNPMethod.cpp in Sources */,
2D913442212CF9F000128AFD /* JSNPObject.cpp in Sources */,
2984F588164BA095004BC0C6 /* LegacyCustomProtocolManagerMessageReceiver.cpp in Sources */,
@@ -12608,6 +12659,7 @@
2019-11-19 05:18:28 +03:00
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 */,
@@ -12632,6 +12684,7 @@
2019-11-19 05:18:28 +03:00
1A2D8439127F65D5001EB962 /* NPObjectMessageReceiverMessageReceiver.cpp in Sources */,
2D92A792212B6AD400F493FD /* NPObjectProxy.cpp in Sources */,
2D92A793212B6AD400F493FD /* NPRemoteObjectMap.cpp in Sources */,
+ D7EB04E72372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm in Sources */,
2019-11-19 05:18:28 +03:00
2D913447212CF9F000128AFD /* NPRuntimeObjectMap.cpp in Sources */,
2D913448212CF9F000128AFD /* NPRuntimeUtilities.cpp in Sources */,
2D92A794212B6AD400F493FD /* NPVariantData.cpp in Sources */,
@@ -12912,6 +12965,7 @@
2D92A78C212B6AB100F493FD /* WebMouseEvent.cpp in Sources */,
31BA924D148831260062EDB5 /* WebNotificationManagerMessageReceiver.cpp in Sources */,
2DF6FE52212E110900469030 /* WebPage.cpp in Sources */,
2019-11-19 05:18:28 +03:00
+ 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 28f509c22ccfea869d1bb975447401b09f75d3cb..f550d91838b250bc184b07ff2f0d3cbb3d8f145d 100644
--- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
+++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
@@ -58,6 +58,7 @@
#include <WebCore/Frame.h>
#include <WebCore/FrameLoader.h>
#include <WebCore/HTMLFrameOwnerElement.h>
+#include <WebCore/InspectorInstrumentationWebKit.h>
#include <WebCore/NetscapePlugInStreamLoader.h>
#include <WebCore/NetworkLoadInformation.h>
#include <WebCore/PlatformStrategies.h>
@@ -228,8 +229,24 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou
}
#endif
+ if (m_emulateOfflineState) {
+ scheduleInternallyFailedLoad(resourceLoader);
+ return;
+ }
+
if (!tryLoadingUsingURLSchemeHandler(resourceLoader, trackingParameters)) {
WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be scheduled with the NetworkProcess");
+
+ RefPtr<ResourceLoader> coreLoader = &resourceLoader;
+ if (!resourceLoader.options().serviceWorkerRegistrationIdentifier) {
+ if (InspectorInstrumentationWebKit::interceptRequest(resourceLoader, [this, coreLoader, trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, resource](bool handled) mutable {
+ if (!handled)
+ scheduleLoadFromNetworkProcess(*coreLoader, coreLoader->request(), trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime(resource));
+ })) {
+ return;
+ }
+ }
+
scheduleLoadFromNetworkProcess(resourceLoader, resourceLoader.request(), trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime(resource));
return;
}
@@ -768,7 +785,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)
@@ -779,6 +796,11 @@ void WebLoaderStrategy::addOnlineStateChangeListener(Function<void(bool)>&& list
void WebLoaderStrategy::setOnLineState(bool isOnLine)
{
+ if (m_emulateOfflineState) {
+ m_isOnLine = isOnLine;
+ return;
+ }
+
if (m_isOnLine == isOnLine)
return;
@@ -787,6 +809,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 22f644fd7f450d32ea45f97e27488ef5f34c153a..9ac93959568cb4561c039cc0ce7b28c404699390 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;
private:
void scheduleLoad(WebCore::ResourceLoader&, WebCore::CachedResource*, bool shouldClearReferrerOnHTTPSToHTTPRedirect);
@@ -126,6 +127,7 @@ private:
HashMap<unsigned long, PreconnectCompletionHandler> m_preconnectCompletionHandlers;
Vector<Function<void(bool)>> m_onlineStateChangeListeners;
bool m_isOnLine { true };
+ bool m_emulateOfflineState { false };
HashSet<WebResourceLoader*> m_loadersWithUploads;
};
diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
index 543de23da89e1b74dba97aa1a3953f2cf69a4d1c..25029c335bd13396b1bc6e14fbc4e6fbc9009fb3 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
@@ -409,6 +409,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);
}
@@ -807,6 +809,13 @@ bool WebChromeClient::canShowDataListSuggestionLabels() const
#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/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
index ef1c8cdbbad2ef5ada3212c851c62a149f9fea0e..142e2ffdc95646eea469c3a51e3c329be10bd57c 100644
--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
+++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
@@ -244,12 +244,20 @@ void DrawingAreaCoordinatedGraphics::updatePreferences(const WebPreferencesStore
settings.setAcceleratedCompositingEnabled(false);
}
#endif
+
+#if USE(LIBWPE)
+ settings.setAcceleratedCompositingEnabled(false);
+ settings.setForceCompositingMode(false);
+ settings.setAcceleratedCompositingForFixedPositionEnabled(false);
+ m_alwaysUseCompositing = false;
+#else
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.
settings.setAcceleratedCompositingForFixedPositionEnabled(settings.acceleratedCompositingEnabled());
m_alwaysUseCompositing = settings.acceleratedCompositingEnabled() && settings.forceCompositingMode();
+#endif
// If async scrolling is disabled, we have to force-disable async frame and overflow scrolling
// to keep the non-async scrolling on those elements working.
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 4376de80738d9e8dc89da363ba6b1e2f703594c0..fcbee333947623540df4e583bb1063472f8a5fde 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
@@ -747,6 +747,9 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters)
send(Messages::WebPageProxy::DidCreateContextForVisibilityPropagation(m_contextForVisibilityPropagation->contextID()));
#endif
+ if (parameters.shouldPauseInInspectorWhenShown)
+ m_page->inspectorController().pauseWhenShown();
+
updateThrottleState();
}
@@ -1506,6 +1509,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, ShouldOpenExternalURLsPolicy::ShouldNotAllow };
+ frame->coreFrame()->loader().load(WTFMove(frameLoadRequest));
+ ASSERT(!m_pendingFrameNavigationID);
+}
+
void WebPage::loadRequest(LoadParameters&& loadParameters)
{
setIsNavigatingToAppBoundDomain(loadParameters.isNavigatingToAppBoundDomain);
@@ -1713,17 +1732,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())
@@ -1740,20 +1755,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));
@@ -1761,7 +1774,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg
send(Messages::WebPageProxy::DidChangeViewportProperties(attr));
#endif
}
-#endif
void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
{
@@ -2052,6 +2064,7 @@ void WebPage::scaleView(double scale)
}
m_page->setViewScaleFactor(scale);
+ send(Messages::WebPageProxy::ViewScaleFactorDidChange(scale));
scalePage(pageScale, scrollPositionAtNewScale);
}
@@ -2156,17 +2169,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)
@@ -3051,6 +3060,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();
@@ -3291,6 +3305,7 @@ void WebPage::didCompletePageTransition()
void WebPage::show()
{
send(Messages::WebPageProxy::ShowPage());
+ m_page->inspectorController().didShowNewWindow();
}
void WebPage::setShouldFireResizeEvents(bool shouldFireResizeEvents)
@@ -6345,6 +6360,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 873986ccd6deead07fb1ada05658d8844ce1aa85..d277b4561243498320bbc01dfa7da8cb80e7976f 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.h
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h
@@ -1150,6 +1150,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();
@@ -1406,6 +1407,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&&);
@@ -1550,9 +1552,7 @@ private:
void countStringMatches(const String&, uint32_t 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);
@@ -2013,6 +2013,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 076c1faf2e44c0c77b949be9eb793d26b35a0f62..ef6c209efe4d238e7208321bc12822fdcb52c8af 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
@@ -128,6 +128,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);
@@ -168,6 +169,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/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp
index 0b9dddb7a61df1259dc8ac3765b72aad1969467b..d23b8c4c225f9ca660e74319ae7b9edd458150fe 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>
@@ -275,6 +276,8 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter
platformInitializeProcess(parameters);
updateCPULimit();
+
+ Inspector::IdentifiersFactory::initializeWithProcessID(parameters.processIdentifier->toUInt64());
}
void WebProcess::initializeConnection(IPC::Connection* connection)
2019-12-24 00:12:56 +03:00
diff --git a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
index 5ba2e78046f46807d18eb418773ae8b21421ffe2..87f931ed6470b09d6982dd60bda7e779ceb7d4f6 100644
2019-12-24 00:12:56 +03:00
--- a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
+++ b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
@@ -4245,7 +4245,7 @@ static BOOL currentScrollIsBlit(NSView *clipView)
2019-12-24 00:12:56 +03:00
_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 d11777db6e16be89dad4d7e680e317b5b7dfe53a..c5ebcb54470a5bc766a6c6466aeb83fc2f51e780 100644
2019-12-24 00:12:56 +03:00
--- a/Source/WebKitLegacy/mac/WebView/WebView.mm
+++ b/Source/WebKitLegacy/mac/WebView/WebView.mm
@@ -4352,7 +4352,7 @@ IGNORE_WARNINGS_END
2019-12-24 00:12:56 +03:00
}
#endif // PLATFORM(IOS_FAMILY)
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(IOS_TOUCH_EVENTS)
- (NSArray *)_touchEventRegions
{
auto* frame = [self _mainCoreFrame];
@@ -4398,7 +4398,7 @@ IGNORE_WARNINGS_END
2019-12-24 00:12:56 +03:00
return eventRegionArray;
}
-#endif // ENABLE(TOUCH_EVENTS)
+#endif // ENABLE(IOS_TOUCH_EVENTS)
// For backwards compatibility with the WebBackForwardList API, we honor both
// a per-WebView and a per-preferences setting for whether to use the back/forward cache.
diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake
index 6ff8c39922a4f3129b687ae0f9d15de3edc64e03..e1cfc6d185f5fe8e2f8a4dc813f2a73b7cdc7f92 100644
--- a/Source/cmake/OptionsGTK.cmake
+++ b/Source/cmake/OptionsGTK.cmake
@@ -3,6 +3,7 @@ include(VersioningUtils)
SET_PROJECT_VERSION(2 29 0)
set(WEBKITGTK_API_VERSION 4.0)
+set(ENABLE_WEBKIT_LEGACY OFF)
CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(WEBKIT 82 0 45)
CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(JAVASCRIPTCORE 35 0 17)
@@ -177,6 +178,13 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_PAINTING_API PRIVATE ${ENABLE_EXPERI
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TYPED_OM PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_CONIC_GRADIENTS PRIVATE ON)
+# Playwright
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_APPLICATION_MANIFEST PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TRAILING_WORD PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LEGACY_CSS_VENDOR_PREFIXES 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 e7ce79997834ddccda17963830bedb1c70d691d4..fb8cf143b12dd5dc83e7ab7be7a9bca9aba6c559 100644
--- a/Source/cmake/OptionsWPE.cmake
+++ b/Source/cmake/OptionsWPE.cmake
@@ -3,6 +3,7 @@ include(VersioningUtils)
SET_PROJECT_VERSION(2 27 4)
set(WPE_API_VERSION 1.0)
+set(ENABLE_WEBKIT_LEGACY OFF)
CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(WEBKIT 12 0 9)
@@ -72,6 +73,14 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBGL2 PRIVATE OFF)
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_RTC PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBXR PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
+# Playwright
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_APPLICATION_MANIFEST PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TRAILING_WORD PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DARK_MODE_CSS PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LEGACY_CSS_VENDOR_PREFIXES 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.
diff --git a/Source/cmake/OptionsWin.cmake b/Source/cmake/OptionsWin.cmake
2020-03-11 22:03:35 +03:00
index 705b2ae2bc5d9ee8f52db307efcd0a1efeddd05d..36da968822e8c00179aa61920607e7d299b7a662 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 ()
2020-03-11 22:03:35 +03:00
@@ -93,6 +94,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/Tools/MiniBrowser/gtk/BrowserTab.c b/Tools/MiniBrowser/gtk/BrowserTab.c
2020-01-27 20:31:27 +03:00
index 9e9978efd3d821c7afcd7b65e14c64e36b355802..a5eef119bddd011470319ac80a0ac443ff0e5441 100644
--- a/Tools/MiniBrowser/gtk/BrowserTab.c
+++ b/Tools/MiniBrowser/gtk/BrowserTab.c
@@ -147,6 +147,11 @@ static void loadChanged(WebKitWebView *webView, WebKitLoadEvent loadEvent, Brows
gtk_container_foreach(GTK_CONTAINER(tab), (GtkCallback)removeChildIfInfoBar, tab);
}
2020-01-27 20:31:27 +03:00
+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);
@@ -457,6 +462,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);
diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.c b/Tools/MiniBrowser/gtk/BrowserWindow.c
index 21c3c3d36b8b9a46a78781e9112ab948d5f667f6..2eb2c45d089d30b281f569d10bc6aee80bbcf06e 100644
--- a/Tools/MiniBrowser/gtk/BrowserWindow.c
+++ b/Tools/MiniBrowser/gtk/BrowserWindow.c
@@ -79,6 +79,8 @@ static const gdouble defaultZoomLevel = 1;
static const gdouble zoomStep = 1.2;
static GList *windowList;
+static gboolean no_quit = false;
+
G_DEFINE_TYPE(BrowserWindow, browser_window, GTK_TYPE_WINDOW)
static char *getExternalURI(const char *uri)
@@ -707,7 +709,7 @@ static void browserWindowFinalize(GObject *gObject)
G_OBJECT_CLASS(browser_window_parent_class)->finalize(gObject);
- if (!windowList)
+ if (!windowList && !no_quit)
gtk_main_quit();
}
@@ -1246,6 +1248,11 @@ void browser_window_set_background_color(BrowserWindow *window, GdkRGBA *rgba)
gtk_widget_set_app_paintable(GTK_WIDGET(window), TRUE);
}
+void browser_window_no_quit(void)
+{
+ no_quit = true;
+}
+
static BrowserWindow *findActiveWindow(void)
{
GList *l;
diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.h b/Tools/MiniBrowser/gtk/BrowserWindow.h
index 1570d65effb5d601ee3c44a2a7461436f4691c2c..65e62adad0c3684e5cec2f6bc8e7f5281e1f77eb 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;
@@ -53,7 +53,7 @@ void browser_window_load_session(BrowserWindow *, const char *sessionFile);
void browser_window_set_background_color(BrowserWindow*, GdkRGBA*);
WebKitWebView* browser_window_get_or_create_web_view_for_automation(void);
WebKitWebView *browser_window_create_web_view_in_new_tab_for_automation(void);
-
+void browser_window_no_quit(void);
G_END_DECLS
#endif
2019-11-19 05:18:28 +03:00
diff --git a/Tools/MiniBrowser/gtk/main.c b/Tools/MiniBrowser/gtk/main.c
index 4c5147dcd38a53e2feaeaae0fce38f92dc60eba6..77d031add801b2f45c9d90e74afab8802aa08e20 100644
2019-11-19 05:18:28 +03:00
--- a/Tools/MiniBrowser/gtk/main.c
+++ b/Tools/MiniBrowser/gtk/main.c
@@ -53,6 +53,10 @@ static const char *cookiesFile;
2019-11-19 05:18:28 +03:00
static const char *cookiesPolicy;
static const char *proxy;
static gboolean darkMode;
+static gboolean inspectorPipe;
+static gboolean headless;
+static gboolean noStartupWindow;
+static const char *userDataDir;
2019-11-19 05:18:28 +03:00
static gboolean printVersion;
typedef enum {
@@ -121,6 +125,10 @@ static const GOptionEntry commandLineOptions[] =
2019-11-19 05:18:28 +03:00
{ "ignore-tls-errors", 0, 0, G_OPTION_ARG_NONE, &ignoreTLSErrors, "Ignore TLS errors", NULL },
{ "content-filter", 0, 0, G_OPTION_ARG_FILENAME, &contentFilter, "JSON with content filtering rules", "FILE" },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WebKitGTK version", NULL },
+ { "inspector-pipe", 0, 0, G_OPTION_ARG_NONE, &inspectorPipe, "Open pipe connection to the remote inspector", NULL },
+ { "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 },
2019-11-19 05:18:28 +03:00
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL…]" },
{ 0, 0, 0, 0, 0, 0, 0 }
};
@@ -498,6 +506,34 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul
2019-11-19 05:18:28 +03:00
g_main_loop_quit(data->mainLoop);
}
+static WebKitWebContext *persistentWebContext = NULL;
+
2019-11-19 05:18:28 +03:00
+static WebKitWebView *createNewPage(WebKitBrowserInspector *browser_inspector, WebKitWebContext *context)
+{
+ if (context == NULL)
+ context = persistentWebContext;
+
2019-11-19 05:18:28 +03:00
+ WebKitWebView *newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", context,
+ "is-ephemeral", webkit_web_context_is_ephemeral(context),
+ "is-controlled-by-automation", TRUE,
+ NULL));
+ GtkWidget *newWindow = browser_window_new(NULL, context);
+ browser_window_append_view(BROWSER_WINDOW(newWindow), newWebView);
+ gtk_widget_grab_focus(GTK_WIDGET(newWebView));
+ gtk_widget_show(GTK_WIDGET(newWindow));
+ webkit_web_view_load_uri(newWebView, "about:blank");
+ return newWebView;
+}
+
+static void configureBrowserInspectorPipe()
2019-11-19 05:18:28 +03:00
+{
+ WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default();
+ g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL);
+
+ webkit_browser_inspector_initialize_pipe(NULL);
2019-11-19 05:18:28 +03:00
+}
+
int main(int argc, char *argv[])
{
#if ENABLE_DEVELOPER_MODE
@@ -541,8 +577,28 @@ int main(int argc, char *argv[])
return 0;
}
- WebKitWebsiteDataManager *manager = (privateMode || automationMode) ? webkit_website_data_manager_new_ephemeral() : webkit_website_data_manager_new(NULL);
+ if (inspectorPipe)
+ configureBrowserInspectorPipe();
+
+ if (noStartupWindow) {
+ browser_window_no_quit();
+ gtk_main();
+ g_clear_object(&webkitSettings);
+ return 0;
+ }
+
+ 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);
+ }
+
2019-11-19 05:18:28 +03:00
WebKitWebContext *webContext = g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, "process-swap-on-cross-site-navigation-enabled", TRUE, NULL);
+ persistentWebContext = webContext;
2019-11-19 05:18:28 +03:00
g_object_unref(manager);
if (cookiesPolicy) {
@@ -648,8 +704,7 @@ int main(int argc, char *argv[])
gtk_main();
- if (privateMode)
- g_object_unref(webContext);
+ g_object_unref(webContext);
return 0;
}
diff --git a/Tools/MiniBrowser/wpe/CMakeLists.txt b/Tools/MiniBrowser/wpe/CMakeLists.txt
index d598df55da9c300c67657a68b87ab008460b051c..6bb9eb7d7b93c0505945868506d7419896092ba2 100644
--- a/Tools/MiniBrowser/wpe/CMakeLists.txt
+++ b/Tools/MiniBrowser/wpe/CMakeLists.txt
@@ -12,6 +12,7 @@ set(MiniBrowser_PRIVATE_INCLUDE_DIRECTORIES
set(MiniBrowser_SYSTEM_INCLUDE_DIRECTORIES
${ATK_INCLUDE_DIRS}
+ ${GLIB_INCLUDE_DIRS}
${WPEBACKEND_FDO_INCLUDE_DIRS}
)
diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp
index a8cccb6c1d567823fe8e6503f1a137856b0a9975..00b39f96b6b48dc0bd3df54659850dfc233ea0be 100644
--- a/Tools/MiniBrowser/wpe/main.cpp
+++ b/Tools/MiniBrowser/wpe/main.cpp
@@ -25,7 +25,7 @@
#include "cmakeconfig.h"
-#include "HeadlessViewBackend.h"
+#include "NullViewBackend.h"
#include "WindowViewBackend.h"
#if ENABLE_WEB_AUDIO || ENABLE_VIDEO
#include <gst/gst.h>
@@ -43,6 +43,9 @@ static gboolean headlessMode;
static gboolean privateMode;
static gboolean automationMode;
static gboolean ignoreTLSErrors;
+static gboolean inspectorPipe;
+static gboolean noStartupWindow;
+static const char* userDataDir;
static const char* contentFilter;
static const char* cookiesFile;
static const char* cookiesPolicy;
@@ -64,6 +67,9 @@ static const GOptionEntry commandLineOptions[] =
{ "content-filter", 0, 0, G_OPTION_ARG_FILENAME, &contentFilter, "JSON with content filtering rules", "FILE" },
{ "bg-color", 0, 0, G_OPTION_ARG_STRING, &bgColor, "Window background color. Default: white", "COLOR" },
{ "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 }
};
@@ -132,7 +138,7 @@ static gboolean decidePermissionRequest(WebKitWebView *, WebKitPermissionRequest
static std::unique_ptr<WPEToolingBackends::ViewBackend> createViewBackend(uint32_t width, uint32_t height)
{
if (headlessMode)
- return std::make_unique<WPEToolingBackends::HeadlessViewBackend>(width, height);
+ return std::make_unique<WPEToolingBackends::NullViewBackend>();
return std::make_unique<WPEToolingBackends::WindowViewBackend>(width, height);
}
@@ -148,13 +154,34 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul
g_main_loop_quit(data->mainLoop);
}
+static gboolean webViewLoadFailed()
+{
+ return TRUE;
+}
+
static void webViewClose(WebKitWebView* webView, gpointer)
{
// Hash table key delete func takes care of unref'ing the view
g_hash_table_remove(openViews, webView);
}
-static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer)
+static gboolean scriptDialog(WebKitWebView*, WebKitScriptDialog* dialog, gpointer)
+{
+ if (inspectorPipe)
+ webkit_script_dialog_ref(dialog);
+ return TRUE;
+}
+
+static gboolean scriptDialogHandled(WebKitWebView*, WebKitScriptDialog* dialog, gpointer)
+{
+ if (inspectorPipe)
+ webkit_script_dialog_unref(dialog);
+ return TRUE;
+}
+
+static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer);
+
+static WebKitWebView* createWebViewImpl(WebKitWebView* webView, WebKitWebContext *webContext)
{
auto backend = createViewBackend(1280, 720);
struct wpe_view_backend* wpeBackend = backend->backend();
@@ -166,16 +193,50 @@ 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));
+ 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, "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 configureBrowserInspector(GMainLoop* mainLoop)
+{
+ WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default();
+ g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL);
+ webkit_browser_inspector_initialize_pipe(mainLoop);
+}
+
int main(int argc, char *argv[])
{
#if ENABLE_DEVELOPER_MODE
@@ -210,6 +271,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();
@@ -219,7 +290,19 @@ int main(int argc, char *argv[])
return 1;
}
- auto* webContext = (privateMode || automationMode) ? webkit_web_context_new_ephemeral() : webkit_web_context_get_default();
+ 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);
+ }
+
+ 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) {
auto* cookieManager = webkit_web_context_get_cookie_manager(webContext);
@@ -300,8 +383,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);
@@ -326,7 +407,7 @@ int main(int argc, char *argv[])
g_object_unref(file);
webkit_web_view_load_uri(webView, url);
g_free(url);
- } else if (automationMode)
+ } else if (automationMode || inspectorPipe)
webkit_web_view_load_uri(webView, "about:blank");
else
webkit_web_view_load_uri(webView, "https://wpewebkit.org");
@@ -336,8 +417,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 44301d5fef9c977dc0228b9de1ae75263efd9014..0c8c7e176a6e02ca04872cdd362d0a8927728557 100644
--- a/Tools/PlatformWin.cmake
+++ b/Tools/PlatformWin.cmake
@@ -10,4 +10,5 @@ endif ()
if (ENABLE_WEBKIT)
add_subdirectory(WebKitTestRunner)
+ add_subdirectory(Playwright/win)
endif ()
diff --git a/Tools/Playwright/Configurations/Base.xcconfig b/Tools/Playwright/Configurations/Base.xcconfig
new file mode 100644
index 0000000000000000000000000000000000000000..fc61d5227c8608488514cbd92a28dc7c1c2efaf4
--- /dev/null
+++ b/Tools/Playwright/Configurations/Base.xcconfig
@@ -0,0 +1,87 @@
+// Copyright (C) 2010-2017 Apple Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include? "../../../../Internal/Configurations/HaveInternalSDK.xcconfig"
+#include "SDKVariant.xcconfig"
+
+USE_INTERNAL_SDK = $(USE_INTERNAL_SDK_$(CONFIGURATION));
+USE_INTERNAL_SDK_Production = YES;
+USE_INTERNAL_SDK_Debug = $(HAVE_INTERNAL_SDK);
+USE_INTERNAL_SDK_Release = $(HAVE_INTERNAL_SDK);
2019-11-19 05:18:28 +03:00
+
+GCC_PREPROCESSOR_DEFINITIONS = DISABLE_LEGACY_WEBKIT_DEPRECATIONS $(inherited);
+
+CLANG_CXX_LANGUAGE_STANDARD = gnu++1z;
+CLANG_CXX_LIBRARY = libc++;
+CLANG_ENABLE_OBJC_WEAK = YES;
+DEBUG_INFORMATION_FORMAT = dwarf-with-dsym;
+PREBINDING = NO
+GCC_C_LANGUAGE_STANDARD = gnu99
+GCC_ENABLE_CPP_EXCEPTIONS = NO;
+GCC_PRECOMPILE_PREFIX_HEADER = YES
+ENABLE_STRICT_OBJC_MSGSEND = YES;
+GCC_TREAT_WARNINGS_AS_ERRORS = YES
+CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+CLANG_WARN_BOOL_CONVERSION = YES;
+CLANG_WARN_COMMA = YES;
+CLANG_WARN_CONSTANT_CONVERSION = YES;
+CLANG_WARN_EMPTY_BODY = YES;
+CLANG_WARN_ENUM_CONVERSION = YES;
+CLANG_WARN_INFINITE_RECURSION = YES;
+CLANG_WARN_INT_CONVERSION = YES;
+CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+CLANG_WARN_STRICT_PROTOTYPES = YES;
+CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+CLANG_WARN_SUSPICIOUS_MOVE = YES;
+CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+CLANG_WARN_UNREACHABLE_CODE = YES;
+GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
+GCC_WARN_ABOUT_RETURN_TYPE = YES;
+GCC_WARN_UNINITIALIZED_AUTOS = YES;
+GCC_WARN_UNUSED_FUNCTION = YES
+GCC_WARN_UNUSED_VARIABLE = YES
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+GCC_WARN_UNDECLARED_SELECTOR = YES;
+CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+WARNING_CFLAGS = -Wall -W -Wno-unused-parameter
+GCC_NO_COMMON_BLOCKS = YES;
+
+SUPPORTED_PLATFORMS = iphoneos iphonesimulator macosx tvos tvsimulator watchos watchsimulator;
+
+TARGET_MAC_OS_X_VERSION_MAJOR = $(TARGET_MAC_OS_X_VERSION_MAJOR$(MACOSX_DEPLOYMENT_TARGET:suffix:identifier));
+TARGET_MAC_OS_X_VERSION_MAJOR_13 = 101300;
+TARGET_MAC_OS_X_VERSION_MAJOR_14 = 101400;
+TARGET_MAC_OS_X_VERSION_MAJOR_15 = 101500;
+TARGET_MAC_OS_X_VERSION_MAJOR_16 = 101600;
+
+SDKROOT = macosx.internal;
+
+OTHER_CFLAGS = $(ASAN_OTHER_CFLAGS);
+OTHER_CPLUSPLUSFLAGS = $(ASAN_OTHER_CPLUSPLUSFLAGS);
+OTHER_LDFLAGS = $(ASAN_OTHER_LDFLAGS);
+
+CODE_SIGN_IDENTITY = -;
diff --git a/Tools/Playwright/Configurations/DebugRelease.xcconfig b/Tools/Playwright/Configurations/DebugRelease.xcconfig
new file mode 100644
index 0000000000000000000000000000000000000000..44dc1139c298bd119368ef4f45bbf0888dc71cdb
--- /dev/null
+++ b/Tools/Playwright/Configurations/DebugRelease.xcconfig
@@ -0,0 +1,45 @@
+// Copyright (C) 2010, 2013 Apple Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "Base.xcconfig"
+
+ARCHS = $(ARCHS_STANDARD_32_64_BIT);
+
+ONLY_ACTIVE_ARCH = YES;
+
+TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR);
+
+MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(TARGET_MAC_OS_X_VERSION_MAJOR))
+MACOSX_DEPLOYMENT_TARGET_101300 = 10.13;
+MACOSX_DEPLOYMENT_TARGET_101400 = 10.14;
+MACOSX_DEPLOYMENT_TARGET_101500 = 10.15;
+MACOSX_DEPLOYMENT_TARGET_101600 = 10.16;
+
+GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
2019-11-19 05:18:28 +03:00
+
+SDKROOT = $(SDKROOT_$(USE_INTERNAL_SDK));
+SDKROOT_ = macosx;
+SDKROOT_YES = macosx.internal;
+
+WK_CCACHE_DIR = $(SRCROOT)/../ccache;
+#include "../../ccache/ccache.xcconfig"
diff --git a/Tools/Playwright/Configurations/Playwright.xcconfig b/Tools/Playwright/Configurations/Playwright.xcconfig
new file mode 100644
index 0000000000000000000000000000000000000000..d05c841a5b0f5fce481f16b8c98caf3a5846db77
--- /dev/null
+++ b/Tools/Playwright/Configurations/Playwright.xcconfig
@@ -0,0 +1,30 @@
+// Copyright (C) 2010 Apple Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+PRODUCT_NAME = Playwright
+PRODUCT_BUNDLE_IDENTIFIER = org.webkit.$(PRODUCT_NAME:rfc1034identifier)
+GCC_PREFIX_HEADER = mac/Playwright_Prefix.pch
+INFOPLIST_FILE = mac/Info.plist
+EXCLUDED_SOURCE_FILE_NAMES[sdk=iphone*] = *
+OTHER_LDFLAGS[sdk=macosx*] = $(inherited) -framework Cocoa -framework WebKit
+STRIP_STYLE = debugging;
diff --git a/Tools/Playwright/Configurations/SDKVariant.xcconfig b/Tools/Playwright/Configurations/SDKVariant.xcconfig
new file mode 100644
index 0000000000000000000000000000000000000000..fcdf7e65a67c61fb19ef19c428652f336c180e8e
--- /dev/null
+++ b/Tools/Playwright/Configurations/SDKVariant.xcconfig
@@ -0,0 +1,45 @@
+// Copyright (C) 2019 Apple Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+WK_EMPTY_ = YES;
+WK_NOT_ = YES;
+WK_NOT_YES = NO;
+
+WK_ALTERNATE_FRAMEWORKS_DIR = $(WK_ALTERNATE_FRAMEWORKS_DIR_$(SDK_VARIANT));
+WK_ALTERNATE_FRAMEWORKS_DIR_iosmac = /System/iOSSupport;
+WK_USE_ALTERNATE_FRAMEWORKS_DIR = $(WK_NOT_$(WK_EMPTY_$(WK_ALTERNATE_FRAMEWORKS_DIR)));
+
+WK_ALTERNATE_PLATFORM_NAME = $(WK_ALTERNATE_PLATFORM_NAME_$(SDK_VARIANT));
+WK_ALTERNATE_PLATFORM_NAME_iosmac = maccatalyst;
+WK_USE_ALTERNATE_PLATFORM_NAME = $(WK_NOT_$(WK_EMPTY_$(WK_ALTERNATE_PLATFORM_NAME)));
+
+WK_ALTERNATE_WEBKIT_SDK_PATH = $(WK_ALTERNATE_WEBKIT_SDK_PATH_$(WK_USE_ALTERNATE_FRAMEWORKS_DIR));
+WK_ALTERNATE_WEBKIT_SDK_PATH_YES = $(WK_ALTERNATE_FRAMEWORKS_DIR)/;
+
+WK_PLATFORM_NAME = $(WK_PLATFORM_NAME_ALTERNATE_$(WK_USE_ALTERNATE_PLATFORM_NAME));
+WK_PLATFORM_NAME_ALTERNATE_YES = $(WK_ALTERNATE_PLATFORM_NAME);
+WK_PLATFORM_NAME_ALTERNATE_NO = $(PLATFORM_NAME);
2019-11-19 05:18:28 +03:00
+
+EFFECTIVE_PLATFORM_NAME = $(EFFECTIVE_PLATFORM_NAME_ALTERNATE_$(WK_USE_ALTERNATE_PLATFORM_NAME));
+EFFECTIVE_PLATFORM_NAME_ALTERNATE_YES = -$(WK_ALTERNATE_PLATFORM_NAME);
+EFFECTIVE_PLATFORM_NAME_ALTERNATE_NO = $(EFFECTIVE_PLATFORM_NAME);
diff --git a/Tools/Playwright/MBToolbarItem.h b/Tools/Playwright/MBToolbarItem.h
new file mode 100644
index 0000000000000000000000000000000000000000..9971d4c1023a9f6e57c6058ae20729e51bb6d503
--- /dev/null
+++ b/Tools/Playwright/MBToolbarItem.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+@interface MBToolbarItem : NSToolbarItem
+@end
diff --git a/Tools/Playwright/MBToolbarItem.m b/Tools/Playwright/MBToolbarItem.m
new file mode 100644
index 0000000000000000000000000000000000000000..56f777891519e820105ae50a86141a534ec4794b
--- /dev/null
+++ b/Tools/Playwright/MBToolbarItem.m
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "MBToolbarItem.h"
+
+@implementation MBToolbarItem
+
+- (void)validate
+{
+ [self setEnabled:[[self target] validateUserInterfaceItem:self]];
+}
+
+@end
diff --git a/Tools/Playwright/Makefile b/Tools/Playwright/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..58e52428388d927ae7681d999e6dd28e0fb3ec6b
--- /dev/null
+++ b/Tools/Playwright/Makefile
@@ -0,0 +1,21 @@
+# Build Playwright only on SnowLeopard and later.
+
+OSX_VERSION ?= $(shell sw_vers -productVersion | cut -d. -f 2)
+BUILD_PLAYWRIGHT = $(shell (( $(OSX_VERSION) >= 6 )) && echo "YES" )
+
+ifeq "$(BUILD_PLAYWRIGHT)" "YES"
+
+SCRIPTS_PATH = ../Scripts
+include ../../Makefile.shared
+
+else
+
+all: ;
+
+debug d development dev develop: ;
+
+release r deployment dep deploy: ;
+
+clean: ;
+
+endif
diff --git a/Tools/Playwright/Playwright.xcodeproj/project.pbxproj b/Tools/Playwright/Playwright.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000000000000000000000000000000000..75a945e72d9fcad94bb89fc6325df18d3259383d
--- /dev/null
+++ b/Tools/Playwright/Playwright.xcodeproj/project.pbxproj
@@ -0,0 +1,264 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 256AC3DA0F4B6AC300CF336A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF336A /* AppDelegate.m */; };
+ 51E244FA11EFCE07008228D2 /* MBToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 51E244F911EFCE07008228D2 /* MBToolbarItem.m */; };
+ BC329487116A92E2008635D1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BC329486116A92E2008635D1 /* main.m */; };
+ BC329498116A941B008635D1 /* BrowserWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC329497116A941B008635D1 /* BrowserWindowController.m */; };
+ BC72B89511E57E07001EB4EB /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58150DA1D0A300B3202A /* MainMenu.xib */; };
+ BC72B89611E57E0F001EB4EB /* BrowserWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC3294A2116A9852008635D1 /* BrowserWindow.xib */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1AFFEF761860EE6800DA465F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+ 1AFFEF781860EE6800DA465F /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
+ 1DDD58150DA1D0A300B3202A /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = mac/MainMenu.xib; sourceTree = "<group>"; };
+ 256AC3D80F4B6AC300CF336A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = mac/AppDelegate.h; sourceTree = "<group>"; };
+ 256AC3D90F4B6AC300CF336A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = mac/AppDelegate.m; sourceTree = "<group>"; };
+ 256AC3F00F4B6AF500CF336A /* Playwright_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Playwright_Prefix.pch; path = mac/Playwright_Prefix.pch; sourceTree = "<group>"; };
+ 29B97324FDCFA39411CA2CEB /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+ 29B97325FDCFA39411CA2CEB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+ 37BAF90620218053000EA87A /* Playwright.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Playwright.entitlements; sourceTree = "<group>"; };
+ 51E244F811EFCE07008228D2 /* MBToolbarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBToolbarItem.h; sourceTree = "<group>"; };
+ 51E244F911EFCE07008228D2 /* MBToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBToolbarItem.m; sourceTree = "<group>"; };
+ 8D1107320486CEB800E47091 /* Playwright.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Playwright.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ A1B89B95221E027A00EB4CEB /* SDKVariant.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = SDKVariant.xcconfig; sourceTree = "<group>"; };
+ BC329486116A92E2008635D1 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = mac/main.m; sourceTree = "<group>"; };
+ BC329496116A941B008635D1 /* BrowserWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BrowserWindowController.h; path = mac/BrowserWindowController.h; sourceTree = "<group>"; };
+ BC329497116A941B008635D1 /* BrowserWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BrowserWindowController.m; path = mac/BrowserWindowController.m; sourceTree = "<group>"; };
+ BC3294A2116A9852008635D1 /* BrowserWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = BrowserWindow.xib; path = mac/BrowserWindow.xib; sourceTree = "<group>"; };
+ BC72B89A11E57E8A001EB4EB /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = mac/Info.plist; sourceTree = "<group>"; };
+ BCA8CBDD11E578A000812FB8 /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
+ BCA8CBDE11E578A000812FB8 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; };
+ BCA8CBDF11E578A000812FB8 /* Playwright.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Playwright.xcconfig; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D11072E0486CEB800E47091 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 080E96DDFE201D6D7F000002 /* Playwright */ = {
+ isa = PBXGroup;
+ children = (
+ 256AC3D80F4B6AC300CF336A /* AppDelegate.h */,
+ 256AC3D90F4B6AC300CF336A /* AppDelegate.m */,
+ BC72B89A11E57E8A001EB4EB /* Info.plist */,
+ BC329486116A92E2008635D1 /* main.m */,
+ 51E244F811EFCE07008228D2 /* MBToolbarItem.h */,
+ 51E244F911EFCE07008228D2 /* MBToolbarItem.m */,
+ 37BAF90620218053000EA87A /* Playwright.entitlements */,
+ BC329496116A941B008635D1 /* BrowserWindowController.h */,
+ BC329497116A941B008635D1 /* BrowserWindowController.m */,
+ );
+ name = Playwright;
+ sourceTree = "<group>";
+ };
+ 1058C7A2FEA54F0111CA2CBC /* Other Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 29B97324FDCFA39411CA2CEB /* AppKit.framework */,
+ 1AFFEF781860EE6800DA465F /* CoreData.framework */,
+ 29B97325FDCFA39411CA2CEB /* Foundation.framework */,
+ );
+ name = "Other Frameworks";
+ sourceTree = "<group>";
+ };
+ 19C28FACFE9D520D11CA2CBC /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D1107320486CEB800E47091 /* Playwright.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEB /* Playwright */ = {
+ isa = PBXGroup;
+ children = (
+ 256AC3F00F4B6AF500CF336A /* Playwright_Prefix.pch */,
+ 080E96DDFE201D6D7F000002 /* Playwright */,
+ 29B97317FDCFA39411CA2CEB /* Resources */,
+ BCA8CBDA11E5787800812FB8 /* Configurations */,
+ 29B97323FDCFA39411CA2CEB /* Frameworks */,
+ 19C28FACFE9D520D11CA2CBC /* Products */,
+ );
+ name = Playwright;
+ sourceTree = "<group>";
+ };
+ 29B97317FDCFA39411CA2CEB /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ BC3294A2116A9852008635D1 /* BrowserWindow.xib */,
+ 1DDD58150DA1D0A300B3202A /* MainMenu.xib */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEB /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 1058C7A2FEA54F0111CA2CBC /* Other Frameworks */,
+ 1AFFEF761860EE6800DA465F /* Cocoa.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ BCA8CBDA11E5787800812FB8 /* Configurations */ = {
+ isa = PBXGroup;
+ children = (
+ BCA8CBDD11E578A000812FB8 /* Base.xcconfig */,
+ BCA8CBDE11E578A000812FB8 /* DebugRelease.xcconfig */,
+ BCA8CBDF11E578A000812FB8 /* Playwright.xcconfig */,
+ A1B89B95221E027A00EB4CEB /* SDKVariant.xcconfig */,
+ );
+ path = Configurations;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8D1107260486CEB800E47091 /* Playwright */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = C01FCF4A08A954540054247C /* Build configuration list for PBXNativeTarget "Playwright" */;
+ buildPhases = (
+ 8D1107290486CEB800E47091 /* Resources */,
+ 8D11072C0486CEB800E47091 /* Sources */,
+ 8D11072E0486CEB800E47091 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Playwright;
+ productInstallPath = "$(HOME)/Applications";
+ productName = Playwright;
+ productReference = 8D1107320486CEB800E47091 /* Playwright.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEC /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0700;
+ LastUpgradeCheck = 1000;
+ TargetAttributes = {
+ 8D1107260486CEB800E47091 = {
+ SystemCapabilities = {
+ com.apple.Sandbox = {
+ enabled = 1;
+ };
+ };
+ };
+ };
+ };
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Playwright" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = en;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 29B97314FDCFA39411CA2CEB /* Playwright */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8D1107260486CEB800E47091 /* Playwright */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D1107290486CEB800E47091 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ BC72B89611E57E0F001EB4EB /* BrowserWindow.xib in Resources */,
+ BC72B89511E57E07001EB4EB /* MainMenu.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D11072C0486CEB800E47091 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 256AC3DA0F4B6AC300CF336A /* AppDelegate.m in Sources */,
+ BC329487116A92E2008635D1 /* main.m in Sources */,
+ 51E244FA11EFCE07008228D2 /* MBToolbarItem.m in Sources */,
+ BC329498116A941B008635D1 /* BrowserWindowController.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ C01FCF4B08A954540054247C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = BCA8CBDF11E578A000812FB8 /* Playwright.xcconfig */;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ C01FCF4C08A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = BCA8CBDF11E578A000812FB8 /* Playwright.xcconfig */;
+ buildSettings = {
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = BCA8CBDE11E578A000812FB8 /* DebugRelease.xcconfig */;
+ buildSettings = {
+ GCC_OPTIMIZATION_LEVEL = 0;
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247C /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = BCA8CBDE11E578A000812FB8 /* DebugRelease.xcconfig */;
+ buildSettings = {
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ C01FCF4A08A954540054247C /* Build configuration list for PBXNativeTarget "Playwright" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4B08A954540054247C /* Debug */,
+ C01FCF4C08A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Playwright" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247C /* Debug */,
+ C01FCF5008A954540054247C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEC /* Project object */;
+}
diff --git a/Tools/Playwright/Playwright.xcodeproj/xcshareddata/xcschemes/Playwright.xcscheme b/Tools/Playwright/Playwright.xcodeproj/xcshareddata/xcschemes/Playwright.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..00fb6b0006c743091a8bbf8edb18b21192ea7d6c
--- /dev/null
+++ b/Tools/Playwright/Playwright.xcodeproj/xcshareddata/xcschemes/Playwright.xcscheme
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1140"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8D1107260486CEB800E47090"
+ BuildableName = "Playwright.app"
+ BlueprintName = "Playwright"
+ ReferencedContainer = "container:Playwright.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8D1107260486CEB800E47090"
+ BuildableName = "Playwright.app"
+ BlueprintName = "Playwright"
+ ReferencedContainer = "container:Playwright.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8D1107260486CEB800E47090"
+ BuildableName = "Playwright.app"
+ BlueprintName = "Playwright"
+ ReferencedContainer = "container:Playwright.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/Tools/Playwright/mac/AppDelegate.h b/Tools/Playwright/mac/AppDelegate.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff88daf2035365d0f1d19c5adc47b467c7d4e980
--- /dev/null
+++ b/Tools/Playwright/mac/AppDelegate.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebKit/_WKBrowserInspector.h>
+#import <WebKit/_WKDownloadDelegate.h>
+
+@interface WebViewDialog : NSObject
+@property (nonatomic, strong) WKWebView *webView;
+@property (nonatomic, copy) void (^completionHandler)(BOOL accept, NSString* value);
+@end
+
+@interface BrowserAppDelegate : NSObject <NSApplicationDelegate, WKNavigationDelegate, WKUIDelegate, _WKBrowserInspectorDelegate, _WKDownloadDelegate> {
+ NSMutableSet *_browserWindowControllers;
+ NSMutableSet *_headlessWindows;
+ NSMutableSet *_browserContexts;
+ bool _headless;
+ bool _noStartupWindow;
+ NSMutableSet *_dialogs;
+ NSString* _initialURL;
+ NSString* _userDataDir;
+ IBOutlet NSMenuItem *_newWebKit2WindowItem;
+}
+
+- (void)browserWindowWillClose:(NSWindow *)window;
+
+@end
+
+@interface NSApplication (PlaywrightApplicationExtensions)
+
+- (BrowserAppDelegate *)browserAppDelegate;
+
+@end
diff --git a/Tools/Playwright/mac/AppDelegate.m b/Tools/Playwright/mac/AppDelegate.m
new file mode 100644
index 0000000000000000000000000000000000000000..6eb18b8f492fe3937d2c38b36b4daebbe2199586
--- /dev/null
+++ b/Tools/Playwright/mac/AppDelegate.m
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "AppDelegate.h"
+
+#import "BrowserWindowController.h"
+#import <WebKit/WKNavigationActionPrivate.h>
+#import <WebKit/WKNavigationDelegatePrivate.h>
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKProcessPoolPrivate.h>
+#import <WebKit/WKUserContentControllerPrivate.h>
+#import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WKWebsiteDataStorePrivate.h>
+#import <WebKit/WebNSURLExtras.h>
+#import <WebKit/WebKit.h>
+#import <WebKit/_WKDownload.h>
+#import <WebKit/_WKExperimentalFeature.h>
+#import <WebKit/_WKInternalDebugFeature.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
+#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
+
+@implementation NSApplication (PlaywrightApplicationExtensions)
+
+- (BrowserAppDelegate *)browserAppDelegate
+{
+ return (BrowserAppDelegate *)[self delegate];
+}
+
+@end
+
+@interface NSApplication (TouchBar)
+@property (getter=isAutomaticCustomizeTouchBarMenuItemEnabled) BOOL automaticCustomizeTouchBarMenuItemEnabled;
+
+@property (readonly, nonatomic) WKWebViewConfiguration *defaultConfiguration;
+
+@end
+
+@implementation WebViewDialog
+- (void)dealloc
+{
+ [_webView release];
+ _webView = nil;
+ [super dealloc];
+}
+@end
+
+enum {
+ _NSBackingStoreUnbuffered = 3
+};
+
+NSString* const ActivityReason = @"Batch headless process";
+const NSActivityOptions ActivityOptions =
+ (NSActivityUserInitiatedAllowingIdleSystemSleep |
+ NSActivityLatencyCritical) &
+ ~(NSActivitySuddenTerminationDisabled |
+ NSActivityAutomaticTerminationDisabled);
+
+@implementation BrowserAppDelegate
+
+- (id)init
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ _initialURL = nil;
+ _userDataDir = nil;
+ NSArray *arguments = [[NSProcessInfo processInfo] arguments];
+ NSRange subargs = NSMakeRange(1, [arguments count] - 1);
+ NSArray *subArray = [arguments subarrayWithRange:subargs];
+
+ for (NSString *argument in subArray) {
+ if (![argument hasPrefix:@"--"])
+ _initialURL = argument;
+ if ([argument hasPrefix:@"--user-data-dir="]) {
+ NSRange range = NSMakeRange(16, [argument length] - 16);
+ _userDataDir = [[argument substringWithRange:range] copy];
+ }
+ }
+
+ _headless = [arguments containsObject: @"--headless"];
+ _noStartupWindow = [arguments containsObject: @"--no-startup-window"];
+ _browserContexts = [[NSMutableSet alloc] init];
+
+ if (_headless) {
+ _headlessWindows = [[NSMutableSet alloc] init];
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
+ [[NSProcessInfo processInfo] beginActivityWithOptions:ActivityOptions
+ reason:ActivityReason];
+ _dialogs = [[NSMutableSet alloc] init];
+ } else {
+ [NSApp activateIgnoringOtherApps:YES];
+ _browserWindowControllers = [[NSMutableSet alloc] init];
+ }
+ if ([arguments containsObject: @"--inspector-pipe"])
+ [_WKBrowserInspector initializeRemoteInspectorPipe:self headless:_headless];
+ return self;
+}
+
+- (void)awakeFromNib
+{
+ if ([NSApp respondsToSelector:@selector(setAutomaticCustomizeTouchBarMenuItemEnabled:)])
+ [NSApp setAutomaticCustomizeTouchBarMenuItemEnabled:YES];
+}
+
+- (WKWebsiteDataStore *)persistentDataStore
+{
+ static WKWebsiteDataStore *dataStore;
+
+ if (!dataStore) {
+ _WKWebsiteDataStoreConfiguration *configuration = [[[_WKWebsiteDataStoreConfiguration alloc] init] autorelease];
+ if (_userDataDir) {
+ NSURL *cookieFile = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/cookie.db", _userDataDir]];
+ [configuration _setCookieStorageFile:cookieFile];
+
+ NSURL *applicationCacheDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/ApplicationCache", _userDataDir]];
+ [configuration setApplicationCacheDirectory:applicationCacheDirectory];
+
+ NSURL *cacheStorageDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/CacheStorage", _userDataDir]];
+ [configuration _setCacheStorageDirectory:cacheStorageDirectory];
+
+ NSURL *indexedDBDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/IndexedDB", _userDataDir]];
+ [configuration _setIndexedDBDatabaseDirectory:indexedDBDirectory];
+
+ NSURL *localStorageDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/LocalStorage", _userDataDir]];
+ [configuration _setWebStorageDirectory:localStorageDirectory];
+
+ NSURL *mediaCacheDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/MediaCache", _userDataDir]];
+ [configuration setMediaCacheDirectory:mediaCacheDirectory];
+
+ NSURL *mediaKeysDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/MediaKeys", _userDataDir]];
+ [configuration setMediaKeysStorageDirectory:mediaKeysDirectory];
+
+ NSURL *networkCacheDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/NetworkCache", _userDataDir]];
+ [configuration setNetworkCacheDirectory:networkCacheDirectory];
+
+ NSURL *loadStatsDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/ResourceLoadStatistics", _userDataDir]];
+ [configuration _setResourceLoadStatisticsDirectory:loadStatsDirectory];
+
+ NSURL *serviceWorkersDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/ServiceWorkers", _userDataDir]];
+ [configuration _setServiceWorkerRegistrationDirectory:serviceWorkersDirectory];
+
+ NSURL *webSqlDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/WebSQL", _userDataDir]];
+ [configuration _setWebSQLDatabaseDirectory:webSqlDirectory];
+ }
+ dataStore = [[WKWebsiteDataStore alloc] _initWithConfiguration:configuration];
+ }
+
+ return dataStore;
+}
+
+- (WKWebViewConfiguration *)defaultConfiguration
+{
+ static WKWebViewConfiguration *configuration;
+
+ if (!configuration) {
+ configuration = [[WKWebViewConfiguration alloc] init];
+ configuration.websiteDataStore = [self persistentDataStore];
+ configuration.preferences._fullScreenEnabled = YES;
+ configuration.preferences._developerExtrasEnabled = YES;
+ configuration.preferences._mediaDevicesEnabled = YES;
+ configuration.preferences._mockCaptureDevicesEnabled = YES;
+ configuration.preferences._hiddenPageDOMTimerThrottlingEnabled = NO;
+ configuration.preferences._hiddenPageDOMTimerThrottlingAutoIncreases = NO;
+ configuration.preferences._pageVisibilityBasedProcessSuppressionEnabled = NO;
+ configuration.preferences._domTimersThrottlingEnabled = NO;
+ configuration.preferences._requestAnimationFrameEnabled = YES;
+ _WKProcessPoolConfiguration *processConfiguration = [[[_WKProcessPoolConfiguration alloc] init] autorelease];
+ processConfiguration.forceOverlayScrollbars = YES;
+ configuration.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration AndDataStore:configuration.websiteDataStore] autorelease];
+ }
+ return configuration;
+}
+
+- (BrowserWindowController *)createBrowserWindowController:(id)sender
+{
+ if (_headless)
+ return nil;
+
+ BrowserWindowController *controller = [[[BrowserWindowController alloc] initWithConfiguration:[self defaultConfiguration]] autorelease];
+ if (!controller)
+ return nil;
+ [_browserWindowControllers addObject:controller];
+ return controller;
+}
+
+- (void)browserWindowWillClose:(NSWindow *)window
+{
+ [_browserWindowControllers removeObject:window.windowController];
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
+{
+ if (!_headless)
+ [self _updateNewWindowKeyEquivalents];
+
+ if (_noStartupWindow)
+ return;
+
+ [self createNewPage:0];
+ _initialURL = nil;
+}
+
+- (BrowserWindowController *)frontmostBrowserWindowController
+{
+ for (NSWindow* window in [NSApp windows]) {
+ id delegate = [window delegate];
+
+ if (![delegate isKindOfClass:[BrowserWindowController class]])
+ continue;
+
+ BrowserWindowController *controller = (BrowserWindowController *)delegate;
+ assert([_browserWindowControllers containsObject:controller]);
+ return controller;
+ }
+
+ return nil;
+}
+
+- (void)_updateNewWindowKeyEquivalents
+{
+ NSString *normalWindowEquivalent = @"n";
+ _newWebKit2WindowItem.keyEquivalentModifierMask = NSEventModifierFlagCommand;
+ _newWebKit2WindowItem.keyEquivalent = normalWindowEquivalent;
+}
+
+#pragma mark WKBrowserInspectorDelegate
+
+- (WKWebViewConfiguration *) sessionConfiguration:(uint64_t)sessionID
+{
+ for (_WKBrowserContext *browserContext in _browserContexts) {
+ if ([[browserContext dataStore] sessionID] != sessionID)
+ continue;
+ WKWebViewConfiguration *configuration = [[[self defaultConfiguration] copy] autorelease];
+ configuration.websiteDataStore = [browserContext dataStore];
+ configuration.processPool = [browserContext processPool];
+ return configuration;
+ }
+ return [self defaultConfiguration];
+}
+
+- (WKWebView *)createNewPage:(uint64_t)sessionID
+{
+ NSString* urlString = _initialURL ? _initialURL : @"about:blank";
+ WKWebViewConfiguration *configuration = [self sessionConfiguration:sessionID];
+ if (_headless)
+ return [self createHeadlessPage:configuration withURL:urlString];
+ return [self createHeadfulPage:configuration withURL:urlString];
+}
+
+- (WKWebView *)createHeadfulPage:(WKWebViewConfiguration *)configuration withURL:(NSString*)urlString
+{
+
+ BrowserWindowController *controller = [[[BrowserWindowController alloc] initWithConfiguration:configuration] autorelease];
+ if (!controller)
+ return nil;
+ [[controller window] makeKeyAndOrderFront:nil];
+ [_browserWindowControllers addObject:controller];
+ [controller loadURLString:urlString];
+ return [controller webView];
+}
+
+- (WKWebView *)createHeadlessPage:(WKWebViewConfiguration *)configuration withURL:(NSString*)urlString
+{
+ NSRect rect = NSMakeRect(0, 0, 1024, 768);
+ NSScreen *firstScreen = [[NSScreen screens] objectAtIndex:0];
+ NSRect windowRect = NSOffsetRect(rect, -10000, [firstScreen frame].size.height - rect.size.height + 10000);
+ NSWindow* window = [[NSWindow alloc] initWithContentRect:windowRect styleMask:NSWindowStyleMaskBorderless backing:(NSBackingStoreType)_NSBackingStoreUnbuffered defer:YES];
+
+ WKWebView* webView = [[WKWebView alloc] initWithFrame:[window.contentView bounds] configuration:configuration];
+ webView._windowOcclusionDetectionEnabled = NO;
+ if (!webView)
+ return nil;
+
+ webView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
+ [window.contentView addSubview:webView];
+ if (urlString) {
+ NSURL *url = [NSURL _webkit_URLWithUserTypedString:urlString];
+ [webView loadRequest:[NSURLRequest requestWithURL:url]];
+ }
+ [_headlessWindows addObject:window];
+ webView.navigationDelegate = self;
+ webView.UIDelegate = self;
+ return [webView autorelease];
+}
+
+- (_WKBrowserContext *)createBrowserContext
+{
+ _WKBrowserContext *browserContext = [[_WKBrowserContext alloc] init];
+ _WKProcessPoolConfiguration *processConfiguration = [[[_WKProcessPoolConfiguration alloc] init] autorelease];
+ processConfiguration.forceOverlayScrollbars = YES;
+ browserContext.dataStore = [WKWebsiteDataStore nonPersistentDataStore];
+ browserContext.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration] autorelease];
+ [browserContext.processPool _setDownloadDelegate:self];
+ [_browserContexts addObject:browserContext];
+ return browserContext;
+}
+
+- (void)deleteBrowserContext:(uint64_t)sessionID
+{
+ for (_WKBrowserContext *browserContext in _browserContexts) {
+ if ([[browserContext dataStore] sessionID] != sessionID)
+ continue;
+ [_browserContexts removeObject:browserContext];
+ return;
+ }
+}
+
+- (void)quit
+{
+ [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
+}
+
+#pragma mark WKUIDelegate
+
+- (void)webViewDidClose:(WKWebView *)webView {
+ for (NSWindow *window in _headlessWindows) {
+ if (webView.window != window)
+ continue;
+ [webView removeFromSuperview];
+ [window close];
+ [_headlessWindows removeObject:window];
+ break;
+ }
+}
+
+- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
+{
+ WebViewDialog* dialog = [[WebViewDialog alloc] autorelease];
+ dialog.webView = webView;
+ dialog.completionHandler = ^void (BOOL accept, NSString* value) {
+ completionHandler();
+ };
+ [_dialogs addObject:dialog];
+}
+
+- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
+{
+ WebViewDialog* dialog = [[WebViewDialog alloc] autorelease];
+ dialog.webView = webView;
+ dialog.completionHandler = ^void (BOOL accept, NSString* value) {
+ completionHandler(accept);
+ };
+ [_dialogs addObject:dialog];
+}
+
+- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *result))completionHandler
+{
+ WebViewDialog* dialog = [[WebViewDialog alloc] autorelease];
+ dialog.webView = webView;
+ dialog.completionHandler = ^void (BOOL accept, NSString* value) {
+ completionHandler(accept && value ? value : nil);
+ };
+ [_dialogs addObject:dialog];
+}
+
+- (void)_webView:(WKWebView *)webView runBeforeUnloadConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
+{
+ WebViewDialog* dialog = [[WebViewDialog alloc] autorelease];
+ dialog.webView = webView;
+ dialog.completionHandler = ^void (BOOL accept, NSString* value) {
+ completionHandler(accept);
+ };
+ [_dialogs addObject:dialog];
+}
+
+- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(NSString *)value
+{
+ for (WebViewDialog *dialog in _dialogs) {
+ if (dialog.webView != webView)
+ continue;
+ dialog.completionHandler(accept, value);
+ [_dialogs removeObject:dialog];
+ break;
+ }
+}
+
+- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
+{
+ return [self createHeadlessPage:configuration withURL:nil];
+}
+
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
+{
+ LOG(@"decidePolicyForNavigationAction");
+
+ if (navigationAction._canHandleRequest) {
+ decisionHandler(WKNavigationActionPolicyAllow);
+ return;
+ }
+ decisionHandler(WKNavigationActionPolicyCancel);
+}
+
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
+{
+ if (![navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]]) {
+ decisionHandler(WKNavigationResponsePolicyAllow);
+ return;
+ }
+ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)navigationResponse.response;
+
+ NSString *disposition = [[httpResponse allHeaderFields] objectForKey:@"Content-Disposition"];
+ if (disposition && [disposition hasPrefix:@"attachment"]) {
+ decisionHandler(_WKNavigationResponsePolicyBecomeDownload);
+ return;
+ }
+ decisionHandler(WKNavigationResponsePolicyAllow);
+}
+
+#pragma mark _WKDownloadDelegate
+
+- (void)_download:(_WKDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename completionHandler:(void (^)(BOOL allowOverwrite, NSString *destination))completionHandler
+{
+ completionHandler(NO, @"");
+}
+
+@end
diff --git a/Tools/Playwright/mac/BrowserWindow.xib b/Tools/Playwright/mac/BrowserWindow.xib
new file mode 100644
index 0000000000000000000000000000000000000000..f6f3d8e3a0f163e61b2f3d54819e9d25a0a3eb75
--- /dev/null
+++ b/Tools/Playwright/mac/BrowserWindow.xib
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11191" systemVersion="16D17a" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
+ <dependencies>
+ <deployment identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11191"/>
+ </dependencies>
+ <objects>
+ <customObject id="-2" userLabel="File's Owner" customClass="BrowserWindowController">
+ <connections>
+ <outlet property="backButton" destination="40" id="46"/>
+ <outlet property="containerView" destination="9" id="37"/>
+ <outlet property="forwardButton" destination="42" id="47"/>
+ <outlet property="progressIndicator" destination="21" id="33"/>
+ <outlet property="reloadButton" destination="23" id="34"/>
+ <outlet property="share" destination="1hB-AH-eUl" id="si4-8e-DsM"/>
+ <outlet property="toggleUseShrinkToFitButton" destination="82" id="9w7-AB-Ye3"/>
+ <outlet property="toolbar" destination="48" id="67"/>
+ <outlet property="urlText" destination="10" id="32"/>
+ <outlet property="window" destination="1" id="3"/>
+ </connections>
+ </customObject>
+ <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+ <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" frameAutosaveName="Main Window" animationBehavior="default" id="1">
+ <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" unifiedTitleAndToolbar="YES" fullSizeContentView="YES"/>
+ <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+ <rect key="contentRect" x="517" y="330" width="776" height="608"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1177"/>
+ <view key="contentView" id="2">
+ <rect key="frame" x="0.0" y="0.0" width="776" height="608"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <customView id="9">
+ <rect key="frame" x="0.0" y="0.0" width="776" height="608"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ </customView>
+ </subviews>
+ </view>
+ <toolbar key="toolbar" implicitIdentifier="994A0CB1-7575-4F39-A65B-7165AB1E8015" displayMode="iconOnly" sizeMode="regular" id="48">
+ <allowedToolbarItems>
+ <toolbarItem implicitItemIdentifier="73DE9F4B-73E2-4036-A134-2D9E029DA980" label="Go Back" paletteLabel="Go Back" image="NSGoLeftTemplate" id="56" customClass="MBToolbarItem">
+ <nil key="toolTip"/>
+ <size key="minSize" width="32" height="27"/>
+ <size key="maxSize" width="32" height="25"/>
+ <button key="view" verticalHuggingPriority="750" id="40">
+ <rect key="frame" x="10" y="14" width="32" height="25"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSGoLeftTemplate" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="41">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ </button>
+ <connections>
+ <action selector="goBack:" target="-2" id="61"/>
+ </connections>
+ </toolbarItem>
+ <toolbarItem implicitItemIdentifier="E1A9D32A-59E3-467B-9ABA-A95780416E69" label="Go Forward" paletteLabel="Go Forward" image="NSGoRightTemplate" id="57" customClass="MBToolbarItem">
+ <nil key="toolTip"/>
+ <size key="minSize" width="32" height="27"/>
+ <size key="maxSize" width="32" height="27"/>
+ <button key="view" verticalHuggingPriority="750" id="42">
+ <rect key="frame" x="18" y="14" width="32" height="25"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSGoRightTemplate" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="43">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ </button>
+ <connections>
+ <action selector="goForward:" target="-2" id="62"/>
+ </connections>
+ </toolbarItem>
+ <toolbarItem implicitItemIdentifier="88C16109-D40F-4682-BCE4-CBEE2EDE32D2" label="Refresh" paletteLabel="Refresh" image="NSRefreshTemplate" id="58" customClass="MBToolbarItem">
+ <nil key="toolTip"/>
+ <size key="minSize" width="29" height="27"/>
+ <size key="maxSize" width="29" height="27"/>
+ <button key="view" verticalHuggingPriority="750" id="23">
+ <rect key="frame" x="10" y="14" width="29" height="25"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSRefreshTemplate" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="24">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="reload:" target="-2" id="35"/>
+ </connections>
+ </button>
+ </toolbarItem>
+ <toolbarItem implicitItemIdentifier="F1738B7F-895C-48F7-955D-0915E150BE1B" label="Share" paletteLabel="Share" image="NSShareTemplate" id="dJx-dw-gcC" customClass="MBToolbarItem">
+ <nil key="toolTip"/>
+ <size key="minSize" width="29" height="27"/>
+ <size key="maxSize" width="29" height="27"/>
+ <button key="view" verticalHuggingPriority="750" id="1hB-AH-eUl">
+ <rect key="frame" x="5" y="14" width="29" height="25"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSShareTemplate" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="S1v-UD-QhI">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <connections>
+ <action selector="share:" target="-2" id="5e3-hg-bKN"/>
+ </connections>
+ </buttonCell>
+ </button>
+ </toolbarItem>
+ <toolbarItem implicitItemIdentifier="255D29F2-C9AA-4B4B-BB43-B38FCD6A0BBB" label="Location" paletteLabel="Location" id="59">
+ <nil key="toolTip"/>
+ <size key="minSize" width="200" height="22"/>
+ <size key="maxSize" width="100000" height="22"/>
+ <textField key="view" verticalHuggingPriority="750" id="10">
+ <rect key="frame" x="0.0" y="14" width="565" height="22"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="11">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ <connections>
+ <action selector="fetch:" target="-2" id="36"/>
+ </connections>
+ </textField>
+ </toolbarItem>
+ <toolbarItem implicitItemIdentifier="86912BAA-B8D0-400F-BFEE-71FC166986E6" label="Progress" paletteLabel="Progress" tag="-1" id="60">
+ <nil key="toolTip"/>
+ <size key="minSize" width="16" height="16"/>
+ <size key="maxSize" width="16" height="16"/>
+ <progressIndicator key="view" horizontalHuggingPriority="750" verticalHuggingPriority="750" maxValue="1" displayedWhenStopped="NO" bezeled="NO" controlSize="small" style="spinning" id="21">
+ <rect key="frame" x="19" y="14" width="16" height="16"/>
+ <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
+ </progressIndicator>
+ </toolbarItem>
+ </allowedToolbarItems>
+ <defaultToolbarItems>
+ <toolbarItem reference="56"/>
+ <toolbarItem reference="57"/>
+ <toolbarItem reference="58"/>
+ <toolbarItem reference="59"/>
+ <toolbarItem reference="60"/>
+ <toolbarItem reference="dJx-dw-gcC"/>
+ </defaultToolbarItems>
+ </toolbar>
+ <connections>
+ <outlet property="delegate" destination="-2" id="4"/>
+ </connections>
+ </window>
+ </objects>
+ <resources>
+ <image name="NSEnterFullScreenTemplate" width="15" height="15"/>
+ <image name="NSGoLeftTemplate" width="9" height="12"/>
+ <image name="NSGoRightTemplate" width="9" height="12"/>
+ <image name="NSRefreshTemplate" width="11" height="15"/>
+ <image name="NSShareTemplate" width="11" height="16"/>
+ </resources>
+</document>
diff --git a/Tools/Playwright/mac/BrowserWindowController.h b/Tools/Playwright/mac/BrowserWindowController.h
new file mode 100644
index 0000000000000000000000000000000000000000..4dbf13c8fb31a745ae8e1965a457d4fbcd8e5866
--- /dev/null
+++ b/Tools/Playwright/mac/BrowserWindowController.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+@class WKWebView;
+
+@interface BrowserWindowController : NSWindowController
+
+- (IBAction)goBack:(id)sender;
+- (IBAction)goForward:(id)sender;
+- (IBAction)reload:(id)sender;
+- (IBAction)saveAsPDF:(id)sender;
+- (IBAction)saveAsWebArchive:(id)sender;
+- (IBAction)zoomIn:(id)sender;
+- (IBAction)zoomOut:(id)sender;
+- (IBAction)resetZoom:(id)sender;
+- (IBAction)showHideWebInspector:(id)sender;
+
+- (IBAction)setPageScale:(id)sender;
+- (IBAction)setViewScale:(id)sender;
+- (instancetype)initWithConfiguration:(WKWebViewConfiguration *)configuration;
+- (void)loadURLString:(NSString *)urlString;
+- (WKWebView *)webView;
+
+@end
diff --git a/Tools/Playwright/mac/BrowserWindowController.m b/Tools/Playwright/mac/BrowserWindowController.m
new file mode 100644
index 0000000000000000000000000000000000000000..8d4cf055b4e93f2990801cfbddc20182534ce594
--- /dev/null
+++ b/Tools/Playwright/mac/BrowserWindowController.m
@@ -0,0 +1,838 @@
+/*
+ * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "BrowserWindowController.h"
+
+#import "AppDelegate.h"
+#import <WebKit/WKFrameInfo.h>
+#import <WebKit/WKNavigationActionPrivate.h>
+#import <WebKit/WKNavigationDelegatePrivate.h>
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKUIDelegate.h>
+#import <WebKit/WKUIDelegatePrivate.h>
+#import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WKWebViewPrivateForTesting.h>
+#import <WebKit/WKWebsiteDataStorePrivate.h>
+#import <WebKit/WebNSURLExtras.h>
+#import <WebKit/_WKIconLoadingDelegate.h>
+#import <WebKit/_WKInspector.h>
+#import <WebKit/_WKLinkIconParameters.h>
+#import <WebKit/_WKUserInitiatedAction.h>
+
+static void* keyValueObservingContext = &keyValueObservingContext;
+
+@interface PlaywrightNSTextFinder : NSTextFinder
+
+@property (nonatomic, copy) dispatch_block_t hideInterfaceCallback;
+
+@end
+
+@implementation PlaywrightNSTextFinder
+
+- (void)performAction:(NSTextFinderAction)op
+{
+ [super performAction:op];
+
+ if (op == NSTextFinderActionHideFindInterface && _hideInterfaceCallback)
+ _hideInterfaceCallback();
+}
+
+@end
+
+@interface BrowserWindowController () <NSTextFinderBarContainer, WKNavigationDelegate, WKUIDelegate, _WKIconLoadingDelegate, NSSharingServicePickerDelegate, NSSharingServiceDelegate>
+@end
+
+@implementation BrowserWindowController {
+ IBOutlet NSProgressIndicator *progressIndicator;
+ IBOutlet NSButton *reloadButton;
+ IBOutlet NSButton *backButton;
+ IBOutlet NSButton *forwardButton;
+ IBOutlet NSButton *share;
+ IBOutlet NSToolbar *toolbar;
+ IBOutlet NSTextField *urlText;
+ IBOutlet NSView *containerView;
+ IBOutlet NSButton *toggleUseShrinkToFitButton;
+
+ WKWebViewConfiguration *_configuration;
+ WKWebView *_webView;
+ BOOL _zoomTextOnly;
+ BOOL _isPrivateBrowsingWindow;
+ NSAlert* _alert;
+
+ BOOL _useShrinkToFit;
+
+ PlaywrightNSTextFinder *_textFinder;
+ NSView *_textFindBarView;
+ BOOL _findBarVisible;
+}
+
+- (id)initWithWindow:(NSWindow *)window
+{
+ self = [super initWithWindow:window];
+ return self;
+}
+
+- (void)windowDidLoad
+{
+ [share sendActionOn:NSEventMaskLeftMouseDown];
+ [super windowDidLoad];
+}
+
+- (IBAction)openLocation:(id)sender
+{
+ [[self window] makeFirstResponder:urlText];
+}
+
+- (NSString *)addProtocolIfNecessary:(NSString *)address
+{
+ if ([address rangeOfString:@"://"].length > 0)
+ return address;
+
+ if ([address hasPrefix:@"data:"])
+ return address;
+
+ if ([address hasPrefix:@"about:"])
+ return address;
+
+ return [@"http://" stringByAppendingString:address];
+}
+
+- (IBAction)share:(id)sender
+{
+ NSSharingServicePicker *picker = [[NSSharingServicePicker alloc] initWithItems:@[ self.currentURL ]];
+ picker.delegate = self;
+ [picker showRelativeToRect:NSZeroRect ofView:sender preferredEdge:NSRectEdgeMinY];
+}
+
+- (IBAction)showHideWebView:(id)sender
+{
+ self.mainContentView.hidden = !self.mainContentView.isHidden;
+}
+
+- (CGFloat)pageScaleForMenuItemTag:(NSInteger)tag
+{
+ if (tag == 1)
+ return 1;
+ if (tag == 2)
+ return 1.25;
+ if (tag == 3)
+ return 1.5;
+ if (tag == 4)
+ return 2.0;
+
+ return 1;
+}
+
+- (void)awakeFromNib
+{
+ _webView = [[WKWebView alloc] initWithFrame:[containerView bounds] configuration:_configuration];
+ _webView._windowOcclusionDetectionEnabled = NO;
+
+ _webView.allowsMagnification = YES;
+ _webView.allowsBackForwardNavigationGestures = YES;
+
+ [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
+ [containerView addSubview:_webView];
+
+ [progressIndicator bind:NSHiddenBinding toObject:_webView withKeyPath:@"loading" options:@{ NSValueTransformerNameBindingOption : NSNegateBooleanTransformerName }];
+ [progressIndicator bind:NSValueBinding toObject:_webView withKeyPath:@"estimatedProgress" options:nil];
+
+ [_webView addObserver:self forKeyPath:@"title" options:0 context:keyValueObservingContext];
+ [_webView addObserver:self forKeyPath:@"URL" options:0 context:keyValueObservingContext];
+
+ _webView.navigationDelegate = self;
+ _webView.UIDelegate = self;
+
+ _webView._observedRenderingProgressEvents = _WKRenderingProgressEventFirstLayout
+ | _WKRenderingProgressEventFirstVisuallyNonEmptyLayout
+ | _WKRenderingProgressEventFirstPaintWithSignificantArea
+ | _WKRenderingProgressEventFirstLayoutAfterSuppressedIncrementalRendering
+ | _WKRenderingProgressEventFirstPaintAfterSuppressedIncrementalRendering;
+
+ _webView.customUserAgent = @"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15";
+
+ _webView._usePlatformFindUI = NO;
+
+ _textFinder = [[PlaywrightNSTextFinder alloc] init];
+ _textFinder.incrementalSearchingEnabled = YES;
+ _textFinder.incrementalSearchingShouldDimContentView = NO;
+ _textFinder.client = _webView;
+ _textFinder.findBarContainer = self;
+ _textFinder.hideInterfaceCallback = ^{
+ [_webView _hideFindUI];
+ };
+
+ _zoomTextOnly = NO;
+}
+
+- (instancetype)initWithConfiguration:(WKWebViewConfiguration *)configuration
+{
+ if (!(self = [super initWithWindowNibName:@"BrowserWindow"]))
+ return nil;
+ _configuration = [configuration copy];
+ _isPrivateBrowsingWindow = !_configuration.websiteDataStore.isPersistent;
+ self.window.styleMask &= ~NSWindowStyleMaskFullSizeContentView;
+ return self;
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ [progressIndicator unbind:NSHiddenBinding];
+ [progressIndicator unbind:NSValueBinding];
+
+ [_textFinder release];
+ [_webView release];
+ [_configuration release];
+
+ [super dealloc];
+}
+
+- (IBAction)fetch:(id)sender
+{
+ [urlText setStringValue:[self addProtocolIfNecessary:urlText.stringValue]];
+ NSURL *url = [NSURL _webkit_URLWithUserTypedString:urlText.stringValue];
+ [_webView loadRequest:[NSURLRequest requestWithURL:url]];
+}
+
+- (IBAction)setPageScale:(id)sender
+{
+ CGFloat scale = [self pageScaleForMenuItemTag:[sender tag]];
+ [_webView _setPageScale:scale withOrigin:CGPointZero];
+}
+
+- (CGFloat)viewScaleForMenuItemTag:(NSInteger)tag
+{
+ if (tag == 1)
+ return 1;
+ if (tag == 2)
+ return 0.75;
+ if (tag == 3)
+ return 0.5;
+ if (tag == 4)
+ return 0.25;
+
+ return 1;
+}
+
+- (IBAction)setViewScale:(id)sender
+{
+ CGFloat scale = [self viewScaleForMenuItemTag:[sender tag]];
+ CGFloat oldScale = [_webView _viewScale];
+
+ if (scale == oldScale)
+ return;
+
+ [_webView _setLayoutMode:_WKLayoutModeDynamicSizeComputedFromViewScale];
+
+ NSRect oldFrame = self.window.frame;
+ NSSize newFrameSize = NSMakeSize(oldFrame.size.width * (scale / oldScale), oldFrame.size.height * (scale / oldScale));
+ [self.window setFrame:NSMakeRect(oldFrame.origin.x, oldFrame.origin.y - (newFrameSize.height - oldFrame.size.height), newFrameSize.width, newFrameSize.height) display:NO animate:NO];
+
+ [_webView _setViewScale:scale];
+}
+
+static BOOL areEssentiallyEqual(double a, double b)
+{
+ double tolerance = 0.001;
+ return (fabs(a - b) <= tolerance);
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-implementations"
+- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
+#pragma GCC diagnostic pop
+{
+ SEL action = menuItem.action;
+
+ if (action == @selector(saveAsPDF:))
+ return YES;
+ if (action == @selector(saveAsWebArchive:))
+ return YES;
+
+ if (action == @selector(zoomIn:))
+ return [self canZoomIn];
+ if (action == @selector(zoomOut:))
+ return [self canZoomOut];
+ if (action == @selector(resetZoom:))
+ return [self canResetZoom];
+
+ if (action == @selector(toggleZoomMode:))
+ [menuItem setState:_zoomTextOnly ? NSControlStateValueOn : NSControlStateValueOff];
+ else if (action == @selector(showHideWebInspector:))
+ [menuItem setTitle:_webView._inspector.isVisible ? @"Close Web Inspector" : @"Show Web Inspector"];
+
+ if (action == @selector(setPageScale:))
+ [menuItem setState:areEssentiallyEqual([_webView _pageScale], [self pageScaleForMenuItemTag:[menuItem tag]])];
+
+ if (action == @selector(setViewScale:))
+ [menuItem setState:areEssentiallyEqual([_webView _viewScale], [self viewScaleForMenuItemTag:[menuItem tag]])];
+
+ return YES;
+}
+
+- (IBAction)reload:(id)sender
+{
+ [_webView reload];
+}
+
+- (IBAction)goBack:(id)sender
+{
+ [_webView goBack];
+}
+
+- (IBAction)goForward:(id)sender
+{
+ [_webView goForward];
+}
+
+- (IBAction)toggleZoomMode:(id)sender
+{
+ if (_zoomTextOnly) {
+ _zoomTextOnly = NO;
+ double currentTextZoom = _webView._textZoomFactor;
+ _webView._textZoomFactor = 1;
+ _webView.pageZoom = currentTextZoom;
+ } else {
+ _zoomTextOnly = YES;
+ double currentPageZoom = _webView._pageZoomFactor;
+ _webView._textZoomFactor = currentPageZoom;
+ _webView.pageZoom = 1;
+ }
+}
+
+- (IBAction)resetZoom:(id)sender
+{
+ if (![self canResetZoom])
+ return;
+
+ if (_zoomTextOnly)
+ _webView._textZoomFactor = 1;
+ else
+ _webView.pageZoom = 1;
+}
+
+- (BOOL)canResetZoom
+{
+ return _zoomTextOnly ? (_webView._textZoomFactor != 1) : (_webView.pageZoom != 1);
+}
+
+- (IBAction)showHideWebInspector:(id)sender
+{
+ _WKInspector *inspector = _webView._inspector;
+ if (inspector.isVisible)
+ [inspector hide];
+ else
+ [inspector show];
+}
+
+- (NSURL *)currentURL
+{
+ return _webView.URL;
+}
+
+- (NSView *)mainContentView
+{
+ return _webView;
+}
+
+- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
+{
+ SEL action = item.action;
+
+ if (action == @selector(goBack:) || action == @selector(goForward:))
+ return [_webView validateUserInterfaceItem:item];
+
+ return YES;
+}
+
+- (void)validateToolbar
+{
+ [toolbar validateVisibleItems];
+}
+
+- (BOOL)windowShouldClose:(id)sender
+{
+ return YES;
+}
+
+- (void)windowWillClose:(NSNotification *)notification
+{
+ [[[NSApplication sharedApplication] browserAppDelegate] browserWindowWillClose:self.window];
+ [_webView removeObserver:self forKeyPath:@"title"];
+ [_webView removeObserver:self forKeyPath:@"URL"];
+ [self autorelease];
+}
+
+- (void)webViewDidClose:(WKWebView *)webView {
+ [self.window close];
+}
+
+#define DefaultMinimumZoomFactor (.5)
+#define DefaultMaximumZoomFactor (3.0)
+#define DefaultZoomFactorRatio (1.2)
+
+- (CGFloat)currentZoomFactor
+{
+ return _zoomTextOnly ? _webView._textZoomFactor : _webView.pageZoom;
+}
+
+- (void)setCurrentZoomFactor:(CGFloat)factor
+{
+ if (_zoomTextOnly)
+ _webView._textZoomFactor = factor;
+ else
+ _webView.pageZoom = factor;
+}
+
+- (BOOL)canZoomIn
+{
+ return self.currentZoomFactor * DefaultZoomFactorRatio < DefaultMaximumZoomFactor;
+}
+
+- (void)zoomIn:(id)sender
+{
+ if (!self.canZoomIn)
+ return;
+
+ self.currentZoomFactor *= DefaultZoomFactorRatio;
+}
+
+- (BOOL)canZoomOut
+{
+ return self.currentZoomFactor / DefaultZoomFactorRatio > DefaultMinimumZoomFactor;
+}
+
+- (void)zoomOut:(id)sender
+{
+ if (!self.canZoomIn)
+ return;
+
+ self.currentZoomFactor /= DefaultZoomFactorRatio;
+}
+
+- (void)updateTitle:(NSString *)title
+{
+ if (!title) {
+ NSURL *url = _webView.URL;
+ title = url.lastPathComponent ?: url._web_userVisibleString;
+ }
+
+ self.window.title = [NSString stringWithFormat:@"%@%@ [%d]%@", _isPrivateBrowsingWindow ? @"🙈 " : @"", title, _webView._webProcessIdentifier, @""];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+ if (context != keyValueObservingContext || object != _webView)
+ return;
+
+ if ([keyPath isEqualToString:@"title"])
+ [self updateTitle:_webView.title];
+ else if ([keyPath isEqualToString:@"URL"])
+ [self updateTextFieldFromURL:_webView.URL];
+}
+
+- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
+{
+ BrowserWindowController *controller = [[BrowserWindowController alloc] initWithConfiguration:configuration];
+ [controller.window makeKeyAndOrderFront:self];
+
+ return controller->_webView;
+}
+
+- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
+{
+ NSAlert* alert = [[NSAlert alloc] init];
+
+ [alert setMessageText:[NSString stringWithFormat:@"JavaScript alert dialog from %@.", [frame.request.URL absoluteString]]];
+ [alert setInformativeText:message];
+ [alert addButtonWithTitle:@"OK"];
+
+ _alert = alert;
+ [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) {
+ completionHandler();
+ [alert release];
+ _alert = nil;
+ }];
+}
+
+- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
+{
+ NSAlert* alert = [[NSAlert alloc] init];
+
+ [alert setMessageText:[NSString stringWithFormat:@"JavaScript confirm dialog from %@.", [frame.request.URL absoluteString]]];
+ [alert setInformativeText:message];
+
+ [alert addButtonWithTitle:@"OK"];
+ [alert addButtonWithTitle:@"Cancel"];
+
+ _alert = alert;
+ [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) {
+ completionHandler(response == NSAlertFirstButtonReturn);
+ [alert release];
+ _alert = nil;
+ }];
+}
+
+- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *result))completionHandler
+{
+ NSAlert* alert = [[NSAlert alloc] init];
+
+ [alert setMessageText:[NSString stringWithFormat:@"JavaScript prompt dialog from %@.", [frame.request.URL absoluteString]]];
+ [alert setInformativeText:prompt];
+
+ [alert addButtonWithTitle:@"OK"];
+ [alert addButtonWithTitle:@"Cancel"];
+
+ NSTextField* input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
+ [input setStringValue:defaultText];
+ [alert setAccessoryView:input];
+
+ _alert = alert;
+ [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) {
+ [input validateEditing];
+ completionHandler(response == NSAlertFirstButtonReturn ? [input stringValue] : nil);
+ [alert release];
+ _alert = nil;
+ }];
+}
+
+- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(NSString *)value
+{
+ if (!_alert)
+ return;
+ NSTextField* input = (NSTextField*)_alert.accessoryView;
+ if (accept && input && value)
+ [input setStringValue:value];
+ [self.window endSheet:_alert.window returnCode: accept ? NSAlertFirstButtonReturn : NSModalResponseCancel];
+}
+
+#if __has_feature(objc_generics)
+- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray<NSURL *> * URLs))completionHandler
+#else
+- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray *URLs))completionHandler
+#endif
+{
+ NSOpenPanel *openPanel = [NSOpenPanel openPanel];
+
+ openPanel.allowsMultipleSelection = parameters.allowsMultipleSelection;
+
+ [openPanel beginSheetModalForWindow:webView.window completionHandler:^(NSInteger result) {
+ if (result == NSModalResponseOK)
+ completionHandler(openPanel.URLs);
+ else
+ completionHandler(nil);
+ }];
+}
+
+- (void)_webView:(WebView *)sender runBeforeUnloadConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
+{
+ NSAlert *alert = [[NSAlert alloc] init];
+
+ alert.messageText = [NSString stringWithFormat:@"JavaScript before unload dialog from %@.", [frame.request.URL absoluteString]];
+ alert.informativeText = message;
+
+ [alert addButtonWithTitle:@"Leave Page"];
+ [alert addButtonWithTitle:@"Stay On Page"];
+
+ _alert = alert;
+ [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) {
+ completionHandler(response == NSAlertFirstButtonReturn);
+ [alert release];
+ _alert = nil;
+ }];
+}
+
+- (WKDragDestinationAction)_webView:(WKWebView *)webView dragDestinationActionMaskForDraggingInfo:(id)draggingInfo
+{
+ return WKDragDestinationActionAny;
+}
+
+- (void)updateTextFieldFromURL:(NSURL *)URL
+{
+ if (!URL)
+ return;
+
+ if (!URL.absoluteString.length)
+ return;
+
+ urlText.stringValue = [URL _web_userVisibleString];
+}
+
+- (void)loadURLString:(NSString *)urlString
+{
+ // FIXME: We shouldn't have to set the url text here.
+ [urlText setStringValue:urlString];
+ [self fetch:nil];
+}
+
+- (void)loadHTMLString:(NSString *)HTMLString
+{
+ [_webView loadHTMLString:HTMLString baseURL:nil];
+}
+
+static NSSet *dataTypes()
+{
+ return [WKWebsiteDataStore allWebsiteDataTypes];
+}
+
+- (IBAction)fetchWebsiteData:(id)sender
+{
+ [_configuration.websiteDataStore _fetchDataRecordsOfTypes:dataTypes() withOptions:_WKWebsiteDataStoreFetchOptionComputeSizes completionHandler:^(NSArray *websiteDataRecords) {
+ NSLog(@"did fetch website data %@.", websiteDataRecords);
+ }];
+}
+
+- (IBAction)fetchAndClearWebsiteData:(id)sender
+{
+ [_configuration.websiteDataStore fetchDataRecordsOfTypes:dataTypes() completionHandler:^(NSArray *websiteDataRecords) {
+ [_configuration.websiteDataStore removeDataOfTypes:dataTypes() forDataRecords:websiteDataRecords completionHandler:^{
+ [_configuration.websiteDataStore fetchDataRecordsOfTypes:dataTypes() completionHandler:^(NSArray *websiteDataRecords) {
+ NSLog(@"did clear website data, after clearing data is %@.", websiteDataRecords);
+ }];
+ }];
+ }];
+}
+
+- (IBAction)clearWebsiteData:(id)sender
+{
+ [_configuration.websiteDataStore removeDataOfTypes:dataTypes() modifiedSince:[NSDate distantPast] completionHandler:^{
+ NSLog(@"Did clear website data.");
+ }];
+}
+
+- (IBAction)printWebView:(id)sender
+{
+ [[_webView printOperationWithPrintInfo:[NSPrintInfo sharedPrintInfo]] runOperationModalForWindow:self.window delegate:nil didRunSelector:nil contextInfo:nil];
+}
+
+#pragma mark WKNavigationDelegate
+
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
+{
+ LOG(@"decidePolicyForNavigationAction");
+
+ if (navigationAction._canHandleRequest) {
+ decisionHandler(WKNavigationActionPolicyAllow);
+ return;
+ }
+ decisionHandler(WKNavigationActionPolicyCancel);
+}
+
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
+{
+ if (![navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]]) {
+ decisionHandler(WKNavigationResponsePolicyAllow);
+ return;
+ }
+ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)navigationResponse.response;
+
+ NSString *disposition = [[httpResponse allHeaderFields] objectForKey:@"Content-Disposition"];
+ if (disposition && [disposition hasPrefix:@"attachment"]) {
+ decisionHandler(_WKNavigationResponsePolicyBecomeDownload);
+ return;
+ }
+ decisionHandler(WKNavigationResponsePolicyAllow);
+}
+
+- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
+{
+ LOG(@"didStartProvisionalNavigation: %@", navigation);
+}
+
+- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
+{
+ LOG(@"didReceiveServerRedirectForProvisionalNavigation: %@", navigation);
+}
+
+- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
+{
+ LOG(@"didFailProvisionalNavigation: %@navigation, error: %@", navigation, error);
+}
+
+- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
+{
+ LOG(@"didCommitNavigation: %@", navigation);
+ [self updateTitle:nil];
+}
+
+- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
+{
+ LOG(@"didFinishNavigation: %@", navigation);
+}
+
+- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *__nullable credential))completionHandler
+{
+ LOG(@"didReceiveAuthenticationChallenge: %@", challenge);
+ if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]) {
+ NSAlert *alert = [[NSAlert alloc] init];
+ NSView *container = [[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 48)] autorelease];
+ NSTextField *userInput = [[[NSTextField alloc] initWithFrame:NSMakeRect(0, 24, 200, 24)] autorelease];
+ NSTextField *passwordInput = [[[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)] autorelease];
+
+ [alert setMessageText:[NSString stringWithFormat:@"Log in to %@:%lu.", challenge.protectionSpace.host, challenge.protectionSpace.port]];
+ [alert addButtonWithTitle:@"Log in"];
+ [alert addButtonWithTitle:@"Cancel"];
+ [container addSubview:userInput];
+ [container addSubview:passwordInput];
+ [alert setAccessoryView:container];
+ [userInput setNextKeyView:passwordInput];
+ [alert.window setInitialFirstResponder:userInput];
+
+ [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse response) {
+ [userInput validateEditing];
+ if (response == NSAlertFirstButtonReturn)
+ completionHandler(NSURLSessionAuthChallengeUseCredential, [[[NSURLCredential alloc] initWithUser:[userInput stringValue] password:[passwordInput stringValue] persistence:NSURLCredentialPersistenceForSession] autorelease]);
+ else
+ completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
+ [alert release];
+ }];
+ return;
+ }
+ completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
+}
+
+- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
+{
+ LOG(@"didFailNavigation: %@, error %@", navigation, error);
+}
+
+- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
+{
+ NSLog(@"WebContent process crashed; reloading");
+ [self reload:nil];
+}
+
+- (void)_webView:(WKWebView *)webView renderingProgressDidChange:(_WKRenderingProgressEvents)progressEvents
+{
+ if (progressEvents & _WKRenderingProgressEventFirstLayout)
+ LOG(@"renderingProgressDidChange: %@", @"first layout");
+
+ if (progressEvents & _WKRenderingProgressEventFirstVisuallyNonEmptyLayout)
+ LOG(@"renderingProgressDidChange: %@", @"first visually non-empty layout");
+
+ if (progressEvents & _WKRenderingProgressEventFirstPaintWithSignificantArea)
+ LOG(@"renderingProgressDidChange: %@", @"first paint with significant area");
+
+ if (progressEvents & _WKRenderingProgressEventFirstLayoutAfterSuppressedIncrementalRendering)
+ LOG(@"renderingProgressDidChange: %@", @"first layout after suppressed incremental rendering");
+
+ if (progressEvents & _WKRenderingProgressEventFirstPaintAfterSuppressedIncrementalRendering)
+ LOG(@"renderingProgressDidChange: %@", @"first paint after suppressed incremental rendering");
+}
+
+- (void)webView:(WKWebView *)webView shouldLoadIconWithParameters:(_WKLinkIconParameters *)parameters completionHandler:(void (^)(void (^)(NSData*)))completionHandler
+{
+ completionHandler(^void (NSData *data) {
+ LOG(@"Icon URL %@ received icon data of length %u", parameters.url, (unsigned)data.length);
+ });
+}
+
+#pragma mark Find in Page
+
+- (IBAction)performTextFinderAction:(id)sender
+{
+ [_textFinder performAction:[sender tag]];
+}
+
+- (NSView *)findBarView
+{
+ return _textFindBarView;
+}
+
+- (void)setFindBarView:(NSView *)findBarView
+{
+ _textFindBarView = findBarView;
+ _findBarVisible = YES;
+ [_textFindBarView setFrame:NSMakeRect(0, 0, containerView.bounds.size.width, _textFindBarView.frame.size.height)];
+}
+
+- (BOOL)isFindBarVisible
+{
+ return _findBarVisible;
+}
+
+- (void)setFindBarVisible:(BOOL)findBarVisible
+{
+ _findBarVisible = findBarVisible;
+ if (findBarVisible)
+ [containerView addSubview:_textFindBarView];
+ else
+ [_textFindBarView removeFromSuperview];
+}
+
+- (NSView *)contentView
2019-11-19 05:18:28 +03:00
+{
+ return _webView;
+}
+
+- (void)findBarViewDidChangeHeight
+{
+}
2019-11-19 05:18:28 +03:00
+
+- (void)_webView:(WKWebView *)webView requestMediaCaptureAuthorization: (_WKCaptureDevices)devices decisionHandler:(void (^)(BOOL authorized))decisionHandler
+{
+ decisionHandler(true);
+}
2019-11-19 05:18:28 +03:00
+
+- (void)_webView:(WKWebView *)webView includeSensitiveMediaDeviceDetails:(void (^)(BOOL includeSensitiveDetails))decisionHandler
+{
+ decisionHandler(false);
+}
2019-11-19 05:18:28 +03:00
+
+- (IBAction)saveAsPDF:(id)sender
+{
+ NSSavePanel *panel = [NSSavePanel savePanel];
+ panel.allowedFileTypes = @[ @"pdf" ];
+ [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
+ if (result == NSModalResponseOK) {
+ [_webView createPDFWithConfiguration:nil completionHandler:^(NSData *pdfSnapshotData, NSError *error) {
+ [pdfSnapshotData writeToURL:[panel URL] options:0 error:nil];
+ }];
+ }
+ }];
2019-11-19 05:18:28 +03:00
+}
+
+- (IBAction)saveAsWebArchive:(id)sender
2019-11-19 05:18:28 +03:00
+{
+ NSSavePanel *panel = [NSSavePanel savePanel];
+ panel.allowedFileTypes = @[ @"webarchive" ];
+ [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
+ if (result == NSModalResponseOK) {
+ [_webView createWebArchiveDataWithCompletionHandler:^(NSData *archiveData, NSError *error) {
+ [archiveData writeToURL:[panel URL] options:0 error:nil];
+ }];
+ }
+ }];
2019-11-19 05:18:28 +03:00
+}
+
+- (WKWebView *)webView
+{
+ return _webView;
+}
2019-11-19 05:18:28 +03:00
+
+@end
diff --git a/Tools/Playwright/mac/CMakeLists.txt b/Tools/Playwright/mac/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..410d47425b79367114b17274355350894a70a5e6
--- /dev/null
+++ b/Tools/Playwright/mac/CMakeLists.txt
@@ -0,0 +1,43 @@
+set(PLAYWRIGHT_DIR "${TOOLS_DIR}/Playwright/mac")
+
+#FIXME: This should not need WEBCORE_EXPORT defined. This means we are including WebCore headers, and we should not.
+add_definitions("-include Playwright_Prefix.pch -DWEBCORE_EXPORT=")
+
+set(Playwright_SOURCES
+ ${PLAYWRIGHT_DIR}/AppDelegate.m
+ ${PLAYWRIGHT_DIR}/BrowserWindowController.m
+ ${PLAYWRIGHT_DIR}/main.m
+ ${TOOLS_DIR}/Playwright/MBToolbarItem.m
+)
+
+set(Playwright_INCLUDE_DIRECTORIES
+ ${CMAKE_SOURCE_DIR}/Source
+ ${FORWARDING_HEADERS_DIR}
+ ${PLAYWRIGHT_DIR}
+)
+
+set(Playwright_LIBRARIES
+ WebKit
+)
+
+set(CMAKE_EXE_LINKER_FLAGS "-framework Cocoa")
+
+set(EXECUTABLE_NAME Playwright)
+set(PRODUCT_NAME Playwright)
+
+set(Playwright_Contents_Directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Playwright.app/Contents)
+make_directory(${Playwright_Contents_Directory}/Resources)
+add_custom_command(OUTPUT ${Playwright_Contents_Directory}/Resources/BrowserWindow.nib
+ COMMAND ibtool --compile ${Playwright_Contents_Directory}/Resources/BrowserWindow.nib ${PLAYWRIGHT_DIR}/BrowserWindow.xib VERBATIM)
+add_custom_command(OUTPUT ${Playwright_Contents_Directory}/Resources/MainMenu.nib
+ COMMAND ibtool --compile ${Playwright_Contents_Directory}/Resources/MainMenu.nib ${PLAYWRIGHT_DIR}/MainMenu.xib VERBATIM)
+add_custom_target(PlaywrightNibs ALL DEPENDS
+ ${Playwright_Contents_Directory}/Resources/BrowserWindow.nib
+ ${Playwright_Contents_Directory}/Resources/MainMenu.nib
+)
+
+include_directories(${Playwright_INCLUDE_DIRECTORIES})
+add_executable(Playwright MACOSX_BUNDLE ${Playwright_SOURCES})
+set_target_properties(Playwright PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PLAYWRIGHT_DIR}/Info.plist)
+target_link_libraries(Playwright ${Playwright_LIBRARIES})
+add_dependencies(Playwright PlaywrightNibs)
diff --git a/Tools/Playwright/mac/Info.plist b/Tools/Playwright/mac/Info.plist
new file mode 100644
index 0000000000000000000000000000000000000000..4ed50c40f2f0dfd0ddf7c546b3451ab426c0501e
--- /dev/null
+++ b/Tools/Playwright/mac/Info.plist
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string>WebKit Browser</string>
+ <key>CFBundleIdentifier</key>
+ <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ </dict>
+ <key>NSSupportsAutomaticGraphicsSwitching</key>
+ <true/>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>html</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>text/html</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>HTML</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/Tools/Playwright/mac/MainMenu.xib b/Tools/Playwright/mac/MainMenu.xib
new file mode 100644
index 0000000000000000000000000000000000000000..b16d639a1ad18354e058c613987d846acd70b361
--- /dev/null
+++ b/Tools/Playwright/mac/MainMenu.xib
@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15505"/>
+ </dependencies>
+ <objects>
+ <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
+ <connections>
+ <outlet property="delegate" destination="494" id="495"/>
+ </connections>
+ </customObject>
+ <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+ <menu title="AMainMenu" systemMenu="main" id="29">
+ <items>
+ <menuItem title="Playwright" id="56">
+ <menu key="submenu" title="Playwright" systemMenu="apple" id="57">
+ <items>
+ <menuItem title="About Playwright" id="58">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="236">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Preferences…" keyEquivalent="," id="129"/>
+ <menuItem isSeparatorItem="YES" id="143">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Services" id="131">
+ <menu key="submenu" title="Services" systemMenu="services" id="130"/>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="144">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Hide Playwright" keyEquivalent="h" id="134">
+ <connections>
+ <action selector="hide:" target="-1" id="367"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Hide Others" keyEquivalent="h" id="145">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="hideOtherApplications:" target="-1" id="368"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Show All" id="150">
+ <connections>
+ <action selector="unhideAllApplications:" target="-1" id="370"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="149">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Quit Playwright" keyEquivalent="q" id="136">
+ <connections>
+ <action selector="terminate:" target="-3" id="449"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="File" id="83">
+ <menu key="submenu" title="File" id="81">
+ <items>
+ <menuItem title="Open Location " tag="1" keyEquivalent="l" id="82">
+ <connections>
+ <action selector="openLocation:" target="-1" id="575"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="79">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Close" keyEquivalent="w" id="73">
+ <connections>
+ <action selector="performClose:" target="-1" id="193"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Save" keyEquivalent="s" id="75">
+ <connections>
+ <action selector="saveDocument:" target="-1" id="362"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Save As…" keyEquivalent="S" id="80">
+ <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
+ <connections>
+ <action selector="saveDocumentAs:" target="-1" id="363"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Save As PDF…" keyEquivalent="S" id="gmS-3Q-oLs">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="saveAsPDF:" target="-1" id="25T-Id-334"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Save As WebArchive..." id="112">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="saveAsWebArchive:" target="-1" id="AGx-3e-6Nt"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="74">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Page Setup..." keyEquivalent="P" id="77">
+ <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
+ <connections>
+ <action selector="runPageLayout:" target="-1" id="87"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Print…" keyEquivalent="p" id="78">
+ <connections>
+ <action selector="printWebView:" target="-1" id="86"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Edit" id="217">
+ <menu key="submenu" title="Edit" id="205">
+ <items>
+ <menuItem title="Undo" keyEquivalent="z" id="207">
+ <connections>
+ <action selector="undo:" target="-1" id="223"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Redo" keyEquivalent="Z" id="215">
+ <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
+ <connections>
+ <action selector="redo:" target="-1" id="231"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="206">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Cut" keyEquivalent="x" id="199">
+ <connections>
+ <action selector="cut:" target="-1" id="228"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Copy" keyEquivalent="c" id="197">
+ <connections>
+ <action selector="copy:" target="-1" id="224"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Paste" keyEquivalent="v" id="203">
+ <connections>
+ <action selector="paste:" target="-1" id="226"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Delete" id="202">
+ <connections>
+ <action selector="delete:" target="-1" id="235"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Select All" keyEquivalent="a" id="198">
+ <connections>
+ <action selector="selectAll:" target="-1" id="232"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="214">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Find" id="218">
+ <menu key="submenu" title="Find" id="220">
+ <items>
+ <menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
+ <connections>
+ <action selector="performTextFinderAction:" target="-1" id="241"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Find Next" tag="2" keyEquivalent="g" id="208">
+ <connections>
+ <action selector="performTextFinderAction:" target="-1" id="487"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
+ <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
+ <connections>
+ <action selector="performTextFinderAction:" target="-1" id="488"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221">
+ <connections>
+ <action selector="performTextFinderAction:" target="-1" id="489"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Jump to Selection" keyEquivalent="j" id="210">
+ <connections>
+ <action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="View" id="295">
+ <menu key="submenu" title="View" id="296">
+ <items>
+ <menuItem title="Zoom In" keyEquivalent="+" id="555">
+ <connections>
+ <action selector="zoomIn:" target="-1" id="559"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Zoom Out" keyEquivalent="-" id="557">
+ <connections>
+ <action selector="zoomOut:" target="-1" id="560"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Reset Zoom" keyEquivalent="0" id="558">
+ <connections>
+ <action selector="resetZoom:" target="-1" id="561"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Zoom Text Only" id="562">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleZoomMode:" target="-1" id="564"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Page Scale" id="Hzb-c3-Qfv">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Page Scale" id="jdo-5V-3CM">
+ <items>
+ <menuItem title="100%" state="on" tag="1" keyEquivalent="1" id="wHb-mR-Fv0">
+ <connections>
+ <action selector="setPageScale:" target="-1" id="uMw-eY-289"/>
+ </connections>
+ </menuItem>
+ <menuItem title="125%" tag="2" keyEquivalent="2" id="u4i-F7-rPb">
+ <connections>
+ <action selector="setPageScale:" target="-1" id="IbE-Ep-hfc"/>
+ </connections>
+ </menuItem>
+ <menuItem title="150%" tag="3" keyEquivalent="3" id="fwT-Iy-oK9">
+ <connections>
+ <action selector="setPageScale:" target="-1" id="9c0-eN-0f5"/>
+ </connections>
+ </menuItem>
+ <menuItem title="200%" tag="4" keyEquivalent="4" id="R5e-ct-O2u">
+ <connections>
+ <action selector="setPageScale:" target="-1" id="mkk-gh-dlN"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="View Scale" id="8UY-Pj-H13">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="View Scale" id="Ml8-mk-ffu">
+ <items>
+ <menuItem title="100%" state="on" tag="1" id="EAm-Xn-VrC">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="setViewScale:" target="-1" id="dkW-CI-RG4"/>
+ </connections>
+ </menuItem>
+ <menuItem title="75%" tag="2" id="jcA-I1-Cbq">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="setViewScale:" target="-1" id="BAF-Ym-IqV"/>
+ </connections>
+ </menuItem>
+ <menuItem title="50%" tag="3" id="BRM-D5-YNO">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="setViewScale:" target="-1" id="nXy-2b-9Zz"/>
+ </connections>
+ </menuItem>
+ <menuItem title="25%" tag="4" id="gzk-YK-x0W">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="setViewScale:" target="-1" id="KXK-f6-24N"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Reload Page" keyEquivalent="r" id="579">
+ <connections>
+ <action selector="reload:" target="-1" id="582"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Debug" id="534">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Debug" id="535">
+ <items>
+ <menuItem title="Show Web Inspector" keyEquivalent="i" id="xso-9z-R4u">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="showHideWebInspector:" target="-1" id="Cmx-g7-EPb"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Window" id="19">
+ <menu key="submenu" title="Window" systemMenu="window" id="24">
+ <items>
+ <menuItem title="Minimize" keyEquivalent="m" id="23">
+ <connections>
+ <action selector="performMiniaturize:" target="-1" id="37"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Zoom" id="239">
+ <connections>
+ <action selector="performZoom:" target="-1" id="240"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="92">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Bring All to Front" id="5">
+ <connections>
+ <action selector="arrangeInFront:" target="-1" id="39"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ </items>
+ <point key="canvasLocation" x="139" y="-50"/>
+ </menu>
+ <customObject id="494" customClass="BrowserAppDelegate"/>
+ </objects>
+</document>
diff --git a/Tools/Playwright/mac/Playwright_Prefix.pch b/Tools/Playwright/mac/Playwright_Prefix.pch
new file mode 100644
index 0000000000000000000000000000000000000000..ab6e9bce9a41291bb35664c2c63751c3413601f2
--- /dev/null
+++ b/Tools/Playwright/mac/Playwright_Prefix.pch
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef __OBJC__
+#import <Cocoa/Cocoa.h>
+#import <WebKit/WebKit.h>
+#endif
+
+#define ENABLE_LOGGING 0
+
+#if ENABLE_LOGGING
+#define LOG NSLog
+#else
+#define LOG(...) ((void)0)
+#endif
diff --git a/Tools/Playwright/mac/main.m b/Tools/Playwright/mac/main.m
new file mode 100644
index 0000000000000000000000000000000000000000..ba2ca12482c0ab809998131f693c876019c595f1
--- /dev/null
+++ b/Tools/Playwright/mac/main.m
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"WebKitLinkedOnOrAfterEverything"];
+
+ return NSApplicationMain(argc, (const char **) argv);
+}
diff --git a/Tools/Playwright/win/CMakeLists.txt b/Tools/Playwright/win/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b8076d8a4caa71c078499e03220fbd3b5ca77f3f
--- /dev/null
+++ b/Tools/Playwright/win/CMakeLists.txt
@@ -0,0 +1,42 @@
+set(Playwright_INCLUDE_DIRECTORIES
+ ${PAL_FRAMEWORK_HEADERS_DIR}
+ ${WebCore_PRIVATE_FRAMEWORK_HEADERS_DIR}
+ ${WebKit_FRAMEWORK_HEADERS_DIR}
+ ${WebKit_PRIVATE_FRAMEWORK_HEADERS_DIR}
+)
+
+set(Playwright_SOURCES
+ Common.cpp
+ MainWindow.cpp
+ PlaywrightLib.rc
+ WebKitBrowserWindow.cpp
+ WinMain.cpp
+ stdafx.cpp
+)
+
+set(Playwright_LIBRARIES
+ DbgHelp
+ WebKit::WTF
+ comctl32
+ comsupp
+ comsuppw
+ shlwapi
+ WebKit
+)
+
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MSVC_RUNTIME_LINKER_FLAGS}")
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wWinMainCRTStartup")
+
+if (${WTF_PLATFORM_WIN_CAIRO})
+ add_definitions(-DWIN_CAIRO)
+endif ()
+add_definitions(-D_UNICODE)
+include_directories(${Playwright_INCLUDE_DIRECTORIES})
+add_library(PlaywrightLib SHARED ${Playwright_SOURCES})
+target_link_libraries(PlaywrightLib ${Playwright_LIBRARIES})
+
+add_executable(Playwright WIN32 ${TOOLS_DIR}/win/DLLLauncher/DLLLauncherMain.cpp Playwright.rc)
+target_link_libraries(Playwright shlwapi)
+set_target_properties(Playwright PROPERTIES OUTPUT_NAME "Playwright")
+
+add_dependencies(Playwright PlaywrightLib)
diff --git a/Tools/Playwright/win/Common.cpp b/Tools/Playwright/win/Common.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..969425bec9f9fc0bef0330224b9e6d6b853222e5
--- /dev/null
+++ b/Tools/Playwright/win/Common.cpp
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2006, 2008, 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2011 Brent Fulgham. All rights reserved.
+ * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
+ * Copyright (C) 2013 Alex Christensen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stdafx.h"
+#include "Common.h"
+
+#include "DialogHelper.h"
+#include "PlaywrightLibResource.h"
+#include "PlaywrightReplace.h"
+#include <dbghelp.h>
+#include <shlobj.h>
+#include <wtf/Optional.h>
+#include <wtf/StdLibExtras.h>
+#include <vector>
+
+// Global Variables:
+HINSTANCE hInst;
+
+// Support moving the transparent window
+POINT s_windowPosition = { 100, 100 };
+SIZE s_windowSize = { 500, 200 };
+
+namespace WebCore {
+float deviceScaleFactorForWindow(HWND);
+}
+
+void computeFullDesktopFrame()
+{
+ RECT desktop;
+ if (!::SystemParametersInfo(SPI_GETWORKAREA, 0, static_cast<void*>(&desktop), 0))
+ return;
+
+ float scaleFactor = WebCore::deviceScaleFactorForWindow(nullptr);
+
+ s_windowPosition.x = 0;
+ s_windowPosition.y = 0;
+ s_windowSize.cx = scaleFactor * (desktop.right - desktop.left);
+ s_windowSize.cy = scaleFactor * (desktop.bottom - desktop.top);
+}
+
+BOOL WINAPI DllMain(HINSTANCE dllInstance, DWORD reason, LPVOID)
+{
+ if (reason == DLL_PROCESS_ATTACH)
+ hInst = dllInstance;
+
+ return TRUE;
+}
+
+bool getAppDataFolder(_bstr_t& directory)
+{
+ wchar_t appDataDirectory[MAX_PATH];
+ if (FAILED(SHGetFolderPathW(0, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, appDataDirectory)))
+ return false;
+
+ wchar_t executablePath[MAX_PATH];
+ if (!::GetModuleFileNameW(0, executablePath, MAX_PATH))
+ return false;
+
+ ::PathRemoveExtensionW(executablePath);
+
+ directory = _bstr_t(appDataDirectory) + L"\\" + ::PathFindFileNameW(executablePath);
+
+ return true;
+}
+
+void createCrashReport(EXCEPTION_POINTERS* exceptionPointers)
+{
+ _bstr_t directory;
+
+ if (!getAppDataFolder(directory))
+ return;
+
+ if (::SHCreateDirectoryEx(0, directory, 0) != ERROR_SUCCESS
+ && ::GetLastError() != ERROR_FILE_EXISTS
+ && ::GetLastError() != ERROR_ALREADY_EXISTS)
+ return;
+
+ std::wstring fileName = std::wstring(static_cast<const wchar_t*>(directory)) + L"\\CrashReport.dmp";
+ HANDLE miniDumpFile = ::CreateFile(fileName.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (miniDumpFile && miniDumpFile != INVALID_HANDLE_VALUE) {
+
+ MINIDUMP_EXCEPTION_INFORMATION mdei;
+ mdei.ThreadId = ::GetCurrentThreadId();
+ mdei.ExceptionPointers = exceptionPointers;
+ mdei.ClientPointers = 0;
+
+#ifdef _DEBUG
+ MINIDUMP_TYPE dumpType = MiniDumpWithFullMemory;
+#else
+ MINIDUMP_TYPE dumpType = MiniDumpNormal;
+#endif
+
+ ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), miniDumpFile, dumpType, &mdei, 0, 0);
+ ::CloseHandle(miniDumpFile);
+ processCrashReport(fileName.c_str());
+ }
+}
+
+bool askProxySettings(HWND hwnd, ProxySettings& settings)
+{
+ class ProxyDialog : public Dialog {
+ public:
+ ProxyDialog(ProxySettings& settings)
+ : settings { settings }
+ {
+ }
+
+ protected:
+ ProxySettings& settings;
+
+ void setup() final
+ {
+ auto command = commandForProxyChoice();
+ proxyChoice().set(command);
+ setText(IDC_PROXY_URL, settings.url);
+ setText(IDC_PROXY_EXCLUDE, settings.excludeHosts);
+ }
+
+ void ok() final
+ {
+ settings.url = getText(IDC_PROXY_URL);
+ settings.excludeHosts = getText(IDC_PROXY_EXCLUDE);
+ updateProxyChoice(proxyChoice().get());
+ }
+
+ bool validate() final
+ {
+ bool valid = true;
+
+ if (proxyChoice().get() == IDC_PROXY_CUSTOM) {
+ setEnabled(IDC_PROXY_URL, true);
+ setEnabled(IDC_PROXY_EXCLUDE, true);
+
+ if (!getTextLength(IDC_PROXY_URL))
+ valid = false;
+ } else {
+ setEnabled(IDC_PROXY_URL, false);
+ setEnabled(IDC_PROXY_EXCLUDE, false);
+ }
+
+ return valid;
+ }
+
+ RadioGroup proxyChoice()
+ {
+ return radioGroup(IDC_PROXY_DEFAULT, IDC_PROXY_DISABLE);
+ }
+
+ int commandForProxyChoice()
+ {
+ if (!settings.enable)
+ return IDC_PROXY_DISABLE;
+ if (settings.custom)
+ return IDC_PROXY_CUSTOM;
+ return IDC_PROXY_DEFAULT;
+ }
+
+ void updateProxyChoice(int command)
+ {
+ switch (command) {
+ case IDC_PROXY_DEFAULT:
+ settings.enable = true;
+ settings.custom = false;
+ break;
+ case IDC_PROXY_CUSTOM:
+ settings.enable = true;
+ settings.custom = true;
+ break;
+ case IDC_PROXY_DISABLE:
+ settings.enable = false;
+ settings.custom = false;
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ ProxyDialog dialog { settings };
+ return dialog.run(hInst, hwnd, IDD_PROXY);
+}
+
+Optional<Credential> askCredential(HWND hwnd, const std::wstring& realm)
+{
+ struct AuthDialog : public Dialog {
+ std::wstring realm;
+ Credential credential;
+
+ protected:
+ void setup()
+ {
+ setText(IDC_REALM_TEXT, realm);
+ }
+
+ void ok() final
+ {
+ credential.username = getText(IDC_AUTH_USER);
+ credential.password = getText(IDC_AUTH_PASSWORD);
+ }
+ };
+
+ AuthDialog dialog;
+ dialog.realm = realm;
+
+ if (dialog.run(hInst, hwnd, IDD_AUTH))
+ return dialog.credential;
+ return WTF::nullopt;
+}
+
+bool askServerTrustEvaluation(HWND hwnd, const std::wstring& text)
+{
+ class ServerTrustEvaluationDialog : public Dialog {
+ public:
+ ServerTrustEvaluationDialog(const std::wstring& text)
+ : m_text { text }
+ {
+ SendMessage(GetDlgItem(this->hDlg(), IDC_SERVER_TRUST_TEXT), WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), TRUE);
+ }
+
+ protected:
+ std::wstring m_text;
+
+ void setup()
+ {
+ setText(IDC_SERVER_TRUST_TEXT, m_text);
+ }
+
+ void ok() final
+ {
+
+ }
+ };
+
+ ServerTrustEvaluationDialog dialog { text };
+ return dialog.run(hInst, hwnd, IDD_SERVER_TRUST);
+}
+
+CommandLineOptions parseCommandLine()
+{
+ CommandLineOptions options;
+
+ int argc = 0;
+ WCHAR** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ for (int i = 1; i < argc; ++i) {
+ if (!wcsicmp(argv[i], L"--desktop"))
+ options.useFullDesktop = true;
+ else if (!wcsicmp(argv[i], L"--inspector-pipe"))
+ options.inspectorPipe = true;
+ else if (!wcsncmp(argv[i], L"--user-data-dir=", 16))
+ options.userDataDir = argv[i] + 16;
+ else if (!wcsicmp(argv[i], L"--headless"))
+ options.headless = true;
+ else if (!wcsicmp(argv[i], L"--no-startup-window"))
+ options.noStartupWindow = true;
+ else if (!options.requestedURL)
+ options.requestedURL = argv[i];
+ }
+
+ return options;
+}
+
+std::wstring replaceString(std::wstring src, const std::wstring& oldValue, const std::wstring& newValue)
+{
+ if (src.empty() || oldValue.empty())
+ return src;
+
+ size_t pos = 0;
+ while ((pos = src.find(oldValue, pos)) != src.npos) {
+ src.replace(pos, oldValue.length(), newValue);
+ pos += newValue.length();
+ }
+
+ return src;
+}
+
+std::wstring createString(WKStringRef wkString)
+{
+ size_t maxSize = WKStringGetLength(wkString);
+
+ std::vector<WKChar> wkCharBuffer(maxSize);
+ size_t actualLength = WKStringGetCharacters(wkString, wkCharBuffer.data(), maxSize);
+ return std::wstring(wkCharBuffer.data(), actualLength);
+}
+
+std::wstring createString(WKURLRef wkURL)
+{
+ if (!wkURL)
+ return { };
+ WKRetainPtr<WKStringRef> url = adoptWK(WKURLCopyString(wkURL));
+ return createString(url.get());
+}
+
+std::string createUTF8String(const wchar_t* src, size_t srcLength)
+{
+ int length = WideCharToMultiByte(CP_UTF8, 0, src, srcLength, 0, 0, nullptr, nullptr);
+ std::vector<char> buffer(length);
+ size_t actualLength = WideCharToMultiByte(CP_UTF8, 0, src, srcLength, buffer.data(), length, nullptr, nullptr);
+ return { buffer.data(), actualLength };
+}
+
+WKRetainPtr<WKStringRef> createWKString(_bstr_t str)
+{
+ auto utf8 = createUTF8String(str, str.length());
+ return adoptWK(WKStringCreateWithUTF8CString(utf8.data()));
+}
+
+WKRetainPtr<WKStringRef> createWKString(const std::wstring& str)
+{
+ auto utf8 = createUTF8String(str.c_str(), str.length());
+ return adoptWK(WKStringCreateWithUTF8CString(utf8.data()));
+}
+
+WKRetainPtr<WKURLRef> createWKURL(_bstr_t str)
+{
+ auto utf8 = createUTF8String(str, str.length());
+ return adoptWK(WKURLCreateWithUTF8CString(utf8.data()));
+}
+
+WKRetainPtr<WKURLRef> createWKURL(const std::wstring& str)
+{
+ auto utf8 = createUTF8String(str.c_str(), str.length());
+ return adoptWK(WKURLCreateWithUTF8CString(utf8.data()));
+}
diff --git a/Tools/Playwright/win/Common.h b/Tools/Playwright/win/Common.h
new file mode 100644
index 0000000000000000000000000000000000000000..da9b00c96f9bc9c3c52e76a719650e8d604b1e0a
--- /dev/null
+++ b/Tools/Playwright/win/Common.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "stdafx.h"
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKString.h>
+#include <WebKit/WKURL.h>
+#include <wtf/Optional.h>
+
+struct CommandLineOptions {
+ bool useFullDesktop { };
+ bool inspectorPipe { };
+ bool headless { };
+ bool noStartupWindow { };
+ _bstr_t requestedURL;
+ _bstr_t userDataDir;
+
+ CommandLineOptions()
+ {
+ }
+};
+
+struct Credential {
+ std::wstring username;
+ std::wstring password;
+};
+
+struct ProxySettings {
+ bool enable { true };
+ bool custom { false };
+ std::wstring url;
+ std::wstring excludeHosts;
+};
+
+void computeFullDesktopFrame();
+bool getAppDataFolder(_bstr_t& directory);
+CommandLineOptions parseCommandLine();
+void createCrashReport(EXCEPTION_POINTERS*);
+Optional<Credential> askCredential(HWND, const std::wstring& realm);
+bool askProxySettings(HWND, ProxySettings&);
+
+bool askServerTrustEvaluation(HWND, const std::wstring& text);
+std::wstring replaceString(std::wstring src, const std::wstring& oldValue, const std::wstring& newValue);
+
+extern HINSTANCE hInst;
+extern POINT s_windowPosition;
+extern SIZE s_windowSize;
+
+std::wstring createString(WKStringRef wkString);
+std::wstring createString(WKURLRef wkURL);
+std::string createUTF8String(const wchar_t* src, size_t srcLength);
+WKRetainPtr<WKStringRef> createWKString(_bstr_t str);
+WKRetainPtr<WKStringRef> createWKString(const std::wstring& str);
+WKRetainPtr<WKURLRef> createWKURL(_bstr_t str);
+WKRetainPtr<WKURLRef> createWKURL(const std::wstring& str);
diff --git a/Tools/Playwright/win/DialogHelper.h b/Tools/Playwright/win/DialogHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..6590fe00255841fa93a0fe7c6bffbc0dc13fd2d0
--- /dev/null
+++ b/Tools/Playwright/win/DialogHelper.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2018 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "stdafx.h"
+#include <string>
+#include <vector>
+
+class Dialog {
+public:
+ bool run(HINSTANCE hInst, HWND hwnd, int dialogId)
+ {
+ auto result = DialogBoxParam(hInst, MAKEINTRESOURCE(dialogId), hwnd, doalogProc, reinterpret_cast<LPARAM>(this));
+ return (result > 0);
+ }
+
+ static INT_PTR CALLBACK doalogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+ {
+ if (message == WM_INITDIALOG)
+ SetWindowLongPtr(hDlg, DWLP_USER, lParam);
+ else
+ lParam = GetWindowLongPtr(hDlg, DWLP_USER);
+
+ auto* dialog = reinterpret_cast<Dialog*>(lParam);
+ return dialog->handle(hDlg, message, wParam);
+ }
+
+protected:
+ INT_PTR handle(HWND hDlg, UINT message, WPARAM wParam)
+ {
+ switch (message) {
+ case WM_INITDIALOG: {
+ m_hDlg = hDlg;
+ setup();
+ update();
+ return TRUE;
+ }
+ case WM_COMMAND:
+ int wmId = LOWORD(wParam);
+ switch (wmId) {
+ case IDOK:
+ ok();
+ close(true);
+ return TRUE;
+ case IDCANCEL:
+ cancel();
+ close(false);
+ return TRUE;
+ default:
+ auto handled = command(wmId);
+ update();
+ return handled;
+ }
+ }
+ return FALSE;
+ }
+
+ virtual void setup() { }
+ virtual void update() { updateOkButton(validate()); }
+ virtual bool validate() { return true; }
+ virtual void updateOkButton(bool isValid) { setEnabled(IDOK, isValid); }
+ virtual bool command(int wmId) { return false; }
+ virtual void ok() { }
+ virtual void cancel() { }
+
+ void close(bool success) { EndDialog(m_hDlg, success); }
+
+ HWND hDlg() { return m_hDlg; }
+
+ HWND item(int itemId) { return GetDlgItem(m_hDlg, itemId); }
+
+ void setEnabled(int itemId, bool enabled)
+ {
+ EnableWindow(item(itemId), enabled);
+ }
+
+ void setText(int itemId, const std::wstring& str)
+ {
+ SetDlgItemText(m_hDlg, itemId, _bstr_t(str.c_str()));
+ }
+
+ std::wstring getText(int itemId)
+ {
+ auto length = getTextLength(itemId);
+ std::vector<TCHAR> buffer(length + 1, 0);
+ GetWindowText(item(itemId), buffer.data(), length + 1);
+ return std::wstring { buffer.data() };
+ }
+
+ int getTextLength(int itemId)
+ {
+ return GetWindowTextLength(item(itemId));
+ }
+
+ class RadioGroup {
+ public:
+ RadioGroup(Dialog& dialog, int first, int last)
+ : m_dialog(dialog)
+ , m_first(first)
+ , m_last(last)
+ {
+ }
+
+ void set(int item)
+ {
+ CheckRadioButton(m_dialog.hDlg(), m_first, m_last, item);
+ }
+
+ int get()
+ {
+ for (int id = m_first; id <= m_last; id++) {
+ if (IsDlgButtonChecked(m_dialog.hDlg(), id) == BST_CHECKED)
+ return id;
+ }
+ return 0;
+ }
+
+ private:
+ Dialog& m_dialog;
+ int m_first;
+ int m_last;
+ };
+
+ RadioGroup radioGroup(int first, int last)
+ {
+ return RadioGroup(*this, first, last);
+ }
+
+ HWND m_hDlg { };
+};
diff --git a/Tools/Playwright/win/MainWindow.cpp b/Tools/Playwright/win/MainWindow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..690c5e1d1fbef1f9420392b241a9f2c0247081c2
--- /dev/null
+++ b/Tools/Playwright/win/MainWindow.cpp
@@ -0,0 +1,517 @@
+/*
+ * Copyright (C) 2018 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stdafx.h"
+#include "Common.h"
+#include "MainWindow.h"
+#include "PlaywrightLibResource.h"
+#include "WebKitBrowserWindow.h"
+#include <sstream>
+
+namespace WebCore {
+float deviceScaleFactorForWindow(HWND);
+}
+
+static const wchar_t* kPlaywrightRegistryKey = L"Software\\WebKit\\Playwright";
+
+static constexpr int kToolbarImageSize = 32;
+static constexpr int kToolbarURLBarIndex = 4;
+static constexpr int kToolbarProgressIndicatorIndex = 5;
+
+static WNDPROC DefEditProc = nullptr;
+
+static LRESULT CALLBACK EditProc(HWND, UINT, WPARAM, LPARAM);
+static INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
+
+std::wstring MainWindow::s_windowClass;
+size_t MainWindow::s_numInstances;
+
+bool MainWindow::s_headless = false;
+bool MainWindow::s_noStartupWindow = false;
+
+void MainWindow::configure(bool headless, bool noStartupWindow) {
+ s_headless = headless;
+ s_noStartupWindow = noStartupWindow;
+}
+
+static std::wstring loadString(int id)
+{
+ constexpr size_t length = 100;
+ wchar_t buff[length];
+ LoadString(hInst, id, buff, length);
+ return buff;
+}
+
+void MainWindow::registerClass(HINSTANCE hInstance)
+{
+ static bool initialized = false;
+ if (initialized)
+ return;
+ initialized = true;
+
+ s_windowClass = loadString(IDC_PLAYWRIGHT);
+
+ WNDCLASSEX wcex;
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.style = CS_HREDRAW | CS_VREDRAW;
+ wcex.lpfnWndProc = WndProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = hInstance;
+ wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PLAYWRIGHT));
+ wcex.hCursor = LoadCursor(0, IDC_ARROW);
+ wcex.hbrBackground = 0;
+ wcex.lpszMenuName = MAKEINTRESOURCE(IDC_PLAYWRIGHT);
+ wcex.lpszClassName = s_windowClass.c_str();
+ wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
+
+ RegisterClassEx(&wcex);
+}
+
+bool MainWindow::isInstance(HWND hwnd)
+{
+ wchar_t buff[64];
+ if (!GetClassName(hwnd, buff, _countof(buff)))
+ return false;
+ return s_windowClass == buff;
+}
+
+MainWindow::MainWindow()
+{
+ s_numInstances++;
+}
+
+MainWindow::~MainWindow()
+{
+ s_numInstances--;
+}
+
+void MainWindow::createToolbar(HINSTANCE hInstance)
+{
+ m_hToolbarWnd = CreateWindowEx(0, TOOLBARCLASSNAME, nullptr,
+ WS_CHILD | WS_BORDER | TBSTYLE_FLAT | TBSTYLE_LIST | TBSTYLE_TOOLTIPS, 0, 0, 0, 0,
+ m_hMainWnd, nullptr, hInstance, nullptr);
+
+ if (!m_hToolbarWnd)
+ return;
+
+ const int ImageListID = 0;
+ const int numButtons = 4;
+
+ HIMAGELIST hImageList;
+ hImageList = ImageList_LoadImage(hInstance, MAKEINTRESOURCE(IDB_TOOLBAR), kToolbarImageSize, 0, CLR_DEFAULT, IMAGE_BITMAP, 0);
+
+ SendMessage(m_hToolbarWnd, TB_SETIMAGELIST, ImageListID, reinterpret_cast<LPARAM>(hImageList));
+ SendMessage(m_hToolbarWnd, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS | TBSTYLE_EX_MIXEDBUTTONS);
+
+ const DWORD buttonStyles = BTNS_AUTOSIZE;
+
+ TBBUTTON tbButtons[] = {
+ { MAKELONG(0, ImageListID), IDM_HISTORY_BACKWARD, TBSTATE_ENABLED, buttonStyles | BTNS_DROPDOWN, { }, 0, (INT_PTR)L"Back" },
+ { MAKELONG(1, ImageListID), IDM_HISTORY_FORWARD, TBSTATE_ENABLED, buttonStyles | BTNS_DROPDOWN, { }, 0, (INT_PTR)L"Forward"},
+ { MAKELONG(2, ImageListID), IDM_RELOAD, TBSTATE_ENABLED, buttonStyles, { }, 0, (INT_PTR)L"Reload"},
+ { MAKELONG(3, ImageListID), IDM_GO_HOME, TBSTATE_ENABLED, buttonStyles, { }, 0, (INT_PTR)L"Home"},
+ { 0, 0, TBSTATE_ENABLED, BTNS_SEP, { }, 0, 0}, // URL bar
+ { 0, 0, TBSTATE_ENABLED, BTNS_SEP, { }, 0, 0}, // Progress indicator
+ };
+ ASSERT(tbButtons[kToolbarURLBarIndex].fsStyle == BTNS_SEP);
+ ASSERT(tbButtons[kToolbarProgressIndicatorIndex].fsStyle == BTNS_SEP);
+
+ SendMessage(m_hToolbarWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
+ SendMessage(m_hToolbarWnd, TB_ADDBUTTONS, _countof(tbButtons), reinterpret_cast<LPARAM>(&tbButtons));
+ ShowWindow(m_hToolbarWnd, true);
+
+ m_hURLBarWnd = CreateWindow(L"EDIT", 0, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, 0, 0, 0, 0, m_hToolbarWnd, 0, hInstance, 0);
+ m_hProgressIndicator = CreateWindow(L"STATIC", 0, WS_CHILD | WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE, 0, 0, 0, 0, m_hToolbarWnd, 0, hInstance, 0);
+
+ DefEditProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(m_hURLBarWnd, GWLP_WNDPROC));
+ SetWindowLongPtr(m_hURLBarWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(EditProc));
+}
+
+void MainWindow::resizeToolbar(int parentWidth)
+{
+ TBBUTTONINFO info { sizeof(TBBUTTONINFO), TBIF_BYINDEX | TBIF_SIZE };
+ info.cx = parentWidth - m_toolbarItemsWidth;
+ SendMessage(m_hToolbarWnd, TB_SETBUTTONINFO, kToolbarURLBarIndex, reinterpret_cast<LPARAM>(&info));
+
+ SendMessage(m_hToolbarWnd, TB_AUTOSIZE, 0, 0);
+
+ RECT rect;
+ SendMessage(m_hToolbarWnd, TB_GETITEMRECT, kToolbarURLBarIndex, reinterpret_cast<LPARAM>(&rect));
+ MoveWindow(m_hURLBarWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, true);
+
+ SendMessage(m_hToolbarWnd, TB_GETITEMRECT, kToolbarProgressIndicatorIndex, reinterpret_cast<LPARAM>(&rect));
+ MoveWindow(m_hProgressIndicator, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, true);
+}
+
+void MainWindow::rescaleToolbar()
+{
+ const float scaleFactor = WebCore::deviceScaleFactorForWindow(m_hMainWnd);
+ const int scaledImageSize = kToolbarImageSize * scaleFactor;
+
+ TBBUTTONINFO info { sizeof(TBBUTTONINFO), TBIF_BYINDEX | TBIF_SIZE };
+
+ info.cx = 0;
+ SendMessage(m_hToolbarWnd, TB_SETBUTTONINFO, kToolbarURLBarIndex, reinterpret_cast<LPARAM>(&info));
+ info.cx = scaledImageSize * 2;
+ SendMessage(m_hToolbarWnd, TB_SETBUTTONINFO, kToolbarProgressIndicatorIndex, reinterpret_cast<LPARAM>(&info));
+
+ SendMessage(m_hToolbarWnd, TB_AUTOSIZE, 0, 0);
+
+ int numItems = SendMessage(m_hToolbarWnd, TB_BUTTONCOUNT, 0, 0);
+
+ RECT rect;
+ SendMessage(m_hToolbarWnd, TB_GETITEMRECT, numItems-1, reinterpret_cast<LPARAM>(&rect));
+ m_toolbarItemsWidth = rect.right;
+}
+
+bool MainWindow::init(HINSTANCE hInstance, WKContextRef context, WKWebsiteDataStoreRef dataStore)
+{
+ auto conf = adoptWK(WKPageConfigurationCreate());
+ auto prefs = adoptWK(WKPreferencesCreate());
+
+ auto pageGroup = adoptWK(WKPageGroupCreateWithIdentifier(createWKString("WinPlaywright").get()));
+ WKPageConfigurationSetPageGroup(conf.get(), pageGroup.get());
+ WKPageGroupSetPreferences(pageGroup.get(), prefs.get());
+
+ WKPreferencesSetMediaCapabilitiesEnabled(prefs.get(), false);
+ WKPreferencesSetDeveloperExtrasEnabled(prefs.get(), true);
+ WKPageConfigurationSetPreferences(conf.get(), prefs.get());
+
+ WKPageConfigurationSetContext(conf.get(), context);
+ WKPageConfigurationSetWebsiteDataStore(conf.get(), dataStore);
+
+ return init(hInstance, conf.get());
+}
+
+bool MainWindow::init(HINSTANCE hInstance, WKPageConfigurationRef conf)
+{
+ m_configuration = conf;
+
+ registerClass(hInstance);
+
+ auto title = loadString(IDS_APP_TITLE);
+
+ m_hMainWnd = CreateWindowExW(s_headless ? WS_EX_NOACTIVATE : 0, s_windowClass.c_str(), title.c_str(),
+ WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance, this);
+
+ if (!m_hMainWnd)
+ return false;
+
+ if (!s_headless) {
+ createToolbar(hInstance);
+ if (!m_hToolbarWnd)
+ return false;
+ }
+
+ m_browserWindow.reset(new WebKitBrowserWindow(*this, m_hMainWnd, conf));
+
+ updateDeviceScaleFactor();
+ resizeSubViews();
+
+ if (s_headless) {
+ SetMenu(m_hMainWnd, NULL);
+ } else {
+ SetFocus(m_hURLBarWnd);
+ ShowWindow(m_hMainWnd, SW_SHOW);
+ }
+ return true;
+}
+
+void MainWindow::resizeSubViews()
+{
+ RECT rcClient;
+ GetClientRect(m_hMainWnd, &rcClient);
+ if (s_headless) {
+ MoveWindow(m_browserWindow->hwnd(), 0, 0, rcClient.right, rcClient.bottom, true);
+ return;
+ }
+
+ resizeToolbar(rcClient.right);
+
+ RECT rect;
+ GetWindowRect(m_hToolbarWnd, &rect);
+ POINT toolbarBottom = { 0, rect.bottom };
+ ScreenToClient(m_hMainWnd, &toolbarBottom);
+ auto height = toolbarBottom.y;
+ MoveWindow(m_browserWindow->hwnd(), 0, height, rcClient.right, rcClient.bottom - height, true);
+}
+
+LRESULT CALLBACK MainWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT result = 0;
+ MainWindow* thisWindow = reinterpret_cast<MainWindow*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
+ if (!thisWindow && message != WM_CREATE)
+ return DefWindowProc(hWnd, message, wParam, lParam);
+
+ switch (message) {
+ case WM_ACTIVATE:
+ switch (LOWORD(wParam)) {
+ case WA_ACTIVE:
+ case WA_CLICKACTIVE:
+ SetFocus(thisWindow->browserWindow()->hwnd());
+ }
+ break;
+ case WM_CREATE:
+ SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(reinterpret_cast<LPCREATESTRUCT>(lParam)->lpCreateParams));
+ break;
+ case WM_APPCOMMAND: {
+ auto cmd = GET_APPCOMMAND_LPARAM(lParam);
+ switch (cmd) {
+ case APPCOMMAND_BROWSER_BACKWARD:
+ thisWindow->browserWindow()->navigateForwardOrBackward(false);
+ result = 1;
+ break;
+ case APPCOMMAND_BROWSER_FORWARD:
+ thisWindow->browserWindow()->navigateForwardOrBackward(true);
+ result = 1;
+ break;
+ case APPCOMMAND_BROWSER_HOME:
+ thisWindow->goHome();
+ break;
+ case APPCOMMAND_BROWSER_REFRESH:
+ thisWindow->browserWindow()->reload();
+ result = 1;
+ break;
+ case APPCOMMAND_BROWSER_STOP:
+ break;
+ }
+ break;
+ }
+ case WM_COMMAND: {
+ int wmId = LOWORD(wParam);
+ int wmEvent = HIWORD(wParam);
+ switch (wmEvent) {
+ case 0: // Menu or BN_CLICKED
+ case 1: // Accelerator
+ break;
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ // Parse the menu selections:
+ switch (wmId) {
+ case IDC_URL_BAR:
+ thisWindow->onURLBarEnter();
+ break;
+ case IDM_NEW_WEBKIT_WINDOW: {
+ auto* newWindow = new MainWindow();
+ newWindow->init(hInst, thisWindow->m_configuration.get());
+ break;
+ }
+ case IDM_CLOSE_WINDOW:
+ PostMessage(hWnd, WM_CLOSE, 0, 0);
+ break;
+ case IDM_ABOUT:
+ DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
+ break;
+ case IDM_GO_HOME:
+ thisWindow->goHome();
+ break;
+ case IDM_EXIT:
+ DestroyWindow(hWnd);
+ break;
+ case IDM_WEB_INSPECTOR:
+ thisWindow->browserWindow()->launchInspector();
+ break;
+ case IDM_HISTORY_BACKWARD:
+ case IDM_HISTORY_FORWARD:
+ thisWindow->browserWindow()->navigateForwardOrBackward(wmId == IDM_HISTORY_FORWARD);
+ break;
+ case IDM_ACTUAL_SIZE:
+ thisWindow->browserWindow()->resetZoom();
+ break;
+ case IDM_RELOAD:
+ thisWindow->browserWindow()->reload();
+ break;
+ case IDM_ZOOM_IN:
+ thisWindow->browserWindow()->zoomIn();
+ break;
+ case IDM_ZOOM_OUT:
+ thisWindow->browserWindow()->zoomOut();
+ break;
+ default:
+ if (!thisWindow->toggleMenuItem(wmId))
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ }
+ break;
+ case WM_DESTROY:
+ SetWindowLongPtr(hWnd, GWLP_USERDATA, 0);
+ delete thisWindow;
+ if (s_noStartupWindow || s_numInstances > 1)
+ return 0;
+ PostQuitMessage(0);
+ break;
+ case WM_SIZE:
+ thisWindow->resizeSubViews();
+ break;
+ case WM_DPICHANGED: {
+ thisWindow->updateDeviceScaleFactor();
+ auto& rect = *reinterpret_cast<RECT*>(lParam);
+ SetWindowPos(hWnd, nullptr, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE);
+ break;
+ }
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+
+ return result;
+}
+
+static bool menuItemIsChecked(const MENUITEMINFO& info)
+{
+ return info.fState & MFS_CHECKED;
+}
+
+bool MainWindow::toggleMenuItem(UINT menuID)
+{
+ if (s_headless)
+ return (INT_PTR)FALSE;
+
+ HMENU menu = ::GetMenu(hwnd());
+
+ MENUITEMINFO info = { };
+ info.cbSize = sizeof(info);
+ info.fMask = MIIM_STATE;
+
+ if (!::GetMenuItemInfo(menu, menuID, FALSE, &info))
+ return false;
+
+ BOOL newState = !menuItemIsChecked(info);
+ info.fState = (newState) ? MFS_CHECKED : MFS_UNCHECKED;
+ ::SetMenuItemInfo(menu, menuID, FALSE, &info);
+
+ return true;
+}
+
+LRESULT CALLBACK EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case WM_SETFOCUS:
+ PostMessage(hWnd, EM_SETSEL, 0, -1);
+ break;
+ case WM_CHAR:
+ if (wParam == 13) {
+ // Enter Key
+ ::PostMessage(GetParent(hWnd), static_cast<UINT>(WM_COMMAND), MAKELPARAM(IDC_URL_BAR, 0), 0);
+ return 0;
+ }
+ break;
+ }
+ return CallWindowProc(DefEditProc, hWnd, message, wParam, lParam);
+}
+
+// Message handler for about box.
+INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ UNREFERENCED_PARAMETER(lParam);
+ switch (message) {
+ case WM_INITDIALOG:
+ return (INT_PTR)TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
+ EndDialog(hDlg, LOWORD(wParam));
+ return (INT_PTR)TRUE;
+ }
+ break;
+ }
+ return (INT_PTR)FALSE;
+}
+
+void MainWindow::loadURL(std::wstring url)
+{
+ if (::PathFileExists(url.c_str()) || ::PathIsUNC(url.c_str())) {
+ wchar_t fileURL[INTERNET_MAX_URL_LENGTH];
+ DWORD fileURLLength = _countof(fileURL);
+
+ if (SUCCEEDED(::UrlCreateFromPath(url.c_str(), fileURL, &fileURLLength, 0)))
+ url = fileURL;
+ }
+ if (url.find(L"://") == url.npos && url.find(L"about:blank") == url.npos)
+ url = L"http://" + url;
+
+ if (FAILED(m_browserWindow->loadURL(_bstr_t(url.c_str()))))
+ return;
+
+ if (!s_headless)
+ SetFocus(m_browserWindow->hwnd());
+}
+
+void MainWindow::goHome()
+{
+ std::wstring defaultURL = L"about:blank";
+ loadURL(defaultURL);
+}
+
+void MainWindow::onURLBarEnter()
+{
+ if (s_headless)
+ return;
+ wchar_t url[INTERNET_MAX_URL_LENGTH];
+ GetWindowText(m_hURLBarWnd, url, INTERNET_MAX_URL_LENGTH);
+ loadURL(url);
+}
+
+void MainWindow::updateDeviceScaleFactor()
+{
+ if (s_headless)
+ return;
+ if (m_hURLBarFont)
+ ::DeleteObject(m_hURLBarFont);
+
+ rescaleToolbar();
+
+ RECT rect;
+ GetClientRect(m_hToolbarWnd, &rect);
+ int fontHeight = rect.bottom * 3. / 4;
+
+ m_hURLBarFont = ::CreateFont(fontHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
+ OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, FF_DONTCARE, L"Tahoma");
+ ::SendMessage(m_hURLBarWnd, static_cast<UINT>(WM_SETFONT), reinterpret_cast<WPARAM>(m_hURLBarFont), TRUE);
+}
+
+void MainWindow::progressChanged(double progress)
+{
+ if (s_headless)
+ return;
+ std::wostringstream text;
+ text << static_cast<int>(progress * 100) << L'%';
+ SetWindowText(m_hProgressIndicator, text.str().c_str());
+}
+
+void MainWindow::progressFinished()
+{
+ if (s_headless)
+ return;
+ SetWindowText(m_hProgressIndicator, L"");
+}
+
+void MainWindow::activeURLChanged(std::wstring url)
+{
+ if (s_headless)
+ return;
+ SetWindowText(m_hURLBarWnd, url.c_str());
+}
diff --git a/Tools/Playwright/win/MainWindow.h b/Tools/Playwright/win/MainWindow.h
new file mode 100644
index 0000000000000000000000000000000000000000..b173f44a96dee7f0b80c8689b007754920fc64a3
--- /dev/null
+++ b/Tools/Playwright/win/MainWindow.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "WebKitBrowserWindow.h"
+
+#include <WebKit/WKBase.h>
+#include <WebKit/WKRetainPtr.h>
+#include <functional>
+#include <memory>
+#include <string>
+
+class MainWindow : public BrowserWindowClient {
+public:
+ static void configure(bool headless, bool noStartupWindow);
+
+ MainWindow();
+
+ ~MainWindow();
+ bool init(HINSTANCE hInstance, WKContextRef, WKWebsiteDataStoreRef);
+ bool init(HINSTANCE hInstance, WKPageConfigurationRef);
+
+ void resizeSubViews();
+ HWND hwnd() const { return m_hMainWnd; }
+ WebKitBrowserWindow* browserWindow() const { return m_browserWindow.get(); }
+
+ void loadURL(std::wstring);
+ void goHome();
+
+ static bool isInstance(HWND);
+
+private:
+ static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+ static void registerClass(HINSTANCE hInstance);
+ static std::wstring s_windowClass;
+ static size_t s_numInstances;
+ static bool s_headless;
+ static bool s_noStartupWindow;
+
+ bool toggleMenuItem(UINT menuID);
+ void onURLBarEnter();
+ void updateDeviceScaleFactor();
+
+ void createToolbar(HINSTANCE);
+ void resizeToolbar(int);
+ void rescaleToolbar();
+
+ // BrowserWindowClient
+ void progressChanged(double) final;
+ void progressFinished() final;
+ void activeURLChanged(std::wstring) final;
+
+ HWND m_hMainWnd { nullptr };
+ HWND m_hToolbarWnd { nullptr };
+ HWND m_hURLBarWnd { nullptr };
+ HWND m_hProgressIndicator { nullptr };
+ HWND m_hCacheWnd { nullptr };
+ HGDIOBJ m_hURLBarFont { nullptr };
+ // WKPageConfigurationRef retains page and WebKitBrowserWindow retains page via view
+ // make sure view is deleted after the page.
+ std::unique_ptr<WebKitBrowserWindow> m_browserWindow;
+ WKRetainPtr<WKPageConfigurationRef> m_configuration;
+ int m_toolbarItemsWidth { };
+};
diff --git a/Tools/Playwright/win/Playwright.ico b/Tools/Playwright/win/Playwright.ico
new file mode 100644
index 0000000000000000000000000000000000000000..d551aa3aaf80adf9b7760e2eb8de95a5c3e53df6
Binary files /dev/null and b/Tools/Playwright/win/Playwright.ico differ
diff --git a/Tools/Playwright/win/Playwright.rc b/Tools/Playwright/win/Playwright.rc
new file mode 100644
index 0000000000000000000000000000000000000000..4430f19062cc9fd048e4b1d5d8d33c5a119a8409
--- /dev/null
+++ b/Tools/Playwright/win/Playwright.rc
@@ -0,0 +1,76 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "PlaywrightResource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_PLAYWRIGHT ICON "Playwright.ico"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "PlaywrightResource.\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Tools/Playwright/win/PlaywrightLib.rc b/Tools/Playwright/win/PlaywrightLib.rc
new file mode 100644
index 0000000000000000000000000000000000000000..24192b98bdd5b55e94a7fd33c13d8301ee4ddc42
--- /dev/null
+++ b/Tools/Playwright/win/PlaywrightLib.rc
@@ -0,0 +1,358 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "PlaywrightLibResource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_PLAYWRIGHT ICON "Playwright.ico"
+
+IDI_SMALL ICON "small.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDC_PLAYWRIGHT MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "E&xit", IDM_EXIT
+ MENUITEM "New WebKit Window", IDM_NEW_WEBKIT_WINDOW
+ MENUITEM "Close\tCtrl-W", IDM_CLOSE_WINDOW
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "Reload\tCtrl-R", IDM_RELOAD
+ MENUITEM "Actual Size\tCtrl+0", IDM_ACTUAL_SIZE
+ MENUITEM "Zoom In\tCtrl++", IDM_ZOOM_IN
+ MENUITEM "Zoom Out\tCtrl+-", IDM_ZOOM_OUT
+ MENUITEM "Invert Colors", IDM_INVERT_COLORS
+ MENUITEM "Go Home", IDM_GO_HOME
+ END
+ POPUP "&History"
+ BEGIN
+ MENUITEM "Back", IDM_HISTORY_BACKWARD
+ MENUITEM "Forward", IDM_HISTORY_FORWARD
+ END
+ POPUP "D&evelop"
+ BEGIN
+ MENUITEM "Show Web Inspector", IDM_WEB_INSPECTOR
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About ...", IDM_ABOUT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDC_PLAYWRIGHT ACCELERATORS
+BEGIN
+ "/", IDM_ABOUT, ASCII, ALT, NOINVERT
+ "0", IDM_ACTUAL_SIZE, VIRTKEY, CONTROL, NOINVERT
+ "?", IDM_ABOUT, ASCII, ALT, NOINVERT
+ "R", IDM_RELOAD, VIRTKEY, CONTROL, NOINVERT
+ VK_ADD, IDM_ZOOM_IN, VIRTKEY, CONTROL, NOINVERT
+ VK_OEM_MINUS, IDM_ZOOM_OUT, VIRTKEY, CONTROL, NOINVERT
+ VK_OEM_PLUS, IDM_ZOOM_IN, VIRTKEY, CONTROL, NOINVERT
+ VK_SUBTRACT, IDM_ZOOM_OUT, VIRTKEY, CONTROL, NOINVERT
+END
+
+IDR_ACCELERATORS_PRE ACCELERATORS
+BEGIN
+ "W", IDM_CLOSE_WINDOW, VIRTKEY, CONTROL, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOGEX 22, 17, 230, 41
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ ICON IDI_PLAYWRIGHT,IDC_MYICON,14,9,20,20
+ LTEXT "Playwright Version 1.1",IDC_STATIC,49,10,119,8
+ LTEXT "Copyright (C) 2015-2019",IDC_STATIC,49,20,119,8
+ DEFPUSHBUTTON "OK",IDOK,186,10,30,11,WS_GROUP
+END
+
+IDD_CACHES DIALOGEX 0, 0, 401, 456
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,287,435,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,344,435,50,14
+ GROUPBOX "FastMalloc",IDC_STATIC,208,14,186,67
+ GROUPBOX "WebCore Cache",IDC_STATIC,17,83,376,105
+ GROUPBOX "JavaScript Heap",IDC_STATIC,18,193,376,168
+ GROUPBOX "Site Icon Database",IDC_STATIC,18,366,142,65
+ GROUPBOX "Font and Glyph Caches",IDC_STATIC,168,366,226,66
+ GROUPBOX "CFURLCache",IDC_STATIC,7,14,197,67
+ PUSHBUTTON "Empty URLCache",IDC_EMPTY_URL_CACHE,131,63,69,14,WS_DISABLED
+ PUSHBUTTON "Return Free Memory",IDC_RETURN_FREE_MEMORY,308,63,76,14,WS_DISABLED
+ PUSHBUTTON "Empty WebCore Cache",IDC_EMPTY_WEBCORE_CACHE,21,170,83,14,WS_DISABLED
+ CONTROL "Disable WebCore Cache",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,119,172,93,10
+ PUSHBUTTON "Garbage Collect JavaScript Objects",IDC_GC_JSC,253,343,135,14,WS_DISABLED
+ RTEXT "Reserved VM",IDC_STATIC,212,26,67,9
+ RTEXT "0",IDC_RESERVED_VM,290,26,94,8
+ RTEXT "Committed VM",IDC_STATIC,211,39,67,8
+ RTEXT "0",IDC_COMMITTED_VM,290,39,94,8
+ RTEXT "Free List Bytes",IDC_STATIC,211,52,67,8
+ RTEXT "0",IDC_FREE_LIST_BYTES,290,52,94,8
+ RTEXT "Images",IDC_STATIC,37,106,24,8
+ RTEXT "CSS",IDC_STATIC,47,116,14,8
+ RTEXT "XSL",IDC_STATIC,49,126,12,8
+ RTEXT "JavaScript",IDC_STATIC,27,135,34,8
+ RTEXT "Total",IDC_STATIC,43,146,17,8
+ LTEXT "Objects",IDC_STATIC,111,96,26,8
+ LTEXT "Bytes",IDC_STATIC,175,96,19,8
+ LTEXT "Live",IDC_STATIC,232,96,14,8
+ LTEXT "Decoded",IDC_STATIC,284,96,29,8
+ LTEXT "Purgeable",IDC_STATIC,351,96,33,8
+ RTEXT "0",IDC_IMAGES_OBJECT_COUNT,100,106,32,8
+ RTEXT "0",IDC_CSS_OBJECT_COUNT,100,116,32,8
+ RTEXT "0",IDC_XSL_OBJECT_COUNT,100,126,32,8
+ RTEXT "0",IDC_JSC_OBJECT_COUNT,100,135,32,8
+ RTEXT "0",IDC_TOTAL_OBJECT_COUNT,100,146,32,8
+ RTEXT "0",IDC_IMAGES_BYTES,162,106,32,8
+ RTEXT "0",IDC_CSS_BYTES,162,116,32,8
+ RTEXT "0",IDC_XSL_BYTES,162,126,32,8
+ RTEXT "0",IDC_JSC_BYTES,162,135,32,8
+ RTEXT "0",IDC_TOTAL_BYTES,162,146,32,8
+ RTEXT "0",IDC_IMAGES_LIVE_COUNT,221,106,32,8
+ RTEXT "0",IDC_CSS_LIVE_COUNT,221,116,32,8
+ RTEXT "0",IDC_XSL_LIVE_COUNT,221,126,32,8
+ RTEXT "0",IDC_JSC_LIVE_COUNT,221,135,32,8
+ RTEXT "0",IDC_TOTAL_LIVE_COUNT,221,146,32,8
+ RTEXT "0",IDC_IMAGES_DECODED_COUNT,284,106,32,8
+ RTEXT "0",IDC_CSS_DECODED_COUNT,284,116,32,8
+ RTEXT "0",IDC_XSL_DECODED_COUNT,284,126,32,8
+ RTEXT "0",IDC_JSC_DECODED_COUNT,284,135,32,8
+ RTEXT "0",IDC_TOTAL_DECODED,284,146,32,8
+ RTEXT "0",IDC_IMAGES_PURGEABLE_COUNT,354,106,32,8
+ RTEXT "0",IDC_CSS_PURGEABLE_COUNT,354,116,32,8
+ RTEXT "0",IDC_XSL_PURGEABLE_COUNT,354,126,32,8
+ RTEXT "0",IDC_JSC_PURGEABLE_COUNT,354,135,32,8
+ RTEXT "0",IDC_TOTAL_PURGEABLE,354,146,32,8
+ RTEXT "Total Objects",IDC_STATIC,63,207,44,8
+ RTEXT "Global Objects",IDC_STATIC,56,217,51,8
+ RTEXT "Protected Objects",IDC_STATIC,48,227,59,8
+ RTEXT "0",IDC_TOTAL_JSC_HEAP_OBJECTS,127,207,56,8
+ RTEXT "0",IDC_GLOBAL_JSC_HEAP_OBJECTS,127,217,56,8
+ RTEXT "0",IDC_PROTECTED_JSC_HEAP_OBJECTS,127,227,56,8
+ RTEXT "Size",IDC_STATIC56,223,207,14,8
+ RTEXT "Free",IDC_STATIC57,222,217,16,8
+ RTEXT "0",IDC_JSC_HEAP_SIZE,270,207,56,8
+ RTEXT "0",IDC_JSC_HEAP_FREE,270,217,56,8
+ PUSHBUTTON "Purge Inactive Font Data",IDC_BUTTON5,293,415,95,14,WS_DISABLED
+ LTEXT "Total Font Data Objects",IDC_STATIC,208,379,78,8
+ LTEXT "Inactive Font Data Objects",IDC_STATIC,198,390,88,8
+ LTEXT "Glyph Pages",IDC_STATIC,246,402,40,8
+ RTEXT "0",IDC_TOTAL_FONT_OBJECTS,329,379,56,8
+ RTEXT "0",IDC_INACTIVE_FONT_OBJECTS,329,390,56,8
+ RTEXT "0",IDC_GLYPH_PAGES,329,402,56,8
+ LTEXT "Page URL Mappings",IDC_STATIC,33,380,64,8
+ LTEXT "Retained Page URLs",IDC_STATIC,31,390,66,8
+ LTEXT "Site Icon Records",IDC_STATIC,40,400,57,8
+ LTEXT "Site Icons with Data",IDC_STATIC,32,410,65,8
+ RTEXT "0",IDC_PAGE_URL_MAPPINGS,101,380,52,8
+ RTEXT "0",IDC_RETAINED_PAGE_URLS,101,390,52,8
+ RTEXT "0",IDC_SITE_ICON_RECORDS,101,400,52,8
+ RTEXT "0",IDC_SITE_ICONS_WITH_DATA,101,410,52,8
+END
+
+IDD_AUTH DIALOGEX 0, 0, 231, 119
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Authentication Required"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "Sign In",IDOK,116,98,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,174,98,50,14
+ LTEXT "Realm",IDC_REALM_TEXT,67,21,157,8
+ RTEXT "User Name:",IDC_STATIC,7,41,57,8
+ EDITTEXT IDC_AUTH_USER,67,39,157,14,ES_AUTOHSCROLL
+ RTEXT "Password:",IDC_STATIC,7,66,57,8
+ EDITTEXT IDC_AUTH_PASSWORD,67,64,157,14,ES_PASSWORD | ES_AUTOHSCROLL
+END
+
+IDD_PROXY DIALOGEX 0, 0, 310, 176
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Proxy Configuration"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,199,155,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,253,155,50,14
+ CONTROL "Use system default proxy configuration.",IDC_PROXY_DEFAULT,
+ "Button",BS_AUTORADIOBUTTON | WS_GROUP,22,15,226,10
+ CONTROL "Use custom proxy configuration:",IDC_PROXY_CUSTOM,
+ "Button",BS_AUTORADIOBUTTON,22,33,226,10
+ CONTROL "Don't use proxy.",IDC_PROXY_DISABLE,"Button",BS_AUTORADIOBUTTON,22,117,226,10
+ EDITTEXT IDC_PROXY_URL,76,52,193,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_PROXY_EXCLUDE,76,85,193,14,ES_AUTOHSCROLL
+ LTEXT "URL:",IDC_STATIC,30,55,43,8,0,WS_EX_RIGHT
+ LTEXT "Excude list:",IDC_STATIC,30,88,43,8,0,WS_EX_RIGHT
+ LTEXT "Example: http://192.168.0.2:8000",IDC_STATIC,80,68,194,8
+ LTEXT "Comma separated hostnames.",IDC_STATIC,80,101,194,8
+END
+
+IDD_SERVER_TRUST DIALOGEX 0, 0, 319, 184
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Server Trust Evaluation Request"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "Yes",IDOK,197,163,50,14
+ PUSHBUTTON "No",IDCANCEL,262,163,50,14
+ LTEXT "Certificate information",IDC_STATIC,7,7,294,17
+ EDITTEXT IDC_SERVER_TRUST_TEXT,7,24,305,130,ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "PlaywrightLibResource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_ABOUTBOX, DIALOG
+ BEGIN
+ END
+
+ IDD_CACHES, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 394
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 449
+ END
+
+ IDD_AUTH, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 224
+ VERTGUIDE, 64
+ VERTGUIDE, 67
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 92
+ HORZGUIDE, 25
+ HORZGUIDE, 50
+ END
+
+ IDD_PROXY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 303
+ VERTGUIDE, 22
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 169
+ END
+
+ IDD_SERVER_TRUST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 312
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 177
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_TOOLBAR BITMAP "toolbar.bmp"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_APP_TITLE "Playwright"
+ IDC_PLAYWRIGHT "Playwright"
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Tools/Playwright/win/PlaywrightLibResource.h b/Tools/Playwright/win/PlaywrightLibResource.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b1409e2d95a9a64af763915871eea5fed579e78
--- /dev/null
+++ b/Tools/Playwright/win/PlaywrightLibResource.h
@@ -0,0 +1,119 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by PlaywrightLib.rc
+//
+#define IDC_MYICON 2
+#define IDD_PLAYWRIGHT_DIALOG 102
+#define IDS_APP_TITLE 103
+#define IDD_ABOUTBOX 103
+#define IDM_ABOUT 104
+#define IDM_EXIT 105
+#define IDI_PLAYWRIGHT 107
+#define IDI_SMALL 108
+#define IDC_PLAYWRIGHT 109
+#define IDM_WEB_INSPECTOR 120
+#define IDM_INVERT_COLORS 125
+#define IDR_MAINFRAME 128
+#define IDD_CACHES 129
+#define IDM_HISTORY_BACKWARD 130
+#define IDD_USER_AGENT 130
+#define IDM_HISTORY_FORWARD 131
+#define IDM_HISTORY_LINK0 150
+#define IDM_HISTORY_LINK1 151
+#define IDM_HISTORY_LINK2 152
+#define IDM_HISTORY_LINK3 153
+#define IDM_HISTORY_LINK4 154
+#define IDM_HISTORY_LINK5 155
+#define IDM_HISTORY_LINK6 156
+#define IDM_HISTORY_LINK7 157
+#define IDM_HISTORY_LINK8 158
+#define IDM_HISTORY_LINK9 159
+#define IDT_UPDATE_STATS 160
+#define IDM_ACTUAL_SIZE 172
+#define IDM_ZOOM_IN 173
+#define IDM_ZOOM_OUT 174
+#define IDD_AUTH 176
+#define IDD_PROXY 178
+#define IDD_SERVER_TRUST 179
+#define IDR_ACCELERATORS_PRE 180
+#define IDB_TOOLBAR 181
+#define IDC_EMPTY_URL_CACHE 1000
+#define IDC_RETURN_FREE_MEMORY 1001
+#define IDC_EMPTY_WEBCORE_CACHE 1002
+#define IDC_CHECK1 1003
+#define IDC_HEAP_OBJECTS 1005
+#define IDC_GC_JSC 1006
+#define IDC_RESERVED_VM 1007
+#define IDC_COMMITTED_VM 1008
+#define IDC_FREE_LIST_BYTES 1009
+#define IDC_IMAGES_OBJECT_COUNT 1011
+#define IDC_CSS_OBJECT_COUNT 1012
+#define IDC_XSL_OBJECT_COUNT 1013
+#define IDC_JSC_OBJECT_COUNT 1014
+#define IDC_TOTAL_OBJECT_COUNT 1015
+#define IDC_IMAGES_BYTES 1016
+#define IDC_CSS_BYTES 1017
+#define IDC_XSL_BYTES 1018
+#define IDC_JSC_BYTES 1019
+#define IDC_TOTAL_BYTES 1020
+#define IDC_IMAGES_LIVE_COUNT 1021
+#define IDC_CSS_LIVE_COUNT 1022
+#define IDC_XSL_LIVE_COUNT 1023
+#define IDC_JSC_LIVE_COUNT 1024
+#define IDC_TOTAL_LIVE_COUNT 1025
+#define IDC_IMAGES_DECODED_COUNT 1026
+#define IDC_CSS_DECODED_COUNT 1027
+#define IDC_XSL_DECODED_COUNT 1028
+#define IDC_JSC_DECODED_COUNT 1029
+#define IDC_TOTAL_DECODED 1030
+#define IDC_IMAGES_PURGEABLE_COUNT 1031
+#define IDC_CSS_PURGEABLE_COUNT 1032
+#define IDC_XSL_PURGEABLE_COUNT 1033
+#define IDC_JSC_PURGEABLE_COUNT 1034
+#define IDC_TOTAL_PURGEABLE 1035
+#define IDC_TOTAL_JSC_HEAP_OBJECTS 1036
+#define IDC_GLOBAL_JSC_HEAP_OBJECTS 1037
+#define IDC_PROTECTED_JSC_HEAP_OBJECTS 1038
+#define IDC_STATIC56 1039
+#define IDC_STATIC57 1040
+#define IDC_JSC_HEAP_SIZE 1041
+#define IDC_JSC_HEAP_FREE 1042
+#define IDC_BUTTON5 1043
+#define IDC_TOTAL_FONT_OBJECTS 1044
+#define IDC_Message 1044
+#define IDC_INACTIVE_FONT_OBJECTS 1045
+#define IDC_GLYPH_PAGES 1046
+#define IDC_PAGE_URL_MAPPINGS 1047
+#define IDC_RETAINED_PAGE_URLS 1048
+#define IDC_SITE_ICON_RECORDS 1049
+#define IDC_TOTAL_FONT_OBJECTS5 1050
+#define IDC_SITE_ICONS_WITH_DATA 1051
+#define IDC_USER_AGENT_INPUT 1052
+#define IDC_AUTH_USER 1053
+#define IDC_AUTH_PASSWORD 1054
+#define IDC_URL_BAR 1055
+#define IDC_REALM_TEXT 1056
+#define IDC_PROXY_URL 1057
+#define IDC_PROXY_DEFAULT 1058
+#define IDC_PROXY_CUSTOM 1059
+#define IDC_PROXY_EXCLUDE 1060
+#define IDC_PROXY_DISABLE 1061
+#define IDC_SERVER_TRUST_TEXT 1062
+#define IDM_NEW_WEBKIT_WINDOW 32776
+#define IDM_NEW_WEBKITLEGACY_WINDOW 32777
+#define IDM_RELOAD 32779
+#define IDM_CLOSE_WINDOW 32780
+#define IDM_GO_HOME 32781
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 182
+#define _APS_NEXT_COMMAND_VALUE 32783
+#define _APS_NEXT_CONTROL_VALUE 1063
+#define _APS_NEXT_SYMED_VALUE 110
+#endif
+#endif
diff --git a/Tools/Playwright/win/PlaywrightReplace.h b/Tools/Playwright/win/PlaywrightReplace.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd134b879ea6aee23826e9ed2f6773d8c1466118
--- /dev/null
+++ b/Tools/Playwright/win/PlaywrightReplace.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 Alex Christensen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+// This file is to make it easier for users to manage changes to the internals of Playwright
+
+static void processCrashReport(const wchar_t* fileName) { ::MessageBox(0, fileName, L"Crash Report", MB_OK); }
diff --git a/Tools/Playwright/win/PlaywrightResource.h b/Tools/Playwright/win/PlaywrightResource.h
new file mode 100644
index 0000000000000000000000000000000000000000..c60d7b73f18d0e7f220e68c2a22e5d9911bf8960
--- /dev/null
+++ b/Tools/Playwright/win/PlaywrightResource.h
@@ -0,0 +1,20 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by PlaywrightLauncher.rc
+//
+#define IDD_PLAYWRIGHT_DIALOG 102
+#define IDI_PLAYWRIGHT 107
+#define IDR_MAINFRAME 128
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 129
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 110
+#endif
+#endif
diff --git a/Tools/Playwright/win/WebKitBrowserWindow.cpp b/Tools/Playwright/win/WebKitBrowserWindow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..742a817f8bb8934751d057eca55d11e050255487
--- /dev/null
+++ b/Tools/Playwright/win/WebKitBrowserWindow.cpp
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2018 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "stdafx.h"
+#include "Common.h"
+#include "MainWindow.h"
+#include "PlaywrightLibResource.h"
+#include "WebKitBrowserWindow.h"
+#include <WebCore/GDIUtilities.h>
+#include <WebKit/WKAuthenticationChallenge.h>
+#include <WebKit/WKAuthenticationDecisionListener.h>
+#include <WebKit/WKCertificateInfoCurl.h>
+#include <WebKit/WKCredential.h>
+#include <WebKit/WKFramePolicyListener.h>
+#include <WebKit/WKInspector.h>
+#include <WebKit/WKProtectionSpace.h>
+#include <WebKit/WKProtectionSpaceCurl.h>
+#include <WebKit/WKWebsiteDataStoreRef.h>
+#include <WebKit/WKWebsiteDataStoreRefCurl.h>
+#include <vector>
+
+std::wstring createPEMString(WKCertificateInfoRef certificateInfo)
+{
+ auto chainSize = WKCertificateInfoGetCertificateChainSize(certificateInfo);
+
+ std::wstring pems;
+
+ for (auto i = 0; i < chainSize; i++) {
+ auto certificate = adoptWK(WKCertificateInfoCopyCertificateAtIndex(certificateInfo, i));
+ auto size = WKDataGetSize(certificate.get());
+ auto data = WKDataGetBytes(certificate.get());
+
+ for (size_t i = 0; i < size; i++)
+ pems.push_back(data[i]);
+ }
+
+ return replaceString(pems, L"\n", L"\r\n");
+}
+
+WebKitBrowserWindow::WebKitBrowserWindow(BrowserWindowClient& client, HWND mainWnd, WKPageConfigurationRef conf)
+ : m_client(client)
+ , m_hMainWnd(mainWnd)
+{
+ RECT rect = { };
+ m_view = adoptWK(WKViewCreate(rect, conf, mainWnd));
+ WKViewSetIsInWindow(m_view.get(), true);
+
+ auto page = WKViewGetPage(m_view.get());
+
+ WKPageNavigationClientV0 navigationClient = { };
+ navigationClient.base.version = 0;
+ navigationClient.base.clientInfo = this;
+ navigationClient.didReceiveAuthenticationChallenge = didReceiveAuthenticationChallenge;
+ WKPageSetPageNavigationClient(page, &navigationClient.base);
+
+ WKPageUIClientV14 uiClient = { };
+ uiClient.base.version = 14;
+ uiClient.base.clientInfo = this;
+ uiClient.createNewPage = createNewPage;
+ uiClient.didNotHandleKeyEvent = didNotHandleKeyEvent;
+ uiClient.close = closeWindow;
+ uiClient.runJavaScriptAlert = runJavaScriptAlert;
+ uiClient.runJavaScriptConfirm = runJavaScriptConfirm;
+ uiClient.runJavaScriptPrompt = runJavaScriptPrompt;
+ uiClient.runBeforeUnloadConfirmPanel = runBeforeUnloadConfirmPanel;
+ uiClient.handleJavaScriptDialog = handleJavaScriptDialog;
+ WKPageSetPageUIClient(page, &uiClient.base);
+
+ WKPageStateClientV0 stateClient = { };
+ stateClient.base.version = 0;
+ stateClient.base.clientInfo = this;
+ stateClient.didChangeTitle = didChangeTitle;
+ stateClient.didChangeIsLoading = didChangeIsLoading;
+ stateClient.didChangeEstimatedProgress = didChangeEstimatedProgress;
+ stateClient.didChangeActiveURL = didChangeActiveURL;
+ WKPageSetPageStateClient(page, &stateClient.base);
+
+ WKPagePolicyClientV1 policyClient = { };
+ policyClient.base.version = 1;
+ policyClient.base.clientInfo = this;
+ policyClient.decidePolicyForResponse_deprecatedForUseWithV0 = decidePolicyForResponse;
+ WKPageSetPagePolicyClient(page, &policyClient.base);
+ resetZoom();
+}
+
+WebKitBrowserWindow::~WebKitBrowserWindow()
+{
+ if (m_alertDialog) {
+ WKRelease(m_alertDialog);
+ m_alertDialog = NULL;
+ }
+
+ if (m_confirmDialog) {
+ WKRelease(m_confirmDialog);
+ m_confirmDialog = NULL;
+ }
+
+ if (m_promptDialog) {
+ WKRelease(m_promptDialog);
+ m_promptDialog = NULL;
+ }
+
+ if (m_beforeUnloadDialog) {
+ WKRelease(m_beforeUnloadDialog);
+ m_beforeUnloadDialog = NULL;
+ }
+}
+
+HWND WebKitBrowserWindow::hwnd()
+{
+ return WKViewGetWindow(m_view.get());
+}
+
+HRESULT WebKitBrowserWindow::loadURL(const BSTR& url)
+{
+ auto page = WKViewGetPage(m_view.get());
+ WKPageLoadURL(page, createWKURL(_bstr_t(url)).get());
+ return true;
+}
+
+void WebKitBrowserWindow::reload()
+{
+ auto page = WKViewGetPage(m_view.get());
+ WKPageReload(page);
+}
+
+void WebKitBrowserWindow::navigateForwardOrBackward(bool forward)
+{
+ auto page = WKViewGetPage(m_view.get());
+ if (forward)
+ WKPageGoForward(page);
+ else
+ WKPageGoBack(page);
+}
+
+void WebKitBrowserWindow::launchInspector()
+{
+ auto page = WKViewGetPage(m_view.get());
+ auto inspector = WKPageGetInspector(page);
+ WKInspectorShow(inspector);
+}
+
+void WebKitBrowserWindow::setUserAgent(_bstr_t& customUAString)
+{
+ auto page = WKViewGetPage(m_view.get());
+ auto ua = createWKString(customUAString);
+ WKPageSetCustomUserAgent(page, ua.get());
+}
+
+_bstr_t WebKitBrowserWindow::userAgent()
+{
+ auto page = WKViewGetPage(m_view.get());
+ auto ua = adoptWK(WKPageCopyUserAgent(page));
+ return createString(ua.get()).c_str();
+}
+
+void WebKitBrowserWindow::resetZoom()
+{
+ auto page = WKViewGetPage(m_view.get());
+ WKPageSetPageZoomFactor(page, WebCore::deviceScaleFactorForWindow(hwnd()));
+}
+
+void WebKitBrowserWindow::zoomIn()
+{
+ auto page = WKViewGetPage(m_view.get());
+ double s = WKPageGetPageZoomFactor(page);
+ WKPageSetPageZoomFactor(page, s * 1.25);
+}
+
+void WebKitBrowserWindow::zoomOut()
+{
+ auto page = WKViewGetPage(m_view.get());
+ double s = WKPageGetPageZoomFactor(page);
+ WKPageSetPageZoomFactor(page, s * 0.8);
+}
+
+static WebKitBrowserWindow& toWebKitBrowserWindow(const void *clientInfo)
+{
+ return *const_cast<WebKitBrowserWindow*>(static_cast<const WebKitBrowserWindow*>(clientInfo));
+}
+
+void WebKitBrowserWindow::didChangeTitle(const void* clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ auto page = WKViewGetPage(thisWindow.m_view.get());
+ WKRetainPtr<WKStringRef> title = adoptWK(WKPageCopyTitle(page));
+ std::wstring titleString = createString(title.get()) + L" [WebKit]";
+ SetWindowText(thisWindow.m_hMainWnd, titleString.c_str());
+}
+
+void WebKitBrowserWindow::didChangeIsLoading(const void* clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ thisWindow.m_client.progressFinished();
+}
+
+void WebKitBrowserWindow::didChangeEstimatedProgress(const void* clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ auto page = WKViewGetPage(thisWindow.m_view.get());
+ thisWindow.m_client.progressChanged(WKPageGetEstimatedProgress(page));
+}
+
+void WebKitBrowserWindow::didChangeActiveURL(const void* clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ auto page = WKViewGetPage(thisWindow.m_view.get());
+ WKRetainPtr<WKURLRef> url = adoptWK(WKPageCopyActiveURL(page));
+ thisWindow.m_client.activeURLChanged(createString(url.get()));
+}
+
+void WebKitBrowserWindow::didReceiveAuthenticationChallenge(WKPageRef page, WKAuthenticationChallengeRef challenge, const void* clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ auto protectionSpace = WKAuthenticationChallengeGetProtectionSpace(challenge);
+ auto decisionListener = WKAuthenticationChallengeGetDecisionListener(challenge);
+ auto authenticationScheme = WKProtectionSpaceGetAuthenticationScheme(protectionSpace);
+
+ if (authenticationScheme == kWKProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested) {
+ if (thisWindow.canTrustServerCertificate(protectionSpace)) {
+ WKRetainPtr<WKStringRef> username = createWKString("accept server trust");
+ WKRetainPtr<WKStringRef> password = createWKString("");
+ WKRetainPtr<WKCredentialRef> wkCredential = adoptWK(WKCredentialCreate(username.get(), password.get(), kWKCredentialPersistenceForSession));
+ WKAuthenticationDecisionListenerUseCredential(decisionListener, wkCredential.get());
+ return;
+ }
+ } else {
+ WKRetainPtr<WKStringRef> realm(WKProtectionSpaceCopyRealm(protectionSpace));
+
+ if (auto credential = askCredential(thisWindow.hwnd(), createString(realm.get()))) {
+ WKRetainPtr<WKStringRef> username = createWKString(credential->username);
+ WKRetainPtr<WKStringRef> password = createWKString(credential->password);
+ WKRetainPtr<WKCredentialRef> wkCredential = adoptWK(WKCredentialCreate(username.get(), password.get(), kWKCredentialPersistenceForSession));
+ WKAuthenticationDecisionListenerUseCredential(decisionListener, wkCredential.get());
+ return;
+ }
+ }
+
+ WKAuthenticationDecisionListenerUseCredential(decisionListener, nullptr);
+}
+
+bool WebKitBrowserWindow::canTrustServerCertificate(WKProtectionSpaceRef protectionSpace)
+{
+ auto host = createString(adoptWK(WKProtectionSpaceCopyHost(protectionSpace)).get());
+ auto certificateInfo = adoptWK(WKProtectionSpaceCopyCertificateInfo(protectionSpace));
+ auto verificationError = WKCertificateInfoGetVerificationError(certificateInfo.get());
+ auto description = createString(adoptWK(WKCertificateInfoCopyVerificationErrorDescription(certificateInfo.get())).get());
+ auto pem = createPEMString(certificateInfo.get());
+
+ auto it = m_acceptedServerTrustCerts.find(host);
+ if (it != m_acceptedServerTrustCerts.end() && it->second == pem)
+ return true;
+
+ std::wstring textString = L"[HOST] " + host + L"\r\n";
+ textString.append(L"[ERROR] " + std::to_wstring(verificationError) + L"\r\n");
+ textString.append(L"[DESCRIPTION] " + description + L"\r\n");
+ textString.append(pem);
+
+ if (askServerTrustEvaluation(hwnd(), textString)) {
+ m_acceptedServerTrustCerts.emplace(host, pem);
+ return true;
+ }
+
+ return false;
+}
+
+void WebKitBrowserWindow::closeWindow(WKPageRef page, const void* clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ PostMessage(thisWindow.m_hMainWnd, WM_CLOSE, 0, 0);
+}
+
+void WebKitBrowserWindow::runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptAlertResultListenerRef listener, const void *clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ WKRetain(listener);
+ thisWindow.m_alertDialog = listener;
+}
+
+void WebKitBrowserWindow::runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptConfirmResultListenerRef listener, const void *clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ WKRetain(listener);
+ thisWindow.m_confirmDialog = listener;
+}
+
+void WebKitBrowserWindow::runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptPromptResultListenerRef listener, const void *clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ WKRetain(listener);
+ thisWindow.m_promptDialog = listener;
+}
+
+void WebKitBrowserWindow::runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, WKPageRunBeforeUnloadConfirmPanelResultListenerRef listener, const void *clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ WKRetain(listener);
+ thisWindow.m_beforeUnloadDialog = listener;
+}
+
+void WebKitBrowserWindow::handleJavaScriptDialog(WKPageRef page, bool accept, WKStringRef value, const void *clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ if (thisWindow.m_alertDialog) {
+ WKPageRunJavaScriptAlertResultListenerCall(thisWindow.m_alertDialog);
+ WKRelease(thisWindow.m_alertDialog);
+ thisWindow.m_alertDialog = NULL;
+ }
+
+ if (thisWindow.m_confirmDialog) {
+ WKPageRunJavaScriptConfirmResultListenerCall(thisWindow.m_confirmDialog, accept);
+ WKRelease(thisWindow.m_confirmDialog);
+ thisWindow.m_confirmDialog = NULL;
+ }
+
+ if (thisWindow.m_promptDialog) {
+ WKPageRunJavaScriptPromptResultListenerCall(thisWindow.m_promptDialog, accept ? value : NULL);
+ WKRelease(thisWindow.m_promptDialog);
+ thisWindow.m_promptDialog = NULL;
+ }
+
+ if (thisWindow.m_beforeUnloadDialog) {
+ WKPageRunBeforeUnloadConfirmPanelResultListenerCall(thisWindow.m_beforeUnloadDialog, accept);
+ WKRelease(thisWindow.m_beforeUnloadDialog);
+ thisWindow.m_beforeUnloadDialog = NULL;
+ }
+}
+
+WKPageRef WebKitBrowserWindow::createPageCallback(WKPageConfigurationRef configuration)
+{
+ return WebKitBrowserWindow::createViewCallback(configuration, true);
+}
+
+WKPageRef WebKitBrowserWindow::createViewCallback(WKPageConfigurationRef configuration, bool navigate)
+{
+ auto* newWindow = new MainWindow();
+ bool ok = newWindow->init(hInst, configuration);
+ if (navigate)
+ newWindow->browserWindow()->loadURL(_bstr_t("about:blank").GetBSTR());
+
+ auto* newBrowserWindow = newWindow->browserWindow();
+ return WKViewGetPage(newBrowserWindow->m_view.get());
+}
+
+
+WKPageRef WebKitBrowserWindow::createNewPage(WKPageRef, WKPageConfigurationRef configuration, WKNavigationActionRef, WKWindowFeaturesRef, const void*)
+{
+ // Retain popups as per API contract.
+ WKRetainPtr<WKPageRef> newPage = createViewCallback(configuration, false);
+ return newPage.leakRef();
+}
+
+void WebKitBrowserWindow::didNotHandleKeyEvent(WKPageRef, WKNativeEventPtr event, const void* clientInfo)
+{
+ auto& thisWindow = toWebKitBrowserWindow(clientInfo);
+ PostMessage(thisWindow.m_hMainWnd, event->message, event->wParam, event->lParam);
+}
+
+void WebKitBrowserWindow::decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
+{
+ if (WKURLResponseIsAttachment(response))
+ WKFramePolicyListenerDownload(listener);
+ else
+ WKFramePolicyListenerUse(listener);
+}
diff --git a/Tools/Playwright/win/WebKitBrowserWindow.h b/Tools/Playwright/win/WebKitBrowserWindow.h
new file mode 100644
index 0000000000000000000000000000000000000000..29e11623eac55a979db444df1d5a04106caf5431
--- /dev/null
+++ b/Tools/Playwright/win/WebKitBrowserWindow.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#pragma once
+
+#include "Common.h"
+#include <WebKit/WKBase.h>
+#include <WebKit/WebKit2_C.h>
+#include <unordered_map>
+
+class BrowserWindowClient {
+public:
+ virtual void progressChanged(double) = 0;
+ virtual void progressFinished() = 0;
+ virtual void activeURLChanged(std::wstring) = 0;
+};
+
+class WebKitBrowserWindow {
+public:
+ static WKPageRef createPageCallback(WKPageConfigurationRef);
+ WebKitBrowserWindow(BrowserWindowClient&, HWND mainWnd, WKPageConfigurationRef);
+ ~WebKitBrowserWindow();
+
+ HRESULT loadURL(const BSTR& url);
+ void reload();
+ void navigateForwardOrBackward(bool forward);
+ void launchInspector();
+
+ _bstr_t userAgent();
+ void setUserAgent(_bstr_t&);
+
+ void resetZoom();
+ void zoomIn();
+ void zoomOut();
+
+ bool canTrustServerCertificate(WKProtectionSpaceRef);
+ HWND hwnd();
+
+private:
+ static WKPageRef createViewCallback(WKPageConfigurationRef, bool navigate);
+
+ static void didChangeTitle(const void*);
+ static void didChangeIsLoading(const void*);
+ static void didChangeEstimatedProgress(const void*);
+ static void didChangeActiveURL(const void*);
+ static void didReceiveAuthenticationChallenge(WKPageRef, WKAuthenticationChallengeRef, const void*);
+ static WKPageRef createNewPage(WKPageRef, WKPageConfigurationRef, WKNavigationActionRef, WKWindowFeaturesRef, const void *);
+ static void closeWindow(WKPageRef, const void*);
+ static void runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptAlertResultListenerRef listener, const void *clientInfo);
+ static void runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptConfirmResultListenerRef listener, const void *clientInfo);
+ static void runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptPromptResultListenerRef listener, const void *clientInfo);
+ static void runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, WKPageRunBeforeUnloadConfirmPanelResultListenerRef listener, const void *clientInfo);
+ static void handleJavaScriptDialog(WKPageRef page, bool accept, WKStringRef value, const void *clientInfo);
+ static void didNotHandleKeyEvent(WKPageRef, WKNativeEventPtr, const void*);
+ static void decidePolicyForResponse(WKPageRef, WKFrameRef, WKURLResponseRef, WKURLRequestRef, WKFramePolicyListenerRef, WKTypeRef, const void*);
+
+ BrowserWindowClient& m_client;
+ WKRetainPtr<WKViewRef> m_view;
+ HWND m_hMainWnd { nullptr };
+ ProxySettings m_proxy { };
+ std::unordered_map<std::wstring, std::wstring> m_acceptedServerTrustCerts;
+ WKPageRunJavaScriptAlertResultListenerRef m_alertDialog = { };
+ WKPageRunJavaScriptConfirmResultListenerRef m_confirmDialog = { };
+ WKPageRunJavaScriptPromptResultListenerRef m_promptDialog = { };
+ WKPageRunBeforeUnloadConfirmPanelResultListenerRef m_beforeUnloadDialog = { };
+};
diff --git a/Tools/Playwright/win/WinMain.cpp b/Tools/Playwright/win/WinMain.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b19855c53902fd161f3e42858d5828adae1af464
--- /dev/null
+++ b/Tools/Playwright/win/WinMain.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2006, 2008, 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2011 Brent Fulgham. All rights reserved.
+ * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
+ * Copyright (C) 2013 Alex Christensen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma warning(disable: 4091)
+
+#include "stdafx.h"
+#include "Common.h"
+#include "MainWindow.h"
+#include "PlaywrightLibResource.h"
+#include "PlaywrightReplace.h"
+#include <WebKit/WKContext.h>
+#include <WebKit/WKWebsiteDataStoreConfigurationRef.h>
+#include <WebKit/WKWebsiteDataStoreRef.h>
+#include <wtf/win/SoftLinking.h>
+#include "WebKitBrowserWindow.h"
+#include <wtf/MainThread.h>
+#include <WebKit/WKInspector.h>
+
+SOFT_LINK_LIBRARY(user32);
+SOFT_LINK_OPTIONAL(user32, SetProcessDpiAwarenessContext, BOOL, STDAPICALLTYPE, (DPI_AWARENESS_CONTEXT));
+
+WKRetainPtr<WKStringRef> toWK(const std::string& string)
+{
+ return adoptWK(WKStringCreateWithUTF8CString(string.c_str()));
+}
+
+std::string toUTF8String(const wchar_t* src, size_t srcLength)
+{
+ int length = WideCharToMultiByte(CP_UTF8, 0, src, srcLength, 0, 0, nullptr, nullptr);
+ std::vector<char> buffer(length);
+ size_t actualLength = WideCharToMultiByte(CP_UTF8, 0, src, srcLength, buffer.data(), length, nullptr, nullptr);
+ return { buffer.data(), actualLength };
+}
+
+int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpstrCmdLine, _In_ int nCmdShow)
+{
+#ifdef _CRTDBG_MAP_ALLOC
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
+#endif
+
+ MSG msg { };
+ HACCEL hAccelTable, hPreAccelTable;
+
+ INITCOMMONCONTROLSEX InitCtrlEx;
+
+ InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ InitCtrlEx.dwICC = 0x00004000; // ICC_STANDARD_CLASSES;
+ InitCommonControlsEx(&InitCtrlEx);
+
+ auto options = parseCommandLine();
+ if (options.inspectorPipe) {
+ WKInspectorInitializeRemoteInspectorPipe(
+ WebKitBrowserWindow::createPageCallback,
+ []() { PostQuitMessage(0); });
+ }
+
+ if (options.useFullDesktop)
+ computeFullDesktopFrame();
+
+ // Init COM
+ OleInitialize(nullptr);
+
+ if (SetProcessDpiAwarenessContextPtr())
+ SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_UNAWARE);
+
+ MainWindow::configure(options.headless, options.noStartupWindow);
+
+ if (!options.noStartupWindow) {
+ auto configuration = adoptWK(WKWebsiteDataStoreConfigurationCreate());
+ if (options.userDataDir.length()) {
+ std::string profileFolder = toUTF8String(options.userDataDir, options.userDataDir.length());
+ WKWebsiteDataStoreConfigurationSetApplicationCacheDirectory(configuration.get(), toWK(profileFolder + "\\ApplicationCache").get());
+ WKWebsiteDataStoreConfigurationSetNetworkCacheDirectory(configuration.get(), toWK(profileFolder + "\\Cache").get());
+ WKWebsiteDataStoreConfigurationSetCacheStorageDirectory(configuration.get(), toWK(profileFolder + "\\CacheStorage").get());
+ WKWebsiteDataStoreConfigurationSetIndexedDBDatabaseDirectory(configuration.get(), toWK(profileFolder + "\\Databases" + "\\IndexedDB").get());
+ WKWebsiteDataStoreConfigurationSetLocalStorageDirectory(configuration.get(), toWK(profileFolder + "\\LocalStorage").get());
+ WKWebsiteDataStoreConfigurationSetWebSQLDatabaseDirectory(configuration.get(), toWK(profileFolder + "\\Databases" + "\\WebSQL").get());
+ WKWebsiteDataStoreConfigurationSetMediaKeysStorageDirectory(configuration.get(), toWK(profileFolder + "\\MediaKeys").get());
+ WKWebsiteDataStoreConfigurationSetResourceLoadStatisticsDirectory(configuration.get(), toWK(profileFolder + "\\ResourceLoadStatistics").get());
+ WKWebsiteDataStoreConfigurationSetServiceWorkerRegistrationDirectory(configuration.get(), toWK(profileFolder + "\\ServiceWorkers").get());
+ }
+ auto context = adoptWK(WKContextCreateWithConfiguration(nullptr));
+ auto dataStore = adoptWK(WKWebsiteDataStoreCreateWithConfiguration(configuration.get()));
+ WKContextSetPrimaryDataStore(context.get(), dataStore.get());
+
+ auto* mainWindow = new MainWindow();
+ HRESULT hr = mainWindow->init(hInst, context.get(), dataStore.get());
+ if (FAILED(hr))
+ goto exit;
+
+ if (options.requestedURL.length())
+ mainWindow->loadURL(options.requestedURL.GetBSTR());
+ else
+ mainWindow->goHome();
+ }
+
+ hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_PLAYWRIGHT));
+ hPreAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCELERATORS_PRE));
+
+#pragma warning(disable:4509)
+
+ // Main message loop:
+ __try {
+ while (GetMessage(&msg, nullptr, 0, 0)) {
+ if (TranslateAccelerator(msg.hwnd, hPreAccelTable, &msg))
+ continue;
+ bool processed = false;
+ if (MainWindow::isInstance(msg.hwnd))
+ processed = TranslateAccelerator(msg.hwnd, hAccelTable, &msg);
+ if (!processed) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ } __except(createCrashReport(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) { }
+
+exit:
+#ifdef _CRTDBG_MAP_ALLOC
+ _CrtDumpMemoryLeaks();
+#endif
+
+ // Shut down COM.
+ OleUninitialize();
+
+ return static_cast<int>(msg.wParam);
+}
+
+extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpstrCmdLine, int nCmdShow)
+{
+ return wWinMain(hInstance, hPrevInstance, lpstrCmdLine, nCmdShow);
+}
diff --git a/Tools/Playwright/win/resource.h b/Tools/Playwright/win/resource.h
new file mode 100644
index 0000000000000000000000000000000000000000..6a2168457084e26663486a741d39f84beb38e0b5
--- /dev/null
+++ b/Tools/Playwright/win/resource.h
@@ -0,0 +1,27 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by WinLauncher.rc
+//
+#define IDC_MYICON 2
+#define IDD_WINLAUNCHER_DIALOG 102
+#define IDS_APP_TITLE 103
+#define IDD_ABOUTBOX 103
+#define IDM_ABOUT 104
+#define IDM_EXIT 105
+#define IDI_WINLAUNCHER 107
+#define IDI_SMALL 108
+#define IDC_WINLAUNCHER 109
+#define IDR_MAINFRAME 128
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 129
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 110
+#endif
+#endif
diff --git a/Tools/Playwright/win/small.ico b/Tools/Playwright/win/small.ico
new file mode 100644
index 0000000000000000000000000000000000000000..d551aa3aaf80adf9b7760e2eb8de95a5c3e53df6
Binary files /dev/null and b/Tools/Playwright/win/small.ico differ
diff --git a/Tools/Playwright/win/stdafx.cpp b/Tools/Playwright/win/stdafx.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3c4e5e52a16a300e36f4f9d8c5c490634ed02257
--- /dev/null
+++ b/Tools/Playwright/win/stdafx.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// stdafx.cpp : source file that includes just the standard includes
+// Spinneret.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/Tools/Playwright/win/stdafx.h b/Tools/Playwright/win/stdafx.h
new file mode 100644
index 0000000000000000000000000000000000000000..8436fba636da15aa7a9f2f9e6b6667908d7c7b85
--- /dev/null
+++ b/Tools/Playwright/win/stdafx.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE)
+#include "cmakeconfig.h"
+#endif
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+// Needed for limit defines, like INTMAX_MAX, which is used by the std C++ library
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+
+#include <assert.h>
+#include <comdef.h>
+#include <comip.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include <comutil.h>
+#include <malloc.h>
+#include <memory.h>
+#include <objbase.h>
+#include <shellapi.h>
+#include <shlwapi.h>
+#include <stdlib.h>
+#include <string>
+#include <tchar.h>
+#include <windows.h>
+#include <wininet.h>
+#include <wtf/Platform.h>
+
+#include <JavaScriptCore/JSExportMacros.h>
+#include <WebCore/PlatformExportMacros.h>
+
+#if 0
+// Visual Studio Leak Detection
+// <http://msdn2.microsoft.com/en-US/library/e5ewb1h3.aspx>
+#if defined(_MSC_VER) && defined(_DEBUG)
+#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+#include <crtdbg.h>
+#endif
+#endif
diff --git a/Tools/Playwright/win/toolbar.bmp b/Tools/Playwright/win/toolbar.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..f06d7f785a8743513db6aeb3361f4094237c2c3d
Binary files /dev/null and b/Tools/Playwright/win/toolbar.bmp differ
diff --git a/Tools/Scripts/build-webkit b/Tools/Scripts/build-webkit
index 8909b3cff450d6a94d8777bc065f16945f8a794e..1be2d5d4939a9c92b5bbe1c115248d3c39883fc7 100755
--- a/Tools/Scripts/build-webkit
+++ b/Tools/Scripts/build-webkit
@@ -243,7 +243,7 @@ if (isAppleCocoaWebKit()) {
push @projects, ("Source/WebKit");
if (!isIOSWebKit()) {
- 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/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp
index 82e976bd7bdeb1c9539a9925ca4eb0fc5b3d728c..f0510926733dda5bb898a84468157e3925cb86e7 100644
--- a/Tools/WebKitTestRunner/TestController.cpp
+++ b/Tools/WebKitTestRunner/TestController.cpp
@@ -727,7 +727,8 @@ void TestController::createWebViewWithOptions(const TestOptions& options)
0, // didResignInputElementStrongPasswordAppearance
0, // requestStorageAccessConfirm
shouldAllowDeviceOrientationAndMotionAccess,
- runWebAuthenticationPanel
+ runWebAuthenticationPanel,
+ 0 // handleJavaScriptDialog
};
WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient.base);
2020-01-17 04:50:20 +03:00
diff --git a/Tools/WebKitTestRunner/win/EventSenderProxyWin.cpp b/Tools/WebKitTestRunner/win/EventSenderProxyWin.cpp
index 06f19261b387ce02a44c319bd7016e824847ad24..c4e2f8f8816b06a105c18872e735ae4dbca6fe68 100644
--- a/Tools/WebKitTestRunner/win/EventSenderProxyWin.cpp
+++ b/Tools/WebKitTestRunner/win/EventSenderProxyWin.cpp
@@ -312,4 +312,59 @@ void EventSenderProxy::keyDown(WKStringRef keyRef, WKEventModifiers wkModifiers,
SetKeyboardState(keyState);
}
+void EventSenderProxy::addTouchPoint(int, int)
+{
+ notImplemented();
+}
+
+void EventSenderProxy::updateTouchPoint(int, int, int)
+{
+ notImplemented();
+}
+
+void EventSenderProxy::setTouchModifier(WKEventModifiers, bool)
+{
+ notImplemented();
+}
+
+void EventSenderProxy::setTouchPointRadius(int, int)
+{
+ notImplemented();
+}
+
+void EventSenderProxy::touchStart()
+{
+ notImplemented();
+}
+
+void EventSenderProxy::touchMove()
+{
+ notImplemented();
+}
+
+void EventSenderProxy::touchEnd()
+{
+ notImplemented();
+}
+
+void EventSenderProxy::touchCancel()
+{
+ notImplemented();
+}
+
+void EventSenderProxy::clearTouchPoints()
+{
+ notImplemented();
+}
+
+void EventSenderProxy::releaseTouchPoint(int)
+{
+ notImplemented();
+}
+
+void EventSenderProxy::cancelTouchPoint(int)
+{
+ notImplemented();
+}
+
} // namespace WTR
diff --git a/Tools/wpe/backends/CMakeLists.txt b/Tools/wpe/backends/CMakeLists.txt
index f0f80b35cd5e72dcf763425bfdef99585ab4226a..e3f82f9a9d5d0abf27ebe5a71ee386851724f1bc 100644
--- a/Tools/wpe/backends/CMakeLists.txt
+++ b/Tools/wpe/backends/CMakeLists.txt
@@ -10,6 +10,7 @@ file(MAKE_DIRECTORY ${DERIVED_SOURCES_WPETOOLINGBACKENDS_DIR})
set(WPEToolingBackends_SOURCES
${DERIVED_SOURCES_WPETOOLINGBACKENDS_DIR}/xdg-shell-unstable-v6-protocol.c
${TOOLS_DIR}/wpe/backends/HeadlessViewBackend.cpp
+ ${TOOLS_DIR}/wpe/backends/NullViewBackend.cpp
${TOOLS_DIR}/wpe/backends/ViewBackend.cpp
${TOOLS_DIR}/wpe/backends/WebKitAccessibleApplication.cpp
${TOOLS_DIR}/wpe/backends/WindowViewBackend.cpp
diff --git a/Tools/wpe/backends/NullViewBackend.cpp b/Tools/wpe/backends/NullViewBackend.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..033ff802d3971a455667cd64c0e68dd10f448aa7
--- /dev/null
+++ b/Tools/wpe/backends/NullViewBackend.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "NullViewBackend.h"
+
+#include <wpe/fdo-egl.h>
+
+namespace WPEToolingBackends {
+
+NullViewBackend::NullViewBackend()
+ : ViewBackend(1, 1)
+{
+ static struct wpe_view_backend_exportable_fdo_egl_client exportableClient = { nullptr, nullptr, nullptr, nullptr, nullptr };
+ m_exportable = wpe_view_backend_exportable_fdo_egl_create(&exportableClient, this, 1, 1);
+ initializeAccessibility();
+ addActivityState(wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window);
+}
+
+} // namespace WPEToolingBackends
diff --git a/Tools/wpe/backends/NullViewBackend.h b/Tools/wpe/backends/NullViewBackend.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4489294acfe73adcb3593f2d54a3be625307f28
--- /dev/null
+++ b/Tools/wpe/backends/NullViewBackend.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ViewBackend.h"
+#include <cairo.h>
+#include <glib.h>
+#include <unordered_map>
+
+namespace WPEToolingBackends {
+
+class NullViewBackend final : public ViewBackend {
+public:
+ NullViewBackend();
+ virtual ~NullViewBackend() = default;
+private:
+ void displayBuffer(struct wpe_fdo_egl_exported_image*) override { };
+#if WPE_FDO_CHECK_VERSION(1, 5, 0)
+ void displayBuffer(struct wpe_fdo_shm_exported_buffer*) override { };
+#endif
+};
+
+} // namespace WPEToolingBackends