playwright/browser_patches/webkit/patches/bootstrap.diff

16235 lines
719 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index 91e427c30c51163edd9f106d42f95e09d02be9c4..b7a591467cea135960be9ac4d8fbaadcdcdcaf5b 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -1144,16 +1144,20 @@ set(JavaScriptCore_INSPECTOR_DOMAINS
${JAVASCRIPTCORE_DIR}/inspector/protocol/Animation.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/ApplicationCache.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Audit.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Browser.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/CSS.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Canvas.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Console.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Dialog.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/DOM.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMDebugger.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMStorage.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Database.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Debugger.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Emulation.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/GenericTypes.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Heap.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Input.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Inspector.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/LayerTree.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Network.json
diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make
index e2a36fa8764909abfd0e1896d3a9a7c361f1b23a..e3ed01ae7cf8ce68a4fd8308e0ea2819638a78d3 100644
--- a/Source/JavaScriptCore/DerivedSources.make
+++ b/Source/JavaScriptCore/DerivedSources.make
@@ -241,16 +241,20 @@ INSPECTOR_DOMAINS := \
$(JavaScriptCore)/inspector/protocol/Animation.json \
$(JavaScriptCore)/inspector/protocol/ApplicationCache.json \
$(JavaScriptCore)/inspector/protocol/Audit.json \
+ $(JavaScriptCore)/inspector/protocol/Browser.json \
$(JavaScriptCore)/inspector/protocol/CSS.json \
$(JavaScriptCore)/inspector/protocol/Canvas.json \
$(JavaScriptCore)/inspector/protocol/Console.json \
+ $(JavaScriptCore)/inspector/protocol/Dialog.json \
$(JavaScriptCore)/inspector/protocol/DOM.json \
$(JavaScriptCore)/inspector/protocol/DOMDebugger.json \
$(JavaScriptCore)/inspector/protocol/DOMStorage.json \
$(JavaScriptCore)/inspector/protocol/Database.json \
$(JavaScriptCore)/inspector/protocol/Debugger.json \
+ $(JavaScriptCore)/inspector/protocol/Emulation.json \
$(JavaScriptCore)/inspector/protocol/GenericTypes.json \
$(JavaScriptCore)/inspector/protocol/Heap.json \
+ $(JavaScriptCore)/inspector/protocol/Input.json \
$(JavaScriptCore)/inspector/protocol/Inspector.json \
$(JavaScriptCore)/inspector/protocol/LayerTree.json \
$(JavaScriptCore)/inspector/protocol/Network.json \
diff --git a/Source/JavaScriptCore/bindings/ScriptValue.cpp b/Source/JavaScriptCore/bindings/ScriptValue.cpp
index dece6ac51e3a85b1e094e405effc6203887ddfd4..9bf7519d894eceb06b40d754c4fb7940399eba84 100644
--- a/Source/JavaScriptCore/bindings/ScriptValue.cpp
+++ b/Source/JavaScriptCore/bindings/ScriptValue.cpp
@@ -81,7 +81,10 @@ static RefPtr<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/InspectorBackendDispatcher.cpp b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
index 038cb646d31706905deff8935040d63c0afd00f9..2fca7b043f15a8cce3819cc827912fb719a345db 100644
--- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
+++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
@@ -102,7 +102,7 @@ void BackendDispatcher::registerDispatcherForDomain(const String& domain, Supple
m_dispatchers.set(domain, dispatcher);
}
-void BackendDispatcher::dispatch(const String& message)
+BackendDispatcher::DispatchResult BackendDispatcher::dispatch(const String& message, Mode mode, Interceptor&& interceptor)
{
Ref<BackendDispatcher> protect(*this);
@@ -120,29 +120,32 @@ void BackendDispatcher::dispatch(const String& message)
if (!JSON::Value::parseJSON(message, parsedMessage)) {
reportProtocolError(ParseError, "Message must be in JSON format"_s);
sendPendingErrors();
- return;
+ return DispatchResult::Finished;
}
if (!parsedMessage->asObject(messageObject)) {
reportProtocolError(InvalidRequest, "Message must be a JSONified object"_s);
sendPendingErrors();
- return;
+ return DispatchResult::Finished;
}
RefPtr<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)
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)
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
--- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
+++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
@@ -82,7 +82,11 @@ public:
};
void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*);
- void dispatch(const String& message);
+
+ enum class DispatchResult { Finished, Continue };
+ enum class Mode { FailIfDomainIsMissing, ContinueIfDomainIsMissing };
+ using Interceptor = WTF::Function<DispatchResult(const RefPtr<JSON::Object>&)>;
+ DispatchResult dispatch(const String& message, Mode mode = Mode::FailIfDomainIsMissing, Interceptor&& interceptor = Interceptor());
// Note that 'unused' is a workaround so the compiler can pick the right sendResponse based on arity.
// When <http://webkit.org/b/179847> is fixed or this class is renamed for the JSON::Object case,
diff --git a/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp b/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp
index d408d364f1986983161f9d44efbc8bc6f6898676..1375ce9990f0c63d7e6f33ee62930051d6cd44cb 100644
--- a/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp
+++ b/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp
@@ -49,7 +49,7 @@ void FrontendRouter::connectFrontend(FrontendChannel& connection)
void FrontendRouter::disconnectFrontend(FrontendChannel& connection)
{
if (!m_connections.contains(&connection)) {
- ASSERT_NOT_REACHED();
+ ASSERT(m_connections.isEmpty());
return;
}
diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.cpp b/Source/JavaScriptCore/inspector/InspectorTarget.cpp
index 0cc2127c9c12c2d82dea9550bad73f4ffb99ba24..490238b408da6b6ce7fbcccf138849977862c897 100644
--- a/Source/JavaScriptCore/inspector/InspectorTarget.cpp
+++ b/Source/JavaScriptCore/inspector/InspectorTarget.cpp
@@ -52,7 +52,6 @@ void InspectorTarget::resume()
void InspectorTarget::setResumeCallback(WTF::Function<void()>&& callback)
{
- ASSERT(!m_resumeCallback);
m_resumeCallback = WTFMove(callback);
}
diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.h b/Source/JavaScriptCore/inspector/InspectorTarget.h
index 4b95964db4d902b4b7f4b0b4c40afea51654ff2f..db2fde501b30c8e4fafcac3b2b403713c768c34f 100644
--- a/Source/JavaScriptCore/inspector/InspectorTarget.h
+++ b/Source/JavaScriptCore/inspector/InspectorTarget.h
@@ -47,6 +47,7 @@ public:
virtual InspectorTargetType type() const = 0;
virtual bool isProvisional() const { return false; }
+ virtual String oldTargetID() const { return String(); }
bool isPaused() const { return m_isPaused; }
void pause();
void resume();
@@ -56,6 +57,8 @@ public:
virtual void connect(FrontendChannel::ConnectionType) = 0;
virtual void disconnect() = 0;
virtual void sendMessageToTargetBackend(const String&) = 0;
+ virtual void activate(String& error) { error = "Target cannot be activated"; }
+ virtual void close(String& error, bool /* runBeforeUnload */) { error = "Target cannot be closed"; }
private:
WTF::Function<void()> m_resumeCallback;
diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
index 8fcb5a1e55750d325a84824d86c49cfe6fb04268..b56ffaa68a34aa3e7119962cd8404cafb9b420ec 100644
--- 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
target->sendMessageToTargetBackend(message);
}
+void InspectorTargetAgent::activate(ErrorString& errorString, const String& targetId)
+{
+ InspectorTarget* target = m_targets.get(targetId);
+ if (!target) {
+ errorString = "Missing target for given targetId"_s;
+ return;
+ }
+
+ target->activate(errorString);
+}
+
+void InspectorTargetAgent::close(ErrorString& errorString, const String& targetId, const bool* runBeforeUnload)
+{
+ InspectorTarget* target = m_targets.get(targetId);
+ if (!target) {
+ errorString = "Missing target for given targetId"_s;
+ return;
+ }
+
+ target->close(errorString, runBeforeUnload && *runBeforeUnload);
+}
+
void InspectorTargetAgent::sendMessageFromTargetToFrontend(const String& targetId, const String& message)
{
ASSERT_WITH_MESSAGE(m_targets.get(targetId), "Sending a message from an untracked target to the frontend.");
@@ -115,8 +137,10 @@ static Ref<Protocol::Target::TargetInfo> buildTargetInfoObject(const InspectorTa
.setTargetId(target.identifier())
.setType(targetTypeToProtocolType(target.type()))
.release();
- if (target.isProvisional())
+ if (target.isProvisional()) {
result->setIsProvisional(true);
+ result->setOldTargetId(target.oldTargetID());
+ }
if (target.isPaused())
result->setIsPaused(true);
return result;
@@ -144,7 +168,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 +193,18 @@ void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID,
m_frontendDispatcher->didCommitProvisionalTarget(oldTargetID, committedTargetID);
}
+void InspectorTargetAgent::ensureConnected(const String& targetID)
+{
+ if (!m_isConnected)
+ return;
+
+ auto* target = m_targets.get(targetID);
+ if (!target)
+ return;
+
+ target->connect(connectionType());
+}
+
FrontendChannel::ConnectionType InspectorTargetAgent::connectionType() const
{
return m_router.hasLocalFrontend() ? Inspector::FrontendChannel::ConnectionType::Local : Inspector::FrontendChannel::ConnectionType::Remote;
diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h
index 1eb7abb2fa21d7a8ec0833160f53e5c523ec4317..7709bcc2ec69aab0589ca1b954db1fb241bb583b 100644
--- 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;
void sendMessageToTarget(ErrorString&, const String& targetId, const String& message) final;
+ void activate(ErrorString&, const String& targetId) override;
+ void close(ErrorString&, const String& targetId, const bool* runBeforeUnload) override;
// Target lifecycle.
void targetCreated(InspectorTarget&);
void targetDestroyed(InspectorTarget&);
+ void targetCrashed(InspectorTarget&);
void didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID);
+ void ensureConnected(const String& targetID);
// Target messages.
void sendMessageFromTargetToFrontend(const String& targetId, const String& message);
+ bool isConnected() { return m_isConnected; }
+
private:
// FrontendChannel
FrontendChannel::ConnectionType connectionType() const;
diff --git a/Source/JavaScriptCore/inspector/protocol/Browser.json b/Source/JavaScriptCore/inspector/protocol/Browser.json
new file mode 100644
index 0000000000000000000000000000000000000000..0f9b1c8950b8f5631ddfd8180a851d1ecea4c475
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Browser.json
@@ -0,0 +1,210 @@
+{
+ "domain": "Browser",
+ "availability": ["web"],
+ "types": [
+ {
+ "id": "ContextID",
+ "type": "string",
+ "description": "Id of Browser context."
+ },
+ {
+ "id": "PageProxyID",
+ "type": "string",
+ "description": "Id of WebPageProxy."
+ },
+ {
+ "id": "PageProxyInfo",
+ "type": "object",
+ "description": "Tab info object",
+ "properties": [
+ { "name": "pageProxyId", "$ref": "PageProxyID" },
+ { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." },
+ { "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",
+ "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": "grantPermissions",
+ "parameters": [
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." },
+ { "name": "origin", "type": "string" },
+ { "name": "permissions", "type": "array", "items": { "type": "string" } }
+ ],
+ "description": "Overrides the permissions."
+ },
+ {
+ "name": "resetPermissions",
+ "parameters": [
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
+ ],
+ "description": "Clears permission overrides."
+ },
+ {
+ "name": "setLanguages",
+ "description": "Allows to set locale language for context.",
+ "parameters": [
+ { "name": "languages", "type": "array", "items": { "type": "string" } },
+ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "pageProxyCreated",
+ "parameters": [
+ { "name": "pageProxyInfo", "$ref": "PageProxyInfo" }
+ ]
+ },
+ {
+ "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." }
+ ]
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/DOM.json b/Source/JavaScriptCore/inspector/protocol/DOM.json
index 38cb48bedf2b168149ff79423b7fafc1e63ce8b3..e3d044934f5a0dc2331534439daa53116019548f 100644
--- a/Source/JavaScriptCore/inspector/protocol/DOM.json
+++ b/Source/JavaScriptCore/inspector/protocol/DOM.json
@@ -79,6 +79,16 @@
{ "name": "value", "type": "string", "description": "The value that is resolved to with this data binding relationship." }
]
},
+ {
+ "id": "Rect",
+ "type": "object",
+ "properties": [
+ { "name": "x", "type": "integer", "description": "X coordinate" },
+ { "name": "y", "type": "integer", "description": "Y coordinate" },
+ { "name": "width", "type": "integer", "description": "Rectangle width" },
+ { "name": "height", "type": "integer", "description": "Rectangle height" }
+ ]
+ },
{
"id": "EventListener",
"type": "object",
@@ -167,6 +177,16 @@
{ "name": "borderColor", "$ref": "RGBAColor", "optional": true, "description": "The border highlight fill color (default: transparent)." },
{ "name": "marginColor", "$ref": "RGBAColor", "optional": true, "description": "The margin highlight fill color (default: transparent)." }
]
+ },
+ {
+ "id": "FilePayload",
+ "type": "object",
+ "description": "Data to construct File object.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "File name." },
+ { "name": "type", "type": "string", "description": "File type." },
+ { "name": "data", "type": "string", "description": "Base64-encoded file data." }
+ ]
}
],
"commands": [
@@ -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 @@
"parameters": [
{ "name": "allow", "type": "boolean" }
]
+ },
+ {
+ "name": "describeNode",
+ "description": "Returns node description.",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." }
+ ],
+ "returns": [
+ { "name": "contentFrameId", "$ref": "Network.FrameId", "optional": true, "description": "Frame ID for frame owner elements." },
+ { "name": "ownerFrameId", "$ref": "Network.FrameId", "optional": true, "description": "ID of the owning frame element." }
+ ]
+ },
+ {
+ "name": "scrollIntoViewIfNeeded",
+ "description": "Scrolls the given rect into view if not already in the viewport.",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." },
+ { "name": "rect", "$ref": "Rect", "optional": true, "description": "Rect relative to the node's border box, in CSS pixels." }
+ ]
+ },
+ {
+ "name": "getContentQuads",
+ "description": "Returns quads that describe node position on the page. This method\nmight return multiple quads for inline nodes.",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." }
+ ],
+ "returns": [
+ {
+ "name": "quads", "type": "array", "items": { "$ref": "Quad" }, "description": "Quads that describe node layout relative to viewport."
+ }
+ ]
+ },
+ {
+ "name": "setInputFiles",
+ "description": "Sets input files for given <input type=file>",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Input element handle." },
+ { "name": "files", "type": "array", "items": { "$ref": "FilePayload" }, "description": "Files to set" }
+ ]
}
],
"events": [
diff --git a/Source/JavaScriptCore/inspector/protocol/Dialog.json b/Source/JavaScriptCore/inspector/protocol/Dialog.json
new file mode 100644
index 0000000000000000000000000000000000000000..79edea03fed4e9be5da96e1275e182a479cb7a0a
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Dialog.json
@@ -0,0 +1,36 @@
+{
+ "domain": "Dialog",
+ "description": "Actions and events related to alert boxes.",
+ "availability": ["web"],
+ "types": [
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables dialog domain notifications."
+ },
+ {
+ "name": "disable",
+ "description": "Disables dialog domain notifications."
+ },
+ {
+ "name": "handleJavaScriptDialog",
+ "description": "Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).",
+ "parameters": [
+ { "name": "accept", "type": "boolean", "description": "Whether to accept or dismiss the dialog."},
+ { "name": "promptText", "optional": true, "type": "string", "description": "The text to enter into the dialog prompt before accepting. Used only if this is a prompt dialog."}
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "javascriptDialogOpening",
+ "description": "Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) is about to open.",
+ "parameters": [
+ { "name": "type", "type": "string", "description": "Dialog type."},
+ { "name": "message", "type": "string", "description": "Message that will be displayed by the dialog."},
+ { "name": "defaultPrompt", "optional": true, "type": "string", "description": "Default dialog prompt."}
+ ]
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/Emulation.json b/Source/JavaScriptCore/inspector/protocol/Emulation.json
new file mode 100644
index 0000000000000000000000000000000000000000..552e5dd60fa53fada79f8d6e333f52bc10a2bead
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Emulation.json
@@ -0,0 +1,39 @@
+{
+ "domain": "Emulation",
+ "availability": ["web"],
+ "commands": [
+ {
+ "name": "setDeviceMetricsOverride",
+ "description": "Overrides device metrics with provided values.",
+ "async": true,
+ "parameters": [
+ { "name": "width", "type": "integer" },
+ { "name": "height", "type": "integer" },
+ { "name": "deviceScaleFactor", "type": "number" },
+ { "name": "fixedLayout", "type": "boolean" }
+ ]
+ },
+ {
+ "name": "setJavaScriptEnabled",
+ "description": "Allows to disable script execution for the page.",
+ "parameters": [
+ { "name": "enabled", "type": "boolean" }
+ ]
+ },
+ {
+ "name": "setAuthCredentials",
+ "description": "Credentials to use during HTTP authentication.",
+ "parameters": [
+ { "name": "username", "type": "string", "optional": true },
+ { "name": "password", "type": "string", "optional": true }
+ ]
+ },
+ {
+ "name": "setActiveAndFocused",
+ "description": "Makes page focused for test.",
+ "parameters": [
+ { "name": "active", "type": "boolean", "optional": true }
+ ]
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/Input.json b/Source/JavaScriptCore/inspector/protocol/Input.json
new file mode 100644
index 0000000000000000000000000000000000000000..34909cce9f6d8d7c74be4c96e40f80cadb2f931d
--- /dev/null
+++ b/Source/JavaScriptCore/inspector/protocol/Input.json
@@ -0,0 +1,165 @@
+{
+ "domain": "Input",
+ "availability": ["web"],
+ "types": [
+ {
+ "id": "TimeSinceEpoch",
+ "description": "UTC time in seconds, counted from January 1, 1970.",
+ "type": "number"
+ }
+ ],
+ "commands": [
+ {
+ "name": "dispatchKeyEvent",
+ "description": "Dispatches a key event to the page.",
+ "async": true,
+ "parameters": [
+ {
+ "name": "type",
+ "description": "Type of the key event.",
+ "type": "string",
+ "enum": [
+ "keyDown",
+ "keyUp"
+ ]
+ },
+ {
+ "name": "modifiers",
+ "description": "Bit field representing pressed modifier keys. (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "text",
+ "description": "Text as generated by processing a virtual key code with a keyboard layout. Not needed for\nfor `keyUp` and `rawKeyDown` events (default: \"\")",
+ "optional": true,
+ "type": "string"
+ },
+ {
+ "name": "unmodifiedText",
+ "description": "Text that would have been generated by the keyboard if no modifiers were pressed (except for\nshift). Useful for shortcut (accelerator) key handling (default: \"\").",
+ "optional": true,
+ "type": "string"
+ },
+ {
+ "name": "code",
+ "description": "Unique DOM defined string value for each physical key (e.g., 'KeyA') (default: \"\").",
+ "optional": true,
+ "type": "string"
+ },
+ {
+ "name": "key",
+ "description": "Unique DOM defined string value describing the meaning of the key in the context of active\nmodifiers, keyboard layout, etc (e.g., 'AltGr') (default: \"\").",
+ "optional": true,
+ "type": "string"
+ },
+ {
+ "name": "windowsVirtualKeyCode",
+ "description": "Windows virtual key code (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "nativeVirtualKeyCode",
+ "description": "Native virtual key code (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "autoRepeat",
+ "description": "Whether the event was generated from auto repeat (default: false).",
+ "optional": true,
+ "type": "boolean"
+ },
+ {
+ "name": "isKeypad",
+ "description": "Whether the event was generated from the keypad (default: false).",
+ "optional": true,
+ "type": "boolean"
+ },
+ {
+ "name": "isSystemKey",
+ "description": "Whether the event was a system key event (default: false).",
+ "optional": true,
+ "type": "boolean"
+ },
+ {
+ "name": "macCommands",
+ "description": "Mac editing commands associated with this key",
+ "type": "array",
+ "optional": true,
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ {
+ "name": "dispatchMouseEvent",
+ "description": "Dispatches a mouse event to the page.",
+ "async": true,
+ "parameters": [
+ {
+ "name": "type",
+ "description": "Type of the mouse event.",
+ "type": "string",
+ "enum": [ "move", "down", "up", "wheel"]
+ },
+ {
+ "name": "x",
+ "description": "X coordinate of the event relative to the main frame's viewport in CSS pixels.",
+ "type": "integer"
+ },
+ {
+ "name": "y",
+ "description": "Y coordinate of the event relative to the main frame's viewport in CSS pixels. 0 refers to\nthe top of the viewport and Y increases as it proceeds towards the bottom of the viewport.",
+ "type": "integer"
+ },
+ {
+ "name": "modifiers",
+ "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8\n(default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "button",
+ "description": "Mouse button (default: \"none\").",
+ "optional": true,
+ "type": "string",
+ "enum": [
+ "none",
+ "left",
+ "middle",
+ "right",
+ "back",
+ "forward"
+ ]
+ },
+ {
+ "name": "buttons",
+ "description": "A number indicating which buttons are pressed on the mouse when a mouse event is triggered.\nLeft=1, Right=2, Middle=4, Back=8, Forward=16, None=0.",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "clickCount",
+ "description": "Number of times the mouse button was clicked (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "deltaX",
+ "description": "X delta in CSS pixels for mouse wheel event (default: 0).",
+ "optional": true,
+ "type": "integer"
+ },
+ {
+ "name": "deltaY",
+ "description": "Y delta in CSS pixels for mouse wheel event (default: 0).",
+ "optional": true,
+ "type": "integer"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Source/JavaScriptCore/inspector/protocol/Network.json b/Source/JavaScriptCore/inspector/protocol/Network.json
index 658f14f8af68073b99a01dd7332628223b67fcd7..cd28887b9a01826c2d374bdada487c81467fdade 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.",
diff --git a/Source/JavaScriptCore/inspector/protocol/Page.json b/Source/JavaScriptCore/inspector/protocol/Page.json
index a8fc5332ac92424b00a3dec62152fd3c5f28544e..2fba82d5f991bcfc1315628728771ff167154b7c 100644
--- a/Source/JavaScriptCore/inspector/protocol/Page.json
+++ b/Source/JavaScriptCore/inspector/protocol/Page.json
@@ -110,6 +110,41 @@
{ "name": "session", "type": "boolean", "description": "True in case of session cookie." },
{ "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." }
]
+ },
+ {
+ "id": "AXNode",
+ "type": "object",
+ "description": "Accessibility Node",
+ "properties": [
+ { "name": "role", "type": "string", "description": "The role."},
+ { "name": "name", "type": "string","optional": true, "description": "A human readable name for the node."},
+ { "name": "value", "type": "any", "optional": true, "description": "The current value of the node."},
+ { "name": "description", "type": "string", "optional": true, "description": "An additional human readable description of the node."},
+ { "name": "keyshortcuts", "type": "string", "optional": true, "description": "Keyboard shortcuts associated with this node."},
+ { "name": "roledescription", "type": "string", "optional": true, "description": "A human readable alternative to the role."},
+ { "name": "valuetext", "type": "string", "optional": true, "description": "A description of the current value."},
+ { "name": "disabled", "type": "boolean", "optional": true, "description": "Whether the node is disabled."},
+ { "name": "expanded", "type": "boolean", "optional": true, "description": "Whether the node is expanded or collapsed."},
+ { "name": "focused", "type": "boolean", "optional": true, "description": "Whether the node is focused."},
+ { "name": "modal", "type": "boolean", "optional": true, "description": "Whether the node is modal."},
+ { "name": "multiline", "type": "boolean", "optional": true, "description": "Whether the node text input supports multiline."},
+ { "name": "multiselectable", "type": "boolean", "optional": true, "description": "Whether more than one child can be selected."},
+ { "name": "readonly", "type": "boolean", "optional": true, "description": "Whether the node is read only."},
+ { "name": "required", "type": "boolean", "optional": true, "description": "Whether the node is required."},
+ { "name": "selected", "type": "boolean", "optional": true, "description": "Whether the node is selected in its parent node."},
+ { "name": "checked", "type": "string", "optional": true, "enum": ["true", "false", "mixed"], "description": "Whether the checkbox is checked, or \"mixed\"."},
+ { "name": "pressed", "type": "string", "optional": true, "enum": ["true", "false", "mixed"], "description": "Whether the toggle button is checked, or \"mixed\"."},
+ { "name": "level", "type": "integer", "optional": true, "description": "The level of a heading."},
+ { "name": "valuemin", "type": "number", "optional": true, "description": "The minimum value in a node."},
+ { "name": "valuemax", "type": "number", "optional": true, "description": "The maximum value in a node."},
+ { "name": "autocomplete", "type": "string", "optional": true, "description": "What kind of autocomplete is supported by a control."},
+ { "name": "haspopup", "type": "string", "optional": true, "description": "What kind of popup is currently being shown for a node."},
+ { "name": "invalid", "type": "string", "optional": true, "enum": ["true", "false", "grammar", "spelling"], "description": "Whether and in what way this node's value is invalid."},
+ { "name": "orientation", "type": "string", "optional": true, "description": "Whether the node is oriented horizontally or vertically."},
+ { "name": "focusable", "type": "boolean", "optional": true, "description": "Whether the node is focusable."},
+ { "name": "children", "type": "array", "optional": true, "items": { "$ref": "AXNode"}, "description": "Child AXNodes of this node, if any."},
+ { "name": "found", "type": "boolean", "optional": true, "description": "True if this AXNode corresponds with the ObjectId passed into acessibilitySnapshot."}
+ ]
}
],
"commands": [
@@ -129,11 +164,21 @@
{ "name": "revalidateAllResources", "type": "boolean", "optional": true, "description": "If true, all cached subresources will be revalidated when the main resource loads. Otherwise, only expired cached subresources will be revalidated (the default behavior for most WebKit clients)." }
]
},
+ {
+ "name": "goBack",
+ "description": "Goes back in the history."
+ },
+ {
+ "name": "goForward",
+ "description": "Goes forward in the history."
+ },
{
"name": "navigate",
"description": "Navigates current page to the given URL.",
"parameters": [
- { "name": "url", "type": "string", "description": "URL to navigate the page to." }
+ { "name": "url", "type": "string", "description": "URL to navigate the page to." },
+ { "name": "frameId", "$ref": "Network.FrameId", "optional": true, "description": "Id of the frame to navigate."},
+ { "name": "referrer", "type": "string", "optional": true, "description": "Referrer URL." }
]
},
{
@@ -246,6 +291,20 @@
{ "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 }
+ ]
+ },
+ {
+ "name": "setTouchEmulationEnabled",
+ "description": "Enables touch events on platforms that lack them.",
+ "parameters": [
+ {"name": "enabled", "type": "boolean", "description": "Whether touch should be enabled."}
+ ]
+ },
{
"name": "snapshotNode",
"description": "Capture a snapshot of the specified node that does not include unrelated layers.",
@@ -276,19 +335,70 @@
"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"
}
],
"events": [
{
"name": "domContentEventFired",
"parameters": [
- { "name": "timestamp", "type": "number" }
+ { "name": "timestamp", "type": "number" },
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired DOMContentLoaded event." }
]
},
{
"name": "loadEventFired",
"parameters": [
- { "name": "timestamp", "type": "number" }
+ { "name": "timestamp", "type": "number" },
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired load event." }
]
},
{
@@ -298,6 +408,14 @@
{ "name": "frame", "$ref": "Frame", "description": "Frame object." }
]
},
+ {
+ "name": "frameAttached",
+ "description": "Fired when frame has been attached to its parent.",
+ "parameters": [
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has been detached." },
+ { "name": "parentFrameId", "$ref": "Network.FrameId", "optional": true, "description": "Parent frame id if non-root." }
+ ]
+ },
{
"name": "frameDetached",
"description": "Fired when frame has been detached from its parent.",
@@ -334,12 +452,36 @@
{ "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has cleared its scheduled navigation." }
]
},
+ {
+ "name": "navigatedWithinDocument",
+ "description": "Fired when same-document navigation happens, e.g. due to history API usage or anchor navigation.",
+ "parameters": [
+ {
+ "name": "frameId",
+ "description": "Id of the frame.",
+ "$ref": "Network.FrameId"
+ },
+ {
+ "name": "url",
+ "description": "Frame's new url.",
+ "type": "string"
+ }
+ ]
+ },
{
"name": "defaultAppearanceDidChange",
"description": "Fired when page's default appearance changes, even if there is a forced appearance.",
"parameters": [
{ "name": "appearance", "$ref": "Appearance", "description": "Name of the appearance that is active (not considering any forced appearance.)" }
]
+ },
+ {
+ "name": "fileChooserOpened",
+ "description": "Fired when the page shows file chooser for it's <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/Target.json b/Source/JavaScriptCore/inspector/protocol/Target.json
index 52920cded24a9c6b0ef6fb4e518664955db4f9fa..11d40820629d3104408e14a3f92d9f0265b78ce1 100644
--- a/Source/JavaScriptCore/inspector/protocol/Target.json
+++ b/Source/JavaScriptCore/inspector/protocol/Target.json
@@ -10,7 +10,8 @@
"properties": [
{ "name": "targetId", "type": "string", "description": "Unique identifier for the target." },
{ "name": "type", "type": "string", "enum": ["page", "service-worker", "worker"] },
- { "name": "isProvisional", "type": "boolean", "optional": true, "description": "Whether this is a provisional page target." },
+ { "name": "isProvisional", "type": "boolean", "optional": true, "description": "True value indicates that this is a provisional page target i.e. Such target may be created when current page starts cross-origin navigation. Eventually each provisional target is either committed and swaps with the current target or gets destroyed, e.g. in case of load request failure." },
+ { "name": "oldTargetId", "type": "string", "optional": true, "description": "Unique identifier of the target which is going to be replaced if this target is committed. Only set for provisional targets." },
{ "name": "isPaused", "type": "boolean", "optional": true, "description": "Whether the target is paused on start and has to be explicitely resumed by inspector." }
]
}
@@ -37,6 +38,21 @@
{ "name": "targetId", "type": "string" },
{ "name": "message", "type": "string", "description": "JSON Inspector Protocol message (command) to be dispatched on the backend." }
]
+ },
+ {
+ "name": "activate",
+ "description": "Reveals the target on screen.",
+ "parameters": [
+ { "name": "targetId", "type": "string" }
+ ]
+ },
+ {
+ "name": "close",
+ "description": "Closes the target.",
+ "parameters": [
+ { "name": "targetId", "type": "string" },
+ { "name": "runBeforeUnload", "type": "boolean", "optional": true }
+ ]
}
],
"events": [
@@ -49,7 +65,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 9817a45ea2f3a22844ed3e56816cff94eb051423..67f7459a556ed22740fbfcd2b1b7b530d34d5bb5 100644
--- a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
+++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
@@ -39,6 +39,7 @@
#include <unicode/ucal.h>
#include <unicode/udatpg.h>
#include <unicode/uenum.h>
+#include <wtf/DateMath.h>
#include <wtf/text/StringBuilder.h>
#if JSC_ICU_HAS_UFIELDPOSITER
@@ -113,6 +114,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 602f89a49d454cc5e5acd030024227d49d98c61f..41811e65bd0f15b443fb90d37ee4d0a21780a518 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/PlatformHave.h b/Source/WTF/wtf/PlatformHave.h
index d24b85e2da241346e00b7337a59683be61020c28..3998c2ebe7f860195da802777308dd385b2c9b02 100644
--- a/Source/WTF/wtf/PlatformHave.h
+++ b/Source/WTF/wtf/PlatformHave.h
@@ -379,7 +379,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;
}
diff --git a/Source/WebCore/PAL/pal/SessionID.cpp b/Source/WebCore/PAL/pal/SessionID.cpp
index 6b30b4a06bab48ca69e4955e52cb4162bb20780f..ea94293a0bb15b4dd1aa85706f97030f4fe50de1 100644
--- a/Source/WebCore/PAL/pal/SessionID.cpp
+++ b/Source/WebCore/PAL/pal/SessionID.cpp
@@ -27,11 +27,11 @@
#include "SessionID.h"
#include <wtf/MainThread.h>
+#include <wtf/CryptographicallyRandomNumber.h>
namespace PAL {
static uint64_t currentPersistentID = SessionID::DefaultSessionID;
-static uint64_t currentEphemeralID = SessionID::LegacyPrivateSessionID;
static bool generationProtectionEnabled;
SessionID SessionID::generatePersistentSessionID()
@@ -47,7 +47,10 @@ SessionID SessionID::generateEphemeralSessionID()
ASSERT(isMainThread());
RELEASE_ASSERT(!generationProtectionEnabled);
- return SessionID(++currentEphemeralID);
+ uint64_t sessionId;
+ cryptographicallyRandomValues(&sessionId, sizeof(sessionId));
+ sessionId = sessionId | SessionConstants::EphemeralSessionMask;
+ return SessionID(sessionId);
}
void SessionID::enableGenerationProtection()
diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt
index ab3a579490c93aa5230a64ce8b3896c9b910d285..ee82d8efe153a66bac4becf1885935236c1e124f 100644
--- a/Source/WebCore/SourcesCocoa.txt
+++ b/Source/WebCore/SourcesCocoa.txt
@@ -645,7 +645,7 @@ WHLSLStandardLibraryFunctionMap.cpp
#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
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index f24ca354d6c9744d918c65dfa1a7d46c2407bd20..76b32e382007813e63ee3f43058ee426c0ef01da 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -4933,6 +4933,14 @@
EDE3A5000C7A430600956A37 /* ColorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = EDE3A4FF0C7A430600956A37 /* ColorMac.h */; settings = {ATTRIBUTES = (Private, ); }; };
EDEC98030AED7E170059137F /* WebCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EDEC98020AED7E170059137F /* WebCorePrefix.h */; };
EFCC6C8F20FE914400A2321B /* CanvasActivityRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16923AD660C0011CE47 /* Touch.cpp */; };
+ F050E16D23AD66630011CE47 /* TouchList.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16B23AD66620011CE47 /* TouchList.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E16E23AD66630011CE47 /* TouchList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16C23AD66630011CE47 /* TouchList.cpp */; };
+ F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16F23AD669E0011CE47 /* TouchEvent.cpp */; };
+ F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17023AD669F0011CE47 /* TouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F050E17423AD6A800011CE47 /* DocumentTouch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E17323AD6A800011CE47 /* DocumentTouch.cpp */; };
+ F050E17823AD70C50011CE47 /* PlatformTouchPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
F12171F516A8CED2000053CA /* WebVTTElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F12171F316A8BC63000053CA /* WebVTTElement.cpp */; };
F12171F616A8CF0B000053CA /* WebVTTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = F12171F416A8BC63000053CA /* WebVTTElement.h */; };
F32BDCD92363AACA0073B6AE /* UserGestureEmulationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = F32BDCD72363AACA0073B6AE /* UserGestureEmulationScope.h */; };
@@ -15376,6 +15384,14 @@
EDEC98020AED7E170059137F /* WebCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCorePrefix.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
EFB7287B2124C73D005C2558 /* CanvasActivityRecord.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CanvasActivityRecord.cpp; sourceTree = "<group>"; };
EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanvasActivityRecord.h; sourceTree = "<group>"; };
+ F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchEvent.h; sourceTree = "<group>"; };
+ F050E16923AD660C0011CE47 /* Touch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Touch.cpp; path = dom/Touch.cpp; sourceTree = SOURCE_ROOT; };
+ F050E16B23AD66620011CE47 /* TouchList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TouchList.h; path = dom/TouchList.h; sourceTree = SOURCE_ROOT; };
+ F050E16C23AD66630011CE47 /* TouchList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TouchList.cpp; path = dom/TouchList.cpp; sourceTree = SOURCE_ROOT; };
+ F050E16F23AD669E0011CE47 /* TouchEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TouchEvent.cpp; path = dom/TouchEvent.cpp; sourceTree = SOURCE_ROOT; };
+ F050E17023AD669F0011CE47 /* TouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TouchEvent.h; path = dom/TouchEvent.h; sourceTree = SOURCE_ROOT; };
+ F050E17323AD6A800011CE47 /* DocumentTouch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentTouch.cpp; sourceTree = "<group>"; };
+ F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchPoint.h; sourceTree = "<group>"; };
F12171F316A8BC63000053CA /* WebVTTElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebVTTElement.cpp; sourceTree = "<group>"; };
F12171F416A8BC63000053CA /* WebVTTElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebVTTElement.h; sourceTree = "<group>"; };
F32BDCD52363AAC90073B6AE /* UserGestureEmulationScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserGestureEmulationScope.cpp; sourceTree = "<group>"; };
@@ -20608,7 +20624,12 @@
2D2E34A921A4E191004598B5 /* EditableImageReference.h */,
1AF326770D78B9440068F0C4 /* EditorClient.h */,
93C09A800B064F00005ABD4D /* EventHandler.cpp */,
+ F050E16F23AD669E0011CE47 /* TouchEvent.cpp */,
+ F050E17023AD669F0011CE47 /* TouchEvent.h */,
93C09A520B064DB3005ABD4D /* EventHandler.h */,
+ F050E16923AD660C0011CE47 /* Touch.cpp */,
+ F050E16C23AD66630011CE47 /* TouchList.cpp */,
+ F050E16B23AD66620011CE47 /* TouchList.h */,
E0FEF371B27C53EAC1C1FBEE /* EventSource.cpp */,
E0FEF371B17C53EAC1C1FBEE /* EventSource.h */,
E0FEF371B07C53EAC1C1FBEE /* EventSource.idl */,
@@ -25825,7 +25846,9 @@
1A2E6E560CC551E0004A2062 /* sql */,
B2C3D9EC0D006C1D00EF6F26 /* text */,
DFDB912CF8E88A6DA1AD264F /* AbortableTaskQueue.h */,
+ F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */,
49AE2D94134EE5F90072920A /* CalculationValue.cpp */,
+ F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */,
49AE2D95134EE5F90072920A /* CalculationValue.h */,
C330A22113EC196B0000B45B /* ColorChooser.h */,
C37CDEBC149EF2030042090D /* ColorChooserClient.h */,
@@ -28043,6 +28066,7 @@
BCCFBAE70B5152ED0001F1D7 /* DocumentParser.h */,
AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */,
AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */,
+ F050E17323AD6A800011CE47 /* DocumentTouch.cpp */,
6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */,
6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */,
6BDB5DC5227CA0EB00919770 /* DocumentStorageAccess.idl */,
@@ -28923,6 +28947,7 @@
93C4F6EB1108F9A50099D0DB /* AccessibilityScrollbar.h in Headers */,
29489FC712C00F0300D83F0F /* AccessibilityScrollView.h in Headers */,
0709FC4E1025DEE30059CDBA /* AccessibilitySlider.h in Headers */,
+ F050E16D23AD66630011CE47 /* TouchList.h in Headers */,
29D7BCFA1444AF7D0070619C /* AccessibilitySpinButton.h in Headers */,
69A6CBAD1C6BE42C00B836E9 /* AccessibilitySVGElement.h in Headers */,
AAC08CF315F941FD00F1E188 /* AccessibilitySVGRoot.h in Headers */,
@@ -30761,6 +30786,7 @@
6E4ABCD5138EA0B70071D291 /* JSHTMLUnknownElement.h in Headers */,
E44614170CD6826900FADA75 /* JSHTMLVideoElement.h in Headers */,
81BE20D311F4BC3200915DFA /* JSIDBCursor.h in Headers */,
+ F050E17823AD70C50011CE47 /* PlatformTouchPoint.h in Headers */,
7C3D8EF01E0B21430023B084 /* JSIDBCursorDirection.h in Headers */,
C585A68311D4FB08004C3E4B /* JSIDBDatabase.h in Headers */,
C585A69711D4FB13004C3E4B /* JSIDBFactory.h in Headers */,
@@ -32664,9 +32690,11 @@
A7DBF8DE1276919C006B6008 /* TextCheckingHelper.h in Headers */,
B2C3DA3A0D006C1D00EF6F26 /* TextCodec.h in Headers */,
26E98A10130A9FCA008EB7B2 /* TextCodecASCIIFastPath.h in Headers */,
+ F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */,
B2C3DA3C0D006C1D00EF6F26 /* TextCodecICU.h in Headers */,
B2C3DA3E0D006C1D00EF6F26 /* TextCodecLatin1.h in Headers */,
57EF5E601D20C83900171E60 /* TextCodecReplacement.h in Headers */,
+ F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */,
B2C3DA400D006C1D00EF6F26 /* TextCodecUserDefined.h in Headers */,
B2C3DA420D006C1D00EF6F26 /* TextCodecUTF16.h in Headers */,
9343CB8212F25E510033C5EE /* TextCodecUTF8.h in Headers */,
@@ -33547,6 +33575,7 @@
CDDE02ED18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm in Sources */,
CDDE02F018B5651300CF7FF1 /* CDMSessionAVStreamSession.mm in Sources */,
CDE5959D1BF2757100A1CBE8 /* CDMSessionMediaSourceAVFObjC.mm in Sources */,
+ F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */,
A14090FB1AA51E1D0091191A /* ContentFilterUnblockHandlerCocoa.mm in Sources */,
07AFF4231EFB144900B545B3 /* CoreAudioCaptureSourceIOS.mm in Sources */,
46C696CC1E7205FC00597937 /* CPUMonitor.cpp in Sources */,
@@ -33620,6 +33649,7 @@
51058ADF1D67C229009A538C /* MockGamepad.cpp in Sources */,
51058AE11D67C229009A538C /* MockGamepadProvider.cpp in Sources */,
CDF2B0121820540600F2B424 /* MockMediaPlayerMediaSource.cpp in Sources */,
+ F050E17423AD6A800011CE47 /* DocumentTouch.cpp in Sources */,
CDF2B0141820540600F2B424 /* MockMediaSourcePrivate.cpp in Sources */,
CDF2B0161820540700F2B424 /* MockSourceBufferPrivate.cpp in Sources */,
2D9BF7421DBFDC27007A7D99 /* NavigatorEME.cpp in Sources */,
@@ -33705,6 +33735,7 @@
538EC8881F993F9C004D22A8 /* UnifiedSource23.cpp in Sources */,
DE5F85801FA1ABF4006DB63A /* UnifiedSource24-mm.mm in Sources */,
538EC8891F993F9D004D22A8 /* UnifiedSource24.cpp in Sources */,
+ F050E16E23AD66630011CE47 /* TouchList.cpp in Sources */,
DE5F85811FA1ABF4006DB63A /* UnifiedSource25-mm.mm in Sources */,
538EC88A1F993F9D004D22A8 /* UnifiedSource25.cpp in Sources */,
DE5F85821FA1ABF4006DB63A /* UnifiedSource26-mm.mm in Sources */,
@@ -34237,6 +34268,7 @@
2D8B92F1203D13E1009C868F /* UnifiedSource516.cpp in Sources */,
2D8B92F2203D13E1009C868F /* UnifiedSource517.cpp in Sources */,
2D8B92F3203D13E1009C868F /* UnifiedSource518.cpp in Sources */,
+ F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */,
2D8B92F4203D13E1009C868F /* UnifiedSource519.cpp in Sources */,
2D8B92F5203D13E1009C868F /* UnifiedSource520.cpp in Sources */,
2D8B92F6203D13E1009C868F /* UnifiedSource521.cpp in Sources */,
diff --git a/Source/WebCore/html/FileInputType.cpp b/Source/WebCore/html/FileInputType.cpp
index 4e41fd3f807e8f34bfef3f63f0ba6119a619821e..1f7be602cb2134f8867bf95afe0c9337bce57055 100644
--- a/Source/WebCore/html/FileInputType.cpp
+++ b/Source/WebCore/html/FileInputType.cpp
@@ -36,6 +36,7 @@
#include "HTMLNames.h"
#include "Icon.h"
#include "InputTypeNames.h"
+#include "InspectorInstrumentation.h"
#include "LocalizedStrings.h"
#include "RenderFileUploadControl.h"
#include "RuntimeEnabledFeatures.h"
@@ -205,6 +206,11 @@ void FileInputType::handleDOMActivateEvent(Event& event)
if (input.isDisabledFormControl())
return;
+ bool intercept = false;
+ InspectorInstrumentation::runOpenPanel(input.document().frame(), element(), &intercept);
+ if (intercept)
+ return;
+
if (!UserGestureIndicator::processingUserGesture())
return;
diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp
index 3dc7b494d6656a91c7dd9c68e1c9eaf789666d01..54ff59eaec197fdd12248cd4542b91db2b5bb83a 100644
--- a/Source/WebCore/inspector/InspectorInstrumentation.cpp
+++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp
@@ -621,6 +621,12 @@ void InspectorInstrumentation::didFailLoadingImpl(InstrumentingAgents& instrumen
consoleAgent->didFailLoading(identifier, error); // This should come AFTER resource notification, front-end relies on this.
}
+void InspectorInstrumentation::didReceiveMainResourceErrorImpl(InstrumentingAgents& instrumentingAgents, Frame& frame, const ResourceError&)
+{
+ if (auto* pageRuntimeAgent = instrumentingAgents.pageRuntimeAgent())
+ pageRuntimeAgent->didReceiveMainResourceError(frame);
+}
+
void InspectorInstrumentation::willLoadXHRSynchronouslyImpl(InstrumentingAgents& instrumentingAgents)
{
if (InspectorNetworkAgent* networkAgent = instrumentingAgents.inspectorNetworkAgent())
@@ -653,20 +659,17 @@ void InspectorInstrumentation::didReceiveScriptResponseImpl(InstrumentingAgents&
void InspectorInstrumentation::domContentLoadedEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
{
- if (!frame.isMainFrame())
- return;
-
if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
- pageAgent->domContentEventFired();
+ pageAgent->domContentEventFired(frame);
}
void InspectorInstrumentation::loadEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame* frame)
{
- if (!frame || !frame->isMainFrame())
+ if (!frame)
return;
if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
- pageAgent->loadEventFired();
+ pageAgent->loadEventFired(*frame);
}
void InspectorInstrumentation::frameDetachedFromParentImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
@@ -744,12 +747,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()) {
@@ -786,6 +783,12 @@ void InspectorInstrumentation::frameClearedScheduledNavigationImpl(Instrumenting
inspectorPageAgent->frameClearedScheduledNavigation(frame);
}
+void InspectorInstrumentation::didNavigateWithinPageImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
+{
+ if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.inspectorPageAgent())
+ inspectorPageAgent->didNavigateWithinPage(frame);
+}
+
void InspectorInstrumentation::defaultAppearanceDidChangeImpl(InstrumentingAgents& instrumentingAgents, bool useDarkAppearance)
{
if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.inspectorPageAgent())
@@ -1288,6 +1291,31 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents& ins
layerTreeAgent->renderLayerDestroyed(renderLayer);
}
+void InspectorInstrumentation::runOpenPanelImpl(InstrumentingAgents& instrumentingAgents, HTMLInputElement* element, bool* intercept)
+{
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
+ pageAgent->runOpenPanel(element, intercept);
+}
+
+void InspectorInstrumentation::frameAttachedImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) {
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
+ pageAgent->frameAttached(frame);
+}
+
+bool InspectorInstrumentation::shouldBypassCSPImpl(InstrumentingAgents& instrumentingAgents)
+{
+ if (InspectorPageAgent* pageAgent = instrumentingAgents.inspectorPageAgent())
+ return pageAgent->shouldBypassCSP();
+ return false;
+}
+
+bool InspectorInstrumentation::interceptRequestImpl(InstrumentingAgents& instrumentingAgents, ResourceLoader& loader, 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;
diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h
index b246eaa559a75265c890dfa47d01d311c186a403..57460008e1925fe15ea37d1eee194836afed8370 100644
--- a/Source/WebCore/inspector/InspectorInstrumentation.h
+++ b/Source/WebCore/inspector/InspectorInstrumentation.h
@@ -45,11 +45,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 +79,7 @@ class DOMWrapperWorld;
class Document;
class DocumentLoader;
class EventListener;
+class HTMLInputElement;
class HTTPHeaderMap;
class InspectorTimelineAgent;
class InstrumentingAgents;
@@ -197,6 +200,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&);
@@ -223,11 +227,11 @@ public:
static void frameDetachedFromParent(Frame&);
static void didCommitLoad(Frame&, DocumentLoader*);
static void frameDocumentUpdated(Frame&);
- static void loaderDetachedFromFrame(Frame&, DocumentLoader&);
static void frameStartedLoading(Frame&);
static void frameStoppedLoading(Frame&);
static void frameScheduledNavigation(Frame&, Seconds delay);
static void frameClearedScheduledNavigation(Frame&);
+ static void didNavigateWithinPage(Frame&);
static void defaultAppearanceDidChange(Page&, bool useDarkAppearance);
static void willDestroyCachedResource(CachedResource&);
@@ -317,6 +321,11 @@ public:
static void layerTreeDidChange(Page*);
static void renderLayerDestroyed(Page*, const RenderLayer&);
+ static void runOpenPanel(Frame*, HTMLInputElement*, bool*);
+ static void frameAttached(Frame*);
+ static bool shouldBypassCSP(ScriptExecutionContext*);
+ static bool interceptRequest(ResourceLoader&, Function<void(bool handled)>&&);
+
static void frontendCreated();
static void frontendDeleted();
static bool hasFrontends() { return InspectorInstrumentationPublic::hasFrontends(); }
@@ -417,6 +426,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);
@@ -427,11 +437,11 @@ private:
static void frameDetachedFromParentImpl(InstrumentingAgents&, Frame&);
static void didCommitLoadImpl(InstrumentingAgents&, Frame&, DocumentLoader*);
static void frameDocumentUpdatedImpl(InstrumentingAgents&, Frame&);
- static void loaderDetachedFromFrameImpl(InstrumentingAgents&, DocumentLoader&);
static void frameStartedLoadingImpl(InstrumentingAgents&, Frame&);
static void frameStoppedLoadingImpl(InstrumentingAgents&, Frame&);
static void frameScheduledNavigationImpl(InstrumentingAgents&, Frame&, Seconds delay);
static void frameClearedScheduledNavigationImpl(InstrumentingAgents&, Frame&);
+ static void didNavigateWithinPageImpl(InstrumentingAgents&, Frame&);
static void defaultAppearanceDidChangeImpl(InstrumentingAgents&, bool useDarkAppearance);
static void willDestroyCachedResourceImpl(CachedResource&);
@@ -517,6 +527,11 @@ private:
static void layerTreeDidChangeImpl(InstrumentingAgents&);
static void renderLayerDestroyedImpl(InstrumentingAgents&, const RenderLayer&);
+ static void runOpenPanelImpl(InstrumentingAgents&, HTMLInputElement*, bool*);
+ static void frameAttachedImpl(InstrumentingAgents&, Frame&);
+ static bool shouldBypassCSPImpl(InstrumentingAgents&);
+ static bool interceptRequestImpl(InstrumentingAgents&, ResourceLoader&, Function<void(bool handled)>&&);
+
static InstrumentingAgents& instrumentingAgentsForPage(Page&);
static InstrumentingAgents& instrumentingAgentsForWorkerGlobalScope(WorkerGlobalScope&);
@@ -1097,6 +1112,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);
@@ -1192,13 +1214,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());
@@ -1227,6 +1242,13 @@ inline void InspectorInstrumentation::frameClearedScheduledNavigation(Frame& fra
frameClearedScheduledNavigationImpl(*instrumentingAgents, frame);
}
+inline void InspectorInstrumentation::didNavigateWithinPage(Frame& frame)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+ didNavigateWithinPageImpl(*instrumentingAgents, frame);
+}
+
inline void InspectorInstrumentation::defaultAppearanceDidChange(Page& page, bool useDarkAppearance)
{
FAST_RETURN_IF_NO_FRONTENDS(void());
@@ -1677,6 +1699,36 @@ inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const Ren
renderLayerDestroyedImpl(*instrumentingAgents, renderLayer);
}
+inline void InspectorInstrumentation::runOpenPanel(Frame* frame, HTMLInputElement* element, bool* intercept)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(*frame))
+ runOpenPanelImpl(*instrumentingAgents, element, intercept);
+}
+
+inline void InspectorInstrumentation::frameAttached(Frame* frame)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+ frameAttachedImpl(*instrumentingAgents, *frame);
+}
+
+inline bool InspectorInstrumentation::shouldBypassCSP(ScriptExecutionContext* context)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(false);
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+ return shouldBypassCSPImpl(*instrumentingAgents);
+ return false;
+}
+
+inline bool InspectorInstrumentation::interceptRequest(ResourceLoader& loader, 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);
diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp
index 0f46a3033aef4007f6eb837a6105f05a0c59067f..38140e53555b86af72b3c9707d4c6bd48350a1e7 100644
--- a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp
@@ -61,12 +61,16 @@
#include "Event.h"
#include "EventListener.h"
#include "EventNames.h"
+#include "File.h"
+#include "FileList.h"
#include "Frame.h"
#include "FrameTree.h"
#include "FrameView.h"
#include "FullscreenManager.h"
+#include "FloatQuad.h"
#include "HTMLElement.h"
#include "HTMLFrameOwnerElement.h"
+#include "HTMLInputElement.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
@@ -93,11 +97,14 @@
#include "Page.h"
#include "Pasteboard.h"
#include "PseudoElement.h"
+#include "RenderLayer.h"
+#include "RenderObject.h"
#include "RenderStyle.h"
#include "RenderStyleConstants.h"
#include "ScriptState.h"
#include "SelectorChecker.h"
#include "ShadowRoot.h"
+#include "SharedBuffer.h"
#include "StaticNodeList.h"
#include "StyleProperties.h"
#include "StyleResolver.h"
@@ -128,7 +135,8 @@ using namespace HTMLNames;
static const size_t maxTextSize = 10000;
static const UChar ellipsisUChar[] = { 0x2026, 0 };
-static Color parseColor(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)
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));
+}
+
+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)
+{
+ Node* node = nodeForObjectId(objectId);
+ if (!node) {
+ errorString = "Node not found"_s;
+ return;
+ }
+ RenderObject* renderer = node->renderer();
+ if (!renderer) {
+ errorString = "Node doesn't have renderer"_s;
+ return;
+ }
+
+ // Ensure quads are up to date.
+ renderer->document().updateLayoutIgnorePendingStylesheets();
+
+ Frame* containingFrame = renderer->document().frame();
+ FrameView* containingView = containingFrame ? containingFrame->view() : nullptr;
+ if (!containingView) {
+ errorString = "Internal error: no containing view"_s;
+ return;
+ }
+ Vector<FloatQuad> quads;
+ renderer->absoluteQuads(quads);
+ for (auto& quad : quads)
+ frameQuadToViewport(*containingView, quad, m_inspectedPage.pageScaleFactor());
+ contentQuads = buildArrayOfQuads(quads);
+}
+
+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)
{
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
diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.h b/Source/WebCore/inspector/agents/InspectorDOMAgent.h
index 7df0e83eb53d75c41c554f1401235ba21719414c..ae6f961a7b7fe63ece60e34210bf333bedef2eee 100644
--- a/Source/WebCore/inspector/agents/InspectorDOMAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.h
@@ -54,6 +54,7 @@ namespace WebCore {
class AXCoreObject;
class CharacterData;
+class Color;
class DOMEditor;
class Document;
class Element;
@@ -88,6 +89,7 @@ public:
static String toErrorString(Exception&&);
static String documentURLString(Document*);
+ static Color parseColor(const JSON::Object*);
// We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently.
// We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics.
@@ -129,7 +131,7 @@ public:
void performSearch(ErrorString&, const String& query, const JSON::Array* nodeIds, const bool* caseSensitive, String* searchId, int* resultCount) override;
void getSearchResults(ErrorString&, const String& searchId, int fromIndex, int toIndex, RefPtr<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:
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;
// 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 31382c765d05a28ca7e787e20730c303f67b8776..c7321a9af1a52eea7a02a818d2a75f68fafccb9e 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,23 @@ using namespace Inspector;
namespace {
+String inspectorInitiatorPrefix()
+{
+ return "InspectorPageAgent.navigate referrer:"_s;
+}
+
+Ref<Inspector::Protocol::Network::WebSocketFrame> buildWebSocketMessage(const WebSocketFrame& frame)
+{
+ return Inspector::Protocol::Network::WebSocketFrame::create()
+ .setOpcode(frame.opCode)
+ .setMask(frame.masked)
+ .setPayloadData(frame.opCode == 1
+ ? String::fromUTF8WithLatin1Fallback(frame.payload, frame.payloadLength)
+ : base64Encode(frame.payload, frame.payloadLength))
+ .setPayloadLength(frame.payloadLength)
+ .release();
+}
+
class InspectorThreadableLoaderClient final : public ThreadableLoaderClient {
WTF_MAKE_NONCOPYABLE(InspectorThreadableLoaderClient);
public:
@@ -438,6 +457,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;
@@ -770,24 +796,12 @@ void InspectorNetworkAgent::didCloseWebSocket(unsigned long identifier)
void InspectorNetworkAgent::didReceiveWebSocketFrame(unsigned long identifier, const WebSocketFrame& frame)
{
- auto frameObject = Inspector::Protocol::Network::WebSocketFrame::create()
- .setOpcode(frame.opCode)
- .setMask(frame.masked)
- .setPayloadData(String::fromUTF8WithLatin1Fallback(frame.payload, frame.payloadLength))
- .setPayloadLength(frame.payloadLength)
- .release();
- m_frontendDispatcher->webSocketFrameReceived(IdentifiersFactory::requestId(identifier), timestamp(), WTFMove(frameObject));
+ m_frontendDispatcher->webSocketFrameReceived(IdentifiersFactory::requestId(identifier), timestamp(), buildWebSocketMessage(frame));
}
void InspectorNetworkAgent::didSendWebSocketFrame(unsigned long identifier, const WebSocketFrame& frame)
{
- auto frameObject = Inspector::Protocol::Network::WebSocketFrame::create()
- .setOpcode(frame.opCode)
- .setMask(frame.masked)
- .setPayloadData(String::fromUTF8WithLatin1Fallback(frame.payload, frame.payloadLength))
- .setPayloadLength(frame.payloadLength)
- .release();
- m_frontendDispatcher->webSocketFrameSent(IdentifiersFactory::requestId(identifier), timestamp(), WTFMove(frameObject));
+ m_frontendDispatcher->webSocketFrameSent(IdentifiersFactory::requestId(identifier), timestamp(), buildWebSocketMessage(frame));
}
void InspectorNetworkAgent::didReceiveWebSocketFrameError(unsigned long identifier, const String& errorMessage)
@@ -839,6 +853,7 @@ void InspectorNetworkAgent::disable(ErrorString&)
m_resourcesData->clear();
m_extraRequestHeaders.clear();
+ continuePendingRequests();
continuePendingResponses();
setResourceCachingDisabled(false);
@@ -862,6 +877,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())
@@ -1018,17 +1043,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)
@@ -1110,19 +1133,128 @@ 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;
+ }
+
+ errorString = "Missing pending intercept response for given requestId"_s;
+}
+
+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;
}
- 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::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());
+ 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;
@@ -1150,20 +1282,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/")
@@ -1293,6 +1431,11 @@ void InspectorNetworkAgent::searchInRequest(ErrorString& errorString, const Stri
results = ContentSearchUtilities::searchInTextByLines(resourceData->content(), query, caseSensitive, isRegex);
}
+String InspectorNetworkAgent::createInitiatorIdentifierForInspectorNavigation(const String& referrer)
+{
+ return inspectorInitiatorPrefix() + referrer;
+}
+
void InspectorNetworkAgent::mainFrameNavigated(DocumentLoader& loader)
{
m_resourcesData->clear(loaderIdentifier(&loader));
diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
index a68f84520736977c8b9216616c5a178fbf5275d6..8d6ed7188bca75fb46d1a5963983f08838a48cbe 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
diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
index d678cddbd20a1a2b410a8ebbb17f5f63f0fc620d..d18dd4c915e239c956cbda56d00c87909d93ae08 100644
--- a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
@@ -32,6 +32,8 @@
#include "config.h"
#include "InspectorPageAgent.h"
+#include "AXObjectCache.h"
+#include "BackForwardController.h"
#include "CachedResource.h"
#include "CachedResourceLoader.h"
#include "Cookie.h"
@@ -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"
+#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,36 @@ void InspectorPageAgent::reload(ErrorString&, const bool* optionalReloadFromOrig
m_inspectedPage.mainFrame().loader().reload(reloadOptions);
}
-void InspectorPageAgent::navigate(ErrorString&, const String& url)
+void InspectorPageAgent::goBack(ErrorString& errorString)
+{
+ if (!m_inspectedPage.backForward().goBack())
+ errorString = "Failed to go back"_s;
+}
+
+void InspectorPageAgent::goForward(ErrorString& errorString)
+{
+ if (!m_inspectedPage.backForward().goForward())
+ errorString = "Failed to go forward"_s;
+}
+
+void InspectorPageAgent::navigate(ErrorString& errorString, const String& url, const String* frameId, const String* referrer)
{
UserGestureIndicator indicator { ProcessingUserGesture };
- Frame& frame = m_inspectedPage.mainFrame();
+ Frame* frame = frameId ? assertFrame(errorString, *frameId) : &m_inspectedPage.mainFrame();
+ if (!frame)
+ return;
+
+ ResourceRequest resourceRequest { frame->document()->completeURL(url) };
+
+ if (!resourceRequest.url().isValid()) {
+ errorString = "Cannot navigate to invalid URL"_s;
+ return;
+ }
- ResourceRequest resourceRequest { frame.document()->completeURL(url) };
- FrameLoadRequest frameLoadRequest { *frame.document(), frame.document()->securityOrigin(), resourceRequest, "_self"_s, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown };
- frame.loader().changeLocation(WTFMove(frameLoadRequest));
+ if (referrer)
+ resourceRequest.setInitiatorIdentifier(InspectorNetworkAgent::createInitiatorIdentifierForInspectorNavigation(*referrer));
+ FrameLoadRequest frameLoadRequest { *frame->document(), frame->document()->securityOrigin(), resourceRequest, "_self"_s, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown };
+ frame->loader().changeLocation(WTFMove(frameLoadRequest));
}
void InspectorPageAgent::overrideUserAgent(ErrorString&, const String* value)
@@ -683,15 +734,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)
@@ -699,13 +751,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)
@@ -717,20 +774,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)
@@ -741,11 +796,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));
@@ -766,6 +816,12 @@ void InspectorPageAgent::frameClearedScheduledNavigation(Frame& frame)
m_frontendDispatcher->frameClearedScheduledNavigation(frameId(&frame));
}
+void InspectorPageAgent::didNavigateWithinPage(Frame& frame)
+{
+ String url = frame.document()->url().string();
+ m_frontendDispatcher->navigatedWithinDocument(frameId(&frame), url);
+}
+
void InspectorPageAgent::defaultAppearanceDidChange(bool useDarkAppearance)
{
m_frontendDispatcher->defaultAppearanceDidChange(useDarkAppearance ? Inspector::Protocol::Page::Appearance::Dark : Inspector::Protocol::Page::Appearance::Light);
@@ -823,6 +879,38 @@ void InspectorPageAgent::didRecalculateStyle()
m_overlay->update();
}
+void InspectorPageAgent::runOpenPanel(HTMLInputElement* element, bool* intercept)
+{
+ if (m_interceptFileChooserDialog) {
+ *intercept = true;
+ } else {
+ return;
+ }
+ Document& document = element->document();
+ auto* frame = document.frame();
+ if (!frame)
+ return;
+
+ auto& state = *mainWorldExecState(frame);
+ auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state);
+ if (injectedScript.hasNoValue())
+ return;
+
+ m_frontendDispatcher->fileChooserOpened(frameId(frame), injectedScript.wrapObject(InspectorDOMAgent::nodeAsScriptValue(state, element), WTF::String()));
+}
+
+void InspectorPageAgent::frameAttached(Frame& frame)
+{
+ Frame* parent = frame.tree().parent();
+ String parentFrameId = frameId(parent);
+ m_frontendDispatcher->frameAttached(frameId(&frame), parent ? &parentFrameId : nullptr);
+}
+
+bool InspectorPageAgent::shouldBypassCSP()
+{
+ return m_bypassCSP;
+}
+
Ref<Inspector::Protocol::Page::Frame> InspectorPageAgent::buildObjectForFrame(Frame* frame)
{
ASSERT_ARG(frame, frame);
@@ -966,6 +1054,29 @@ void InspectorPageAgent::snapshotRect(ErrorString& errorString, int x, int y, in
*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)
+{
+#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)
@@ -983,4 +1094,520 @@ 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;
+ }
+ }
+
+ out_axNode = snapshotForAXObject(makeRefPtr(axObject), node);
+}
+
+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();
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.h b/Source/WebCore/inspector/agents/InspectorPageAgent.h
index 110173dbbfe819226b6c4caa0f65a5dee8c39f2b..52b89efdac4e2c0b7c1f6cbe69ad0a6e8d4bca7e 100644
--- 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:
void enable(ErrorString&) override;
void disable(ErrorString&) override;
void reload(ErrorString&, const bool* optionalReloadFromOrigin, const bool* optionalRevalidateAllResources) override;
- void navigate(ErrorString&, const String& url) override;
+ void goBack(ErrorString&) override;
+ void goForward(ErrorString&) override;
+ void navigate(ErrorString&, const String& url, const String* frameId, const String* referrer) override;
void overrideUserAgent(ErrorString&, const String* value) override;
void overrideSetting(ErrorString&, const String& setting, const bool* value) override;
void getCookies(ErrorString&, RefPtr<JSON::ArrayOf<Inspector::Protocol::Page::Cookie>>& cookies) override;
@@ -111,20 +118,29 @@ public:
void setShowPaintRects(ErrorString&, bool show) override;
void setEmulatedMedia(ErrorString&, const String&) override;
void setForcedAppearance(ErrorString&, const String&) override;
+ void setTimeZone(ErrorString&, const String*) override;
+ void setTouchEmulationEnabled(ErrorString&, bool) override;
void snapshotNode(ErrorString&, int nodeId, String* outDataURL) override;
- void snapshotRect(ErrorString&, int x, int y, int width, int height, const String& coordinateSystem, String* outDataURL) override;
+ void snapshotRect(ErrorString&, int x, int y, int width, int height, const String& coordinateSystem, String* outDataURL) override;
void archive(ErrorString&, String* data) override;
+ void insertText(ErrorString&, const String& text) override;
+ void accessibilitySnapshot(ErrorString&, 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;
// InspectorInstrumentation
- void domContentEventFired();
- void loadEventFired();
+ void domContentEventFired(Frame&);
+ void loadEventFired(Frame&);
void frameNavigated(Frame&);
void frameDetached(Frame&);
- void loaderDetachedFromFrame(DocumentLoader&);
void frameStartedLoading(Frame&);
void frameStoppedLoading(Frame&);
void frameScheduledNavigation(Frame&, Seconds delay);
void frameClearedScheduledNavigation(Frame&);
+ void didNavigateWithinPage(Frame&);
void defaultAppearanceDidChange(bool useDarkAppearance);
void applyUserAgentOverride(String&);
void applyEmulatedMedia(String&);
@@ -133,6 +149,9 @@ public:
void didLayout();
void didScroll();
void didRecalculateStyle();
+ void runOpenPanel(HTMLInputElement* element, bool* intercept);
+ void frameAttached(Frame&);
+ bool shouldBypassCSP();
Frame* frameForId(const String& frameId);
WEBCORE_EXPORT String frameId(Frame*);
@@ -141,6 +160,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);
@@ -152,18 +172,19 @@ private:
RefPtr<Inspector::PageBackendDispatcher> m_backendDispatcher;
Page& m_inspectedPage;
+ Inspector::InjectedScriptManager& m_injectedScriptManager;
InspectorClient* m_client { nullptr };
InspectorOverlay* m_overlay { nullptr };
- HashMap<Frame*, String> m_frameToIdentifier;
HashMap<String, Frame*> m_identifierToFrame;
- HashMap<DocumentLoader*, String> m_loaderToIdentifier;
String m_userAgentOverride;
String m_emulatedMedia;
String m_forcedAppearance;
String m_bootstrapScript;
bool m_isFirstLayoutAfterOnLoad { false };
bool m_showPaintRects { false };
+ bool m_interceptFileChooserDialog { false };
+ bool m_bypassCSP { false };
};
} // namespace WebCore
diff --git a/Source/WebCore/inspector/agents/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/PageRuntimeAgent.cpp b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
index 63336051bb0050d6a55eb5543b0349eb964bbb7a..71abd08516e93b087e506f54b8e093ea300dfe71 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) {
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/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp
index da50315d2160833e02ab19b250ea19ab652246a9..f93887308eba26272449efd1c48afa68d77c4408 100644
--- a/Source/WebCore/loader/DocumentLoader.cpp
+++ b/Source/WebCore/loader/DocumentLoader.cpp
@@ -1286,8 +1286,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 d6a3d0acd246de70cb485880a04b38941c832f65..61c8d5478f5eefccf88532bebf69b94d97e8a88c 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; }
diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp
index 8cf9c5c47cea3ad27f282b5d73cfd5d6e3e7834a..f2daacccff023dbdd8de311e717780fbef3cb318 100644
--- a/Source/WebCore/loader/FrameLoader.cpp
+++ b/Source/WebCore/loader/FrameLoader.cpp
@@ -1178,6 +1178,7 @@ void FrameLoader::loadInSameDocument(const URL& url, SerializedScriptValue* stat
}
m_client.dispatchDidNavigateWithinPage();
+ InspectorInstrumentation::didNavigateWithinPage(m_frame);
m_frame.document()->statePopped(stateObject ? Ref<SerializedScriptValue> { *stateObject } : SerializedScriptValue::nullValue());
m_client.dispatchDidPopStateWithinPage();
@@ -1363,6 +1364,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) {
@@ -1597,6 +1600,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 };
@@ -3182,6 +3187,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)
@@ -3944,24 +3951,29 @@ String FrameLoader::referrer() const
void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
{
- if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
- return;
+ // It is essential that the normal world is cleared first.
+ // Various subsystem (InjectedScriptManager) will reset state upon normal
+ // world initialization.
+ DOMWrapperWorld& mainWorld = mainThreadNormalWorld();
+ dispatchDidClearWindowObjectInWorld(mainWorld);
Vector<Ref<DOMWrapperWorld>> worlds;
ScriptController::getAllWorlds(worlds);
- for (auto& world : worlds)
- dispatchDidClearWindowObjectInWorld(world);
+ for (auto& world : worlds) {
+ if (world.ptr() != &mainWorld)
+ dispatchDidClearWindowObjectInWorld(world);
+ }
}
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 0644fec509e60f7a4cf59a352f32335c2d164d99..acf628996ea020a8f0a2239ef72f5c241d108840 100644
--- a/Source/WebCore/loader/LoaderStrategy.h
+++ b/Source/WebCore/loader/LoaderStrategy.h
@@ -79,6 +79,7 @@ public:
virtual bool isOnLine() const = 0;
virtual void addOnlineStateChangeListener(WTF::Function<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/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/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp
index 523ad3919ef15b3127d2a48a7d891725d619cc43..b2abde5d3c03e32f9a6008ddf10876aef248ee16 100644
--- a/Source/WebCore/page/EventHandler.cpp
+++ b/Source/WebCore/page/EventHandler.cpp
@@ -808,9 +808,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;
@@ -849,8 +847,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
@@ -872,8 +868,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)
@@ -894,7 +892,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);
@@ -911,6 +911,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
@@ -942,6 +944,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())
@@ -1033,7 +1037,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()
{
@@ -1081,9 +1084,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;
@@ -2036,10 +2037,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 ea2472d895c676429482726c143d07f10175592d..010ca06e76136314bca46c1246bf41de70f8e68a 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();
@@ -366,10 +364,8 @@ private:
bool handleMousePressEventDoubleClick(const MouseEventWithHitTestResults&);
bool handleMousePressEventTripleClick(const MouseEventWithHitTestResults&);
-#if ENABLE(DRAG_SUPPORT)
bool handleMouseDraggedEvent(const MouseEventWithHitTestResults&, CheckDragHysteresis = ShouldCheckDragHysteresis);
bool shouldAllowMouseDownToStartDrag() const;
-#endif
WEBCORE_EXPORT bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&);
@@ -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);
@@ -519,10 +514,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 9e6b7fe76ee6d1a92c0f37c1a80daf9e651a6b3d..23571ae7294cb335065ad94818622aa1e8b3880c 100644
--- a/Source/WebCore/page/Frame.cpp
+++ b/Source/WebCore/page/Frame.cpp
@@ -180,6 +180,7 @@ Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient&
void Frame::init()
{
m_loader->init();
+ InspectorInstrumentation::frameAttached(this);
}
Ref<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp
index 41aa08b78e83e0804d947de06cdbdbd06c8f2653..6d2ab607c50b4801d297f17902a737928b66ec75 100644
--- a/Source/WebCore/page/FrameView.cpp
+++ b/Source/WebCore/page/FrameView.cpp
@@ -3033,7 +3033,7 @@ void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
void FrameView::updateBackgroundRecursively(const Optional<Color>& backgroundColor)
{
-#if HAVE(OS_DARK_MODE_SUPPORT)
+#if HAVE(OS_DARK_MODE_SUPPORT) && (defined(WTF_PLATFORM_MAC) && WTF_PLATFORM_MAC) || (defined(WTF_PLATFORM_IOS_FAMILY) && WTF_PLATFORM_IOS_FAMILY)
Color baseBackgroundColor = backgroundColor.valueOr(RenderTheme::singleton().systemColor(CSSValueAppleSystemControlBackground, styleColorOptions()));
#else
Color baseBackgroundColor = backgroundColor.valueOr(Color::white);
diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp
index 9c58b06f4c471130ce4815f11d14cb78f81b49a0..3d624733c36f09518b12095d91e67a2ae67879e2 100644
--- 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/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)...)) {
diff --git a/Source/WebCore/platform/PlatformKeyboardEvent.h b/Source/WebCore/platform/PlatformKeyboardEvent.h
index f423a4a1d5399326fc48fe4d4a8a8fb9d4df861e..b4b60162d8b0d34113df052b04a1695d481d266e 100644
--- a/Source/WebCore/platform/PlatformKeyboardEvent.h
+++ b/Source/WebCore/platform/PlatformKeyboardEvent.h
@@ -138,6 +138,7 @@ namespace WebCore {
static String keyCodeForHardwareKeyCode(unsigned);
static String keyIdentifierForGdkKeyCode(unsigned);
static int windowsKeyCodeForGdkKeyCode(unsigned);
+ static unsigned gdkKeyCodeForWindowsKeyCode(int);
static String singleCharacterString(unsigned);
static bool modifiersContainCapsLock(unsigned);
#endif
@@ -147,6 +148,7 @@ namespace WebCore {
static String keyCodeForHardwareKeyCode(unsigned);
static String keyIdentifierForWPEKeyCode(unsigned);
static int windowsKeyCodeForWPEKeyCode(unsigned);
+ static unsigned WPEKeyCodeForWindowsKeyCode(int);
static String singleCharacterString(unsigned);
#endif
diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h
index fdddf2f9beb7e0b28f072cb121d1ee117bf00969..6c6acba2e5795319b60bd3031f37d8872d5a2011 100644
--- a/Source/WebCore/platform/ScrollableArea.h
+++ b/Source/WebCore/platform/ScrollableArea.h
@@ -103,7 +103,7 @@ public:
void updateScrollSnapState();
#if ENABLE(TOUCH_EVENTS)
- virtual bool handleTouchEvent(const PlatformTouchEvent&);
+ WEBCORE_EXPORT virtual bool handleTouchEvent(const PlatformTouchEvent&);
#endif
#if PLATFORM(IOS_FAMILY)
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp
index 3cc3dc9012e8ff409141dd43808b71264c8cd337..e44eca80b5a7f0ac8360d39d78ec7097d5296dc3 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"
diff --git a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
index 269008b9053c8d8b6787cf22f13b44b46dace333..d3ba16947bc8964a7cfe746cabbf99d32a673cef 100644
--- a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
+++ b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
@@ -36,8 +36,10 @@
#include "WindowsKeyboardCodes.h"
#include <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
--- a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp
+++ b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp
@@ -30,8 +30,10 @@
#include "WindowsKeyboardCodes.h"
#include <wpe/wpe.h>
+#include <wtf/HashMap.h>
#include <wtf/HexNumber.h>
#include <wtf/text/StringBuilder.h>
+#include <mutex>
namespace WebCore {
@@ -1291,6 +1293,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(unsigned keycode)
return 0;
}
+static const HashMap<int, unsigned>& WPEToWindowsKeyCodeMap()
+{
+ static HashMap<int, unsigned>* result;
+ static std::once_flag once;
+ std::call_once(
+ once,
+ [] {
+ const unsigned WPEKeyCodes[] = {
+ WPE_KEY_Cancel,
+ // FIXME: non-keypad keys should take precedence, so we skip WPE_KEY_KP_*
+ // WPE_KEY_KP_0,
+ // WPE_KEY_KP_1,
+ // WPE_KEY_KP_2,
+ // WPE_KEY_KP_3,
+ // WPE_KEY_KP_4,
+ // WPE_KEY_KP_5,
+ // WPE_KEY_KP_6,
+ // WPE_KEY_KP_7,
+ // WPE_KEY_KP_8,
+ // WPE_KEY_KP_9,
+ // WPE_KEY_KP_Multiply,
+ // WPE_KEY_KP_Add,
+ // WPE_KEY_KP_Subtract,
+ // WPE_KEY_KP_Decimal,
+ // WPE_KEY_KP_Divide,
+ // WPE_KEY_KP_Page_Up,
+ // WPE_KEY_KP_Page_Down,
+ // WPE_KEY_KP_End,
+ // WPE_KEY_KP_Home,
+ // WPE_KEY_KP_Left,
+ // WPE_KEY_KP_Up,
+ // WPE_KEY_KP_Right,
+ // WPE_KEY_KP_Down,
+ WPE_KEY_BackSpace,
+ // WPE_KEY_ISO_Left_Tab,
+ // WPE_KEY_3270_BackTab,
+ WPE_KEY_Tab,
+ WPE_KEY_Clear,
+ // WPE_KEY_ISO_Enter,
+ // WPE_KEY_KP_Enter,
+ WPE_KEY_Return,
+ WPE_KEY_Menu,
+ WPE_KEY_Pause,
+ WPE_KEY_AudioPause,
+ WPE_KEY_Caps_Lock,
+ WPE_KEY_Kana_Lock,
+ WPE_KEY_Kana_Shift,
+ WPE_KEY_Hangul,
+ WPE_KEY_Hangul_Hanja,
+ WPE_KEY_Kanji,
+ WPE_KEY_Escape,
+ WPE_KEY_space,
+ WPE_KEY_Page_Up,
+ WPE_KEY_Page_Down,
+ WPE_KEY_End,
+ WPE_KEY_Home,
+ WPE_KEY_Left,
+ WPE_KEY_Up,
+ WPE_KEY_Right,
+ WPE_KEY_Down,
+ WPE_KEY_Select,
+ WPE_KEY_Print,
+ WPE_KEY_Execute,
+ WPE_KEY_Insert,
+ WPE_KEY_KP_Insert,
+ WPE_KEY_Delete,
+ WPE_KEY_KP_Delete,
+ WPE_KEY_Help,
+ WPE_KEY_0,
+ WPE_KEY_parenright,
+ WPE_KEY_1,
+ WPE_KEY_exclam,
+ WPE_KEY_2,
+ WPE_KEY_at,
+ WPE_KEY_3,
+ WPE_KEY_numbersign,
+ WPE_KEY_4,
+ WPE_KEY_dollar,
+ WPE_KEY_5,
+ WPE_KEY_percent,
+ WPE_KEY_6,
+ WPE_KEY_asciicircum,
+ WPE_KEY_7,
+ WPE_KEY_ampersand,
+ WPE_KEY_8,
+ WPE_KEY_asterisk,
+ WPE_KEY_9,
+ WPE_KEY_parenleft,
+ WPE_KEY_a,
+ WPE_KEY_A,
+ WPE_KEY_b,
+ WPE_KEY_B,
+ WPE_KEY_c,
+ WPE_KEY_C,
+ WPE_KEY_d,
+ WPE_KEY_D,
+ WPE_KEY_e,
+ WPE_KEY_E,
+ WPE_KEY_f,
+ WPE_KEY_F,
+ WPE_KEY_g,
+ WPE_KEY_G,
+ WPE_KEY_h,
+ WPE_KEY_H,
+ WPE_KEY_i,
+ WPE_KEY_I,
+ WPE_KEY_j,
+ WPE_KEY_J,
+ WPE_KEY_k,
+ WPE_KEY_K,
+ WPE_KEY_l,
+ WPE_KEY_L,
+ WPE_KEY_m,
+ WPE_KEY_M,
+ WPE_KEY_n,
+ WPE_KEY_N,
+ WPE_KEY_o,
+ WPE_KEY_O,
+ WPE_KEY_p,
+ WPE_KEY_P,
+ WPE_KEY_q,
+ WPE_KEY_Q,
+ WPE_KEY_r,
+ WPE_KEY_R,
+ WPE_KEY_s,
+ WPE_KEY_S,
+ WPE_KEY_t,
+ WPE_KEY_T,
+ WPE_KEY_u,
+ WPE_KEY_U,
+ WPE_KEY_v,
+ WPE_KEY_V,
+ WPE_KEY_w,
+ WPE_KEY_W,
+ WPE_KEY_x,
+ WPE_KEY_X,
+ WPE_KEY_y,
+ WPE_KEY_Y,
+ WPE_KEY_z,
+ WPE_KEY_Z,
+ WPE_KEY_Meta_L,
+ WPE_KEY_Meta_R,
+ WPE_KEY_Sleep,
+ WPE_KEY_Num_Lock,
+ WPE_KEY_Scroll_Lock,
+ WPE_KEY_Shift_L,
+ WPE_KEY_Shift_R,
+ WPE_KEY_Control_L,
+ WPE_KEY_Control_R,
+ WPE_KEY_Alt_L,
+ WPE_KEY_Alt_R,
+ WPE_KEY_Back,
+ WPE_KEY_Forward,
+ WPE_KEY_Refresh,
+ WPE_KEY_Stop,
+ WPE_KEY_Search,
+ WPE_KEY_Favorites,
+ WPE_KEY_HomePage,
+ WPE_KEY_AudioMute,
+ WPE_KEY_AudioLowerVolume,
+ WPE_KEY_AudioRaiseVolume,
+ WPE_KEY_AudioNext,
+ WPE_KEY_AudioPrev,
+ WPE_KEY_AudioStop,
+ WPE_KEY_AudioMedia,
+ WPE_KEY_semicolon,
+ WPE_KEY_colon,
+ WPE_KEY_plus,
+ WPE_KEY_equal,
+ WPE_KEY_comma,
+ WPE_KEY_less,
+ WPE_KEY_minus,
+ WPE_KEY_underscore,
+ WPE_KEY_period,
+ WPE_KEY_greater,
+ WPE_KEY_slash,
+ WPE_KEY_question,
+ WPE_KEY_asciitilde,
+ WPE_KEY_quoteleft,
+ WPE_KEY_bracketleft,
+ WPE_KEY_braceleft,
+ WPE_KEY_backslash,
+ WPE_KEY_bar,
+ WPE_KEY_bracketright,
+ WPE_KEY_braceright,
+ WPE_KEY_quoteright,
+ WPE_KEY_quotedbl,
+ WPE_KEY_AudioRewind,
+ WPE_KEY_AudioForward,
+ WPE_KEY_AudioPlay,
+ WPE_KEY_F1,
+ WPE_KEY_F2,
+ WPE_KEY_F3,
+ WPE_KEY_F4,
+ WPE_KEY_F5,
+ WPE_KEY_F6,
+ WPE_KEY_F7,
+ WPE_KEY_F8,
+ WPE_KEY_F9,
+ WPE_KEY_F10,
+ WPE_KEY_F11,
+ WPE_KEY_F12,
+ WPE_KEY_F13,
+ WPE_KEY_F14,
+ WPE_KEY_F15,
+ WPE_KEY_F16,
+ WPE_KEY_F17,
+ WPE_KEY_F18,
+ WPE_KEY_F19,
+ WPE_KEY_F20,
+ WPE_KEY_F21,
+ WPE_KEY_F22,
+ WPE_KEY_F23,
+ WPE_KEY_F24,
+ WPE_KEY_VoidSymbol,
+ WPE_KEY_Red,
+ WPE_KEY_Green,
+ WPE_KEY_Yellow,
+ WPE_KEY_Blue,
+ WPE_KEY_PowerOff,
+ WPE_KEY_AudioRecord,
+ WPE_KEY_Display,
+ WPE_KEY_Subtitle,
+ WPE_KEY_Video
+ };
+ result = new HashMap<int, unsigned>();
+ for (unsigned WPEKeyCode : WPEKeyCodes) {
+ int winKeyCode = PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(WPEKeyCode);
+ // If several gdk key codes map to the same win key code first one is used.
+ result->add(winKeyCode, WPEKeyCode);
+ }
+ });
+ return *result;
+}
+
+unsigned PlatformKeyboardEvent::WPEKeyCodeForWindowsKeyCode(int keycode)
+{
+ return WPEToWindowsKeyCodeMap().get(keycode);
+}
+
String PlatformKeyboardEvent::singleCharacterString(unsigned val)
{
switch (val) {
diff --git a/Source/WebCore/platform/network/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/CookieJarCurl.cpp b/Source/WebCore/platform/network/curl/CookieJarCurl.cpp
index 5ecba66ef94984ebff5e3ff034375abb68ca72fa..e834685842aabf572b488394d961566aa8160be7 100644
--- a/Source/WebCore/platform/network/curl/CookieJarCurl.cpp
+++ b/Source/WebCore/platform/network/curl/CookieJarCurl.cpp
@@ -152,6 +152,25 @@ void CookieJarCurl::deleteAllCookiesModifiedSince(const NetworkStorageSession&,
// FIXME: Not yet implemented
}
+Vector<Cookie> CookieJarCurl::getAllCookies(const NetworkStorageSession& session) const
+{
+ CookieJarDB& cookieJarDB = session.cookieDatabase();
+ return cookieJarDB.getAllCookies();
+}
+
+void CookieJarCurl::setCookie(const NetworkStorageSession& session, const Cookie& cookie) const
+{
+ CookieJarDB& cookieJarDB = session.cookieDatabase();
+ cookieJarDB.setCookie(cookie);
+}
+
+void CookieJarCurl::deleteCookie(const NetworkStorageSession& session, const Cookie& cookie) const
+{
+ String url = (cookie.secure ? "https" : "http") + ("://" + cookie.domain + cookie.path);
+ CookieJarDB& cookieJarDB = session.cookieDatabase();
+ cookieJarDB.deleteCookie(url, cookie.name);
+}
+
} // namespace WebCore
#endif // USE(CURL)
diff --git a/Source/WebCore/platform/network/curl/CookieJarCurl.h b/Source/WebCore/platform/network/curl/CookieJarCurl.h
index 5e974f5fbdb8c04975a5511b0dc4a142d101a308..ab2af278059bc47c61dfd3254d0e0cca5aad302b 100644
--- a/Source/WebCore/platform/network/curl/CookieJarCurl.h
+++ b/Source/WebCore/platform/network/curl/CookieJarCurl.h
@@ -58,6 +58,9 @@ public:
void deleteCookiesForHostnames(const NetworkStorageSession&, const Vector<String>& cookieHostNames) const;
void deleteAllCookies(const NetworkStorageSession&) const;
void deleteAllCookiesModifiedSince(const NetworkStorageSession&, WallTime) const;
+ Vector<Cookie> getAllCookies(const NetworkStorageSession& session) const;
+ void setCookie(const NetworkStorageSession& session, const Cookie& cookie) const;
+ void deleteCookie(const NetworkStorageSession& session, const Cookie& cookie) const;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/curl/CookieJarDB.cpp b/Source/WebCore/platform/network/curl/CookieJarDB.cpp
index 101624f2900a94cc7d1a89989676d6b45ab7fa3d..6f446b2d57801d8971a3692b7039fec2210fd218 100644
--- a/Source/WebCore/platform/network/curl/CookieJarDB.cpp
+++ b/Source/WebCore/platform/network/curl/CookieJarDB.cpp
@@ -445,6 +445,36 @@ Optional<Vector<Cookie>> CookieJarDB::searchCookies(const URL& firstParty, const
return results;
}
+Vector<Cookie> CookieJarDB::getAllCookies()
+{
+ Vector<Cookie> result;
+ if (!isEnabled() || !m_database.isOpen())
+ return result;
+
+ const String sql = "SELECT name, value, domain, path, expires, httponly, secure, session FROM Cookie";
+
+ auto pstmt = makeUnique<SQLiteStatement>(m_database, sql);
+ if (!pstmt)
+ return result;
+ pstmt->prepare();
+
+ while (pstmt->step() == SQLITE_ROW) {
+ Cookie cookie;
+ cookie.name = pstmt->getColumnText(0);
+ cookie.value = pstmt->getColumnText(1);
+ cookie.domain = pstmt->getColumnText(2).convertToASCIILowercase();
+ cookie.path = pstmt->getColumnText(3);
+ cookie.expires = (double)pstmt->getColumnInt64(4) * 1000;
+ cookie.httpOnly = (pstmt->getColumnInt(5) == 1);
+ cookie.secure = (pstmt->getColumnInt(6) == 1);
+ cookie.session = (pstmt->getColumnInt(7) == 1);
+ result.append(WTFMove(cookie));
+ }
+ pstmt->finalize();
+
+ return result;
+}
+
bool CookieJarDB::hasHttpOnlyCookie(const String& name, const String& domain, const String& path)
{
auto& statement = preparedStatement(CHECK_EXISTS_HTTPONLY_COOKIE_SQL);
diff --git a/Source/WebCore/platform/network/curl/CookieJarDB.h b/Source/WebCore/platform/network/curl/CookieJarDB.h
index 2687ae74fb9d9942972bedcac6ab9b1159a7e50f..b62e2a2b032f938065ea4e4d8e093153b4f17cf5 100644
--- a/Source/WebCore/platform/network/curl/CookieJarDB.h
+++ b/Source/WebCore/platform/network/curl/CookieJarDB.h
@@ -64,6 +64,7 @@ public:
bool deleteCookies(const String& url);
bool deleteAllCookies();
+ Vector<Cookie> getAllCookies();
WEBCORE_EXPORT CookieJarDB(const String& databasePath);
WEBCORE_EXPORT ~CookieJarDB();
diff --git a/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp b/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp
index 5cf1e1ea2a712a7033e8390da781283c620b1caa..d02ca0e5e1dc14ca99a2676c1304ee43e58ae522 100644
--- a/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp
+++ b/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp
@@ -62,7 +62,7 @@ static String defaultCookieJarPath()
NetworkStorageSession::NetworkStorageSession(PAL::SessionID sessionID)
: m_sessionID(sessionID)
, m_cookieStorage(makeUniqueRef<CookieJarCurl>())
- , m_cookieDatabase(makeUniqueRef<CookieJarDB>(defaultCookieJarPath()))
+ , m_cookieDatabase(makeUniqueRef<CookieJarDB>(sessionID.isEphemeral() ? ":memory:" : defaultCookieJarPath()))
{
}
@@ -113,14 +113,14 @@ void NetworkStorageSession::setCookies(const Vector<Cookie>&, const URL&, const
// FIXME: Implement for WebKit to use.
}
-void NetworkStorageSession::setCookie(const Cookie&)
+void NetworkStorageSession::setCookie(const Cookie& cookie)
{
- // FIXME: Implement for WebKit to use.
+ cookieStorage().setCookie(*this, cookie);
}
-void NetworkStorageSession::deleteCookie(const Cookie&)
+void NetworkStorageSession::deleteCookie(const Cookie& cookie)
{
- // FIXME: Implement for WebKit to use.
+ cookieStorage().deleteCookie(*this, cookie);
}
void NetworkStorageSession::deleteCookie(const URL& url, const String& cookie) const
@@ -152,8 +152,7 @@ void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& cook
Vector<Cookie> NetworkStorageSession::getAllCookies()
{
- // FIXME: Implement for WebKit to use.
- return { };
+ return cookieStorage().getAllCookies(*this);
}
void NetworkStorageSession::getHostnamesWithCookies(HashSet<String>& hostnames)
diff --git a/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp b/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp
index 3ee77ec5f759857c6742780e8602694ec1ba9847..c4f09e6ab9f5bf205bc7c40cc59d016dcba780bc 100644
--- a/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp
+++ b/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp
@@ -413,8 +413,13 @@ void NetworkStorageSession::getHostnamesWithCookies(HashSet<String>& hostnames)
Vector<Cookie> NetworkStorageSession::getAllCookies()
{
- // FIXME: Implement for WK2 to use.
- return { };
+ Vector<Cookie> cookies;
+ GUniquePtr<GSList> cookiesList(soup_cookie_jar_all_cookies(cookieStorage()));
+ for (GSList* item = cookiesList.get(); item; item = g_slist_next(item)) {
+ GUniquePtr<SoupCookie> soupCookie(static_cast<SoupCookie*>(item->data));
+ cookies.append(WebCore::Cookie(soupCookie.get()));
+ }
+ return cookies;
}
Vector<Cookie> NetworkStorageSession::getCookies(const URL& url)
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 24fc5e45945c6f6a5dd394245b2b0bea98e567f1..059d32db6a3db77225c500e028c321225265c3cc 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"
@@ -590,6 +589,35 @@ void NetworkProcess::destroySession(PAL::SessionID sessionID)
m_storageManagerSet->remove(sessionID);
}
+void NetworkProcess::getAllCookies(PAL::SessionID sessionID, CompletionHandler<void(Vector<WebCore::Cookie>&&)>&& completionHandler)
+{
+ if (auto* networkStorageSession = storageSession(sessionID)) {
+ completionHandler(networkStorageSession->getAllCookies());
+ return;
+ }
+ completionHandler({ });
+}
+
+void NetworkProcess::setCookies(PAL::SessionID sessionID, Vector<WebCore::Cookie> cookies, CompletionHandler<void(bool)>&& completionHandler) {
+ if (auto* networkStorageSession = storageSession(sessionID)) {
+ for (auto cookie : cookies)
+ networkStorageSession->setCookie(cookie);
+ completionHandler(true);
+ return;
+ }
+ completionHandler(false);
+}
+
+void NetworkProcess::deleteAllCookies(PAL::SessionID sessionID, CompletionHandler<void(bool)>&& completionHandler)
+{
+ if (auto* networkStorageSession = storageSession(sessionID)) {
+ networkStorageSession->deleteAllCookies();
+ completionHandler(true);
+ return;
+ }
+ completionHandler(false);
+}
+
#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 6665afdb88887bff144dc9c7c6e7b8e747f8f180..2bd76e9c2d6ae22d51590d1856d220efe0cfe29b 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.h
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.h
@@ -74,6 +74,7 @@ class SessionID;
namespace WebCore {
class CertificateInfo;
+struct Cookie;
class CurlProxySettings;
class DownloadID;
class ProtectionSpace;
@@ -201,6 +202,10 @@ 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)>&&);
+
#if ENABLE(RESOURCE_LOAD_STATISTICS)
void clearPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
void clearUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
@@ -309,6 +314,7 @@ public:
#if PLATFORM(COCOA)
NetworkHTTPSUpgradeChecker& networkHTTPSUpgradeChecker();
+ bool ignoreTLSErrors() const { return m_ignoreTLSErrors; }
#endif
const String& uiProcessBundleIdentifier() const { return m_uiProcessBundleIdentifier; }
@@ -420,8 +426,10 @@ private:
void syncAllCookies();
void didSyncAllCookies();
-#if USE(SOUP)
+#if PLATFORM(COCOA) || USE(CURL) || USE(SOUP)
void setIgnoreTLSErrors(bool);
+#endif
+#if USE(SOUP)
void userPreferredLanguagesChanged(const Vector<String>&);
void setNetworkProxySettings(const WebCore::SoupNetworkProxySettings&);
#endif
@@ -569,6 +577,7 @@ private:
#if PLATFORM(COCOA)
std::unique_ptr<NetworkHTTPSUpgradeChecker> m_networkHTTPSUpgradeChecker;
+ bool m_ignoreTLSErrors { false };
#endif
#if ENABLE(RESOURCE_LOAD_STATISTICS)
diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
index 433447ba14e4302e978507fb512e993096ced4c2..cd80803a7c6c48c81bd6d7469d7669af1a898070 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
@@ -27,8 +27,10 @@ messages -> NetworkProcess LegacyReceiver {
# Creates a connection for communication with a WebProcess
CreateNetworkConnectionToWebProcess(WebCore::ProcessIdentifier processIdentifier, PAL::SessionID sessionID) -> (Optional<IPC::Attachment> connectionIdentifier, enum:uint8_t WebCore::HTTPCookieAcceptPolicy cookieAcceptPolicy) Async
-#if USE(SOUP)
+#if USE(SOUP) || PLATFORM(COCOA) || USE(CURL)
SetIgnoreTLSErrors(bool ignoreTLSErrors)
+#endif
+#if USE(SOUP)
UserPreferredLanguagesChanged(Vector<String> languages)
SetNetworkProxySettings(struct WebCore::SoupNetworkProxySettings settings)
PrefetchDNS(String hostname)
@@ -80,6 +82,10 @@ messages -> NetworkProcess LegacyReceiver {
PrepareToSuspend(bool isSuspensionImminent) -> () Async
ProcessDidResume()
+ GetAllCookies(PAL::SessionID sessionID) -> (Vector<WebCore::Cookie> cookies) Async
+ SetCookies(PAL::SessionID sessionID, Vector<WebCore::Cookie> cookies) -> (bool success) Async
+ DeleteAllCookies(PAL::SessionID sessionID) -> (bool success) Async
+
#if ENABLE(RESOURCE_LOAD_STATISTICS)
ClearPrevalentResource(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async
ClearUserInteraction(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async
diff --git a/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h b/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h
index 1c4764fac33a706ef42438e4e11bffbc30d1abb6..307439e138ce4946cc879d440ce6994293151fa5 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h
+++ b/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h
@@ -75,9 +75,9 @@ struct NetworkProcessCreationParameters {
WebsiteDataStoreParameters defaultDataStoreParameters;
+ bool ignoreTLSErrors { false };
#if USE(SOUP)
WebCore::HTTPCookieAcceptPolicy cookieAcceptPolicy { WebCore::HTTPCookieAcceptPolicy::AlwaysAccept };
- bool ignoreTLSErrors { false };
Vector<String> languages;
WebCore::SoupNetworkProxySettings proxySettings;
#endif
diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm
index 7ee5a35ad4c1b93936c0b086fb1bae8b15a534a6..6d6efb44de5fab4b7c606dea6188e961cbd1f008 100644
--- a/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm
+++ b/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm
@@ -89,6 +89,8 @@ void NetworkProcess::platformInitializeNetworkProcessCocoa(const NetworkProcessC
#endif
#endif
+ setIgnoreTLSErrors(parameters.ignoreTLSErrors);
+
_CFNetworkSetATSContext(parameters.networkATSContext.get());
m_uiProcessBundleIdentifier = parameters.uiProcessBundleIdentifier;
@@ -210,6 +212,7 @@ void NetworkProcess::syncAllCookies()
});
}
+
#if HAVE(FOUNDATION_WITH_SAVE_COOKIES_WITH_COMPLETION_HANDLER)
static void saveCookies(NSHTTPCookieStorage *cookieStorage, CompletionHandler<void()>&& completionHandler)
{
@@ -240,6 +243,11 @@ void NetworkProcess::platformSyncAllCookies(CompletionHandler<void()>&& completi
ALLOW_DEPRECATED_DECLARATIONS_END
}
+void NetworkProcess::setIgnoreTLSErrors(bool ignoreTLSErrors)
+{
+ m_ignoreTLSErrors = ignoreTLSErrors;
+}
+
void NetworkProcess::platformPrepareToSuspend(CompletionHandler<void()>&& completionHandler)
{
completionHandler();
diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h
index 4ad2c101be7a9e79f8d350265d788c38d02e5858..0acbd8a5971cc1d2fa16cffc46a0bd41f71cbb00 100644
--- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h
+++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h
@@ -77,7 +77,7 @@ public:
const String& dataConnectionServiceType() const;
#endif
- static bool allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge&);
+ bool allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge&);
void continueDidReceiveChallenge(SessionWrapper&, const WebCore::AuthenticationChallenge&, NegotiatedLegacyTLS, NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*, CompletionHandler<void(WebKit::AuthenticationChallengeDisposition, const WebCore::Credential&)>&&);
diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
index 2a359242a7b377b80ab613924977a95cef6da900..57d998453f89148d27120ae129d74621afbce2c6 100644
--- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
+++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
@@ -637,7 +637,7 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa& session, Se
NegotiatedLegacyTLS negotiatedLegacyTLS = NegotiatedLegacyTLS::No;
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
- if (NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(challenge))
+ if (sessionCocoa->allowsSpecificHTTPSCertificateForHost(challenge))
return completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
#if HAVE(TLS_PROTOCOL_VERSION_T)
@@ -1310,6 +1310,9 @@ static bool certificatesMatch(SecTrustRef trust1, SecTrustRef trust2)
bool NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge& challenge)
{
+ if (networkProcess().ignoreTLSErrors())
+ return true;
+
const String& host = challenge.protectionSpace().host();
NSArray *certificates = [NSURLRequest allowsSpecificHTTPSCertificateForHost:host];
if (!certificates)
diff --git a/Source/WebKit/NetworkProcess/curl/NetworkProcessCurl.cpp b/Source/WebKit/NetworkProcess/curl/NetworkProcessCurl.cpp
index 5be170266f45b8bf72ef56b10087cb59bb56dba9..24f8885a0054c1a64cb7deebb00bb4421c56a858 100644
--- a/Source/WebKit/NetworkProcess/curl/NetworkProcessCurl.cpp
+++ b/Source/WebKit/NetworkProcess/curl/NetworkProcessCurl.cpp
@@ -94,4 +94,9 @@ void NetworkProcess::setNetworkProxySettings(PAL::SessionID sessionID, WebCore::
ASSERT_NOT_REACHED();
}
+void NetworkProcess::setIgnoreTLSErrors(bool ignoreTLSErrors)
+{
+ CurlContext::singleton().sslHandle().setIgnoreSSLErrors(ignoreTLSErrors);
+}
+
} // namespace WebKit
diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake
index 04be8137187da994348d4e836a0f0c2fc6cab327..c6ac5d454242387dc4f406152f5550cf26e8b624 100644
--- a/Source/WebKit/PlatformWPE.cmake
+++ b/Source/WebKit/PlatformWPE.cmake
@@ -249,6 +249,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 b7755dc7daf5615f22881c28f26d6b5d29c59ffd..dbe69adbb70cafc3f5f52ca68dcbd67da7f0a02f 100644
--- a/Source/WebKit/PlatformWin.cmake
+++ b/Source/WebKit/PlatformWin.cmake
@@ -56,8 +56,12 @@ list(APPEND WebKit_SOURCES
UIProcess/WebsiteData/win/WebsiteDataStoreWin.cpp
+ UIProcess/win/InspectorTargetProxyWin.cpp
+ UIProcess/win/InspectorBrowserAgentClientWin.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
diff --git a/Source/WebKit/Shared/API/c/wpe/WebKit.h b/Source/WebKit/Shared/API/c/wpe/WebKit.h
index 898e30b370db8176e886fbbde0cd960e38a64818..74945e06fac0eb14936578de6a599a123364a63a 100644
--- a/Source/WebKit/Shared/API/c/wpe/WebKit.h
+++ b/Source/WebKit/Shared/API/c/wpe/WebKit.h
@@ -78,6 +78,7 @@
// From Source/WebKit/UIProcess/API/C
#include <WebKit/WKBackForwardListItemRef.h>
#include <WebKit/WKBackForwardListRef.h>
+#include <WebKit/WKBrowserInspector.h>
#include <WebKit/WKContext.h>
#include <WebKit/WKContextConfigurationRef.h>
#include <WebKit/WKCredential.h>
diff --git a/Source/WebKit/Shared/NativeWebKeyboardEvent.h b/Source/WebKit/Shared/NativeWebKeyboardEvent.h
index f08c19fb95ec8c8cca8f4ca2aa4049885637febf..c09e35e1b4fbf95b31f8d890bf09231055e4373a 100644
--- 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&);
enum class HandledByInputMethod : bool { No, Yes };
NativeWebKeyboardEvent(GdkEvent*, const String&, HandledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&, Vector<String>&& commands);
+ NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<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/WebEvent.h b/Source/WebKit/Shared/WebEvent.h
index 224ef51567fdf5eb7321a3411faccd283b5b2813..7c102952d5821486f0c6a0af0b8d3286ace96b93 100644
--- a/Source/WebKit/Shared/WebEvent.h
+++ b/Source/WebKit/Shared/WebEvent.h
@@ -37,6 +37,7 @@
#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)
WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, const Vector<WebCore::KeypressCommand>&, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
+ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp, Vector<WebCore::KeypressCommand>&& commands);
#elif PLATFORM(GTK)
WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&, Vector<String>&& commands, bool isKeypad, OptionSet<Modifier>, WallTime timestamp);
+ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp, Vector<String>&& commands);
#elif PLATFORM(IOS_FAMILY)
WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
#elif USE(LIBWPE)
WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&, bool isKeypad, OptionSet<Modifier>, WallTime timestamp);
+ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
#else
WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
+ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
#endif
const String& text() const { return m_text; }
@@ -301,7 +306,7 @@ private:
int32_t m_nativeVirtualKeyCode;
int32_t m_macCharCode;
#if USE(APPKIT) || USE(UIKIT_KEYBOARD_ADDITIONS) || PLATFORM(GTK) || USE(LIBWPE)
- bool m_handledByInputMethod;
+ bool m_handledByInputMethod = false;
#endif
#if PLATFORM(GTK) || USE(LIBWPE)
Optional<Vector<WebCore::CompositionUnderline>> m_preeditUnderlines;
diff --git a/Source/WebKit/Shared/WebKeyboardEvent.cpp b/Source/WebKit/Shared/WebKeyboardEvent.cpp
index cccb560418f32fad40587ac083b95f398eb1399d..f6b0aee44e5f12055dd14ad0636d780d2d4ece5d 100644
--- a/Source/WebKit/Shared/WebKeyboardEvent.cpp
+++ b/Source/WebKit/Shared/WebKeyboardEvent.cpp
@@ -35,6 +35,7 @@ WebKeyboardEvent::WebKeyboardEvent()
{
}
+
#if USE(APPKIT)
WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, const Vector<WebCore::KeypressCommand>& commands, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
@@ -56,6 +57,24 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String&
ASSERT(isKeyboardEventType(type));
}
+WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp, Vector<WebCore::KeypressCommand>&& commands)
+ : WebEvent(type, modifiers, timestamp)
+ , m_text(text)
+ , m_unmodifiedText(text)
+ , m_key(key)
+ , m_code(code)
+ , m_keyIdentifier(keyIdentifier)
+ , m_windowsVirtualKeyCode(windowsVirtualKeyCode)
+ , m_nativeVirtualKeyCode(nativeVirtualKeyCode)
+ , m_macCharCode(0)
+ , m_commands(WTFMove(commands))
+ , m_isAutoRepeat(isAutoRepeat)
+ , m_isKeypad(isKeypad)
+ , m_isSystemKey(isSystemKey)
+{
+ ASSERT(isKeyboardEventType(type));
+}
+
#elif PLATFORM(GTK)
WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&& preeditUnderlines, Optional<EditingRange>&& preeditSelectionRange, Vector<String>&& commands, bool isKeypad, OptionSet<Modifier> modifiers, WallTime timestamp)
@@ -79,6 +98,24 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String&
ASSERT(isKeyboardEventType(type));
}
+WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp, Vector<String>&& commands)
+ : WebEvent(type, modifiers, timestamp)
+ , m_text(text)
+ , m_unmodifiedText(text)
+ , m_key(key)
+ , m_code(code)
+ , m_keyIdentifier(keyIdentifier)
+ , m_windowsVirtualKeyCode(windowsVirtualKeyCode)
+ , m_nativeVirtualKeyCode(nativeVirtualKeyCode)
+ , m_macCharCode(0)
+ , m_commands(WTFMove(commands))
+ , m_isAutoRepeat(isAutoRepeat)
+ , m_isKeypad(isKeypad)
+ , m_isSystemKey(isSystemKey)
+{
+ ASSERT(isKeyboardEventType(type));
+}
+
#elif PLATFORM(IOS_FAMILY)
WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
@@ -144,6 +181,27 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String&
#endif
+#if PLATFORM(WIN) || USE(LIBWPE)
+
+WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
+ : WebEvent(type, modifiers, timestamp)
+ , m_text(text)
+ , m_unmodifiedText(text)
+ , m_key(key)
+ , m_code(code)
+ , m_keyIdentifier(keyIdentifier)
+ , m_windowsVirtualKeyCode(windowsVirtualKeyCode)
+ , m_nativeVirtualKeyCode(nativeVirtualKeyCode)
+ , m_macCharCode(0)
+ , m_isAutoRepeat(isAutoRepeat)
+ , m_isKeypad(isKeypad)
+ , m_isSystemKey(isSystemKey)
+{
+ ASSERT(isKeyboardEventType(type));
+}
+
+#endif
+
WebKeyboardEvent::~WebKeyboardEvent()
{
}
diff --git a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
index 2357f3d58415fae78e48b0f8a25bddad85c786bf..f3941a74922f5a0a3bf59a11cd4c42fbfd33d0af 100644
--- a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
+++ b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
@@ -40,7 +40,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(GdkEvent* event, const String& te
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(const NativeWebKeyboardEvent& event)
- : WebKeyboardEvent(WebEventFactory::createWebKeyboardEvent(event.nativeEvent(), event.text(), event.handledByInputMethod(), Optional<Vector<WebCore::CompositionUnderline>>(event.preeditUnderlines()), Optional<EditingRange>(event.preeditSelectionRange()), Vector<String>(event.commands())))
+ : WebKeyboardEvent(event)
, m_nativeEvent(gdk_event_copy(event.nativeEvent()))
{
}
diff --git a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
index 58e37fe3827cdb08d36ef0c85b8d4a968dee001a..429d245ea99fdee1b598a5caf51de8ce4b47fb02 100644
--- a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
+++ b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
@@ -38,8 +38,8 @@ NativeWebMouseEvent::NativeWebMouseEvent(GdkEvent* event, int eventClickCount, O
}
NativeWebMouseEvent::NativeWebMouseEvent(const NativeWebMouseEvent& event)
- : WebMouseEvent(WebEventFactory::createWebMouseEvent(event.nativeEvent(), event.clickCount(), WebCore::IntPoint(event.deltaX(), event.deltaY())))
- , m_nativeEvent(gdk_event_copy(event.nativeEvent()))
+ : WebMouseEvent(event)
+ , m_nativeEvent(event.nativeEvent() ? gdk_event_copy(event.nativeEvent()) : nullptr)
{
}
diff --git a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
index 7b5eb372880d8662544334cd4697276d543de45b..ba06ecbb2cf5088a4c8c0824b50cb7797605dc57 100644
--- a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
+++ b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "WebEvent.h"
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
#include "WebCoreArgumentCoders.h"
@@ -79,4 +79,4 @@ Optional<WebPlatformTouchPoint> 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();
}
diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt
index 74894bd27baf58951e6af241c87998bc5c5ebae8..62023de36cbe26be32fbf8f4db248bca53b15a5f 100644
--- a/Source/WebKit/Sources.txt
+++ b/Source/WebKit/Sources.txt
@@ -262,16 +262,21 @@ Shared/WebsiteData/WebsiteData.cpp
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/InspectorBrowserAgent.cpp
+UIProcess/InspectorDialogAgent.cpp
UIProcess/LegacyGlobalSettings.cpp
UIProcess/PageLoadState.cpp
UIProcess/ProcessAssertion.cpp
UIProcess/ProcessThrottler.cpp
UIProcess/ProvisionalPageProxy.cpp
+UIProcess/RemoteInspectorPipe.cpp
UIProcess/ResponsivenessTimer.cpp
UIProcess/StatisticsRequest.cpp
UIProcess/SuspendedPageProxy.cpp
@@ -309,6 +314,8 @@ UIProcess/WebOpenPanelResultListenerProxy.cpp
UIProcess/WebPageDiagnosticLoggingClient.cpp
UIProcess/WebPageGroup.cpp
UIProcess/WebPageInjectedBundleClient.cpp
+UIProcess/WebPageInspectorEmulationAgent.cpp
+UIProcess/WebPageInspectorInputAgent.cpp
UIProcess/WebPageProxy.cpp
UIProcess/WebPasteboardProxy.cpp
UIProcess/WebPreferences.cpp
diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt
index e1fc6f7372b1603e5dd25eb0a4a601c6c9be23ea..b67bad92c75c2b1d76514b820b9dfccce79d0347 100644
--- a/Source/WebKit/SourcesCocoa.txt
+++ b/Source/WebKit/SourcesCocoa.txt
@@ -247,6 +247,7 @@ UIProcess/API/Cocoa/_WKApplicationManifest.mm
UIProcess/API/Cocoa/_WKAttachment.mm
UIProcess/API/Cocoa/_WKAutomationSession.mm
UIProcess/API/Cocoa/_WKAutomationSessionConfiguration.mm
+UIProcess/API/Cocoa/_WKBrowserInspector.mm
UIProcess/API/Cocoa/_WKContentRuleListAction.mm
UIProcess/API/Cocoa/_WKContextMenuElementInfo.mm
UIProcess/API/Cocoa/_WKCustomHeaderFields.mm @no-unify
diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt
index eba34614fe0fdcee53c1edc4e940c41bbd24027c..dda27075fa5bbbbd0116b2956a7fbe03542bd588 100644
--- a/Source/WebKit/SourcesGTK.txt
+++ b/Source/WebKit/SourcesGTK.txt
@@ -130,6 +130,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify
UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify
UIProcess/API/glib/WebKitBackForwardList.cpp @no-unify
UIProcess/API/glib/WebKitBackForwardListItem.cpp @no-unify
+UIProcess/API/glib/WebKitBrowserInspector.cpp @no-unify
UIProcess/API/glib/WebKitContextMenuClient.cpp @no-unify
UIProcess/API/glib/WebKitCookieManager.cpp @no-unify
UIProcess/API/glib/WebKitCredential.cpp @no-unify
@@ -237,6 +238,7 @@ UIProcess/WebsiteData/unix/WebsiteDataStoreUnix.cpp
UIProcess/cairo/BackingStoreCairo.cpp @no-unify
+UIProcess/glib/InspectorBrowserAgentClientGLib.cpp
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
UIProcess/gtk/WebContextMenuProxyGtk.cpp
UIProcess/gtk/WebDataListSuggestionsDropdownGtk.cpp
+UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp
+UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp
UIProcess/gtk/WebPageProxyGtk.cpp @no-unify
UIProcess/gtk/WebPasteboardProxyGtk.cpp
UIProcess/gtk/WebPopupMenuProxyGtk.cpp
diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt
index 69a52e17a4a8932b5dfc5edfa72b922c18d43082..f859e07168077d10918f954cca699c4e1729cd44 100644
--- a/Source/WebKit/SourcesWPE.txt
+++ b/Source/WebKit/SourcesWPE.txt
@@ -118,6 +118,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify
UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify
UIProcess/API/glib/WebKitBackForwardList.cpp @no-unify
UIProcess/API/glib/WebKitBackForwardListItem.cpp @no-unify
+UIProcess/API/glib/WebKitBrowserInspector.cpp @no-unify
UIProcess/API/glib/WebKitContextMenuClient.cpp @no-unify
UIProcess/API/glib/WebKitCookieManager.cpp @no-unify
UIProcess/API/glib/WebKitCredential.cpp @no-unify
@@ -193,7 +194,7 @@ UIProcess/Automation/wpe/WebAutomationSessionWPE.cpp
UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
UIProcess/geoclue/GeoclueGeolocationProvider.cpp
-
+UIProcess/glib/InspectorBrowserAgentClientGLib.cpp
UIProcess/glib/WebProcessPoolGLib.cpp
UIProcess/glib/WebProcessProxyGLib.cpp
UIProcess/glib/WebsiteDataStoreGLib.cpp @no-unify
@@ -220,6 +221,10 @@ UIProcess/soup/WebProcessPoolSoup.cpp
UIProcess/wpe/WebPageProxyWPE.cpp
+UIProcess/wpe/InspectorTargetProxyWPE.cpp
+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/APIUIClient.h b/Source/WebKit/UIProcess/API/APIUIClient.h
index 54513035b261bfd5e187ec945796198ed09d88b1..2d3200e4f6e90a16f248b255f75d2a7e17d895a5 100644
--- a/Source/WebKit/UIProcess/API/APIUIClient.h
+++ b/Source/WebKit/UIProcess/API/APIUIClient.h
@@ -97,6 +97,7 @@ public:
virtual void runJavaScriptAlert(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebCore::SecurityOriginData&&, Function<void()>&& completionHandler) { completionHandler(); }
virtual void runJavaScriptConfirm(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebCore::SecurityOriginData&&, Function<void(bool)>&& completionHandler) { completionHandler(false); }
virtual void runJavaScriptPrompt(WebKit::WebPageProxy&, const WTF::String&, const WTF::String&, WebKit::WebFrameProxy*, WebCore::SecurityOriginData&&, 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 743cb854e28f51a0399d6fd1589e767fa3494f25..a6667051636cef88fb9dacc928cde16ba5215266 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..c84fe4e5249cfec5d65805868769c99200eb27da 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 "InspectorBrowserAgentClientWin.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<InspectorBrowserAgentClientWin>(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
diff --git a/Source/WebKit/UIProcess/API/C/WKPage.cpp b/Source/WebKit/UIProcess/API/C/WKPage.cpp
index d7279554675b31a64e5edc1f6f3c83db17929856..8a9b018ae491d7538566ed2771fac46b6d325f57 100644
--- a/Source/WebKit/UIProcess/API/C/WKPage.cpp
+++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp
@@ -1676,6 +1676,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)
@@ -1736,6 +1743,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient
{
if (!m_client.didNotHandleKeyEvent)
return;
+ if (!event.nativeEvent())
+ return;
m_client.didNotHandleKeyEvent(toAPI(page), event.nativeEvent(), m_client.base.clientInfo);
}
diff --git a/Source/WebKit/UIProcess/API/C/WKPageUIClient.h b/Source/WebKit/UIProcess/API/C/WKPageUIClient.h
index 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 866754212ddd7fb8288b6f721929fd2966d38a86..988f8c630e33cb0c995ff460c9d10a3dcf9fc815 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;
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
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebKit/WKFoundation.h>
+#import <WebKit/WKProcessPool.h>
+#import <WebKit/WKWebsiteDataStore.h>
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class WKWebView;
+
+WK_CLASS_AVAILABLE(macos(10.14.0))
+@interface _WKBrowserContext : NSObject
+@property (nonatomic, strong) WKWebsiteDataStore *dataStore;
+@property (nonatomic, strong) WKProcessPool *processPool;
+@end
+
+@protocol _WKBrowserInspectorDelegate <NSObject>
+- (WKWebView *)createNewPage:(uint64_t)sessionID;
+- (_WKBrowserContext *)createBrowserContext;
+- (void)deleteBrowserContext:(uint64_t)sessionID;
+- (void)quit;
+@end
+
+WK_CLASS_AVAILABLE(macos(10.14.0))
+@interface _WKBrowserInspector : NSObject
++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless;
+@end
+
+
+NS_ASSUME_NONNULL_END
+
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm
new file mode 100644
index 0000000000000000000000000000000000000000..f31834b80328fc5c182c64de53ff51e4065c62a9
--- /dev/null
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "_WKBrowserInspector.h"
+
+#include "BrowserInspectorPipe.h"
+#include "InspectorBrowserAgentClientMac.h"
+#include "PageClientImplMac.h"
+#include "WebKit2Initialize.h"
+
+#import "WKWebView.h"
+
+using namespace WebKit;
+
+@implementation _WKBrowserInspector
+
++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless
+{
+#if ENABLE(REMOTE_INSPECTOR)
+ InitializeWebKit2();
+ PageClientImpl::setHeadless(headless);
+ initializeBrowserInspectorPipe(makeUnique<InspectorBrowserAgentClientMac>(delegate));
+#endif
+}
+
+@end
+
+@implementation _WKBrowserContext
+@end
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm
index 2bdb8b9e7256f22096ebaa5d51959aa52389ca0a..2141d9d17497861a6c711f99306de10992a93ce8 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm
@@ -25,6 +25,7 @@
#import "config.h"
#import "_WKRemoteWebInspectorViewController.h"
+#import "WKWebViewPrivate.h"
#if PLATFORM(MAC)
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..70081db72e035ca99c0279ab02da5cfed9256c57
--- /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.
+ */
+
+#include "config.h"
+#include "WebKitBrowserInspector.h"
+
+#include "BrowserInspectorPipe.h"
+#include "InspectorBrowserAgentClientGLib.h"
+#include "WebKitBrowserInspectorPrivate.h"
+#include "WebKitWebViewPrivate.h"
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/WTFGType.h>
+
+/**
+ * SECTION: WebKitBrowserInspector
+ * @Short_description: Access to the WebKit browser inspector
+ * @Title: WebKitBrowserInspector
+ *
+ * The WebKit Browser Inspector is an experimental API that provides
+ * access to the inspector via the remote debugging protocol. The protocol
+ * allows to create ephemeral contexts and create pages in them and then
+ * manipulate them using the inspector commands. This may be useful for
+ * the browser automation or remote debugging.
+ *
+ * Currently the protocol can be exposed to the parent process via a unix
+ * pipe.
+ */
+
+enum {
+ CREATE_NEW_PAGE,
+
+ 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)
+{
+#if ENABLE(REMOTE_INSPECTOR)
+ WebKit::initializeBrowserInspectorPipe(makeUnique<WebKit::InspectorBrowserAgentClientGlib>(mainLoop));
+#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
--- /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.
+ */
+
+#pragma once
+
+#include "WebKitBrowserInspector.h"
+#include "WebPageProxy.h"
+
+WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext*);
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
index f769407fdc660c6f6fef77af90a43bd5dca9d544..ba010ed593bdedc0d70e4f4d3139e73d3c395463 100644
--- a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
+++ b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
@@ -91,6 +91,10 @@ private:
{
webkitWebViewRunJavaScriptPrompt(m_webView, message.utf8(), defaultValue.utf8(), WTFMove(completionHandler));
}
+ void handleJavaScriptDialog(WebPageProxy&, bool accept, const String& value) final
+ {
+ webkitWebViewHandleJavaScriptDialog(m_webView, accept, value);
+ }
bool canRunBeforeUnloadConfirmPanel() const final { return true; }
diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
index 33a9b7d5ad060f275dcf7156a8cff3f37644e736..128a5c75807848de10aed628618fc7d149a42792 100644
--- 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)
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 9633269039aed85e1993b234473509b4ecb39b79..34604cb5723f6ea0157923d2263612f1976f0b55 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*);
diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
index a68a30983f609d925b45ee16fbe34110b6cabe95..533f45fe6810509b8a0e1823087011a86510770a 100644
--- 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)
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
--- /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.
+ */
+
+#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*);
+
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit/UIProcess/API/gtk/webkit2.h b/Source/WebKit/UIProcess/API/gtk/webkit2.h
index 930b17b6629e04d0dfa2222bbc3217877c6e1812..395462e5f01c195231e9296d1204167cded99ad3 100644
--- a/Source/WebKit/UIProcess/API/gtk/webkit2.h
+++ b/Source/WebKit/UIProcess/API/gtk/webkit2.h
@@ -32,6 +32,7 @@
#include <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
--- /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.
+ */
+
+#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*);
+
+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);
}
diff --git a/Source/WebKit/UIProcess/API/wpe/webkit.h b/Source/WebKit/UIProcess/API/wpe/webkit.h
index 02e258253e47fbf6594c20f743d0faeac8a4eefe..e051fdf396dc65717def6b36168b5538e3cb2f4d 100644
--- a/Source/WebKit/UIProcess/API/wpe/webkit.h
+++ b/Source/WebKit/UIProcess/API/wpe/webkit.h
@@ -32,6 +32,7 @@
#include <wpe/WebKitAutomationSession.h>
#include <wpe/WebKitBackForwardList.h>
#include <wpe/WebKitBackForwardListItem.h>
+#include <wpe/WebKitBrowserInspector.h>
#include <wpe/WebKitContextMenu.h>
#include <wpe/WebKitContextMenuActions.h>
#include <wpe/WebKitContextMenuItem.h>
diff --git a/Source/WebKit/UIProcess/BrowserInspectorController.cpp b/Source/WebKit/UIProcess/BrowserInspectorController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5f4c95a9599141c98a1d12f4db12a5fbaf0cfcd7
--- /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.
+ */
+
+#include "config.h"
+#include "BrowserInspectorController.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorBrowserAgent.h"
+#include "InspectorBrowserAgentClient.h"
+#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<InspectorBrowserAgentClient> client)
+ : 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<InspectorBrowserAgent>(m_frontendRouter, m_backendDispatcher, m_browserAgentClient.get(), *map);
+ m_browserAgent = browserAgent.get();
+ m_agents.append(WTFMove(browserAgent));
+}
+
+BrowserInspectorController::~BrowserInspectorController()
+{
+ if (m_frontendChannel)
+ disconnectFrontend();
+}
+
+void BrowserInspectorController::connectFrontend(FrontendChannel& frontendChannel)
+{
+ ASSERT(!m_frontendChannel);
+ m_frontendChannel = &frontendChannel;
+ WebPageInspectorController::setObserver(this);
+
+ bool connectingFirstFrontend = !m_frontendRouter->hasFrontends();
+ m_frontendRouter->connectFrontend(frontendChannel);
+ if (connectingFirstFrontend)
+ m_agents.didCreateFrontendAndBackend(&m_frontendRouter.get(), &m_backendDispatcher.get());
+
+ connectToAllPages();
+}
+
+void BrowserInspectorController::disconnectFrontend()
+{
+ ASSERT(m_frontendChannel);
+ disconnectFromAllPages();
+
+ m_frontendRouter->disconnectFrontend(*m_frontendChannel);
+ if (!m_frontendRouter->hasFrontends())
+ m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectorDestroyed);
+
+ WebPageInspectorController::setObserver(nullptr);
+ m_frontendChannel = nullptr;
+}
+
+void BrowserInspectorController::dispatchMessageFromFrontend(const String& message)
+{
+ m_backendDispatcher->dispatch(message, BackendDispatcher::Mode::FailIfDomainIsMissing, [&](const RefPtr<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;
+ });
+}
+
+void BrowserInspectorController::connectToAllPages()
+{
+ for (auto* page : allPages())
+ connectToPage(*page);
+}
+
+void BrowserInspectorController::disconnectFromAllPages()
+{
+ for (auto it = m_pageProxyChannels.begin(); it != m_pageProxyChannels.end(); ++it)
+ it->value->disconnect();
+ m_pageProxyChannels.clear();
+}
+
+void BrowserInspectorController::connectToPage(WebPageProxy& page)
+{
+ String pageProxyID = InspectorBrowserAgent::toPageProxyIDProtocolString(page);
+ auto pageProxyChannel = makeUnique<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));
+}
+
+void BrowserInspectorController::didCreateInspectorController(WebPageProxy& page)
+{
+ ASSERT(m_frontendChannel);
+ // Auto-connect to all new pages.
+ connectToPage(page);
+ m_browserAgent->didCreateWebPageProxy(page);
+}
+
+void BrowserInspectorController::willDestroyInspectorController(WebPageProxy& page)
+{
+ m_browserAgent->willDestroyWebPageProxy(page);
+
+ String pageProxyID = InspectorBrowserAgent::toPageProxyIDProtocolString(page);
+ auto it = m_pageProxyChannels.find(pageProxyID);
+ ASSERT(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;
+}
+
+} // 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..a6ee1aaaaee4a42ec7afb409c74d3cc3d8eefcd0
--- /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.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorBrowserAgent.h"
+#include "WebPageInspectorController.h"
+#include <JavaScriptCore/InspectorAgentRegistry.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+}
+
+namespace WebKit {
+
+class InspectorBrowserAgent;
+class InspectorBrowserAgentClient;
+
+class BrowserInspectorController : private WebPageInspectorControllerObserver, private PageProxyIDMap {
+ WTF_MAKE_NONCOPYABLE(BrowserInspectorController);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ BrowserInspectorController(std::unique_ptr<InspectorBrowserAgentClient> client);
+ ~BrowserInspectorController();
+
+ void connectFrontend(Inspector::FrontendChannel&);
+ void disconnectFrontend();
+ void dispatchMessageFromFrontend(const String& message);
+
+private:
+ class TargetHandler;
+ class PageProxyChannel;
+
+ // WebPageInspectorControllerObserver
+ void didCreateInspectorController(WebPageProxy&) override;
+ void willDestroyInspectorController(WebPageProxy&) override;
+ void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error) override;
+
+ // PageProxyIDMap
+ WebPageProxy* findPageProxy(const String& pageProxyID) override;
+
+ void connectToAllPages();
+ void disconnectFromAllPages();
+ void connectToPage(WebPageProxy&);
+
+ Inspector::FrontendChannel* m_frontendChannel { nullptr };
+ Ref<Inspector::FrontendRouter> m_frontendRouter;
+ Ref<Inspector::BackendDispatcher> m_backendDispatcher;
+ std::unique_ptr<InspectorBrowserAgentClient> m_browserAgentClient;
+ Inspector::AgentRegistry m_agents;
+ InspectorBrowserAgent* m_browserAgent { nullptr };
+ HashMap<String, std::unique_ptr<PageProxyChannel>> m_pageProxyChannels;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ff2aa2f85ece80f9bf029ca7b54cc42835a253c7
--- /dev/null
+++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BrowserInspectorPipe.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "BrowserInspectorController.h"
+#include "RemoteInspectorPipe.h"
+#include <wtf/NeverDestroyed.h>
+#include "InspectorBrowserAgentClient.h"
+
+namespace WebKit {
+
+void initializeBrowserInspectorPipe(std::unique_ptr<InspectorBrowserAgentClient> client)
+{
+ class BrowserInspectorPipe {
+ public:
+ BrowserInspectorPipe(std::unique_ptr<InspectorBrowserAgentClient> client)
+ : 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..7dd8ee18d2310935db1a9cb6cbc48b7fb4e24f47
--- /dev/null
+++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+namespace WebKit {
+
+class InspectorBrowserAgentClient;
+
+void initializeBrowserInspectorPipe(std::unique_ptr<InspectorBrowserAgentClient> client);
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h
index 454c61ffdefecc476d1560c7c43f5b5d345f281d..6de7509037b7683ddd403ee247bdf2845ce4e87a 100644
--- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h
+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h
@@ -27,6 +27,8 @@
#if HAVE(APP_SSO)
+#include <wtf/Forward.h>
+#include <wtf/CompletionHandler.h>
#include "SOAuthorizationSession.h"
#include <wtf/CompletionHandler.h>
@@ -39,6 +41,8 @@ class NavigationAction;
namespace WebKit {
+class WebPageProxy;
+
// FSM: Idle => Active => Completed
class PopUpSOAuthorizationSession final : public SOAuthorizationSession {
public:
diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm
index 0f18038de989e69a8432c85b71b6c04e931302b3..82a966779403346aed174dcfcd01a79691956d7b 100644
--- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm
+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm
@@ -29,6 +29,7 @@
#if HAVE(APP_SSO)
#import "APINavigationAction.h"
+#import "WebPageProxy.h"
#import "WKNavigationDelegatePrivate.h"
#import "WKUIDelegate.h"
#import "WKWebViewConfigurationPrivate.h"
diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h
index a3593adf44b8d34a7c461c6b29332ba96f67992b..74661155eaa1dd6a9aa6bd177564dbeee7415019 100644
--- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h
+++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h
@@ -91,6 +91,7 @@ private:
void runJavaScriptAlert(WebPageProxy&, const WTF::String&, WebFrameProxy*, WebCore::SecurityOriginData&&, Function<void()>&& completionHandler) final;
void runJavaScriptConfirm(WebPageProxy&, const WTF::String&, WebFrameProxy*, WebCore::SecurityOriginData&&, Function<void(bool)>&& completionHandler) final;
void runJavaScriptPrompt(WebPageProxy&, const WTF::String&, const WTF::String&, WebFrameProxy*, WebCore::SecurityOriginData&&, 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&, API::SecurityOrigin&, Function<void(bool)>&) final;
@@ -171,6 +172,7 @@ private:
bool webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler : 1;
bool webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler : 1;
bool webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler : 1;
+ bool webViewHandleJavaScriptDialogValue : 1;
bool webViewRequestStorageAccessPanelUnderFirstPartyCompletionHandler : 1;
bool webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler : 1;
bool webViewRequestGeolocationPermissionForFrameDecisionHandler : 1;
diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
index a3d0ded6df0566cb74493f98ec28bce0e8d893b3..a4d9a214407eb2c55c07a10b700abbb268768909 100644
--- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
+++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
@@ -104,6 +104,7 @@ void UIDelegate::setDelegate(id <WKUIDelegate> delegate)
m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)];
m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)];
+ m_delegateMethods.webViewHandleJavaScriptDialogValue = [delegate respondsToSelector:@selector(webView:handleJavaScriptDialog:value:)];
m_delegateMethods.webViewRequestStorageAccessPanelUnderFirstPartyCompletionHandler = [delegate respondsToSelector:@selector(_webView:requestStorageAccessPanelForDomain:underCurrentDomain:completionHandler:)];
m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
m_delegateMethods.webViewRequestGeolocationPermissionForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestGeolocationPermissionForFrame:decisionHandler:)];
@@ -341,6 +342,15 @@ void UIDelegate::UIClient::runJavaScriptPrompt(WebPageProxy&, const WTF::String&
}).get()];
}
+void UIDelegate::UIClient::handleJavaScriptDialog(WebKit::WebPageProxy&, bool accept, const WTF::String& value) {
+ if (!m_uiDelegate.m_delegateMethods.webViewHandleJavaScriptDialogValue)
+ return;
+ auto delegate = m_uiDelegate.m_delegate.get();
+ if (!delegate)
+ return;
+ [delegate webView:m_uiDelegate.m_webView handleJavaScriptDialog:accept value:value];
+}
+
void UIDelegate::UIClient::requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler<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 f154a4e6fdfbe1dbcb23f07d329c7ae22bebd7f6..2a6ce63aa57d7a970cf5a8160e072d0dc9c24b82 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
+++ b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
@@ -130,6 +130,13 @@ static void registerUserDefaultsIfNeeded()
[[NSUserDefaults standardUserDefaults] registerDefaults:registrationDictionary];
}
+void WebProcessPool::setIgnoreTLSErrors(bool ignoreTLSErrors)
+{
+ m_ignoreTLSErrors = ignoreTLSErrors;
+ if (m_networkProcess)
+ m_networkProcess->send(Messages::NetworkProcess::SetIgnoreTLSErrors(m_ignoreTLSErrors), 0);
+}
+
void WebProcessPool::updateProcessSuppressionState()
{
if (m_networkProcess)
@@ -385,6 +392,8 @@ void WebProcessPool::platformInitializeNetworkProcess(NetworkProcessCreationPara
}
}
+ parameters.ignoreTLSErrors = m_ignoreTLSErrors;
+
parameters.networkATSContext = adoptCF(_CFNetworkCopyATSContext());
parameters.shouldSuppressMemoryPressureHandler = [defaults boolForKey:WebKitSuppressMemoryPressureHandlerDefaultsKey];
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/DrawingAreaProxy.h b/Source/WebKit/UIProcess/DrawingAreaProxy.h
index 4896c404bc8b25d69360de7d1c509383282b2317..14bdebf732e929ea367c961f9d0bec85202bbae3 100644
--- a/Source/WebKit/UIProcess/DrawingAreaProxy.h
+++ b/Source/WebKit/UIProcess/DrawingAreaProxy.h
@@ -70,6 +70,7 @@ public:
const WebCore::IntSize& size() const { return m_size; }
bool setSize(const WebCore::IntSize&, const WebCore::IntSize& scrollOffset = { });
+ void waitForSizeUpdate(Function<void ()>&&);
// The timeout we use when waiting for a DidUpdateGeometry message.
static constexpr Seconds didUpdateBackingStoreStateTimeout() { return Seconds::fromMilliseconds(500); }
diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp
index 6928ca2fbfb6939062e3cd14bb7ba6f2fdc87f5f..8259a01bb98789c07f88cafd4f3af553e65d0cf9 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,9 +98,35 @@ void InspectorTargetProxy::didCommitProvisionalTarget()
m_provisionalPage = nullptr;
}
+void InspectorTargetProxy::activate(String& error)
+{
+ if (m_type != Inspector::InspectorTargetType::Page)
+ return InspectorTarget::activate(error);
+
+ platformActivate(error);
+}
+
+void InspectorTargetProxy::close(String& error, bool runBeforeUnload)
+{
+ if (m_type != Inspector::InspectorTargetType::Page)
+ return InspectorTarget::close(error, runBeforeUnload);
+
+ if (runBeforeUnload)
+ m_page.tryClose();
+ else
+ m_page.closePage();
+}
+
bool InspectorTargetProxy::isProvisional() const
{
return !!m_provisionalPage;
}
+String InspectorTargetProxy::oldTargetID() const
+{
+ if (!m_provisionalPage)
+ return String();
+ return WebPageInspectorTarget::toTargetID(m_page.webPageID());
+}
+
} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h
index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..f53bd7717be546157dfeb92b835a1df5513a716a 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; }
@@ -51,16 +51,21 @@ public:
void didCommitProvisionalTarget();
bool isProvisional() const override;
+ String oldTargetID() const override;
void connect(Inspector::FrontendChannel::ConnectionType) override;
void disconnect() override;
void sendMessageToTargetBackend(const String&) override;
+ void activate(String& error) override;
+ void close(String& error, bool runBeforeUnload) override;
private:
+ void platformActivate(String& error) const;
+
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 1ee28bf716374371433215148aa20a51927a8a33..444894102b535a957cadb41fab23f37c217f5b1c 100644
--- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
+++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
@@ -26,10 +26,16 @@
#include "config.h"
#include "WebPageInspectorController.h"
+#include "APINavigation.h"
+#include "InspectorDialogAgent.h"
#include "ProvisionalPageProxy.h"
#include "WebFrameProxy.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>
@@ -46,29 +52,90 @@ static String getTargetID(const ProvisionalPageProxy& provisionalPage)
return WebPageInspectorTarget::toTargetID(provisionalPage.webPageID());
}
+WebPageInspectorControllerObserver* WebPageInspectorController::s_observer = nullptr;
+
+void WebPageInspectorController::setObserver(WebPageInspectorControllerObserver* observer)
+{
+ s_observer = observer;
+}
+
WebPageInspectorController::WebPageInspectorController(WebPageProxy& page)
: m_page(page)
, m_frontendRouter(FrontendRouter::create())
, m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
+{
+}
+
+void WebPageInspectorController::init()
{
auto targetAgent = makeUnique<InspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
m_targetAgent = targetAgent.get();
m_agents.append(WTFMove(targetAgent));
-}
+ m_agents.append(makeUnique<WebPageInspectorEmulationAgent>(m_backendDispatcher.get(), m_page));
+ 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));
-void WebPageInspectorController::init()
-{
+ if (s_observer)
+ s_observer->didCreateInspectorController(m_page);
+
+ // window.open will create page with already running process.
+ if (!m_page.hasRunningProcess())
+ return;
String pageTargetId = WebPageInspectorTarget::toTargetID(m_page.webPageID());
createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
}
+void WebPageInspectorController::didFinishAttachingToWebProcess()
+{
+ String pageTargetID = WebPageInspectorTarget::toTargetID(m_page.webPageID());
+ // Create target only after attaching to a Web Process first time. Before that
+ // we cannot event establish frontend connection.
+ if (m_targets.contains(pageTargetID))
+ return;
+ createInspectorTarget(pageTargetID, Inspector::InspectorTargetType::Page);
+}
+
void WebPageInspectorController::pageClosed()
{
+ String pageTargetId = WebPageInspectorTarget::toTargetID(m_page.webPageID());
+ destroyInspectorTarget(pageTargetId);
+
disconnectAllFrontends();
m_agents.discardValues();
+
+ if (s_observer)
+ s_observer->willDestroyInspectorController(m_page);
+}
+
+bool WebPageInspectorController::pageCrashed(ProcessTerminationReason reason)
+{
+ if (reason != ProcessTerminationReason::Crash)
+ return false;
+ String targetId = WebPageInspectorTarget::toTargetID(m_page.webPageID());
+ auto it = m_targets.find(targetId);
+ if (it == m_targets.end())
+ return false;
+ m_targetAgent->targetCrashed(*it->value);
+ m_targets.remove(it);
+
+ return m_targetAgent->isConnected();
+}
+
+void WebPageInspectorController::didProcessAllPendingKeyboardEvents()
+{
+ if (m_frontendRouter->hasFrontends())
+ m_inputAgent->didProcessAllPendingKeyboardEvents();
+}
+
+void WebPageInspectorController::didProcessAllPendingMouseEvents()
+{
+ if (m_frontendRouter->hasFrontends())
+ m_inputAgent->didProcessAllPendingMouseEvents();
}
bool WebPageInspectorController::hasLocalFrontend() const
@@ -80,6 +147,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)
@@ -98,8 +176,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());
@@ -122,6 +202,8 @@ void WebPageInspectorController::disconnectAllFrontends()
// Disconnect any remaining remote frontends.
m_frontendRouter->disconnectAllFrontends();
+ m_pendingNavigations.clear();
+
m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
#if ENABLE(REMOTE_INSPECTOR)
@@ -134,6 +216,11 @@ void WebPageInspectorController::dispatchMessageFromFrontend(const String& messa
m_backendDispatcher->dispatch(message);
}
+bool WebPageInspectorController::dispatchMessageToTargetBackend(const String& message)
+{
+ return m_backendDispatcher->dispatch(message, BackendDispatcher::Mode::ContinueIfDomainIsMissing) == BackendDispatcher::DispatchResult::Finished;
+}
+
#if ENABLE(REMOTE_INSPECTOR)
void WebPageInspectorController::setIndicating(bool indicating)
{
@@ -148,6 +235,55 @@ void WebPageInspectorController::setIndicating(bool indicating)
}
#endif
+void WebPageInspectorController::navigate(WebCore::ResourceRequest&& request, WebFrameProxy* frame, NavigationHandler&& completionHandler)
+{
+ auto navigation = m_page.loadRequestForInspector(WTFMove(request), frame);
+ if (!navigation) {
+ completionHandler("Failed to navigate"_s, 0);
+ return;
+ }
+
+ m_pendingNavigations.set(navigation->navigationID(), WTFMove(completionHandler));
+}
+
+void WebPageInspectorController::didReceivePolicyDecision(WebCore::PolicyAction action, uint64_t navigationID)
+{
+ if (!m_frontendRouter->hasFrontends())
+ return;
+
+ if (!navigationID)
+ return;
+
+ auto completionHandler = m_pendingNavigations.take(navigationID);
+ if (!completionHandler)
+ return;
+
+ if (action == WebCore::PolicyAction::Ignore)
+ completionHandler("Navigation cancelled"_s, 0);
+ else
+ completionHandler(String(), navigationID);
+}
+
+void WebPageInspectorController::didDestroyNavigation(uint64_t navigationID)
+{
+ if (!m_frontendRouter->hasFrontends())
+ return;
+
+ auto completionHandler = m_pendingNavigations.take(navigationID);
+ if (!completionHandler)
+ return;
+
+ // Inspector initiated navigation is destroyed before policy check only when it
+ // becomes a fragment navigation (which always reuses current navigation).
+ completionHandler(String(), 0);
+}
+
+void WebPageInspectorController::didFailProvisionalLoadForFrame(uint64_t navigationID, const WebCore::ResourceError& error)
+{
+ if (s_observer)
+ s_observer->didFailProvisionalLoad(m_page, navigationID, error.localizedDescription());
+}
+
void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
{
addTarget(InspectorTargetProxy::create(m_page, targetId, type));
@@ -167,6 +303,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())
@@ -186,7 +349,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)
@@ -218,4 +381,16 @@ 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);
+}
+
} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
index 78caedf0c0ce83675569502d150fcc44e5f9868c..46b9901263286eab6de0bc4f899349d56b1efb33 100644
--- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
+++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
@@ -26,6 +26,7 @@
#pragma once
#include "InspectorTargetProxy.h"
+#include "ProcessTerminationReason.h"
#include <JavaScriptCore/InspectorAgentRegistry.h>
#include <JavaScriptCore/InspectorTargetAgent.h>
#include <WebCore/PageIdentifier.h>
@@ -37,10 +38,30 @@ namespace Inspector {
class BackendDispatcher;
class FrontendChannel;
class FrontendRouter;
+class InspectorTarget;
+}
+
+namespace WebCore {
+class ResourceError;
+class ResourceRequest;
+enum class PolicyAction : uint8_t;
}
namespace WebKit {
+class WebFrameProxy;
+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;
@@ -48,7 +69,15 @@ public:
WebPageInspectorController(WebPageProxy&);
void init();
+ void didFinishAttachingToWebProcess();
+
+ static void setObserver(WebPageInspectorControllerObserver*);
+
void pageClosed();
+ bool pageCrashed(ProcessTerminationReason);
+
+ void didProcessAllPendingKeyboardEvents();
+ void didProcessAllPendingMouseEvents();
bool hasLocalFrontend() const;
@@ -57,15 +86,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()>&&);
@@ -75,13 +117,18 @@ public:
private:
void addTarget(std::unique_ptr<InspectorTargetProxy>&&);
+ void adjustPageSettings();
WebPageProxy& m_page;
Ref<Inspector::FrontendRouter> m_frontendRouter;
Ref<Inspector::BackendDispatcher> m_backendDispatcher;
Inspector::AgentRegistry m_agents;
- Inspector::InspectorTargetAgent* m_targetAgent;
+ Inspector::InspectorTargetAgent* m_targetAgent { nullptr };
+ WebPageInspectorInputAgent* m_inputAgent { nullptr };
HashMap<String, std::unique_ptr<InspectorTargetProxy>> m_targets;
+ HashMap<uint64_t, NavigationHandler> m_pendingNavigations;
+
+ static WebPageInspectorControllerObserver* s_observer;
};
} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/InspectorBrowserAgent.cpp b/Source/WebKit/UIProcess/InspectorBrowserAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78daef3868dc0036bdd612c8c3cc6ba8fb033af2
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorBrowserAgent.cpp
@@ -0,0 +1,516 @@
+/*
+ * 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 "InspectorBrowserAgent.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "APIPageConfiguration.h"
+#include "InspectorBrowserAgentClient.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>
+
+
+using namespace Inspector;
+
+namespace WebKit {
+
+namespace {
+
+Inspector::Protocol::Browser::CookieSameSitePolicy cookieSameSitePolicy(WebCore::Cookie::SameSitePolicy policy)
+{
+ switch (policy) {
+ case WebCore::Cookie::SameSitePolicy::None:
+ return Inspector::Protocol::Browser::CookieSameSitePolicy::None;
+ case WebCore::Cookie::SameSitePolicy::Lax:
+ return Inspector::Protocol::Browser::CookieSameSitePolicy::Lax;
+ case WebCore::Cookie::SameSitePolicy::Strict:
+ return Inspector::Protocol::Browser::CookieSameSitePolicy::Strict;
+ }
+ ASSERT_NOT_REACHED();
+ return Inspector::Protocol::Browser::CookieSameSitePolicy::None;
+}
+
+Ref<Inspector::Protocol::Browser::Cookie> buildObjectForCookie(const WebCore::Cookie& cookie)
+{
+ return Inspector::Protocol::Browser::Cookie::create()
+ .setName(cookie.name)
+ .setValue(cookie.value)
+ .setDomain(cookie.domain)
+ .setPath(cookie.path)
+ .setExpires(cookie.expires)
+ .setHttpOnly(cookie.httpOnly)
+ .setSecure(cookie.secure)
+ .setSession(cookie.session)
+ .setSameSite(cookieSameSitePolicy(cookie.sameSite))
+ .release();
+}
+
+Ref<Inspector::Protocol::Browser::PageProxyInfo> buildPageProxyInfo(const WebPageProxy& page) {
+ auto result = Inspector::Protocol::Browser::PageProxyInfo::create()
+ .setPageProxyId(InspectorBrowserAgent::toPageProxyIDProtocolString(page))
+ .setBrowserContextId(InspectorBrowserAgent::toBrowserContextIDProtocolString(page.sessionID()))
+ .release();
+ auto* opener = page.configuration().relatedPage();
+ if (opener)
+ result->setOpenerId(InspectorBrowserAgent::toPageProxyIDProtocolString(*opener));
+ return result;
+}
+
+} // namespace
+
+InspectorBrowserAgent::InspectorBrowserAgent(Inspector::FrontendRouter& frontendRouter, Inspector::BackendDispatcher& backendDispatcher, InspectorBrowserAgentClient* client, PageProxyIDMap& pageProxyIDMap)
+ : InspectorAgentBase("Browser"_s)
+ , m_frontendDispatcher(makeUnique<BrowserFrontendDispatcher>(frontendRouter))
+ , m_backendDispatcher(BrowserBackendDispatcher::create(backendDispatcher, this))
+ , m_client(client)
+ , m_pageProxyIDMap(pageProxyIDMap)
+{
+}
+
+InspectorBrowserAgent::~InspectorBrowserAgent() = default;
+
+void InspectorBrowserAgent::didCreateWebPageProxy(const WebPageProxy& page)
+{
+ if (m_isConnected)
+ m_frontendDispatcher->pageProxyCreated(buildPageProxyInfo(page));
+}
+
+void InspectorBrowserAgent::willDestroyWebPageProxy(const WebPageProxy& page)
+{
+ if (m_isConnected)
+ m_frontendDispatcher->pageProxyDestroyed(toPageProxyIDProtocolString(page));
+}
+
+void InspectorBrowserAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
+{
+ m_isConnected = true;
+}
+
+void InspectorBrowserAgent::didFailProvisionalLoad(WebPageProxy& page, uint64_t navigationID, const String& error)
+{
+ if (!m_isConnected)
+ return;
+
+ m_frontendDispatcher->provisionalLoadFailed(toPageProxyIDProtocolString(page), String::number(navigationID), error);
+}
+
+void InspectorBrowserAgent::willDestroyFrontendAndBackend(DisconnectReason)
+{
+ m_isConnected = false;
+}
+
+void InspectorBrowserAgent::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();
+
+ 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 InspectorBrowserAgent::createContext(ErrorString& errorString, String* browserContextID)
+{
+ BrowserContext browserContext = m_client->createBrowserContext(errorString);
+ if (!errorString.isEmpty())
+ return;
+ browserContext.processPool->setPrimaryDataStore(*browserContext.dataStore);
+ browserContext.processPool->ensureNetworkProcess(browserContext.dataStore.get());
+ PAL::SessionID sessionID = browserContext.dataStore->sessionID();
+ *browserContextID = toBrowserContextIDProtocolString(sessionID);
+ m_browserContexts.set(*browserContextID, browserContext);
+}
+
+void InspectorBrowserAgent::deleteContext(ErrorString& errorString, const String& browserContextID)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, &browserContextID);
+ if (!errorString.isEmpty())
+ return;
+
+ Vector<WebPageProxy*> pages;
+ for (auto& process : browserContext.processPool->processes()) {
+ for (auto* page : process->pages())
+ pages.append(page);
+ }
+
+ for (auto* page : pages)
+ page->closePage();
+
+ PAL::SessionID sessionID = browserContext.dataStore->sessionID();
+ m_client->deleteBrowserContext(errorString, sessionID);
+ m_browserContexts.remove(browserContextID);
+}
+
+void InspectorBrowserAgent::createPage(ErrorString& errorString, const String* browserContextID, String* pageProxyID)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return;
+ RefPtr<WebPageProxy> page = m_client->createPage(errorString, browserContext);
+ if (!page)
+ return;
+ page->setPermissionsForAutomation(m_permissions.get(browserContextID ? *browserContextID : ""));
+ *pageProxyID = toPageProxyIDProtocolString(*page);
+}
+
+WebFrameProxy* InspectorBrowserAgent::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 InspectorBrowserAgent::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 InspectorBrowserAgent::setIgnoreCertificateErrors(Inspector::ErrorString& errorString, const String* browserContextID, bool ignore)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return;
+ browserContext.processPool->setIgnoreTLSErrors(ignore);
+}
+
+void InspectorBrowserAgent::getAllCookies(const String* browserContextID, Ref<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::Browser::Cookie>::create();
+ for (const auto& cookie : allCookies)
+ cookies->addItem(buildObjectForCookie(cookie));
+ callback->sendSuccess(WTFMove(cookies));
+ }, 0);
+}
+
+void InspectorBrowserAgent::setCookies(const String* browserContextID, const JSON::Array& in_cookies, Ref<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;
+ }
+
+ obj->getDouble("expires", cookie.expires);
+ obj->getBoolean("httpOnly", cookie.httpOnly);
+ obj->getBoolean("secure", cookie.secure);
+ obj->getBoolean("session", cookie.session);
+ String sameSite;
+ if (obj->getString("sameSite", sameSite)) {
+ if (sameSite == "None")
+ cookie.sameSite = WebCore::Cookie::SameSitePolicy::None;
+ if (sameSite == "Lax")
+ cookie.sameSite = WebCore::Cookie::SameSitePolicy::Lax;
+ if (sameSite == "Strict")
+ cookie.sameSite = WebCore::Cookie::SameSitePolicy::Strict;
+ }
+ cookies.append(WTFMove(cookie));
+ }
+
+ networkProcess->sendWithAsyncReply(Messages::NetworkProcess::SetCookies(sessionID, WTFMove(cookies)),
+ [callback = WTFMove(callback)](bool success) {
+ if (!callback->isActive())
+ return;
+
+ if (success)
+ callback->sendSuccess();
+ else
+ callback->sendFailure("Internal error: no network storage"_s);
+ callback->sendSuccess();
+ }, 0);
+}
+
+void InspectorBrowserAgent::deleteAllCookies(const String* browserContextID, Ref<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 InspectorBrowserAgent::grantPermissions(Inspector::ErrorString& errorString, const String* browserContextID, const String& origin, const JSON::Array& values)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return;
+ HashSet<String> set;
+ for (const auto& value : values) {
+ String name;
+ if (!value->asString(name)) {
+ errorString = "Permission must be a string"_s;
+ return;
+ }
+ set.add(name);
+ }
+ String key = browserContextID ? *browserContextID : "";
+ auto it = m_permissions.add(key, Permissions()).iterator;
+ it->value.set(origin, WTFMove(set));
+ Vector<WebPageProxy*> pages;
+ for (auto& process : browserContext.processPool->processes()) {
+ for (auto* page : process->pages())
+ page->setPermissionsForAutomation(it->value);
+ }
+}
+
+void InspectorBrowserAgent::resetPermissions(Inspector::ErrorString& errorString, const String* browserContextID)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return;
+ m_permissions.clear();
+ for (auto& process : browserContext.processPool->processes()) {
+ for (auto* page : process->pages())
+ page->setPermissionsForAutomation(HashMap<String, HashSet<String>>());
+ }
+}
+
+void InspectorBrowserAgent::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.processPool->setLanguagesForAutomation(WTFMove(items));
+}
+
+void InspectorBrowserAgent::setGeolocationOverride(Inspector::ErrorString& errorString, const String* browserContextID, const JSON::Object* geolocation)
+{
+ BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
+ if (!errorString.isEmpty())
+ return;
+ auto* geoManager = browserContext.processPool->supplement<WebGeolocationManagerProxy>();
+ if (!geoManager) {
+ errorString = "Internal error: geolocation manager is not available.";
+ return;
+ }
+ if (geolocation) {
+ double timestamp = 0;
+ double latitude = 0;
+ double longitude = 0;
+ double accuracy = 0;
+ if (!geolocation->getDouble("timestamp", timestamp) ||
+ !geolocation->getDouble("latitude", latitude) ||
+ !geolocation->getDouble("longitude", longitude) ||
+ !geolocation->getDouble("accuracy", accuracy)) {
+ errorString = "Invalid geolocation format"_s;
+ return;
+ }
+ auto position = WebGeolocationPosition::create(WebCore::GeolocationPositionData(timestamp, latitude, longitude, accuracy));
+ geoManager->providerDidChangePosition(&position.get());
+ } else {
+ geoManager->providerDidFailToDeterminePosition("Position unavailable"_s);
+ }
+}
+
+String InspectorBrowserAgent::toBrowserContextIDProtocolString(const PAL::SessionID& sessionID)
+{
+ StringBuilder builder;
+ builder.append(hex(sessionID.toUInt64(), 16));
+ return builder.toString();
+}
+
+String InspectorBrowserAgent::toPageProxyIDProtocolString(const WebPageProxy& page)
+{
+ return makeString(page.identifier().toUInt64());
+}
+
+BrowserContext InspectorBrowserAgent::lookupBrowserContext(ErrorString& errorString, const String* browserContextID)
+{
+ if (!browserContextID) {
+ auto* pool = WebProcessPool::allProcessPools().first();
+ BrowserContext context;
+ 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/InspectorBrowserAgent.h b/Source/WebKit/UIProcess/InspectorBrowserAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..ad8f3d99f45fa6284738c62fe813330b2c208c92
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorBrowserAgent.h
@@ -0,0 +1,114 @@
+/*
+ * 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 "InspectorBrowserAgentClient.h"
+#include <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+#include <wtf/HashMap.h>
+#include <pal/SessionID.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class BrowserFrontendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+}
+
+namespace PAL {
+class SessionID;
+}
+
+namespace WebKit {
+
+class NetworkProcess;
+class WebFrameProxy;
+class WebProcessPool;
+
+class PageProxyIDMap {
+public:
+ virtual WebPageProxy* findPageProxy(const String& pageProxyID) = 0;
+
+protected:
+ virtual ~PageProxyIDMap() = default;
+};
+
+class InspectorBrowserAgent final : public Inspector::InspectorAgentBase, public Inspector::BrowserBackendDispatcherHandler {
+ WTF_MAKE_NONCOPYABLE(InspectorBrowserAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorBrowserAgent(Inspector::FrontendRouter&, Inspector::BackendDispatcher&, InspectorBrowserAgentClient*, PageProxyIDMap&);
+ ~InspectorBrowserAgent() 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;
+
+ // BrowserBackendDispatcherHandler
+ void close(Ref<CloseCallback>&&) override;
+ void createContext(Inspector::ErrorString&, String* browserContextID) override;
+ void deleteContext(Inspector::ErrorString&, const String& browserContextID) 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 grantPermissions(Inspector::ErrorString&, const String* browserContextID, const String& origin, const JSON::Array& permissions) override;
+ void resetPermissions(Inspector::ErrorString&, const String* browserContextID) override;
+ void setGeolocationOverride(Inspector::ErrorString&, const String* browserContextID, const JSON::Object* geolocation) override;
+ void setLanguages(Inspector::ErrorString&, const JSON::Array& languages, const String* browserContextID) override;
+
+ static String toBrowserContextIDProtocolString(const PAL::SessionID&);
+ static String toPageProxyIDProtocolString(const WebPageProxy&);
+
+private:
+ BrowserContext lookupBrowserContext(Inspector::ErrorString&, const String* browserContextID);
+ WebFrameProxy* frameForID(const String& frameID, String& error);
+
+ std::unique_ptr<Inspector::BrowserFrontendDispatcher> m_frontendDispatcher;
+ Ref<Inspector::BrowserBackendDispatcher> m_backendDispatcher;
+ InspectorBrowserAgentClient* m_client;
+ PageProxyIDMap& m_pageProxyIDMap;
+ using Permissions = HashMap<String, HashSet<String>>;
+ HashMap<String, Permissions> m_permissions;
+ HashMap<String, BrowserContext> m_browserContexts;
+ bool m_isConnected { false };
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/InspectorBrowserAgentClient.h b/Source/WebKit/UIProcess/InspectorBrowserAgentClient.h
new file mode 100644
index 0000000000000000000000000000000000000000..21f8cc9bffd8f2d4a88764a4eafa13f367aa1e7c
--- /dev/null
+++ b/Source/WebKit/UIProcess/InspectorBrowserAgentClient.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 <pal/SessionID.h>
+#include <wtf/Forward.h>
+
+namespace WebKit {
+
+class WebsiteDataStore;
+class WebPageProxy;
+class WebProcessPool;
+
+struct BrowserContext {
+ RefPtr<WebsiteDataStore> dataStore;
+ RefPtr<WebProcessPool> processPool;
+};
+
+class InspectorBrowserAgentClient {
+public:
+ virtual ~InspectorBrowserAgentClient() = 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
+
+#endif // ENABLE(REMOTE_INSPECTOR)
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 {
+
+class NativeWebKeyboardEvent;
+class WebPageProxy;
+
+class InspectorDialogAgent : public Inspector::InspectorAgentBase, public Inspector::DialogBackendDispatcherHandler {
+ WTF_MAKE_NONCOPYABLE(InspectorDialogAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorDialogAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page);
+ ~InspectorDialogAgent() override;
+
+ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+ void enable(Inspector::ErrorString&) override;
+ void disable(Inspector::ErrorString&) override;
+ void handleJavaScriptDialog(Inspector::ErrorString& errorString, bool accept, const String* promptText) override;
+
+ void javascriptDialogOpening(const String& type, const String& message, const String* defaultValue = nullptr);
+
+private:
+ void platformHandleJavaScriptDialog(bool accept, const String* promptText);
+ std::unique_ptr<Inspector::DialogFrontendDispatcher> m_frontendDispatcher;
+ Ref<Inspector::DialogBackendDispatcher> m_backendDispatcher;
+ WebPageProxy& m_page;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp
index 8a871bf2916d5eab86becf5fde0faed79283d88c..a19a429c4d53edf81c3028c7053265e6c22c171a 100644
--- a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp
+++ b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp
@@ -92,8 +92,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..6d19c534e58e35ec2012a36238e25a78706f2786
--- /dev/null
+++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RemoteInspectorPipe.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "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)
+{
+ size_t bytesRead = 0;
+ while (bytesRead < size) {
+#if PLATFORM(WIN)
+ DWORD sizeRead = 0;
+ bool hadError = !ReadFile(readHandle, static_cast<char*>(buffer) + bytesRead,
+ size - bytesRead, &sizeRead, nullptr);
+#else
+ int sizeRead = read(readFD, static_cast<char*>(buffer) + bytesRead,
+ size - bytesRead);
+ if (sizeRead < 0 && errno == EINTR)
+ continue;
+ bool hadError = sizeRead <= 0;
+#endif
+ if (hadError) {
+ return 0;
+ }
+ bytesRead += sizeRead;
+ if (!exact_size)
+ break;
+ }
+ return bytesRead;
+}
+
+void WriteBytes(const char* bytes, size_t size)
+{
+ size_t totalWritten = 0;
+ while (totalWritten < size) {
+ size_t length = size - totalWritten;
+ if (length > kWritePacketSize)
+ length = kWritePacketSize;
+#if PLATFORM(WIN)
+ DWORD bytesWritten = 0;
+ bool hadError = !WriteFile(writeHandle, bytes + totalWritten, static_cast<DWORD>(length), &bytesWritten, nullptr);
+#else
+ int bytesWritten = write(writeFD, bytes + totalWritten, length);
+ if (bytesWritten < 0 && errno == EINTR)
+ continue;
+ bool hadError = bytesWritten <= 0;
+#endif
+ if (hadError)
+ return;
+ totalWritten += bytesWritten;
+ }
+}
+
+} // namespace
+
+class RemoteInspectorPipe::RemoteFrontendChannel : public Inspector::FrontendChannel {
+ WTF_MAKE_FAST_ALLOCATED;
+
+public:
+ RemoteFrontendChannel()
+ : m_senderQueue(WorkQueue::create("Inspector pipe writer"))
+ {
+ }
+
+ ~RemoteFrontendChannel() override = default;
+
+ ConnectionType connectionType() const override
+ {
+ return ConnectionType::Remote;
+ }
+
+ void sendMessageToFrontend(const String& message) override
+ {
+ m_senderQueue->dispatch([message = message.isolatedCopy()]() {
+ WriteBytes(message.ascii().data(), message.length());
+ WriteBytes("\0", 1);
+ });
+ }
+
+private:
+ Ref<WorkQueue> m_senderQueue;
+};
+
+RemoteInspectorPipe::RemoteInspectorPipe(BrowserInspectorController& browserInspectorController)
+ : m_remoteFrontendChannel(makeUnique<RemoteFrontendChannel>())
+ , m_browserInspectorController(browserInspectorController)
+{
+ start();
+}
+
+RemoteInspectorPipe::~RemoteInspectorPipe()
+{
+ stop();
+}
+
+bool RemoteInspectorPipe::start()
+{
+ if (m_receiverThread)
+ return true;
+
+#if PLATFORM(WIN)
+ readHandle = reinterpret_cast<HANDLE>(_get_osfhandle(readFD));
+ writeHandle = reinterpret_cast<HANDLE>(_get_osfhandle(writeFD));
+#endif
+
+ m_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()
+{
+ fprintf(stdout, "\nWeb Inspector is reading from pipe #3\n\n");
+ fflush(stdout);
+
+ 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 {
+
+class BrowserInspectorController;
+
+class RemoteInspectorPipe {
+ WTF_MAKE_NONCOPYABLE(RemoteInspectorPipe);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ explicit RemoteInspectorPipe(BrowserInspectorController&);
+ ~RemoteInspectorPipe();
+
+private:
+ class RemoteFrontendChannel;
+
+ bool start();
+ void stop();
+
+ void workerRun();
+
+ RefPtr<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 73626cc05027ae6e21b28143bc8009b92b1a75b4..52516a7f781c1a39376f9f78ab2f4749025bd34f 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>
diff --git a/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp b/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp
index 04f3227cd55c992a42cd96a3f25d697aed7965a2..f0d36935f47bab03ea2ec50b705092068ecd3efa 100644
--- a/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp
+++ b/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp
@@ -128,7 +128,8 @@ void WebGeolocationManagerProxy::startUpdating(IPC::Connection& connection, WebP
if (!wasUpdating) {
m_provider->setEnableHighAccuracy(*this, isHighAccuracyEnabled());
m_provider->startUpdating(*this);
- } else if (m_lastPosition)
+ }
+ if (m_lastPosition)
connection.send(Messages::WebGeolocationManager::DidChangePosition(m_lastPosition.value()), 0);
}
diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..466d5129363e8b3d2e7cfc10f2a1ac7ae77f634f
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebPageInspectorEmulationAgent.h"
+
+#include "WebPageProxy.h"
+#include "WebPreferences.h"
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <WebCore/Credential.h>
+
+
+namespace WebKit {
+
+using namespace Inspector;
+
+WebPageInspectorEmulationAgent::WebPageInspectorEmulationAgent(BackendDispatcher& backendDispatcher, WebPageProxy& page)
+ : InspectorAgentBase("Emulation"_s)
+ , m_backendDispatcher(EmulationBackendDispatcher::create(backendDispatcher, this))
+ , m_page(page)
+{
+}
+
+WebPageInspectorEmulationAgent::~WebPageInspectorEmulationAgent()
+{
+}
+
+void WebPageInspectorEmulationAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
+{
+}
+
+void WebPageInspectorEmulationAgent::willDestroyFrontendAndBackend(DisconnectReason)
+{
+}
+
+void WebPageInspectorEmulationAgent::setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref<SetDeviceMetricsOverrideCallback>&& callback)
+{
+#if PLATFORM(GTK)
+ // On gtk, fixed layout doesn't work with compositing enabled
+ // FIXME: This turns off compositing forever, even if fixedLayout is disabled.
+ if (fixedlayout) {
+ auto copy = m_page.preferences().copy();
+ copy->setAcceleratedCompositingEnabled(false);
+ m_page.setPreferences(copy);
+ }
+#endif
+
+ m_page.setCustomDeviceScaleFactor(deviceScaleFactor);
+ m_page.setUseFixedLayout(fixedlayout);
+ platformSetSize(width, height, [callback = WTFMove(callback)](const String& error) {
+ if (error.isEmpty())
+ callback->sendSuccess();
+ else
+ callback->sendFailure(error);
+ });
+}
+
+void WebPageInspectorEmulationAgent::setJavaScriptEnabled(ErrorString&, bool enabled)
+{
+ auto copy = m_page.preferences().copy();
+ copy->setJavaScriptEnabled(enabled);
+ m_page.setPreferences(copy);
+}
+
+void WebPageInspectorEmulationAgent::setAuthCredentials(Inspector::ErrorString&, const String* username, const String* password)
+{
+ if (username && password)
+ m_page.setAuthCredentialsForAutomation(WebCore::Credential(*username, *password, CredentialPersistencePermanent));
+ else
+ m_page.setAuthCredentialsForAutomation(Optional<WebCore::Credential>());
+}
+
+void WebPageInspectorEmulationAgent::setActiveAndFocused(Inspector::ErrorString&, const bool* active)
+{
+ Optional<bool> value;
+ if (active)
+ value = *active;
+ m_page.setActiveForAutomation(value);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..43d827233df725fa8c85fc9ff4b20a1f716803e0
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+
+#include <wtf/Forward.h>
+#include <wtf/Function.h>
+#include <wtf/Noncopyable.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+}
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class WebPageInspectorEmulationAgent : public Inspector::InspectorAgentBase, public Inspector::EmulationBackendDispatcherHandler {
+ WTF_MAKE_NONCOPYABLE(WebPageInspectorEmulationAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ WebPageInspectorEmulationAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page);
+ ~WebPageInspectorEmulationAgent() override;
+
+ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+ void setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref<SetDeviceMetricsOverrideCallback>&&) override;
+ void setJavaScriptEnabled(Inspector::ErrorString&, bool enabled) override;
+ void setAuthCredentials(Inspector::ErrorString&, const String*, const String*) override;
+ void setActiveAndFocused(Inspector::ErrorString&, const bool*) override;
+
+private:
+ void platformSetSize(int width, int height, Function<void (const String& error)>&&);
+
+ Ref<Inspector::EmulationBackendDispatcher> m_backendDispatcher;
+ WebPageProxy& m_page;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5043224bbd6378175c9ca7dce63fc5a233649878
--- /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.
+ */
+
+#include "config.h"
+#include "WebPageInspectorInputAgent.h"
+
+#include "NativeWebKeyboardEvent.h"
+#include "NativeWebMouseEvent.h"
+#include "WebPageProxy.h"
+#include <wtf/MathExtras.h>
+
+namespace WebKit {
+
+using namespace Inspector;
+
+namespace {
+
+template<class T>
+class CallbackList {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ ~CallbackList()
+ {
+ for (const auto& callback : m_callbacks)
+ callback->sendFailure("Page closed");
+ }
+
+ void append(Ref<T>&& callback)
+ {
+ m_callbacks.append(WTFMove(callback));
+ }
+
+ void sendSuccess()
+ {
+ for (const auto& callback : m_callbacks)
+ callback->sendSuccess();
+ m_callbacks.clear();
+ }
+
+private:
+ Vector<Ref<T>> m_callbacks;
+};
+
+} // namespace
+
+class WebPageInspectorInputAgent::KeyboardCallbacks : public CallbackList<Inspector::InputBackendDispatcherHandler::DispatchKeyEventCallback> {
+};
+
+class WebPageInspectorInputAgent::MouseCallbacks : public CallbackList<Inspector::InputBackendDispatcherHandler::DispatchMouseEventCallback> {
+};
+
+WebPageInspectorInputAgent::WebPageInspectorInputAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page)
+ : InspectorAgentBase("Input"_s)
+ , m_backendDispatcher(InputBackendDispatcher::create(backendDispatcher, this))
+ , m_page(page)
+{
+}
+
+WebPageInspectorInputAgent::~WebPageInspectorInputAgent() = default;
+
+void WebPageInspectorInputAgent::didProcessAllPendingKeyboardEvents()
+{
+ m_keyboardCallbacks->sendSuccess();
+}
+
+void WebPageInspectorInputAgent::didProcessAllPendingMouseEvents()
+{
+ m_mouseCallbacks->sendSuccess();
+}
+
+void WebPageInspectorInputAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
+{
+ m_keyboardCallbacks = makeUnique<KeyboardCallbacks>();
+ m_mouseCallbacks = makeUnique<MouseCallbacks>();
+}
+
+void WebPageInspectorInputAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
+{
+ m_keyboardCallbacks = nullptr;
+ m_mouseCallbacks = nullptr;
+}
+
+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)
+{
+ WebKit::WebEvent::Type eventType;
+ if (type == "keyDown") {
+ eventType = WebKit::WebEvent::KeyDown;
+ } else if (type == "keyUp") {
+ eventType = WebKit::WebEvent::KeyUp;
+ } else {
+ callback->sendFailure("Unsupported event type.");
+ return;
+ }
+ OptionSet<WebEvent::Modifier> eventModifiers;
+ if (modifiers)
+ eventModifiers = eventModifiers.fromRaw(*modifiers);
+ 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;
+ WallTime timestamp = WallTime::now();
+
+ m_keyboardCallbacks->append(WTFMove(callback));
+ platformDispatchKeyEvent(
+ eventType,
+ eventText,
+ eventUnmodifiedText,
+ eventKey,
+ eventCode,
+ eventWindowsVirtualKeyCode,
+ eventNativeVirtualKeyCode,
+ eventIsAutoRepeat,
+ eventIsKeypad,
+ eventIsSystemKey,
+ eventModifiers,
+ eventCommands,
+ 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)
+{
+ WebEvent::Type eventType = WebEvent::NoType;
+ if (type == "down")
+ eventType = WebEvent::MouseDown;
+ else if (type == "up")
+ eventType = WebEvent::MouseUp;
+ else if (type == "move")
+ eventType = WebEvent::MouseMove;
+ else {
+ callback->sendFailure("Unsupported event type");
+ return;
+ }
+
+ OptionSet<WebEvent::Modifier> eventModifiers;
+ if (modifiers)
+ eventModifiers = eventModifiers.fromRaw(*modifiers);
+
+ WebMouseEvent::Button eventButton = WebMouseEvent::NoButton;
+ if (button) {
+ if (*button == "left")
+ eventButton = WebMouseEvent::LeftButton;
+ else if (*button == "middle")
+ eventButton = WebMouseEvent::MiddleButton;
+ else if (*button == "right")
+ eventButton = WebMouseEvent::RightButton;
+ else if (*button == "none")
+ eventButton = WebMouseEvent::NoButton;
+ else {
+ callback->sendFailure("Unsupported eventButton");
+ return;
+ }
+ }
+
+ unsigned short eventButtons = 0;
+ if (buttons)
+ eventButtons = *buttons;
+
+ int eventClickCount = 0;
+ if (clickCount)
+ eventClickCount = *clickCount;
+ int eventDeltaX = 0;
+ if (deltaX)
+ eventDeltaX = *deltaX;
+ int eventDeltaY = 0;
+ if (deltaY)
+ eventDeltaY = *deltaY;
+ m_mouseCallbacks->append(WTFMove(callback));
+
+ // Convert css coordinates to view coordinates (dip).
+ double totalScale = m_page.pageScaleFactor() * m_page.viewScaleFactor();
+ x = clampToInteger(roundf(x * totalScale));
+ y = clampToInteger(roundf(y * totalScale));
+ eventDeltaX = clampToInteger(roundf(eventDeltaX * totalScale));
+ eventDeltaY = clampToInteger(roundf(eventDeltaY * totalScale));
+
+#if PLATFORM(MAC)
+ platformDispatchMouseEvent(type, x, y, modifiers, button, clickCount);
+#elif PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)
+ WallTime timestamp = WallTime::now();
+ NativeWebMouseEvent event(
+ eventType,
+ eventButton,
+ eventButtons,
+ {x, y},
+ WebCore::IntPoint(),
+ eventDeltaX,
+ eventDeltaY,
+ 0,
+ eventClickCount,
+ eventModifiers,
+ timestamp);
+ m_page.handleMouseEvent(event);
+#endif
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h
new file mode 100644
index 0000000000000000000000000000000000000000..76290475097e756e3d932d22be4d8c797be4aa0c
--- /dev/null
+++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "WebEvent.h"
+
+#include <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+}
+
+namespace WebKit {
+
+class NativeWebKeyboardEvent;
+class WebPageProxy;
+
+class WebPageInspectorInputAgent : public Inspector::InspectorAgentBase, public Inspector::InputBackendDispatcherHandler {
+ WTF_MAKE_NONCOPYABLE(WebPageInspectorInputAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ WebPageInspectorInputAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page);
+ ~WebPageInspectorInputAgent() override;
+
+ void didProcessAllPendingKeyboardEvents();
+ void didProcessAllPendingMouseEvents();
+
+ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
+ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
+
+ // Protocol handler
+ void dispatchKeyEvent(const String& type, 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;
+
+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);
+#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
+
+ Ref<Inspector::InputBackendDispatcher> m_backendDispatcher;
+ WebPageProxy& m_page;
+ // Keep track of currently active modifiers across multiple keystrokes.
+ // Most platforms do not track current modifiers from synthesized events.
+ unsigned m_currentModifiers { 0 };
+ class KeyboardCallbacks;
+ std::unique_ptr<KeyboardCallbacks> m_keyboardCallbacks;
+ class MouseCallbacks;
+ std::unique_ptr<MouseCallbacks> m_mouseCallbacks;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp
index 7522ef16feaeb3a8ea3b28aa386c5bf9afc987ea..7174848efe270f63bcad709f66f8200619c4a58d 100644
--- a/Source/WebKit/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp
@@ -905,6 +905,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason)
m_pageLoadState.didSwapWebProcesses();
if (reason != ProcessLaunchReason::InitialProcess)
m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
+ m_inspectorController->didFinishAttachingToWebProcess();
}
void WebPageProxy::didAttachToRunningProcess()
@@ -1244,6 +1245,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)
@@ -1691,6 +1707,31 @@ void WebPageProxy::setControlledByAutomation(bool controlled)
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());
+}
+
void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
{
MESSAGE_CHECK(m_process, !targetId.isEmpty());
@@ -1833,6 +1874,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())
@@ -2778,7 +2838,7 @@ static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
{
-#if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
+#if ENABLE(ASYNC_SCROLLING) && PLATFORM(IOS_FAMILY)
const EventNames& names = eventNames();
for (auto& touchPoint : touchStartEvent.touchPoints()) {
IntPoint location = touchPoint.location();
@@ -2811,7 +2871,7 @@ void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent
m_touchAndPointerEventTracking.touchStartTracking = TrackingType::Synchronous;
m_touchAndPointerEventTracking.touchMoveTracking = TrackingType::Synchronous;
m_touchAndPointerEventTracking.touchEndTracking = TrackingType::Synchronous;
-#endif // ENABLE(ASYNC_SCROLLING)
+#endif // ENABLE(ASYNC_SCROLLING) && PLATFORM(IOS_FAMILY)
}
TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
@@ -3146,6 +3206,7 @@ void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, A
void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, Optional<WebsitePoliciesData>&& websitePolicies, Ref<PolicyDecisionSender>&& sender, WillContinueLoadInNewProcess willContinueLoadInNewProcess)
{
+ m_inspectorController->didReceivePolicyDecision(action, navigation ? navigation->navigationID() : 0);
if (!hasRunningProcess()) {
sender->send(PolicyAction::Ignore, 0, DownloadID(), WTF::nullopt);
return;
@@ -3830,6 +3891,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;
@@ -4242,6 +4308,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, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData)
@@ -4465,6 +4532,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;
@@ -4907,8 +4976,16 @@ void WebPageProxy::decidePolicyForNavigationActionAsync(FrameIdentifier frameID,
NavigationActionData&& navigationActionData, FrameInfoData&& frameInfoData, 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(frameSecurityOrigin), identifier, navigationID, WTFMove(navigationActionData),
- WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
+ if (m_inspectorController->shouldPauseLoading())
+ m_inspectorController->setContinueLoadingCallback([this, protectedThis = makeRef(*this), frameID, frameSecurityOrigin = WTFMove(frameSecurityOrigin), identifier, navigationID, navigationActionData = WTFMove(navigationActionData),
+ frameInfoData = WTFMove(frameInfoData), originatingPageID, originalRequest, request = WTFMove(request), requestBody = WTFMove(requestBody), redirectResponse = WTFMove(redirectResponse), userData, listenerID] () mutable {
+ decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameSecurityOrigin), identifier, navigationID, WTFMove(navigationActionData),
+ WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
+ });
+ else {
+ decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameSecurityOrigin), identifier, navigationID, WTFMove(navigationActionData),
+ WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
+ }
}
void WebPageProxy::decidePolicyForNavigationActionAsyncShared(Ref<WebProcessProxy>&& process, PageIdentifier webPageID, FrameIdentifier frameID, WebCore::SecurityOriginData&& frameSecurityOrigin,
@@ -5480,6 +5557,8 @@ void WebPageProxy::runJavaScriptAlert(FrameIdentifier frameID, SecurityOriginDat
if (auto* automationSession = process().processPool().automationSession())
automationSession->willShowJavaScriptDialog(*this);
}
+ if (m_inspectorDialogAgent)
+ m_inspectorDialogAgent->javascriptDialogOpening("alert"_s, message);
m_uiClient->runJavaScriptAlert(*this, message, frame, WTFMove(securityOrigin), WTFMove(reply));
}
@@ -5499,6 +5578,8 @@ void WebPageProxy::runJavaScriptConfirm(FrameIdentifier frameID, SecurityOriginD
if (auto* automationSession = process().processPool().automationSession())
automationSession->willShowJavaScriptDialog(*this);
}
+ if (m_inspectorDialogAgent)
+ m_inspectorDialogAgent->javascriptDialogOpening("confirm"_s, message);
m_uiClient->runJavaScriptConfirm(*this, message, frame, WTFMove(securityOrigin), WTFMove(reply));
}
@@ -5518,6 +5599,8 @@ void WebPageProxy::runJavaScriptPrompt(FrameIdentifier frameID, SecurityOriginDa
if (auto* automationSession = process().processPool().automationSession())
automationSession->willShowJavaScriptDialog(*this);
}
+ if (m_inspectorDialogAgent)
+ m_inspectorDialogAgent->javascriptDialogOpening("prompt"_s, message, &defaultValue);
m_uiClient->runJavaScriptPrompt(*this, message, defaultValue, frame, WTFMove(securityOrigin), WTFMove(reply));
}
@@ -5677,6 +5760,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(FrameIdentifier frameID, Security
return;
}
}
+ if (m_inspectorDialogAgent)
+ m_inspectorDialogAgent->javascriptDialogOpening("beforeunload"_s, message);
// Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer and the tryClose timer.
m_process->stopResponsivenessTimer();
@@ -6736,6 +6821,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
if (auto* automationSession = process().processPool().automationSession())
automationSession->mouseEventsFlushedForPage(*this);
didFinishProcessingAllPendingMouseEvents();
+ m_inspectorController->didProcessAllPendingMouseEvents();
}
break;
@@ -6762,7 +6848,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
case WebEvent::RawKeyDown:
case WebEvent::Char: {
LOG(KeyHandling, "WebPageProxy::didReceiveEvent: %s (queue empty %d)", webKeyboardEventTypeString(type), m_keyEventQueue.isEmpty());
-
MESSAGE_CHECK(m_process, !m_keyEventQueue.isEmpty());
NativeWebKeyboardEvent event = m_keyEventQueue.takeFirst();
@@ -6782,7 +6867,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
// The call to doneWithKeyEvent may close this WebPage.
// Protect against this being destroyed.
Ref<WebPageProxy> protect(*this);
-
pageClient().doneWithKeyEvent(event, handled);
if (!handled)
m_uiClient->didNotHandleKeyEvent(this, event);
@@ -6791,6 +6875,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
if (!canProcessMoreKeyEvents) {
if (auto* automationSession = process().processPool().automationSession())
automationSession->keyboardEventsFlushedForPage(*this);
+ m_inspectorController->didProcessAllPendingKeyboardEvents();
}
break;
}
@@ -7259,8 +7344,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
@@ -7733,6 +7820,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)
@@ -7815,7 +7910,8 @@ void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID,
MESSAGE_CHECK(m_process, securityOriginData);
// FIXME: Geolocation should probably be using toString() as its string representation instead of databaseIdentifier().
- auto origin = API::SecurityOrigin::create(securityOriginData->securityOrigin());
+ auto securityOrigin = securityOriginData->securityOrigin();
+ auto origin = API::SecurityOrigin::create(securityOrigin);
auto request = m_geolocationPermissionRequestManager.createRequest(geolocationID);
Function<void(bool)> completionHandler = [request = WTFMove(request)](bool allowed) {
if (allowed)
@@ -7823,6 +7919,11 @@ void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID,
else
request->deny();
};
+ auto permissions = m_permissionsForAutomation.find(securityOrigin->toString());
+ if (permissions != m_permissionsForAutomation.end()) {
+ completionHandler(permissions->value.contains("geolocation"));
+ return;
+ }
// FIXME: Once iOS migrates to the new WKUIDelegate SPI, clean this up
// and make it one UIClient call that calls the completionHandler with false
diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h
index a670856d71ea68c3f5eefa08c0e7c1bf51fe0202..53a5310ee849b15c4badafa7aed61509498c514c 100644
--- 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"
@@ -491,6 +492,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();
@@ -557,6 +560,11 @@ public:
void setPageLoadStateObserver(std::unique_ptr<PageLoadState::Observer>&&);
+ void setAuthCredentialsForAutomation(Optional<WebCore::Credential>&&);
+ void setPermissionsForAutomation(const HashMap<String, HashSet<String>>&);
+ void setActiveForAutomation(Optional<bool> active);
+ void logToStderr(const String& str);
+
void initializeWebPage();
void setDrawingArea(std::unique_ptr<DrawingAreaProxy>&&);
@@ -582,6 +590,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);
@@ -1056,6 +1065,7 @@ public:
#endif
void pageScaleFactorDidChange(double);
+ void viewScaleFactorDidChange(double);
void pluginScaleFactorDidChange(double);
void pluginZoomFactorDidChange(double);
@@ -2299,6 +2309,7 @@ private:
String m_overrideContentSecurityPolicy;
RefPtr<WebInspectorProxy> m_inspector;
+ InspectorDialogAgent* m_inspectorDialogAgent { nullptr };
#if ENABLE(FULLSCREEN_API)
std::unique_ptr<WebFullScreenManagerProxy> m_fullScreenManager;
@@ -2713,6 +2724,9 @@ private:
bool m_isLayerTreeFrozenDueToSwipeAnimation { false };
String m_overriddenMediaType;
+ 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 752093b8649f3725166828a19b38fac934e3b690..b57fbb768ca22710bb19ba71537117b7cd736bd8 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 WebCore::SecurityOriginData frameSecurityOrigin, String message) -> (bool result) Synchronous
RunJavaScriptPrompt(WebCore::FrameIdentifier frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, 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)
@@ -210,6 +211,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 bfb54ba3d628893e0175637b1a2d50a8a0adf67d..ed9110c6d9513450f958092645285028af30b3fe 100644
--- a/Source/WebKit/UIProcess/WebProcessPool.cpp
+++ b/Source/WebKit/UIProcess/WebProcessPool.cpp
@@ -423,12 +423,19 @@ void WebProcessPool::languageChanged(void* context)
static_cast<WebProcessPool*>(context)->languageChanged();
}
+void WebProcessPool::setLanguagesForAutomation(Vector<String>&& languages)
+{
+ m_languagesForAutomation = WTFMove(languages);
+ languageChanged();
+}
+
void WebProcessPool::languageChanged()
{
- sendToAllProcesses(Messages::WebProcess::UserPreferredLanguagesChanged(userPreferredLanguages()));
+ const Vector<String>& languages = m_languagesForAutomation.size() ? m_languagesForAutomation : userPreferredLanguages();
+ sendToAllProcesses(Messages::WebProcess::UserPreferredLanguagesChanged(languages));
#if USE(SOUP)
if (m_networkProcess)
- m_networkProcess->send(Messages::NetworkProcess::UserPreferredLanguagesChanged(userPreferredLanguages()), 0);
+ m_networkProcess->send(Messages::NetworkProcess::UserPreferredLanguagesChanged(languages), 0);
#endif
}
@@ -985,7 +992,10 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa
#endif
parameters.cacheModel = LegacyGlobalSettings::singleton().cacheModel();
- parameters.languages = configuration().overrideLanguages().isEmpty() ? userPreferredLanguages() : configuration().overrideLanguages();
+ if (m_languagesForAutomation.size())
+ parameters.languages = m_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 fcd285ffb45e1b83364b35e930c46d3c866135ef..bb30209108128dc871ee1e25826758269cd03f6f 100644
--- a/Source/WebKit/UIProcess/WebProcessPool.h
+++ b/Source/WebKit/UIProcess/WebProcessPool.h
@@ -416,7 +416,7 @@ public:
void windowServerConnectionStateChanged();
-#if USE(SOUP)
+#if USE(SOUP) || PLATFORM(COCOA) || PLATFORM(WIN)
void setIgnoreTLSErrors(bool);
bool ignoreTLSErrors() const { return m_ignoreTLSErrors; }
#endif
@@ -537,6 +537,8 @@ public:
PlugInAutoStartProvider& plugInAutoStartProvider() { return m_plugInAutoStartProvider; }
+ void setLanguagesForAutomation(Vector<String>&&);
+
void setUseSeparateServiceWorkerProcess(bool);
bool useSeparateServiceWorkerProcess() const { return m_useSeparateServiceWorkerProcess; }
@@ -642,6 +644,7 @@ private:
std::unique_ptr<API::CustomProtocolManagerClient> m_customProtocolManagerClient;
RefPtr<WebAutomationSession> m_automationSession;
+ Vector<String> m_languagesForAutomation;
#if ENABLE(NETSCAPE_PLUGIN_API)
PluginInfoStore m_pluginInfoStore;
@@ -711,8 +714,8 @@ private:
HashMap<uint64_t, RefPtr<DictionaryCallback>> m_dictionaryCallbacks;
HashMap<uint64_t, RefPtr<StatisticsRequest>> m_statisticsRequests;
-#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/geoclue/GeoclueGeolocationProvider.cpp b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp
index dba2a990d15683216a6fa90a48eb30eebd3c526f..6a8afc7c206765670d25152f7b6a1aa7e5563a27 100644
--- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp
+++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp
@@ -55,10 +55,11 @@ void GeoclueGeolocationProvider::start(UpdateNotifyFunction&& updateNotifyFuncti
m_destroyManagerLaterTimer.stop();
m_updateNotifyFunction = WTFMove(updateNotifyFunction);
m_isRunning = true;
-
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", nullptr,
+ "org.freedesktop.GeoClue2", "/org/freedesktop/GeoClue2/Manager", "org.freedesktop.GeoClue2.Manager", m_cancellable_start.get(),
[](GObject*, GAsyncResult* result, gpointer userData) {
auto& provider = *static_cast<GeoclueGeolocationProvider*>(userData);
GUniqueOutPtr<GError> error;
@@ -84,6 +85,12 @@ void GeoclueGeolocationProvider::stop()
m_updateNotifyFunction = nullptr;
g_cancellable_cancel(m_cancellable.get());
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();
}
@@ -121,7 +128,9 @@ void GeoclueGeolocationProvider::setupManager(GRefPtr<GDBusProxy>&& proxy)
return;
}
- g_dbus_proxy_call(m_manager.get(), "CreateClient", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr,
+ g_cancellable_cancel(m_cancellable_setup.get());
+ m_cancellable_setup = adoptGRef(g_cancellable_new());
+ g_dbus_proxy_call(m_manager.get(), "CreateClient", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, m_cancellable_setup.get(),
[](GObject* manager, GAsyncResult* result, gpointer userData) {
auto& provider = *static_cast<GeoclueGeolocationProvider*>(userData);
GUniqueOutPtr<GError> error;
@@ -143,8 +152,10 @@ 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", nullptr,
+ "org.freedesktop.GeoClue2", clientPath, "org.freedesktop.GeoClue2.Client", m_cancellable_create.get(),
[](GObject*, GAsyncResult* result, gpointer userData) {
auto& provider = *static_cast<GeoclueGeolocationProvider*>(userData);
GUniqueOutPtr<GError> error;
@@ -190,6 +201,7 @@ void GeoclueGeolocationProvider::startClient()
g_signal_connect(m_client.get(), "g-signal", G_CALLBACK(clientLocationUpdatedCallback), this);
+ g_cancellable_cancel(m_cancellable.get());
m_cancellable = adoptGRef(g_cancellable_new());
g_dbus_proxy_call(m_client.get(), "Start", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, m_cancellable.get(),
[](GObject* client, GAsyncResult* result, gpointer userData) {
@@ -282,7 +294,8 @@ void GeoclueGeolocationProvider::locationUpdated(GRefPtr<GDBusProxy>&& proxy)
void GeoclueGeolocationProvider::didFail(CString errorMessage)
{
- m_updateNotifyFunction({ }, errorMessage);
+ if (m_updateNotifyFunction)
+ m_updateNotifyFunction({ }, errorMessage);
}
} // namespace WebKit
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/InspectorBrowserAgentClientGLib.cpp b/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0038b09d06d3d92b885d70bfffa9b111766b3f57
--- /dev/null
+++ b/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.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.
+ */
+
+#include "config.h"
+#include "InspectorBrowserAgentClientGLib.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorBrowserAgent.h"
+#include "WebKitBrowserInspectorPrivate.h"
+#include "WebKitWebContextPrivate.h"
+#include "WebKitWebsiteDataManagerPrivate.h"
+#include "WebKitWebViewPrivate.h"
+#include "WebPageProxy.h"
+#include <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/StringView.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+InspectorBrowserAgentClientGlib::InspectorBrowserAgentClientGlib(GMainLoop* mainLoop)
+ : m_mainLoop(mainLoop)
+{
+}
+
+RefPtr<WebPageProxy> InspectorBrowserAgentClientGlib::createPage(WTF::String& error, const BrowserContext& browserContext)
+{
+ auto sessionID = browserContext.dataStore->sessionID();
+ WebKitWebContext* context = m_idToContext.get(sessionID);
+ if (!context && !browserContext.dataStore->isPersistent()) {
+ ASSERT_NOT_REACHED();
+ error = "Context with provided id not found";
+ return nullptr;
+ }
+
+ RefPtr<WebPageProxy> page = webkitBrowserInspectorCreateNewPageInContext(context);
+ if (page == nullptr) {
+ error = "Failed to create new page in the context";
+ return nullptr;
+ }
+
+ if (context == nullptr && sessionID != page->sessionID()) {
+ ASSERT_NOT_REACHED();
+ error = " Failed to create new page in default context";
+ return nullptr;
+ }
+
+ return page;
+}
+
+void InspectorBrowserAgentClientGlib::closeBrowser()
+{
+ m_idToContext.clear();
+#if PLATFORM(GTK)
+ gtk_main_quit();
+#else
+ if (m_mainLoop)
+ g_main_loop_quit(m_mainLoop);
+#endif
+}
+
+static PAL::SessionID sessionIDFromContext(WebKitWebContext* context)
+{
+ WebKitWebsiteDataManager* data_manager = webkit_web_context_get_website_data_manager(context);
+ WebsiteDataStore& websiteDataStore = webkitWebsiteDataManagerGetDataStore(data_manager);
+ return websiteDataStore.sessionID();
+}
+
+BrowserContext InspectorBrowserAgentClientGlib::createBrowserContext(WTF::String& error)
+{
+ BrowserContext browserContext;
+ GRefPtr<WebKitWebsiteDataManager> data_manager = adoptGRef(webkit_website_data_manager_new_ephemeral());
+ GRefPtr<WebKitWebContext> context = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", data_manager.get(), "process-swap-on-cross-site-navigation-enabled", true, nullptr)));
+ if (!context) {
+ error = "Failed to create GLib ephemeral context";
+ return browserContext;
+ }
+ browserContext.processPool = &webkitWebContextGetProcessPool(context.get());
+ browserContext.dataStore = &webkitWebsiteDataManagerGetDataStore(data_manager.get());
+ PAL::SessionID sessionID = sessionIDFromContext(context.get());
+ m_idToContext.set(sessionID, WTFMove(context));
+ return browserContext;
+}
+
+void InspectorBrowserAgentClientGlib::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
+{
+ m_idToContext.remove(sessionID);
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.h b/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.h
new file mode 100644
index 0000000000000000000000000000000000000000..9e27fe017ffdef1e8aafce69344fd688c732c3b4
--- /dev/null
+++ b/Source/WebKit/UIProcess/glib/InspectorBrowserAgentClientGLib.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.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "InspectorBrowserAgentClient.h"
+#include "WebKitWebContext.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebKit {
+
+class InspectorBrowserAgentClientGlib : public InspectorBrowserAgentClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorBrowserAgentClientGlib(GMainLoop* mainLoop);
+ ~InspectorBrowserAgentClientGlib() 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:
+ WebKitWebContext* findContext(WTF::String& error, PAL::SessionID);
+
+ HashMap<PAL::SessionID, GRefPtr<WebKitWebContext>> m_idToContext;
+ GMainLoop* m_mainLoop;
+};
+
+} // 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
diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e5e25acebabb76a05a77db02a99f1267bd99a3af
--- /dev/null
+++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DrawingAreaProxyCoordinatedGraphics.h"
+#include "WebPageInspectorEmulationAgent.h"
+#include "WebPageProxy.h"
+#include <WebCore/IntSize.h>
+#include <gtk/gtk.h>
+
+namespace WebKit {
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
+{
+ GtkWidget* viewWidget = m_page.viewWidget();
+ GtkWidget* window = gtk_widget_get_toplevel(viewWidget);
+ if (!window) {
+ callback("Cannot find parent window"_s);
+ return;
+ }
+ if (!GTK_IS_WINDOW(window)) {
+ callback("Toplevel is not a window"_s);
+ return;
+ }
+ GtkAllocation viewAllocation;
+ gtk_widget_get_allocation(viewWidget, &viewAllocation);
+ if (viewAllocation.width == width && viewAllocation.height == height) {
+ callback(String());
+ return;
+ }
+
+ GtkAllocation windowAllocation;
+ gtk_widget_get_allocation(window, &windowAllocation);
+
+ width += windowAllocation.width - viewAllocation.width;
+ height += windowAllocation.height - viewAllocation.height;
+
+ if (auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(m_page.drawingArea())) {
+ drawingArea->waitForSizeUpdate([callback = WTFMove(callback)]() {
+ callback(String());
+ });
+ } else {
+ callback("No backing store for window"_s);
+ }
+ gtk_window_resize(GTK_WINDOW(window), width, height);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7ad3fe416c5c747eaad8c6948c3549a3984223ea
--- /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.
+ */
+
+#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)
+{
+ 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 63107861d345ca9f2476e65ea797ccc47b4c7518..77f7ad6d2d10648c63737c31ddec782ebbe0541c 100644
--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
@@ -450,6 +450,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
{
+ if (!event.nativeEvent())
+ return;
[m_contentView _didHandleKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled];
}
diff --git a/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.h b/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9e7e5906301bb7add100bba3f88c0c0aef04fd1
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 "InspectorBrowserAgentClient.h"
+#include <wtf/Forward.h>
+
+OBJC_PROTOCOL(_WKBrowserInspectorDelegate);
+
+namespace WebKit {
+
+class InspectorBrowserAgentClientMac : public InspectorBrowserAgentClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorBrowserAgentClientMac(_WKBrowserInspectorDelegate* delegate);
+ ~InspectorBrowserAgentClientMac() 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:
+ _WKBrowserInspectorDelegate* delegate_;
+};
+
+
+} // namespace API
diff --git a/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.mm b/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..fc40a8a0ee3f88a4f15d5b75f060b00e1126f47b
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/InspectorBrowserAgentClientMac.mm
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "InspectorBrowserAgentClientMac.h"
+
+#import <wtf/RefPtr.h>
+#import <wtf/text/WTFString.h>
+#import "WebPageProxy.h"
+#import "WebProcessPool.h"
+#import "WebsiteDataStore.h"
+#import "_WKBrowserInspector.h"
+#import "WKProcessPoolInternal.h"
+#import "WKWebsiteDataStoreInternal.h"
+#import "WKWebView.h"
+#import "WKWebViewInternal.h"
+
+namespace WebKit {
+
+InspectorBrowserAgentClientMac::InspectorBrowserAgentClientMac(_WKBrowserInspectorDelegate* delegate)
+ : delegate_(delegate)
+{
+}
+
+RefPtr<WebPageProxy> InspectorBrowserAgentClientMac::createPage(WTF::String& error, const BrowserContext& browserContext)
+{
+ auto sessionID = browserContext.dataStore->sessionID();
+ WKWebView *webView = [delegate_ createNewPage:sessionID.toUInt64()];
+ if (!webView) {
+ error = "Internal error: can't create page in given context"_s;
+ return nil;
+ }
+ return [webView _page].get();
+}
+
+void InspectorBrowserAgentClientMac::closeBrowser()
+{
+ [delegate_ quit];
+}
+
+BrowserContext InspectorBrowserAgentClientMac::createBrowserContext(WTF::String& error)
+{
+ _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;
+}
+
+void InspectorBrowserAgentClientMac::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
+{
+ [delegate_ deleteBrowserContext:sessionID.toUInt64()];
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm b/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..721826c8c98fc85b68a4f45deaee69c1219a7254
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "InspectorTargetProxy.h"
+#import "WebPageProxy.h"
+
+#if PLATFORM(MAC)
+
+namespace WebKit {
+
+void InspectorTargetProxy::platformActivate(String& error) const
+{
+ NSWindow* window = m_page.platformWindow();
+ [window makeKeyAndOrderFront:nil];
+}
+
+} // namespace WebKit
+
+#endif
diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.h b/Source/WebKit/UIProcess/mac/PageClientImplMac.h
index 0dca8706d42603578612cc77add0babb05f4e8d5..7a17fd28ed76abfaf36675bf472812f02f0e8b58 100644
--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.h
+++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.h
@@ -53,6 +53,8 @@ class PageClientImpl final : public PageClientImplCocoa
#endif
{
public:
+ static void setHeadless(bool headless);
+
PageClientImpl(NSView *, WKWebView *);
virtual ~PageClientImpl();
@@ -206,6 +208,10 @@ private:
void beganExitFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame) override;
#endif
+#if ENABLE(TOUCH_EVENTS)
+ void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled) override;
+#endif
+
void navigationGestureDidBegin() override;
void navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem&) override;
void navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem&) override;
diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm
index af376ae653ab8bffeca10e070954dcdf1ed3de3d..eefb0da9904f41794b328e236bb022804e92e8d4 100644
--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm
+++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm
@@ -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/text/CString.h>
#import <wtf/text/WTFString.h>
@@ -105,6 +106,13 @@ static NSString * const kAXLoadCompleteNotification = @"AXLoadComplete";
namespace WebKit {
using namespace WebCore;
+static bool _headless = false;
+
+// static
+void PageClientImpl::setHeadless(bool headless) {
+ _headless = true;
+}
+
PageClientImpl::PageClientImpl(NSView* view, WKWebView *webView)
: PageClientImplCocoa(webView)
, m_view(view)
@@ -163,6 +171,9 @@ NSWindow *PageClientImpl::activeWindow() const
bool PageClientImpl::isViewWindowActive()
{
+ if (_headless)
+ return true;
+
ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
NSWindow *activeViewWindow = activeWindow();
return activeViewWindow.isKeyWindow || [NSApp keyWindow] == activeViewWindow;
@@ -170,6 +181,9 @@ bool PageClientImpl::isViewWindowActive()
bool PageClientImpl::isViewFocused()
{
+ if (_headless)
+ return true;
+
// FIXME: This is called from the WebPageProxy constructor before we have a WebViewImpl.
// Once WebViewImpl and PageClient merge, this won't be a problem.
if (!m_impl)
@@ -193,6 +207,9 @@ void PageClientImpl::makeFirstResponder()
bool PageClientImpl::isViewVisible()
{
+ if (_headless)
+ return true;
+
NSView *activeView = this->activeView();
NSWindow *activeViewWindow = activeWindow();
@@ -278,7 +295,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)
@@ -456,6 +474,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
{
+ if (!event.nativeEvent())
+ return;
m_impl->doneWithKeyEvent(event.nativeEvent(), eventWasHandled);
}
@@ -760,6 +780,13 @@ void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntR
#endif // ENABLE(FULLSCREEN_API)
+#if ENABLE(TOUCH_EVENTS)
+void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled)
+{
+ notImplemented();
+}
+#endif // ENABLE(TOUCH_EVENTS)
+
void PageClientImpl::navigationGestureDidBegin()
{
m_impl->dismissContentRelativeChildWindowsWithAnimation(true);
@@ -926,6 +953,9 @@ void PageClientImpl::didRestoreScrollPosition()
bool PageClientImpl::windowIsFrontWindowUnderMouse(const NativeWebMouseEvent& event)
{
+ // Simulated event.
+ if (!event.nativeEvent())
+ return false;
return m_impl->windowIsFrontWindowUnderMouse(event.nativeEvent());
}
diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..6113f4cd60a5d72b8ead61176cb43200803478ed
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/WebPageInspectorEmulationAgentMac.mm
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "WebPageInspectorEmulationAgent.h"
+
+#import "WebPageProxy.h"
+
+namespace WebKit {
+
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
+{
+ NSWindow* window = m_page.platformWindow();
+ NSRect windowRect = [window frame];
+ NSRect viewRect = window.contentLayoutRect;
+ windowRect.size.width += width - viewRect.size.width;
+ windowRect.size.height += height - viewRect.size.height;
+ [window setFrame:windowRect display:YES animate:NO];
+ callback(String());
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..30e6ae3bdc8c1695189885afae949071add54c4e
--- /dev/null
+++ b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "NativeWebMouseEvent.h"
+#import "WebPageInspectorInputAgent.h"
+#import "WebPageProxy.h"
+#import <WebCore/IntPoint.h>
+#import <WebCore/IntSize.h>
+#import "NativeWebKeyboardEvent.h"
+#import <wtf/HexNumber.h>
+
+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)
+{
+ 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);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/win/InspectorBrowserAgentClientWin.cpp b/Source/WebKit/UIProcess/win/InspectorBrowserAgentClientWin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7406306e47b4f3469db150eef6a71ac30e8f2f7a
--- /dev/null
+++ b/Source/WebKit/UIProcess/win/InspectorBrowserAgentClientWin.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 "InspectorBrowserAgentClientWin.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "APIPageConfiguration.h"
+#include "APIProcessPoolConfiguration.h"
+#include "InspectorBrowserAgent.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 {
+
+InspectorBrowserAgentClientWin::InspectorBrowserAgentClientWin(CreatePageCallback createPage, QuitCallback quit)
+ : m_createPage(createPage)
+ , m_quit(quit)
+{
+}
+
+RefPtr<WebPageProxy> InspectorBrowserAgentClientWin::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 InspectorBrowserAgentClientWin::closeBrowser()
+{
+ m_quit();
+}
+
+BrowserContext InspectorBrowserAgentClientWin::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 InspectorBrowserAgentClientWin::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
+{
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
diff --git a/Source/WebKit/UIProcess/win/InspectorBrowserAgentClientWin.h b/Source/WebKit/UIProcess/win/InspectorBrowserAgentClientWin.h
new file mode 100644
index 0000000000000000000000000000000000000000..2311841478469154473c259a4e0c669daf4644f9
--- /dev/null
+++ b/Source/WebKit/UIProcess/win/InspectorBrowserAgentClientWin.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 "InspectorBrowserAgentClient.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 InspectorBrowserAgentClientWin : public InspectorBrowserAgentClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorBrowserAgentClientWin(CreatePageCallback, QuitCallback);
+ ~InspectorBrowserAgentClientWin() 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..acb0617bcded07029665d4949659c73adf2fd633 100644
--- a/Source/WebKit/UIProcess/win/WebProcessPoolWin.cpp
+++ b/Source/WebKit/UIProcess/win/WebProcessPoolWin.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "WebProcessPool.h"
-
+#include "NetworkProcessMessages.h"
#include "WebProcessCreationParameters.h"
#include <WebCore/NotImplemented.h>
@@ -97,4 +97,11 @@ void WebProcessPool::platformResolvePathsForSandboxExtensions()
{
}
+void WebProcessPool::setIgnoreTLSErrors(bool ignoreTLSErrors)
+{
+ m_ignoreTLSErrors = ignoreTLSErrors;
+ if (networkProcess())
+ networkProcess()->send(Messages::NetworkProcess::SetIgnoreTLSErrors(m_ignoreTLSErrors), 0);
+}
+
} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7453194ca6f032ba86a4c67f5bf12688ab6ec1be
--- /dev/null
+++ b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorTargetProxy.h"
+
+#include "WebPageProxy.h"
+#include <wpe/wpe.h>
+
+namespace WebKit {
+
+void InspectorTargetProxy::platformActivate(String& error) const
+{
+ struct wpe_view_backend* backend = m_page.viewBackend();
+ wpe_view_backend_add_activity_state(backend, wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5dc76aa302cb574307059e66a1b73730efe920da
--- /dev/null
+++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebPageInspectorEmulationAgent.h"
+
+#include "WebPageProxy.h"
+#include <wpe/wpe.h>
+
+namespace WebKit {
+
+void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
+{
+ struct wpe_view_backend* backend = m_page.viewBackend();
+ wpe_view_backend_dispatch_set_size(backend, width, height);
+ callback(String());
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..585fb151f302e4b376c705ed0d0974d518733605
--- /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.
+ */
+
+#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)
+{
+ 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);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
index d4885b4632de9c88cf0265d5eef9ab0754bf5587..8d1199e64af150875bec0f3943cc83bdffeaa0a6 100644
--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj
+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
@@ -1728,6 +1728,19 @@
CEE4AE2B1A5DCF430002F49B /* UIKitSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE4AE2A1A5DCF430002F49B /* UIKitSPI.h */; };
D3B9484711FF4B6500032B39 /* WebPopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = D3B9484311FF4B6500032B39 /* WebPopupMenu.h */; };
D3B9484911FF4B6500032B39 /* WebSearchPopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */; };
+ D71A94322370E025002C4D9E /* InspectorBrowserAgentClientMac.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94302370E025002C4D9E /* InspectorBrowserAgentClientMac.h */; };
+ D71A94342370E07A002C4D9E /* InspectorBrowserAgentClient.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94332370E07A002C4D9E /* InspectorBrowserAgentClient.h */; };
+ D71A94382370F032002C4D9E /* BrowserInspectorController.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94372370F032002C4D9E /* BrowserInspectorController.h */; };
+ D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */; };
+ D71A94422371F67E002C4D9E /* WebPageInspectorEmulationAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */; };
+ D71A94432371F67E002C4D9E /* WebPageInspectorInputAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */; };
+ D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94492372290B002C4D9E /* _WKBrowserInspector.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */; };
+ D76D6888238DBD81008D314B /* InspectorDialogAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D76D6887238DBD80008D314B /* InspectorDialogAgent.h */; };
+ D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */; };
+ D79902B2236E9404005D6F7E /* InspectorTargetProxyMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */; };
+ D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */; };
+ D7EB04E72372A73B00F744CE /* InspectorBrowserAgentClientMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D7EB04E62372A73B00F744CE /* InspectorBrowserAgentClientMac.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, ); }; };
E105FE5418D7B9DE008F57A8 /* EditingRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E105FE5318D7B9DE008F57A8 /* EditingRange.h */; };
@@ -4999,6 +5012,20 @@
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 /* InspectorBrowserAgentClientMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorBrowserAgentClientMac.h; sourceTree = "<group>"; };
+ D71A94332370E07A002C4D9E /* InspectorBrowserAgentClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorBrowserAgentClient.h; sourceTree = "<group>"; };
+ 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>"; };
+ D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorEmulationAgentMac.mm; sourceTree = "<group>"; };
+ D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorTargetProxyMac.mm; sourceTree = "<group>"; };
+ D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorInputAgentMac.mm; sourceTree = "<group>"; };
+ D7EB04E62372A73B00F744CE /* InspectorBrowserAgentClientMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorBrowserAgentClientMac.mm; sourceTree = "<group>"; };
DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKHTTPCookieStorePrivate.h; sourceTree = "<group>"; };
DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContentWorldPrivate.h; sourceTree = "<group>"; };
DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebWheelEvent.h; sourceTree = "<group>"; };
@@ -6814,6 +6841,7 @@
37C4C08318149C2A003688B9 /* Cocoa */ = {
isa = PBXGroup;
children = (
+ D71A94492372290B002C4D9E /* _WKBrowserInspector.h */,
1A43E826188F38E2009E4D30 /* Deprecated */,
37A5E01218BBF937000A081E /* _WKActivatedElementInfo.h */,
37A5E01118BBF937000A081E /* _WKActivatedElementInfo.mm */,
@@ -8451,6 +8479,13 @@
BC032DC310F438260058C15A /* UIProcess */ = {
isa = PBXGroup;
children = (
+ D76D6887238DBD80008D314B /* InspectorDialogAgent.h */,
+ D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */,
+ D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */,
+ D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */,
+ D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */,
+ D71A94372370F032002C4D9E /* BrowserInspectorController.h */,
+ D71A94332370E07A002C4D9E /* InspectorBrowserAgentClient.h */,
BC032DC410F4387C0058C15A /* API */,
512F588D12A8836F00629530 /* Authentication */,
9955A6E81C79809000EB6A93 /* Automation */,
@@ -8729,6 +8764,7 @@
BC0C376610F807660076D7CB /* C */ = {
isa = PBXGroup;
children = (
+ D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */,
5123CF18133D25E60056F800 /* cg */,
6EE849C41368D9040038D481 /* mac */,
BCB63477116BF10600603215 /* WebKit2_C.h */,
@@ -9331,6 +9367,11 @@
BCCF085C113F3B7500C650C5 /* mac */ = {
isa = PBXGroup;
children = (
+ D7EB04E62372A73B00F744CE /* InspectorBrowserAgentClientMac.mm */,
+ D71A94302370E025002C4D9E /* InspectorBrowserAgentClientMac.h */,
+ D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */,
+ D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */,
+ D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */,
B878B613133428DC006888E9 /* CorrectionPanel.h */,
B878B614133428DC006888E9 /* CorrectionPanel.mm */,
C1817362205844A900DFDA65 /* DisplayLink.cpp */,
@@ -10026,6 +10067,7 @@
5CAFDE452130846300B1F7E1 /* _WKInspector.h in Headers */,
991F492F23A812C60054642B /* _WKInspectorDebuggableInfo.h in Headers */,
99036AE223A949CF0000B06A /* _WKInspectorDebuggableInfoInternal.h in Headers */,
+ D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */,
5CAFDE472130846A00B1F7E1 /* _WKInspectorInternal.h in Headers */,
9979CA58237F49F10039EC05 /* _WKInspectorPrivate.h in Headers */,
A5C0F0AB2000658200536536 /* _WKInspectorWindow.h in Headers */,
@@ -10149,6 +10191,7 @@
7C89D2981A6753B2003A5FDE /* APIPageConfiguration.h in Headers */,
1AC1336C18565C7A00F3EC05 /* APIPageHandle.h in Headers */,
1AFDD3151891B54000153970 /* APIPolicyClient.h in Headers */,
+ D71A94382370F032002C4D9E /* BrowserInspectorController.h in Headers */,
7CE4D2201A4914CA00C7F152 /* APIProcessPoolConfiguration.h in Headers */,
49BCA19223A177660028A836 /* APIResourceLoadStatisticsFirstParty.h in Headers */,
49BCA19723A1930D0028A836 /* APIResourceLoadStatisticsThirdParty.h in Headers */,
@@ -10276,6 +10319,7 @@
BC06F43A12DBCCFB002D78DE /* GeolocationPermissionRequestProxy.h in Headers */,
2DA944A41884E4F000ED86DB /* GestureTypes.h in Headers */,
2DA049B8180CCD0A00AAFA9E /* GraphicsLayerCARemote.h in Headers */,
+ D71A94342370E07A002C4D9E /* InspectorBrowserAgentClient.h in Headers */,
C0CE72AD1247E78D00BC0EC4 /* HandleMessage.h in Headers */,
1AC75A1B1B3368270056745B /* HangDetectionDisabler.h in Headers */,
57AC8F50217FEED90055438C /* HidConnection.h in Headers */,
@@ -10399,8 +10443,10 @@
41DC45961E3D6E2200B11F51 /* NetworkRTCProvider.h in Headers */,
413075AB1DE85F330039EC69 /* NetworkRTCSocket.h in Headers */,
5C20CBA01BB1ECD800895BB1 /* NetworkSession.h in Headers */,
+ D71A94422371F67E002C4D9E /* WebPageInspectorEmulationAgent.h in Headers */,
532159551DBAE7290054AA3C /* NetworkSessionCocoa.h in Headers */,
417915B92257046F00D6F97E /* NetworkSocketChannel.h in Headers */,
+ D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */,
570DAAC22303730300E8FC04 /* NfcConnection.h in Headers */,
570DAAAE23026F5C00E8FC04 /* NfcService.h in Headers */,
31A2EC5614899C0900810D71 /* NotificationPermissionRequest.h in Headers */,
@@ -10482,6 +10528,7 @@
CD2865EE2255562000606AC7 /* ProcessTaskStateObserver.h in Headers */,
463FD4821EB94EC000A2982C /* ProcessTerminationReason.h in Headers */,
86E67A251910B9D100004AB7 /* ProcessThrottler.h in Headers */,
+ D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */,
83048AE61ACA45DC0082C832 /* ProcessThrottlerClient.h in Headers */,
A1E688701F6E2BAB007006A6 /* QuarantineSPI.h in Headers */,
57FD318222B3515E008D0E8B /* RedirectSOAuthorizationSession.h in Headers */,
@@ -10893,6 +10940,7 @@
BCD25F1711D6BDE100169B0E /* WKBundleFrame.h in Headers */,
BCF049E611FE20F600F86A58 /* WKBundleFramePrivate.h in Headers */,
BC49862F124D18C100D834E1 /* WKBundleHitTestResult.h in Headers */,
+ D71A94432371F67E002C4D9E /* WebPageInspectorInputAgent.h in Headers */,
BC204EF211C83EC8008F3375 /* WKBundleInitialize.h in Headers */,
65B86F1E12F11DE300B7DD8A /* WKBundleInspector.h in Headers */,
1A8B66B41BC45B010082DF77 /* WKBundleMac.h in Headers */,
@@ -10944,6 +10992,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 */,
@@ -11093,6 +11142,7 @@
1AB8A1F818400BB800E9AE69 /* WKPageContextMenuClient.h in Headers */,
8372DB251A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h in Headers */,
1AB8A1F418400B8F00E9AE69 /* WKPageFindClient.h in Headers */,
+ D71A94322370E025002C4D9E /* InspectorBrowserAgentClientMac.h in Headers */,
1AB8A1F618400B9D00E9AE69 /* WKPageFindMatchesClient.h in Headers */,
1AB8A1F018400B0000E9AE69 /* WKPageFormClient.h in Headers */,
BC7B633712A45ABA00D174A4 /* WKPageGroup.h in Headers */,
@@ -12118,6 +12168,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 */,
@@ -12128,6 +12179,7 @@
2D92A781212B6A7100F493FD /* MessageReceiverMap.cpp in Sources */,
2D92A782212B6A7100F493FD /* MessageSender.cpp in Sources */,
2D92A77A212B6A6100F493FD /* Module.cpp in Sources */,
+ D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */,
57B826452304F14000B72EB0 /* NearFieldSoftLink.mm in Sources */,
2D913443212CF9F000128AFD /* NetscapeBrowserFuncs.cpp in Sources */,
2D913444212CF9F000128AFD /* NetscapePlugin.cpp in Sources */,
@@ -12152,6 +12204,7 @@
1A2D8439127F65D5001EB962 /* NPObjectMessageReceiverMessageReceiver.cpp in Sources */,
2D92A792212B6AD400F493FD /* NPObjectProxy.cpp in Sources */,
2D92A793212B6AD400F493FD /* NPRemoteObjectMap.cpp in Sources */,
+ D7EB04E72372A73B00F744CE /* InspectorBrowserAgentClientMac.mm in Sources */,
2D913447212CF9F000128AFD /* NPRuntimeObjectMap.cpp in Sources */,
2D913448212CF9F000128AFD /* NPRuntimeUtilities.cpp in Sources */,
2D92A794212B6AD400F493FD /* NPVariantData.cpp in Sources */,
@@ -12421,6 +12474,7 @@
2D92A78C212B6AB100F493FD /* WebMouseEvent.cpp in Sources */,
31BA924D148831260062EDB5 /* WebNotificationManagerMessageReceiver.cpp in Sources */,
2DF6FE52212E110900469030 /* WebPage.cpp in Sources */,
+ D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */,
C0CE72A01247E71D00BC0EC4 /* WebPageMessageReceiver.cpp in Sources */,
BCBD3914125BB1A800D2C29F /* WebPageProxyMessageReceiver.cpp in Sources */,
7CE9CE101FA0767A000177DE /* WebPageUpdatePreferences.cpp in Sources */,
diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
index c47b876533428bcd10c05059f183c7755fddf64d..3a372868db7e75845b1f15050afa1f6ea74f5329 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;
}
@@ -748,7 +765,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)
@@ -759,6 +776,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;
@@ -767,6 +789,12 @@ void WebLoaderStrategy::setOnLineState(bool isOnLine)
listener(isOnLine);
}
+void WebLoaderStrategy::setEmulateOfflineState(bool offline) {
+ m_emulateOfflineState = offline;
+ for (auto& listener : m_onlineStateChangeListeners)
+ listener(offline ? false : m_isOnLine);
+}
+
void WebLoaderStrategy::setCaptureExtraNetworkLoadMetricsEnabled(bool enabled)
{
WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCaptureExtraNetworkLoadMetricsEnabled(enabled), 0);
diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h
index 9a78a5fe24da78b34ebefa785a07b5049ba473ba..17f4f626641629cb6c97d36b7361305a1f5d8258 100644
--- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h
+++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h
@@ -87,6 +87,7 @@ public:
bool isOnLine() const final;
void addOnlineStateChangeListener(Function<void(bool)>&&) final;
void setOnLineState(bool);
+ void setEmulateOfflineState(bool) final;
private:
void scheduleLoad(WebCore::ResourceLoader&, WebCore::CachedResource*, bool shouldClearReferrerOnHTTPSToHTTPRedirect);
@@ -125,6 +126,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 8e4c9375d7b8cc10ffa00803d482173be5a3558a..eaf27b62b1e73517bd4561719fc0065891afeb26 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
@@ -410,6 +410,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);
}
diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
index fbdf254ec42dc736ca0a00f521de8339f08ffbf2..5bd0472c37cc18d5dd6680e833fab3948acf80ff 100644
--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
+++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
@@ -242,12 +242,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 e0284a818241d7130cad2753ddb880008fa9955a..f21f2198159378efa3f71bfbfe69c2d8049dfeab 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
@@ -1568,6 +1568,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)
{
SendStopResponsivenessTimer stopper;
@@ -1751,17 +1767,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())
@@ -1778,20 +1790,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));
@@ -1799,7 +1809,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg
send(Messages::WebPageProxy::DidChangeViewportProperties(attr));
#endif
}
-#endif
void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
{
@@ -2081,6 +2090,7 @@ void WebPage::scaleView(double scale)
}
m_page->setViewScaleFactor(scale);
+ send(Messages::WebPageProxy::ViewScaleFactorDidChange(scale));
scalePage(pageScale, scrollPositionAtNewScale);
}
@@ -2185,17 +2195,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)
@@ -6318,6 +6324,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 f98e94647682ca734c6030eff7b82af3a39fc782..6aecd084fd7a4a2e4021540bc81855d1e0096e44 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.h
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h
@@ -1374,6 +1374,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&&);
@@ -1521,9 +1522,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);
@@ -1983,6 +1982,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 ab97b2b926059907ccdcf99cde9e5bf3d27d7a49..cd48a0a923b90fb4627cbe8ed61ea98a88e74318 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
@@ -167,6 +167,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 4b2409b994d3ae0d2b4314b345c28f1a4d37c709..883472a5a86e537a37ba40499155d27aa64837dd 100644
--- a/Source/WebKit/WebProcess/WebProcess.cpp
+++ b/Source/WebKit/WebProcess/WebProcess.cpp
@@ -78,6 +78,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>
@@ -254,6 +255,8 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter
platformInitializeProcess(parameters);
updateCPULimit();
+
+ Inspector::IdentifiersFactory::initializeWithProcessID(parameters.processIdentifier->toUInt64());
}
void WebProcess::initializeConnection(IPC::Connection* connection)
diff --git a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
index 472773e34a9f4b82b570ff1d5d73758d624cfa88..eed87820524670236eb4f5dad709f7c052f4a69e 100644
--- a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
+++ b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
@@ -4245,7 +4245,7 @@ static BOOL currentScrollIsBlit(NSView *clipView)
_private->handlingMouseDownEvent = NO;
}
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(IOS_TOUCH_EVENTS)
- (void)touch:(WebEvent *)event
{
diff --git a/Source/WebKitLegacy/mac/WebView/WebView.mm b/Source/WebKitLegacy/mac/WebView/WebView.mm
index 22a8804bc0a64648911807fb9c1c7713802f2374..92b977d48e03db0885629b62e0e9cc47df2fbe98 100644
--- a/Source/WebKitLegacy/mac/WebView/WebView.mm
+++ b/Source/WebKitLegacy/mac/WebView/WebView.mm
@@ -4339,7 +4339,7 @@ IGNORE_WARNINGS_END
}
#endif // PLATFORM(IOS_FAMILY)
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(IOS_TOUCH_EVENTS)
- (NSArray *)_touchEventRegions
{
auto* frame = [self _mainCoreFrame];
@@ -4385,7 +4385,7 @@ IGNORE_WARNINGS_END
return eventRegionArray;
}
-#endif // ENABLE(TOUCH_EVENTS)
+#endif // ENABLE(IOS_TOUCH_EVENTS)
// For backwards compatibility with the WebBackForwardList API, we honor both
// a per-WebView and a per-preferences setting for whether to use the back/forward cache.
diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake
index 361c860c8996d42deb7a8feec4980b5a3e704da2..c97db1dfa2a6c0fa82e00334cdfc344d16f757c5 100644
--- a/Source/cmake/OptionsGTK.cmake
+++ b/Source/cmake/OptionsGTK.cmake
@@ -3,6 +3,7 @@ include(VersioningUtils)
SET_PROJECT_VERSION(2 27 4)
set(WEBKITGTK_API_VERSION 4.0)
+set(ENABLE_WEBKIT_LEGACY OFF)
CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(WEBKIT 80 0 43)
CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(JAVASCRIPTCORE 34 0 16)
@@ -172,6 +173,13 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TYPED_OM PRIVATE ${ENABLE_EXPERIMENT
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_POINTER_EVENTS 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 925c79778498dfd76214d80ad37b46753664a9c7..6341c9922b6ee5754247c5b65b2a3a62eee99c04 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)
@@ -66,6 +67,14 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TYPED_OM PRIVATE ${ENABLE_EXPERIMENT
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_POINTER_EVENTS 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_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
index bca9670392b3d84895b4afc42575b4a1aeccba55..0c0faa7f0e8817261a09ec2536af5e52fa9f06d3 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 ()
@@ -93,6 +94,14 @@ 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_POINTER_EVENTS 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
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);
}
+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.h b/Tools/MiniBrowser/gtk/BrowserWindow.h
index 1570d65effb5d601ee3c44a2a7461436f4691c2c..456f96cf589320efa70a76f76e230b6795886b5a 100644
--- a/Tools/MiniBrowser/gtk/BrowserWindow.h
+++ b/Tools/MiniBrowser/gtk/BrowserWindow.h
@@ -37,7 +37,7 @@ G_BEGIN_DECLS
#define BROWSER_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), BROWSER_TYPE_WINDOW))
#define BROWSER_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), BROWSER_TYPE_WINDOW))
#define BROWSER_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), BROWSER_TYPE_WINDOW, BrowserWindowClass))
-#define BROWSER_DEFAULT_URL "http://www.webkitgtk.org/"
+#define BROWSER_DEFAULT_URL "about:blank"
#define BROWSER_ABOUT_SCHEME "minibrowser-about"
typedef struct _BrowserWindow BrowserWindow;
diff --git a/Tools/MiniBrowser/gtk/main.c b/Tools/MiniBrowser/gtk/main.c
index 4c5147dcd38a53e2feaeaae0fce38f92dc60eba6..4b1cab0c187352688740c7cca79483fa256aa7fe 100644
--- a/Tools/MiniBrowser/gtk/main.c
+++ b/Tools/MiniBrowser/gtk/main.c
@@ -53,6 +53,9 @@ static const char *cookiesFile;
static const char *cookiesPolicy;
static const char *proxy;
static gboolean darkMode;
+static gboolean inspectorPipe;
+static gboolean headless;
+static const char *userDataDir;
static gboolean printVersion;
typedef enum {
@@ -121,6 +124,9 @@ static const GOptionEntry commandLineOptions[] =
{ "ignore-tls-errors", 0, 0, G_OPTION_ARG_NONE, &ignoreTLSErrors, "Ignore TLS errors", NULL },
{ "content-filter", 0, 0, G_OPTION_ARG_FILENAME, &contentFilter, "JSON with content filtering rules", "FILE" },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WebKitGTK version", NULL },
+ { "inspector-pipe", 0, 0, G_OPTION_ARG_NONE, &inspectorPipe, "Open pipe connection to the remote inspector", NULL },
+ { "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 },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL…]" },
{ 0, 0, 0, 0, 0, 0, 0 }
};
@@ -498,6 +504,36 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul
g_main_loop_quit(data->mainLoop);
}
+static WebKitWebContext *persistentWebContext = NULL;
+
+static WebKitWebView *createNewPage(WebKitBrowserInspector *browser_inspector, WebKitWebContext *context)
+{
+ if (context == NULL)
+ context = persistentWebContext;
+
+ WebKitWebView *newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", context,
+ "is-ephemeral", webkit_web_context_is_ephemeral(context),
+ "is-controlled-by-automation", TRUE,
+ NULL));
+ GtkWidget *newWindow = browser_window_new(NULL, context);
+ 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(WebKitWebContext *webContext)
+{
+ persistentWebContext = webContext;
+
+ WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default();
+ g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL);
+
+ webkit_browser_inspector_initialize_pipe(NULL);
+}
+
int main(int argc, char *argv[])
{
#if ENABLE_DEVELOPER_MODE
@@ -541,10 +577,22 @@ int main(int argc, char *argv[])
return 0;
}
- WebKitWebsiteDataManager *manager = (privateMode || automationMode) ? webkit_website_data_manager_new_ephemeral() : webkit_website_data_manager_new(NULL);
+ WebKitWebsiteDataManager *manager;
+ if (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 = g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, "process-swap-on-cross-site-navigation-enabled", TRUE, NULL);
g_object_unref(manager);
+ if (inspectorPipe)
+ configureBrowserInspectorPipe(webContext);
+
if (cookiesPolicy) {
WebKitCookieManager *cookieManager = webkit_web_context_get_cookie_manager(webContext);
GEnumClass *enumClass = g_type_class_ref(WEBKIT_TYPE_COOKIE_ACCEPT_POLICY);
@@ -648,8 +696,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/win/BrowserWindow.h b/Tools/MiniBrowser/win/BrowserWindow.h
index 564dd6c29b950a213d83a397cf5edc18af170f29..9d772f310fb5fc13b360b45790ae5c01fa17935b 100644
--- a/Tools/MiniBrowser/win/BrowserWindow.h
+++ b/Tools/MiniBrowser/win/BrowserWindow.h
@@ -51,7 +51,6 @@ public:
virtual void print() = 0;
virtual void launchInspector() = 0;
- virtual void openProxySettings() = 0;
virtual _bstr_t userAgent() = 0;
void setUserAgent(UINT menuID);
diff --git a/Tools/MiniBrowser/win/Common.cpp b/Tools/MiniBrowser/win/Common.cpp
index 87fde928c12a91f13a4f8bc2f2dc24097e42f2d0..c81685683a61cfa9f39de2de695e3c7a9b0ab1e3 100644
--- a/Tools/MiniBrowser/win/Common.cpp
+++ b/Tools/MiniBrowser/win/Common.cpp
@@ -278,6 +278,12 @@ CommandLineOptions parseCommandLine()
#if ENABLE(WEBKIT)
else if (!wcsicmp(argv[i], L"--wk2") || !wcsicmp(argv[i], L"--webkit"))
options.windowType = BrowserWindowType::WebKit;
+ 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;
#endif
else if (!options.requestedURL)
options.requestedURL = argv[i];
diff --git a/Tools/MiniBrowser/win/Common.h b/Tools/MiniBrowser/win/Common.h
index d996feb64e02d7399f2ed0b34d3d0dd03133f824..4ab1fa69437ed5a11a5357a331cb7e1c6fbbb6ef 100644
--- a/Tools/MiniBrowser/win/Common.h
+++ b/Tools/MiniBrowser/win/Common.h
@@ -36,8 +36,11 @@ enum class BrowserWindowType {
struct CommandLineOptions {
bool usesLayeredWebView { };
bool useFullDesktop { };
+ bool inspectorPipe { };
+ bool headless { };
BrowserWindowType windowType;
_bstr_t requestedURL;
+ _bstr_t userDataDir;
CommandLineOptions()
#if ENABLE(WEBKIT)
diff --git a/Tools/MiniBrowser/win/MainWindow.cpp b/Tools/MiniBrowser/win/MainWindow.cpp
index 0502f0d3f9ef6325c3997eacb975f452011a8644..52bc1800ebc87ce84b3e5f1bb09ab1745da2b503 100644
--- a/Tools/MiniBrowser/win/MainWindow.cpp
+++ b/Tools/MiniBrowser/win/MainWindow.cpp
@@ -99,7 +99,10 @@ bool MainWindow::isInstance(HWND hwnd)
return s_windowClass == buff;
}
-MainWindow::MainWindow()
+MainWindow::MainWindow(WKContextRef context, WKWebsiteDataStoreRef dataStore, bool headless)
+ : m_context(context)
+ , m_dataStore(dataStore)
+ , m_headless(headless)
{
s_numInstances++;
}
@@ -109,9 +112,9 @@ MainWindow::~MainWindow()
s_numInstances--;
}
-Ref<MainWindow> MainWindow::create()
+Ref<MainWindow> MainWindow::create(WKContextRef context, WKWebsiteDataStoreRef dataStore, bool headless)
{
- return adoptRef(*new MainWindow());
+ return adoptRef(*new MainWindow(context, dataStore, headless));
}
bool MainWindow::init(BrowserWindowFactory factory, HINSTANCE hInstance, bool usesLayeredWebView)
@@ -120,29 +123,31 @@ bool MainWindow::init(BrowserWindowFactory factory, HINSTANCE hInstance, bool us
auto title = loadString(IDS_APP_TITLE);
- m_hMainWnd = CreateWindow(s_windowClass.c_str(), title.c_str(), WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance, this);
+ m_hMainWnd = CreateWindowExW(m_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 (!m_headless) {
#if !ENABLE(WEBKIT)
- EnableMenuItem(GetMenu(m_hMainWnd), IDM_NEW_WEBKIT_WINDOW, MF_GRAYED);
+ EnableMenuItem(GetMenu(m_hMainWnd), IDM_NEW_WEBKIT_WINDOW, MF_GRAYED);
#endif
#if !ENABLE(WEBKIT_LEGACY)
- EnableMenuItem(GetMenu(m_hMainWnd), IDM_NEW_WEBKITLEGACY_WINDOW, MF_GRAYED);
+ EnableMenuItem(GetMenu(m_hMainWnd), IDM_NEW_WEBKITLEGACY_WINDOW, MF_GRAYED);
#endif
- m_hBackButtonWnd = CreateWindow(L"BUTTON", L"<", WS_CHILD | WS_VISIBLE | BS_TEXT, 0, 0, 0, 0, m_hMainWnd, reinterpret_cast<HMENU>(IDM_HISTORY_BACKWARD), hInstance, 0);
- m_hForwardButtonWnd = CreateWindow(L"BUTTON", L">", WS_CHILD | WS_VISIBLE | BS_TEXT, 0, 0, 0, 0, m_hMainWnd, reinterpret_cast<HMENU>(IDM_HISTORY_FORWARD), hInstance, 0);
- m_hReloadButtonWnd = CreateWindow(L"BUTTON", L"↺", WS_CHILD | WS_VISIBLE | BS_TEXT, 0, 0, 0, 0, m_hMainWnd, reinterpret_cast<HMENU>(IDM_RELOAD), hInstance, 0);
- m_hURLBarWnd = CreateWindow(L"EDIT", 0, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, 0, 0, 0, 0, m_hMainWnd, 0, hInstance, 0);
- m_hProgressIndicator = CreateWindow(L"STATIC", 0, WS_CHILD | WS_VISIBLE | WS_BORDER | SS_CENTER | SS_CENTERIMAGE, 0, 0, 0, 0, m_hMainWnd, 0, hInstance, 0);
+ m_hBackButtonWnd = CreateWindow(L"BUTTON", L"<", WS_CHILD | WS_VISIBLE | BS_TEXT, 0, 0, 0, 0, m_hMainWnd, reinterpret_cast<HMENU>(IDM_HISTORY_BACKWARD), hInstance, 0);
+ m_hForwardButtonWnd = CreateWindow(L"BUTTON", L">", WS_CHILD | WS_VISIBLE | BS_TEXT, 0, 0, 0, 0, m_hMainWnd, reinterpret_cast<HMENU>(IDM_HISTORY_FORWARD), hInstance, 0);
+ m_hReloadButtonWnd = CreateWindow(L"BUTTON", L"↺", WS_CHILD | WS_VISIBLE | BS_TEXT, 0, 0, 0, 0, m_hMainWnd, reinterpret_cast<HMENU>(IDM_RELOAD), hInstance, 0);
+ m_hURLBarWnd = CreateWindow(L"EDIT", 0, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, 0, 0, 0, 0, m_hMainWnd, 0, hInstance, 0);
+ m_hProgressIndicator = CreateWindow(L"STATIC", 0, WS_CHILD | WS_VISIBLE | WS_BORDER | SS_CENTER | SS_CENTERIMAGE, 0, 0, 0, 0, m_hMainWnd, 0, hInstance, 0);
- DefEditProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(m_hURLBarWnd, GWLP_WNDPROC));
- SetWindowLongPtr(m_hURLBarWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(EditProc));
+ DefEditProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(m_hURLBarWnd, GWLP_WNDPROC));
+ SetWindowLongPtr(m_hURLBarWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(EditProc));
+ }
- m_browserWindow = factory(*this, m_hMainWnd, usesLayeredWebView);
+ m_browserWindow = factory(*this, m_hMainWnd, m_context.get(), m_dataStore.get(), usesLayeredWebView);
if (!m_browserWindow)
return false;
HRESULT hr = m_browserWindow->init();
@@ -151,7 +156,13 @@ bool MainWindow::init(BrowserWindowFactory factory, HINSTANCE hInstance, bool us
updateDeviceScaleFactor();
resizeSubViews();
- SetFocus(m_hURLBarWnd);
+
+ if (m_headless) {
+ SetMenu(m_hMainWnd, NULL);
+ } else {
+ SetFocus(m_hURLBarWnd);
+ ShowWindow(m_hMainWnd, SW_SHOW);
+ }
return true;
}
@@ -165,12 +176,13 @@ void MainWindow::resizeSubViews()
int height = scaleFactor * urlBarHeight;
int width = scaleFactor * controlButtonWidth;
- MoveWindow(m_hBackButtonWnd, 0, 0, width, height, TRUE);
- MoveWindow(m_hForwardButtonWnd, width, 0, width, height, TRUE);
- MoveWindow(m_hReloadButtonWnd, width * 2, 0, width, height, TRUE);
- MoveWindow(m_hURLBarWnd, width * 3, 0, rcClient.right - width * 5, height, TRUE);
- MoveWindow(m_hProgressIndicator, rcClient.right - width * 2, 0, width * 2, height, TRUE);
-
+ if (!m_headless) {
+ MoveWindow(m_hBackButtonWnd, 0, 0, width, height, TRUE);
+ MoveWindow(m_hForwardButtonWnd, width, 0, width, height, TRUE);
+ MoveWindow(m_hReloadButtonWnd, width * 2, 0, width, height, TRUE);
+ MoveWindow(m_hURLBarWnd, width * 3, 0, rcClient.right - width * 5, height, TRUE);
+ MoveWindow(m_hProgressIndicator, rcClient.right - width * 2, 0, width * 2, height, TRUE);
+ }
if (m_browserWindow->usesLayeredWebView() || !m_browserWindow->hwnd())
return;
MoveWindow(m_browserWindow->hwnd(), 0, height, rcClient.right, rcClient.bottom - height, TRUE);
@@ -211,17 +223,15 @@ LRESULT CALLBACK MainWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPA
break;
#if ENABLE(WEBKIT)
case IDM_NEW_WEBKIT_WINDOW: {
- auto& newWindow = MainWindow::create().leakRef();
+ auto& newWindow = MainWindow::create(thisWindow->m_context.get(), thisWindow->m_dataStore.get(), false).leakRef();
newWindow.init(WebKitBrowserWindow::create, hInst);
- ShowWindow(newWindow.hwnd(), SW_SHOW);
break;
}
#endif
#if ENABLE(WEBKIT_LEGACY)
case IDM_NEW_WEBKITLEGACY_WINDOW: {
- auto& newWindow = MainWindow::create().leakRef();
+ auto& newWindow = MainWindow::create(thisWindow->m_context.get(), thisWindow->m_dataStore.get(), false).leakRef();
newWindow.init(WebKitLegacyBrowserWindow::create, hInst);
- ShowWindow(newWindow.hwnd(), SW_SHOW);
break;
}
#endif
@@ -240,9 +250,6 @@ LRESULT CALLBACK MainWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPA
case IDM_WEB_INSPECTOR:
thisWindow->browserWindow()->launchInspector();
break;
- case IDM_PROXY_SETTINGS:
- thisWindow->browserWindow()->openProxySettings();
- break;
case IDM_CACHES:
if (!::IsWindow(thisWindow->m_hCacheWnd)) {
thisWindow->m_hCacheWnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_CACHES), hWnd, cachesDialogProc, reinterpret_cast<LPARAM>(thisWindow.get()));
@@ -329,6 +336,9 @@ static void turnOffOtherUserAgents(HMENU menu)
bool MainWindow::toggleMenuItem(UINT menuID)
{
+ if (m_headless)
+ return (INT_PTR)FALSE;
+
HMENU menu = ::GetMenu(hwnd());
switch (menuID) {
@@ -405,6 +415,8 @@ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
INT_PTR CALLBACK MainWindow::cachesDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
MainWindow& thisWindow = *reinterpret_cast<MainWindow*>(GetWindowLongPtr(hDlg, DWLP_USER));
+ if (thisWindow.m_headless)
+ return (INT_PTR)FALSE;
switch (message) {
case WM_INITDIALOG:
SetWindowLongPtr(hDlg, DWLP_USER, lParam);
@@ -435,6 +447,8 @@ INT_PTR CALLBACK MainWindow::cachesDialogProc(HWND hDlg, UINT message, WPARAM wP
INT_PTR CALLBACK MainWindow::customUserAgentDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
MainWindow& thisWindow = *reinterpret_cast<MainWindow*>(GetWindowLongPtr(hDlg, DWLP_USER));
+ if (thisWindow.m_headless)
+ return (INT_PTR)FALSE;
switch (message) {
case WM_INITDIALOG: {
MainWindow& thisWindow = *reinterpret_cast<MainWindow*>(lParam);
@@ -480,17 +494,20 @@ void MainWindow::loadURL(std::wstring url)
if (SUCCEEDED(::UrlCreateFromPath(url.c_str(), fileURL, &fileURLLength, 0)))
url = fileURL;
}
- if (url.find(L"://") == url.npos)
+ 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;
- SetFocus(m_browserWindow->hwnd());
+ if (!m_headless)
+ SetFocus(m_browserWindow->hwnd());
}
void MainWindow::onURLBarEnter()
{
+ if (m_headless)
+ return;
wchar_t strPtr[INTERNET_MAX_URL_LENGTH];
GetWindowText(m_hURLBarWnd, strPtr, INTERNET_MAX_URL_LENGTH);
strPtr[INTERNET_MAX_URL_LENGTH - 1] = 0;
@@ -499,6 +516,8 @@ void MainWindow::onURLBarEnter()
void MainWindow::updateDeviceScaleFactor()
{
+ if (m_headless)
+ return;
if (m_hURLBarFont)
::DeleteObject(m_hURLBarFont);
auto scaleFactor = WebCore::deviceScaleFactorForWindow(m_hMainWnd);
@@ -510,6 +529,8 @@ void MainWindow::updateDeviceScaleFactor()
void MainWindow::progressChanged(double progress)
{
+ if (m_headless)
+ return;
std::wostringstream text;
text << static_cast<int>(progress * 100) << L'%';
SetWindowText(m_hProgressIndicator, text.str().c_str());
@@ -517,10 +538,14 @@ void MainWindow::progressChanged(double progress)
void MainWindow::progressFinished()
{
+ if (m_headless)
+ return;
SetWindowText(m_hProgressIndicator, L"");
}
void MainWindow::activeURLChanged(std::wstring url)
{
+ if (m_headless)
+ return;
SetWindowText(m_hURLBarWnd, url.c_str());
}
diff --git a/Tools/MiniBrowser/win/MainWindow.h b/Tools/MiniBrowser/win/MainWindow.h
index 61e75ba190ee2de5e4229cb4baae85248a9b35b3..a2a92644239b2aa4aa27d5da848ed97cbec279e0 100644
--- a/Tools/MiniBrowser/win/MainWindow.h
+++ b/Tools/MiniBrowser/win/MainWindow.h
@@ -26,6 +26,8 @@
#pragma once
#include "BrowserWindow.h"
+#include <WebKit/WKBase.h>
+#include <WebKit/WKRetainPtr.h>
#include <functional>
#include <memory>
#include <string>
@@ -33,9 +35,9 @@
class MainWindow final : public RefCounted<MainWindow>, public BrowserWindowClient {
public:
- using BrowserWindowFactory = std::function<Ref<BrowserWindow>(BrowserWindowClient&, HWND mainWnd, bool usesLayeredWebView)>;
+ using BrowserWindowFactory = std::function<Ref<BrowserWindow>(BrowserWindowClient&, HWND mainWnd, WKContextRef, WKWebsiteDataStoreRef, bool usesLayeredWebView)>;
- static Ref<MainWindow> create();
+ static Ref<MainWindow> create(WKContextRef context, WKWebsiteDataStoreRef dataStore, bool headless);
~MainWindow();
bool init(BrowserWindowFactory, HINSTANCE hInstance, bool usesLayeredWebView = false);
@@ -56,7 +58,7 @@ private:
static std::wstring s_windowClass;
static size_t s_numInstances;
- MainWindow();
+ MainWindow(WKContextRef context, WKWebsiteDataStoreRef dataStore, bool headless);
bool toggleMenuItem(UINT menuID);
void onURLBarEnter();
void updateDeviceScaleFactor();
@@ -74,5 +76,8 @@ private:
HWND m_hProgressIndicator { nullptr };
HWND m_hCacheWnd { nullptr };
HGDIOBJ m_hURLBarFont { nullptr };
+ WKRetainPtr<WKContextRef> m_context;
+ WKRetainPtr<WKWebsiteDataStoreRef> m_dataStore;
RefPtr<BrowserWindow> m_browserWindow;
+ bool m_headless;
};
diff --git a/Tools/MiniBrowser/win/WebKitBrowserWindow.cpp b/Tools/MiniBrowser/win/WebKitBrowserWindow.cpp
index f590685184e78882f611164a284eb36bf50b5099..43c27fdbdd1e5df25bfb3164edd43b03e6fca527 100644
--- a/Tools/MiniBrowser/win/WebKitBrowserWindow.cpp
+++ b/Tools/MiniBrowser/win/WebKitBrowserWindow.cpp
@@ -39,6 +39,8 @@
#include <WebKit/WKWebsiteDataStoreRefCurl.h>
#include <vector>
+static bool s_headless = false;
+
std::wstring createString(WKStringRef wkString)
{
size_t maxSize = WKStringGetLength(wkString);
@@ -107,7 +109,7 @@ WKRetainPtr<WKURLRef> createWKURL(const std::wstring& str)
return adoptWK(WKURLCreateWithUTF8CString(utf8.data()));
}
-Ref<BrowserWindow> WebKitBrowserWindow::create(BrowserWindowClient& client, HWND mainWnd, bool)
+Ref<BrowserWindow> WebKitBrowserWindow::create(BrowserWindowClient& client, HWND mainWnd, WKContextRef context, WKWebsiteDataStoreRef dataStore, bool)
{
auto conf = adoptWK(WKPageConfigurationCreate());
@@ -121,8 +123,8 @@ Ref<BrowserWindow> WebKitBrowserWindow::create(BrowserWindowClient& client, HWND
WKPreferencesSetDeveloperExtrasEnabled(prefs.get(), true);
WKPageConfigurationSetPreferences(conf.get(), prefs.get());
- auto context =adoptWK(WKContextCreateWithConfiguration(nullptr));
- WKPageConfigurationSetContext(conf.get(), context.get());
+ WKPageConfigurationSetContext(conf.get(), context);
+ WKPageConfigurationSetWebsiteDataStore(conf.get(), dataStore);
return adoptRef(*new WebKitBrowserWindow(client, conf.get(), mainWnd));
}
@@ -143,11 +145,17 @@ WebKitBrowserWindow::WebKitBrowserWindow(BrowserWindowClient& client, WKPageConf
navigationClient.didReceiveAuthenticationChallenge = didReceiveAuthenticationChallenge;
WKPageSetPageNavigationClient(page, &navigationClient.base);
- WKPageUIClientV13 uiClient = { };
- uiClient.base.version = 13;
+ 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 = { };
@@ -159,28 +167,30 @@ WebKitBrowserWindow::WebKitBrowserWindow(BrowserWindowClient& client, WKPageConf
stateClient.didChangeActiveURL = didChangeActiveURL;
WKPageSetPageStateClient(page, &stateClient.base);
- updateProxySettings();
resetZoom();
}
-void WebKitBrowserWindow::updateProxySettings()
+WebKitBrowserWindow::~WebKitBrowserWindow()
{
- auto context = WKPageGetContext(WKViewGetPage(m_view.get()));
- auto store = WKWebsiteDataStoreGetDefaultDataStore();
+ if (m_alertDialog) {
+ WKRelease(m_alertDialog);
+ m_alertDialog = NULL;
+ }
- if (!m_proxy.enable) {
- WKWebsiteDataStoreDisableNetworkProxySettings(store);
- return;
+ if (m_confirmDialog) {
+ WKRelease(m_confirmDialog);
+ m_confirmDialog = NULL;
}
- if (!m_proxy.custom) {
- WKWebsiteDataStoreEnableDefaultNetworkProxySettings(store);
- return;
+ if (m_promptDialog) {
+ WKRelease(m_promptDialog);
+ m_promptDialog = NULL;
}
- auto url = createWKURL(m_proxy.url);
- auto excludeHosts = createWKString(m_proxy.excludeHosts);
- WKWebsiteDataStoreEnableCustomNetworkProxySettings(store, url.get(), excludeHosts.get());
+ if (m_beforeUnloadDialog) {
+ WKRelease(m_beforeUnloadDialog);
+ m_beforeUnloadDialog = NULL;
+ }
}
HRESULT WebKitBrowserWindow::init()
@@ -247,13 +257,6 @@ void WebKitBrowserWindow::launchInspector()
WKInspectorShow(inspector);
}
-void WebKitBrowserWindow::openProxySettings()
-{
- if (askProxySettings(m_hMainWnd, m_proxy))
- updateProxySettings();
-
-}
-
void WebKitBrowserWindow::setUserAgent(_bstr_t& customUAString)
{
auto page = WKViewGetPage(m_view.get());
@@ -381,18 +384,100 @@ bool WebKitBrowserWindow::canTrustServerCertificate(WKProtectionSpaceRef protect
return false;
}
-WKPageRef WebKitBrowserWindow::createNewPage(WKPageRef page, WKPageConfigurationRef configuration, WKNavigationActionRef navigationAction, WKWindowFeaturesRef windowFeatures, const void *clientInfo)
+// static
+void WebKitBrowserWindow::setHeadless(bool headless)
+{
+ s_headless = headless;
+}
+
+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 = MainWindow::create().leakRef();
- auto factory = [configuration](BrowserWindowClient& client, HWND mainWnd, bool) -> auto {
+ auto context = WKPageConfigurationGetContext(configuration);
+ auto dataStore = WKPageConfigurationGetWebsiteDataStore(configuration);
+ auto& newWindow = MainWindow::create(context, dataStore, s_headless).leakRef();
+ auto factory = [configuration](BrowserWindowClient& client, HWND mainWnd, WKContextRef, WKWebsiteDataStoreRef, bool) -> auto {
return adoptRef(*new WebKitBrowserWindow(client, configuration, mainWnd));
};
bool ok = newWindow.init(factory, hInst);
- if (!ok)
- return nullptr;
- ShowWindow(newWindow.hwnd(), SW_SHOW);
+ if (navigate)
+ newWindow.browserWindow()->loadURL(_bstr_t("about:blank").GetBSTR());
+
auto& newBrowserWindow = *static_cast<WebKitBrowserWindow*>(newWindow.browserWindow());
- WKRetainPtr<WKPageRef> newPage = WKViewGetPage(newBrowserWindow.m_view.get());
+ 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();
}
diff --git a/Tools/MiniBrowser/win/WebKitBrowserWindow.h b/Tools/MiniBrowser/win/WebKitBrowserWindow.h
index e8efe3c2838a9bb553a1c59ff6c1fb25d2f96500..9131c6e8259772c8e8c066125acfac82f408ddb9 100644
--- a/Tools/MiniBrowser/win/WebKitBrowserWindow.h
+++ b/Tools/MiniBrowser/win/WebKitBrowserWindow.h
@@ -26,6 +26,7 @@
#include "BrowserWindow.h"
#include "Common.h"
+#include <WebKit/WKBase.h>
#include <WebKit/WKRetainPtr.h>
#include <WebKit/WebKit2_C.h>
#include <unordered_map>
@@ -33,10 +34,14 @@
class WebKitBrowserWindow : public BrowserWindow {
public:
- static Ref<BrowserWindow> create(BrowserWindowClient&, HWND mainWnd, bool useLayeredWebView = false);
+ static Ref<BrowserWindow> create(BrowserWindowClient&, HWND mainWnd, WKContextRef, WKWebsiteDataStoreRef, bool useLayeredWebView = false);
+ static void setHeadless(bool headless);
+ static WKPageRef createPageCallback(WKPageConfigurationRef);
private:
+ static WKPageRef createViewCallback(WKPageConfigurationRef, bool navigate);
WebKitBrowserWindow(BrowserWindowClient&, WKPageConfigurationRef, HWND mainWnd);
+ ~WebKitBrowserWindow() override;
HRESULT init() override;
HWND hwnd() override;
@@ -49,7 +54,6 @@ private:
void print() override;
void launchInspector() override;
- void openProxySettings() override;
_bstr_t userAgent() override;
void setUserAgent(_bstr_t&) override;
@@ -61,8 +65,6 @@ private:
void zoomIn() override;
void zoomOut() override;
- void updateProxySettings();
-
bool canTrustServerCertificate(WKProtectionSpaceRef);
static void didChangeTitle(const void*);
@@ -71,6 +73,12 @@ private:
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*);
BrowserWindowClient& m_client;
@@ -78,4 +86,8 @@ private:
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/MiniBrowser/win/WebKitLegacyBrowserWindow.cpp b/Tools/MiniBrowser/win/WebKitLegacyBrowserWindow.cpp
index f81a9be39f3f6d88a5ba3a418af5d5e84c8fc146..76ae501e345e3da400143f040361abf5d0df196c 100644
--- a/Tools/MiniBrowser/win/WebKitLegacyBrowserWindow.cpp
+++ b/Tools/MiniBrowser/win/WebKitLegacyBrowserWindow.cpp
@@ -407,10 +407,6 @@ void WebKitLegacyBrowserWindow::launchInspector()
m_inspector->show();
}
-void WebKitLegacyBrowserWindow::openProxySettings()
-{
-}
-
void WebKitLegacyBrowserWindow::navigateForwardOrBackward(UINT menuID)
{
if (!m_webView)
diff --git a/Tools/MiniBrowser/win/WebKitLegacyBrowserWindow.h b/Tools/MiniBrowser/win/WebKitLegacyBrowserWindow.h
index f84e5cde0baaa08dab1fc77771e4a62a08a5df78..dac73d3d9db04c5d502432cea8adfa89640dee09 100644
--- a/Tools/MiniBrowser/win/WebKitLegacyBrowserWindow.h
+++ b/Tools/MiniBrowser/win/WebKitLegacyBrowserWindow.h
@@ -77,7 +77,6 @@ private:
void showLastVisitedSites(IWebView&);
void launchInspector();
- void openProxySettings();
void navigateForwardOrBackward(UINT menuID);
void navigateToHistory(UINT menuID);
bool seedInitialDefaultPreferences();
diff --git a/Tools/MiniBrowser/win/WinMain.cpp b/Tools/MiniBrowser/win/WinMain.cpp
index 62386f690b09335b5dc7c6fdd80bd9b62c3856aa..6886dab6dd9d37ddc8cd9a7bc39df7d5dc48e4c4 100644
--- a/Tools/MiniBrowser/win/WinMain.cpp
+++ b/Tools/MiniBrowser/win/WinMain.cpp
@@ -32,6 +32,9 @@
#include "Common.h"
#include "MiniBrowserLibResource.h"
#include "MiniBrowserReplace.h"
+#include <WebKit/WKContext.h>
+#include <WebKit/WKWebsiteDataStoreConfigurationRef.h>
+#include <WebKit/WKWebsiteDataStoreRef.h>
#include <wtf/win/SoftLinking.h>
#if USE(CF)
@@ -47,11 +50,31 @@
#include <WebKitLegacy/WebKitCOMAPI.h>
#endif
+#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)
{
+#if ENABLE(WEBKIT)
+ // WebKit2 does not use RunLoop.
+ WTF::initializeMainThread();
+#endif
#ifdef _CRTDBG_MAP_ALLOC
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
@@ -67,6 +90,12 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
InitCommonControlsEx(&InitCtrlEx);
auto options = parseCommandLine();
+ if (options.inspectorPipe) {
+ WebKitBrowserWindow::setHeadless(options.headless);
+ WKInspectorInitializeRemoteInspectorPipe(
+ WebKitBrowserWindow::createPageCallback,
+ []() { PostQuitMessage(0); });
+ }
if (options.useFullDesktop)
computeFullDesktopFrame();
@@ -75,9 +104,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
OleInitialize(nullptr);
if (SetProcessDpiAwarenessContextPtr())
- SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
- else
- ::SetProcessDPIAware();
+ SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_UNAWARE);
#if !ENABLE(WEBKIT_LEGACY)
auto factory = WebKitBrowserWindow::create;
@@ -86,20 +113,36 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
#else
auto factory = options.windowType == BrowserWindowType::WebKit ? WebKitBrowserWindow::create : WebKitLegacyBrowserWindow::create;
#endif
- auto& mainWindow = MainWindow::create().leakRef();
+
+ 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 = MainWindow::create(context.get(), dataStore.get(), options.headless).leakRef();
HRESULT hr = mainWindow.init(factory, hInst, options.usesLayeredWebView);
if (FAILED(hr))
goto exit;
- ShowWindow(mainWindow.hwnd(), nCmdShow);
-
hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_MINIBROWSER));
hPreAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCELERATORS_PRE));
if (options.requestedURL.length())
mainWindow.loadURL(options.requestedURL.GetBSTR());
else
- mainWindow.browserWindow()->loadURL(_bstr_t(defaultURL).GetBSTR());
+ mainWindow.loadURL(_bstr_t("about:blank").GetBSTR());
#pragma warning(disable:4509)
diff --git a/Tools/MiniBrowser/wpe/CMakeLists.txt b/Tools/MiniBrowser/wpe/CMakeLists.txt
index 245f319abf2595e154d03e1ee8b3250d7f46aafd..9cae87b23deade7c163f34aade2b2aed91d47fc8 100644
--- a/Tools/MiniBrowser/wpe/CMakeLists.txt
+++ b/Tools/MiniBrowser/wpe/CMakeLists.txt
@@ -13,6 +13,7 @@ set(MiniBrowser_INCLUDE_DIRECTORIES
set(MiniBrowser_SYSTEM_INCLUDE_DIRECTORIES
${ATK_INCLUDE_DIRS}
+ ${GLIB_INCLUDE_DIRS}
${WPE_INCLUDE_DIRS}
${WPEBACKEND_FDO_INCLUDE_DIRS}
)
diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp
index a0ca94ac2dcc005b403180aa11407ff7b33dcbc6..ad155edd606477ecfc4a72c524df1fa5af33bab8 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,8 @@ static gboolean headlessMode;
static gboolean privateMode;
static gboolean automationMode;
static gboolean ignoreTLSErrors;
+static gboolean inspectorPipe;
+static const char* userDataDir;
static const char* contentFilter;
static const char* cookiesFile;
static const char* cookiesPolicy;
@@ -63,6 +65,8 @@ 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" },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, nullptr, "[URL]" },
{ nullptr, 0, 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr }
};
@@ -131,7 +135,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);
}
@@ -147,12 +151,33 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul
g_main_loop_quit(data->mainLoop);
}
+static gboolean webViewLoadFailed()
+{
+ return TRUE;
+}
+
static void webViewClose(WebKitWebView* webView, gpointer)
{
g_object_unref(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();
@@ -164,14 +189,56 @@ 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));
+ }
+ auto* settings = webkit_settings_new_with_settings(
+ "enable-developer-extras", TRUE,
+ "enable-webgl", TRUE,
+ "enable-media-stream", TRUE,
+ "enable-encrypted-media", TRUE,
+ nullptr);
+ webkit_web_view_set_settings(newWebView, settings);
g_signal_connect(newWebView, "close", G_CALLBACK(webViewClose), nullptr);
-
+ 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, WebKitWebContext *webContext)
+{
+ persistentWebContext = webContext;
+
+ 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
@@ -215,7 +282,18 @@ 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));
+ g_object_unref(manager);
if (cookiesPolicy) {
auto* cookieManager = webkit_web_context_get_cookie_manager(webContext);
@@ -280,6 +358,9 @@ int main(int argc, char *argv[])
delete static_cast<WPEToolingBackends::ViewBackend*>(data);
}, backend.release());
+ if (inspectorPipe)
+ configureBrowserInspector(loop, webContext);
+
auto* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
"backend", viewBackend,
"web-context", webContext,
@@ -300,7 +381,9 @@ int main(int argc, char *argv[])
g_signal_connect(webContext, "automation-started", G_CALLBACK(automationStartedCallback), webView);
g_signal_connect(webView, "permission-request", G_CALLBACK(decidePermissionRequest), nullptr);
g_signal_connect(webView, "create", G_CALLBACK(createWebView), nullptr);
- g_signal_connect(webView, "close", G_CALLBACK(webViewClose), nullptr);
+ // FIXME(yurys): next line was added in https://trac.webkit.org/r256302 and causes
+ // use after free crashing in playwright. See https://webkit.org/b/207529#c7
+ // g_signal_connect(webView, "close", G_CALLBACK(webViewClose), nullptr);
if (ignoreTLSErrors)
webkit_web_context_set_tls_errors_policy(webContext, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
@@ -319,7 +402,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");
@@ -327,8 +410,7 @@ int main(int argc, char *argv[])
g_main_loop_run(loop);
g_object_unref(webView);
- if (privateMode || automationMode)
- g_object_unref(webContext);
+ g_object_unref(webContext);
g_main_loop_unref(loop);
return 0;
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);
+
+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;
+
+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);
+
+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..41b5751cab626971cd12c5066218c6d14c00fba0
--- /dev/null
+++ b/Tools/Playwright/mac/AppDelegate.h
@@ -0,0 +1,55 @@
+/*
+ * 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>
+
+@interface WebViewDialog : NSObject
+@property (nonatomic, strong) WKWebView *webView;
+@property (nonatomic, copy) void (^completionHandler)(BOOL accept, NSString* value);
+@end
+
+@interface BrowserAppDelegate : NSObject <NSApplicationDelegate, WKUIDelegate, _WKBrowserInspectorDelegate> {
+ NSMutableSet *_browserWindowControllers;
+ NSMutableSet *_headlessWindows;
+ NSMutableSet *_browserContexts;
+ bool _headless;
+ NSMutableSet *_dialogs;
+ NSString* _initialURL;
+ NSString* _userDataDir;
+ IBOutlet NSMenuItem *_newWebKit2WindowItem;
+}
+
+- (void)browserWindowWillClose:(NSWindow *)window;
+
+@property (readonly, nonatomic) WKUserContentController *userContentContoller;
+@property (readonly, nonatomic) WKPreferences *defaultPreferences;
+
+@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..828d172381e12ea0455045fdc098dfa7726ae040
--- /dev/null
+++ b/Tools/Playwright/mac/AppDelegate.m
@@ -0,0 +1,488 @@
+/*
+ * 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/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/_WKExperimentalFeature.h>
+#import <WebKit/_WKInternalDebugFeature.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
+#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
+
+enum {
+ WebKit1NewWindowTag = 1,
+ WebKit2NewWindowTag = 2,
+ WebKit1NewEditorTag = 3,
+ WebKit2NewEditorTag = 4
+};
+
+@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
+@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"];
+ _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];
+ configuration.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration AndDataStore:configuration.websiteDataStore] autorelease];
+ }
+ return configuration;
+}
+
+- (WKPreferences *)defaultPreferences
+{
+ return self.defaultConfiguration.preferences;
+}
+
+- (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;
+}
+
+- (IBAction)newWindow:(id)sender
+{
+ BrowserWindowController *controller = [self createBrowserWindowController:sender];
+ if (!controller)
+ return;
+
+ [[controller window] makeKeyAndOrderFront:sender];
+ [controller loadURLString:@"about:blank"];
+}
+
+- (IBAction)newPrivateWindow:(id)sender
+{
+ if (_headless)
+ return;
+
+ WKWebViewConfiguration *privateConfiguraton = [self.defaultConfiguration copy];
+ privateConfiguraton.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
+
+ BrowserWindowController *controller = [[BrowserWindowController alloc] initWithConfiguration:privateConfiguraton];
+ [privateConfiguraton release];
+
+ [[controller window] makeKeyAndOrderFront:sender];
+ [_browserWindowControllers addObject:controller];
+
+ [controller loadURLString:@"about:blank"];
+}
+
+- (void)browserWindowWillClose:(NSWindow *)window
+{
+ [_browserWindowControllers removeObject:window.windowController];
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
+{
+ if (_headless) {
+ [self createNewPage:0];
+ return;
+ }
+
+ WebHistory *webHistory = [[WebHistory alloc] init];
+ [WebHistory setOptionalSharedHistory:webHistory];
+ [webHistory release];
+
+ [self _updateNewWindowKeyEquivalents];
+ if (!_initialURL)
+ [self newWindow:self];
+ _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;
+}
+
+- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
+{
+ BrowserWindowController *controller = [self createBrowserWindowController:nil];
+ if (!controller)
+ return NO;
+
+ [controller.window makeKeyAndOrderFront:self];
+ [controller loadURLString:_initialURL ? _initialURL : [NSURL fileURLWithPath:filename].absoluteString];
+ return YES;
+}
+
+- (IBAction)openDocument:(id)sender
+{
+ if (_headless)
+ return;
+
+ BrowserWindowController *browserWindowController = [self frontmostBrowserWindowController];
+
+ if (browserWindowController) {
+ NSOpenPanel *openPanel = [[NSOpenPanel openPanel] retain];
+ [openPanel beginSheetModalForWindow:browserWindowController.window completionHandler:^(NSInteger result) {
+ if (result != NSModalResponseOK)
+ return;
+
+ NSURL *url = [openPanel.URLs objectAtIndex:0];
+ [browserWindowController loadURLString:[url absoluteString]];
+ }];
+ return;
+ }
+
+ NSOpenPanel *openPanel = [NSOpenPanel openPanel];
+ [openPanel beginWithCompletionHandler:^(NSInteger result) {
+ if (result != NSModalResponseOK)
+ return;
+
+ BrowserWindowController *controller = [self createBrowserWindowController:nil];
+ [controller.window makeKeyAndOrderFront:self];
+
+ NSURL *url = [openPanel.URLs objectAtIndex:0];
+ [controller loadURLString:[url absoluteString]];
+ }];
+}
+
+- (void)_updateNewWindowKeyEquivalents
+{
+ NSString *normalWindowEquivalent = @"n";
+ _newWebKit2WindowItem.keyEquivalentModifierMask = NSEventModifierFlagCommand;
+ _newWebKit2WindowItem.keyEquivalent = normalWindowEquivalent;
+}
+
+- (WKUserContentController *)userContentContoller
+{
+ return self.defaultConfiguration.userContentController;
+}
+
+#pragma mark WKBrowserInspectorDelegate
+
+- (WKWebViewConfiguration *) sessionConfiguration:(uint64_t)sessionID
+{
+ for (_WKBrowserContext *browserContext in _browserContexts) {
+ if ([[browserContext dataStore] sessionID] != sessionID)
+ continue;
+ WKWebViewConfiguration *configuration = [[[self defaultConfiguration] copy] autorelease];
+ configuration.websiteDataStore = [browserContext dataStore];
+ configuration.processPool = [browserContext processPool];
+ return configuration;
+ }
+ return [self defaultConfiguration];
+}
+
+- (WKWebView *)createNewPage:(uint64_t)sessionID
+{
+ if (_headless)
+ return [self createHeadlessPage:sessionID];
+
+ WKWebViewConfiguration *configuration = [self sessionConfiguration:sessionID];
+ BrowserWindowController *controller = [[[BrowserWindowController alloc] initWithConfiguration:configuration] autorelease];
+ if (!controller)
+ return nil;
+ [[controller window] makeKeyAndOrderFront:nil];
+ [_browserWindowControllers addObject:controller];
+ [controller loadURLString:@"about:blank"];
+ return [controller webView];
+}
+
+- (WKWebView *)createHeadlessWebView:(WKWebViewConfiguration *)configuration forPopup:(BOOL)popup
+{
+ 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 (!popup) {
+ NSURL *url = [NSURL _webkit_URLWithUserTypedString:_initialURL ? _initialURL : @"about:blank"];
+ _initialURL = nil;
+ [webView loadRequest:[NSURLRequest requestWithURL:url]];
+ }
+ [_headlessWindows addObject:window];
+ webView.UIDelegate = self;
+ return [webView autorelease];
+}
+
+- (WKWebView *)createHeadlessPage:(uint64_t)sessionID
+{
+ WKWebViewConfiguration *configuration = [self sessionConfiguration:sessionID];
+ return [self createHeadlessWebView:configuration forPopup:NO];
+}
+
+- (_WKBrowserContext *)createBrowserContext
+{
+ _WKBrowserContext *browserContext = [[_WKBrowserContext alloc] init];
+ _WKProcessPoolConfiguration *processConfiguration = [[[_WKProcessPoolConfiguration alloc] init] autorelease];
+ browserContext.dataStore = [WKWebsiteDataStore nonPersistentDataStore];
+ browserContext.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration] autorelease];
+ [_browserContexts addObject:browserContext];
+ return browserContext;
+}
+
+- (void)deleteBrowserContext:(uint64_t)sessionID
+{
+ for (_WKBrowserContext *browserContext in _browserContexts) {
+ if ([[browserContext dataStore] sessionID] != sessionID)
+ continue;
+ [_browserContexts removeObject:browserContext];
+ return;
+ }
+}
+
+- (void)quit
+{
+ [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
+}
+
+#pragma mark WKUIDelegate
+
+- (void)webViewDidClose:(WKWebView *)webView {
+ for (NSWindow *window in _headlessWindows) {
+ if (webView.window != window)
+ continue;
+ [webView removeFromSuperview];
+ [window close];
+ [_headlessWindows removeObject:window];
+ break;
+ }
+}
+
+- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
+{
+ WebViewDialog* dialog = [[WebViewDialog alloc] autorelease];
+ dialog.webView = webView;
+ dialog.completionHandler = ^void (BOOL accept, NSString* value) {
+ completionHandler();
+ [_dialogs removeObject:dialog];
+ };
+ [_dialogs addObject:dialog];
+}
+
+- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
+{
+ WebViewDialog* dialog = [[WebViewDialog alloc] autorelease];
+ dialog.webView = webView;
+ dialog.completionHandler = ^void (BOOL accept, NSString* value) {
+ completionHandler(accept);
+ [_dialogs removeObject:dialog];
+ };
+ [_dialogs addObject:dialog];
+}
+
+- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *result))completionHandler
+{
+ WebViewDialog* dialog = [[WebViewDialog alloc] autorelease];
+ dialog.webView = webView;
+ dialog.completionHandler = ^void (BOOL accept, NSString* value) {
+ completionHandler(accept && value ? value : nil);
+ [_dialogs removeObject:dialog];
+ };
+ [_dialogs addObject:dialog];
+}
+
+- (void)_webView:(WKWebView *)webView runBeforeUnloadConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
+{
+ WebViewDialog* dialog = [[WebViewDialog alloc] autorelease];
+ dialog.webView = webView;
+ dialog.completionHandler = ^void (BOOL accept, NSString* value) {
+ completionHandler(accept);
+ [_dialogs removeObject:dialog];
+ };
+ [_dialogs addObject:dialog];
+}
+
+- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(NSString *)value
+{
+ for (WebViewDialog *dialog in _dialogs) {
+ if (dialog.webView != webView)
+ continue;
+ dialog.completionHandler(accept, value);
+ break;
+ }
+}
+
+- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
+{
+ return [self createHeadlessWebView:configuration forPopup:YES];
+}
+
+@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..72edf5c432f58659765d16dabdb536b44942b1f2
--- /dev/null
+++ b/Tools/Playwright/mac/BrowserWindowController.m
@@ -0,0 +1,828 @@
+/*
+ * 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/WKNavigationDelegate.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
+{
+ LOG(@"decidePolicyForNavigationResponse");
+ 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
+{
+ return _webView;
+}
+
+- (void)findBarViewDidChangeHeight
+{
+}
+
+- (void)_webView:(WKWebView *)webView requestMediaCaptureAuthorization: (_WKCaptureDevices)devices decisionHandler:(void (^)(BOOL authorized))decisionHandler
+{
+ decisionHandler(true);
+}
+
+- (void)_webView:(WKWebView *)webView includeSensitiveMediaDeviceDetails:(void (^)(BOOL includeSensitiveDetails))decisionHandler
+{
+ decisionHandler(false);
+}
+
+- (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];
+ }];
+ }
+ }];
+}
+
+- (IBAction)saveAsWebArchive:(id)sender
+{
+ 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];
+ }];
+ }
+ }];
+}
+
+- (WKWebView *)webView
+{
+ return _webView;
+}
+
+@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..a291f32251271200132b8eb08d513f6936e5a0a5
--- /dev/null
+++ b/Tools/Playwright/mac/MainMenu.xib
@@ -0,0 +1,366 @@
+<?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 title="New Window" tag="2" keyEquivalent="n" id="571">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="newWindow:" target="-1" id="572"/>
+ </connections>
+ </menuItem>
+ <menuItem title="New Private Window" tag="2" id="Zqs-AO-XAX">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="newPrivateWindow:" target="-1" id="mf5-zi-a5R"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Open…" keyEquivalent="o" id="72">
+ <connections>
+ <action selector="openDocument:" target="-1" id="374"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Open Recent" id="124">
+ <menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
+ <items>
+ <menuItem title="Clear Menu" id="126">
+ <connections>
+ <action selector="clearRecentDocuments:" target="-1" id="127"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </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">
+ <connections>
+ <outlet property="_newWebKit2WindowItem" destination="571" id="1Gv-mK-aul"/>
+ </connections>
+ </customObject>
+ <customObject id="420" customClass="NSFontManager"/>
+ </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/Scripts/build-webkit b/Tools/Scripts/build-webkit
index fc0664a6505546f428c7514b9675119b75a62140..14556b3742856ba88d9363957ea97f337fe63191 100755
--- a/Tools/Scripts/build-webkit
+++ b/Tools/Scripts/build-webkit
@@ -246,7 +246,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 e10ef333190ab71765308d3a6ba034280b07c3bc..c3a8c746f3d11cfac1cebcd1e5d216c5bc677089 100644
--- a/Tools/WebKitTestRunner/TestController.cpp
+++ b/Tools/WebKitTestRunner/TestController.cpp
@@ -718,7 +718,8 @@ void TestController::createWebViewWithOptions(const TestOptions& options)
0, // didResignInputElementStrongPasswordAppearance
0, // requestStorageAccessConfirm
shouldAllowDeviceOrientationAndMotionAccess,
- runWebAuthenticationPanel
+ runWebAuthenticationPanel,
+ 0 // handleJavaScriptDialog
};
WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient.base);
diff --git a/Tools/WebKitTestRunner/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 f30a5126586927933f3b5e4866e170087e59d62d..cf2d5198d07a8c488725536f27c1f55c66cac7ce 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