15476 lines
		
	
	
		
			691 KiB
		
	
	
	
		
			Diff
		
	
	
	
			
		
		
	
	
			15476 lines
		
	
	
		
			691 KiB
		
	
	
	
		
			Diff
		
	
	
	
| diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
 | |
| index 9178d6cff271b4e22b4e85f23473caa703f20fd0..e3063d09c7e817a5f1c1e22808163d2624069d50 100644
 | |
| --- a/Source/JavaScriptCore/CMakeLists.txt
 | |
| +++ b/Source/JavaScriptCore/CMakeLists.txt
 | |
| @@ -1165,22 +1165,27 @@ set(JavaScriptCore_INSPECTOR_DOMAINS
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/CSS.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Canvas.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Console.json
 | |
| +    ${JAVASCRIPTCORE_DIR}/inspector/protocol/Dialog.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/DOM.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMDebugger.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMStorage.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Database.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Debugger.json
 | |
| +    ${JAVASCRIPTCORE_DIR}/inspector/protocol/Emulation.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/GenericTypes.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Heap.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/IndexedDB.json
 | |
| +    ${JAVASCRIPTCORE_DIR}/inspector/protocol/Input.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Inspector.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/LayerTree.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Memory.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Network.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Page.json
 | |
| +    ${JAVASCRIPTCORE_DIR}/inspector/protocol/Playwright.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Recording.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Runtime.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/ScriptProfiler.json
 | |
| +    ${JAVASCRIPTCORE_DIR}/inspector/protocol/Screencast.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Security.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/ServiceWorker.json
 | |
|      ${JAVASCRIPTCORE_DIR}/inspector/protocol/Target.json
 | |
| diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make
 | |
| index 10f9fec51dce48686ff8745beaa4b5b5d5b1033d..770548a5dbfe9650f3d06551556f00b7305b8c53 100644
 | |
| --- a/Source/JavaScriptCore/DerivedSources.make
 | |
| +++ b/Source/JavaScriptCore/DerivedSources.make
 | |
| @@ -260,22 +260,27 @@ INSPECTOR_DOMAINS := \
 | |
|      $(JavaScriptCore)/inspector/protocol/CSS.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Canvas.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Console.json \
 | |
| +    $(JavaScriptCore)/inspector/protocol/Dialog.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/DOM.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/DOMDebugger.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/DOMStorage.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Database.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Debugger.json \
 | |
| +    $(JavaScriptCore)/inspector/protocol/Emulation.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/GenericTypes.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Heap.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/IndexedDB.json \
 | |
| +    $(JavaScriptCore)/inspector/protocol/Input.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Inspector.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/LayerTree.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Memory.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Network.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Page.json \
 | |
| +    $(JavaScriptCore)/inspector/protocol/Playwright.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Recording.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Runtime.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/ScriptProfiler.json \
 | |
| +    $(JavaScriptCore)/inspector/protocol/Screencast.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Security.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/ServiceWorker.json \
 | |
|      $(JavaScriptCore)/inspector/protocol/Target.json \
 | |
| diff --git a/Source/JavaScriptCore/bindings/ScriptValue.cpp b/Source/JavaScriptCore/bindings/ScriptValue.cpp
 | |
| index 6b853c931f1dce9253bbac06a95e6aac527cf25a..bb50bfb871ace62ef84be62c7564f2e3f27dc2bd 100644
 | |
| --- a/Source/JavaScriptCore/bindings/ScriptValue.cpp
 | |
| +++ b/Source/JavaScriptCore/bindings/ScriptValue.cpp
 | |
| @@ -79,7 +79,10 @@ static RefPtr<JSON::Value> jsToInspectorValue(JSGlobalObject* globalObject, JSVa
 | |
|          PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
 | |
|          object.methodTable(vm)->getOwnPropertyNames(&object, globalObject, propertyNames, EnumerationMode());
 | |
|          for (auto& name : propertyNames) {
 | |
| -            auto inspectorValue = jsToInspectorValue(globalObject, object.get(globalObject, name), maxDepth);
 | |
| +            JSValue childValue = object.get(globalObject, name);
 | |
| +            if (childValue.isUndefined())
 | |
| +                continue;
 | |
| +            auto inspectorValue = jsToInspectorValue(globalObject, childValue, maxDepth);
 | |
|              if (!inspectorValue)
 | |
|                  return nullptr;
 | |
|              inspectorObject->setValue(name.string(), WTFMove(inspectorValue));
 | |
| diff --git a/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp b/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp
 | |
| index 95cd87b01b15cb8667e57bc5bb51a71f06bc3760..0481fa93227f297be9d9cf000c5a72235956a390 100644
 | |
| --- a/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp
 | |
| +++ b/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp
 | |
| @@ -30,14 +30,21 @@
 | |
|  namespace Inspector {
 | |
|  
 | |
|  namespace {
 | |
| +static uint64_t s_processID = 0;
 | |
|  static long s_lastUsedIdentifier = 0;
 | |
|  }
 | |
|  
 | |
|  static String addPrefixToIdentifier(const String& identifier)
 | |
|  {
 | |
| -    return makeString("0.", identifier);
 | |
| +    return makeString(s_processID, ".", identifier);
 | |
|  }
 | |
|  
 | |
| +void IdentifiersFactory::initializeWithProcessID(uint64_t processID) {
 | |
| +    ASSERT(!s_processID);
 | |
| +    s_processID = processID;
 | |
| +}
 | |
| +
 | |
| +
 | |
|  String IdentifiersFactory::createIdentifier()
 | |
|  {
 | |
|      return addPrefixToIdentifier(String::number(++s_lastUsedIdentifier));
 | |
| diff --git a/Source/JavaScriptCore/inspector/IdentifiersFactory.h b/Source/JavaScriptCore/inspector/IdentifiersFactory.h
 | |
| index eb25aedee4cd9ebe007e06c2515b37ee095b06f4..badf6559595c8377db1089ca3c25008e1be2c8f1 100644
 | |
| --- a/Source/JavaScriptCore/inspector/IdentifiersFactory.h
 | |
| +++ b/Source/JavaScriptCore/inspector/IdentifiersFactory.h
 | |
| @@ -31,6 +31,7 @@ namespace Inspector {
 | |
|  
 | |
|  class JS_EXPORT_PRIVATE IdentifiersFactory {
 | |
|  public:
 | |
| +    static void initializeWithProcessID(uint64_t);
 | |
|      static String createIdentifier();
 | |
|      static String requestId(unsigned long identifier);
 | |
|  };
 | |
| diff --git a/Source/JavaScriptCore/inspector/InjectedScript.cpp b/Source/JavaScriptCore/inspector/InjectedScript.cpp
 | |
| index cc849f051fa40518a9d1a03429bc2b4dbcfb3102..11b05346f6098fa23f51ba9abc1af0e0e60a626c 100644
 | |
| --- a/Source/JavaScriptCore/inspector/InjectedScript.cpp
 | |
| +++ b/Source/JavaScriptCore/inspector/InjectedScript.cpp
 | |
| @@ -287,9 +287,13 @@ RefPtr<Protocol::Runtime::RemoteObject> InjectedScript::wrapObject(JSC::JSValue
 | |
|      auto callResult = callFunctionWithEvalEnabled(wrapFunction);
 | |
|      if (!callResult)
 | |
|          return nullptr;
 | |
| +    auto callResultValue = callResult.value();
 | |
| +    // callResultValue could be missing if the execution was terminated
 | |
| +    if (!callResultValue)
 | |
| +        return nullptr;
 | |
|  
 | |
|      RefPtr<JSON::Object> resultObject;
 | |
| -    bool castSucceeded = toInspectorValue(globalObject(), callResult.value())->asObject(resultObject);
 | |
| +    bool castSucceeded = toInspectorValue(globalObject(), callResultValue)->asObject(resultObject);
 | |
|      ASSERT_UNUSED(castSucceeded, castSucceeded);
 | |
|  
 | |
|      return BindingTraits<Protocol::Runtime::RemoteObject>::runtimeCast(resultObject);
 | |
| diff --git a/Source/JavaScriptCore/inspector/InjectedScriptSource.js b/Source/JavaScriptCore/inspector/InjectedScriptSource.js
 | |
| index cd593a24af4fe24ba59577b73b26947765edcc32..1f7a04d72065dbd60761c1a72f3254f953d3b9a9 100644
 | |
| --- a/Source/JavaScriptCore/inspector/InjectedScriptSource.js
 | |
| +++ b/Source/JavaScriptCore/inspector/InjectedScriptSource.js
 | |
| @@ -136,7 +136,7 @@ let InjectedScript = class InjectedScript
 | |
|              return;
 | |
|          }
 | |
|  
 | |
| -        if (!(promiseObject instanceof Promise)) {
 | |
| +        if (InjectedScriptHost.internalConstructorName(promiseObject) !== 'Promise') {
 | |
|              callback("Object with given id is not a Promise");
 | |
|              return;
 | |
|          }
 | |
| diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
 | |
| index 693e8b25c73778340e8394046786d9318a8a0924..4be62e0aca82895a96449175adb1af10e7b9daec 100644
 | |
| --- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
 | |
| +++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
 | |
| @@ -101,7 +101,7 @@ void BackendDispatcher::registerDispatcherForDomain(const String& domain, Supple
 | |
|      m_dispatchers.set(domain, dispatcher);
 | |
|  }
 | |
|  
 | |
| -void BackendDispatcher::dispatch(const String& message)
 | |
| +void BackendDispatcher::dispatch(const String& message, Interceptor&& interceptor)
 | |
|  {
 | |
|      Ref<BackendDispatcher> protect(*this);
 | |
|  
 | |
| @@ -142,6 +142,9 @@ void BackendDispatcher::dispatch(const String& message)
 | |
|          }
 | |
|      }
 | |
|  
 | |
| +    if (interceptor && interceptor(messageObject) == InterceptionResult::Intercepted)
 | |
| +        return;
 | |
| +
 | |
|      {
 | |
|          // We could be called re-entrantly from a nested run loop, so restore the previous id.
 | |
|          SetForScope<Optional<long>> scopedRequestId(m_currentRequestId, requestId);
 | |
| diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
 | |
| index 95d9d81188e735e8f1b70cc0deee2682cb6714f0..fbab25a07bf35c49faf026a3dfaccd50f50d1ab8 100644
 | |
| --- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
 | |
| +++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
 | |
| @@ -82,7 +82,10 @@ public:
 | |
|      };
 | |
|  
 | |
|      void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*);
 | |
| -    void dispatch(const String& message);
 | |
| +
 | |
| +    enum class InterceptionResult { Intercepted, Continue };
 | |
| +    using Interceptor = WTF::Function<InterceptionResult(const RefPtr<JSON::Object>&)>;
 | |
| +    void dispatch(const String& message, Interceptor&& interceptor = Interceptor());
 | |
|  
 | |
|      // Note that 'unused' is a workaround so the compiler can pick the right sendResponse based on arity.
 | |
|      // When <http://webkit.org/b/179847> is fixed or this class is renamed for the JSON::Object case,
 | |
| diff --git a/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp b/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp
 | |
| index d408d364f1986983161f9d44efbc8bc6f6898676..1375ce9990f0c63d7e6f33ee62930051d6cd44cb 100644
 | |
| --- a/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp
 | |
| +++ b/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp
 | |
| @@ -49,7 +49,7 @@ void FrontendRouter::connectFrontend(FrontendChannel& connection)
 | |
|  void FrontendRouter::disconnectFrontend(FrontendChannel& connection)
 | |
|  {
 | |
|      if (!m_connections.contains(&connection)) {
 | |
| -        ASSERT_NOT_REACHED();
 | |
| +        ASSERT(m_connections.isEmpty());
 | |
|          return;
 | |
|      }
 | |
|  
 | |
| diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.cpp b/Source/JavaScriptCore/inspector/InspectorTarget.cpp
 | |
| index 0cc2127c9c12c2d82dea9550bad73f4ffb99ba24..8ca65cc042d435cbc0e05dcc5c5dfc958eb24f5a 100644
 | |
| --- a/Source/JavaScriptCore/inspector/InspectorTarget.cpp
 | |
| +++ b/Source/JavaScriptCore/inspector/InspectorTarget.cpp
 | |
| @@ -44,6 +44,8 @@ void InspectorTarget::resume()
 | |
|      ASSERT(m_isPaused);
 | |
|      m_isPaused = false;
 | |
|  
 | |
| +    willResume();
 | |
| +
 | |
|      if (m_resumeCallback) {
 | |
|          m_resumeCallback();
 | |
|          m_resumeCallback = nullptr;
 | |
| @@ -52,7 +54,6 @@ void InspectorTarget::resume()
 | |
|  
 | |
|  void InspectorTarget::setResumeCallback(WTF::Function<void()>&& callback)
 | |
|  {
 | |
| -    ASSERT(!m_resumeCallback);
 | |
|      m_resumeCallback = WTFMove(callback);
 | |
|  }
 | |
|  
 | |
| diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.h b/Source/JavaScriptCore/inspector/InspectorTarget.h
 | |
| index 4b95964db4d902b4b7f4b0b4c40afea51654ff2f..966a5927702b65edb343369decafda7fc83eaec7 100644
 | |
| --- a/Source/JavaScriptCore/inspector/InspectorTarget.h
 | |
| +++ b/Source/JavaScriptCore/inspector/InspectorTarget.h
 | |
| @@ -56,8 +56,12 @@ public:
 | |
|      virtual void connect(FrontendChannel::ConnectionType) = 0;
 | |
|      virtual void disconnect() = 0;
 | |
|      virtual void sendMessageToTargetBackend(const String&) = 0;
 | |
| +    virtual void activate(String& error) { error = "Target cannot be activated"; }
 | |
| +    virtual void close(String& error, bool /* runBeforeUnload */) { error = "Target cannot be closed"; }
 | |
|  
 | |
|  private:
 | |
| +    virtual void willResume() { }
 | |
| +
 | |
|      WTF::Function<void()> m_resumeCallback;
 | |
|      bool m_isPaused { false };
 | |
|  };
 | |
| diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
 | |
| index 8fcb5a1e55750d325a84824d86c49cfe6fb04268..ed2525df326bfe649793701a112eefa30952e375 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.");
 | |
| @@ -144,7 +166,17 @@ void InspectorTargetAgent::targetDestroyed(InspectorTarget& target)
 | |
|      if (!m_isConnected)
 | |
|          return;
 | |
|  
 | |
| -    m_frontendDispatcher->targetDestroyed(target.identifier());
 | |
| +    m_frontendDispatcher->targetDestroyed(target.identifier(), false);
 | |
| +}
 | |
| +
 | |
| +void InspectorTargetAgent::targetCrashed(InspectorTarget& target)
 | |
| +{
 | |
| +    m_targets.remove(target.identifier());
 | |
| +
 | |
| +    if (!m_isConnected)
 | |
| +        return;
 | |
| +
 | |
| +    m_frontendDispatcher->targetDestroyed(target.identifier(), true);
 | |
|  }
 | |
|  
 | |
|  void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID)
 | |
| @@ -159,6 +191,18 @@ void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID,
 | |
|      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 b929ddffe29c3fb088ab6714087c99302c275214..2670ff3ba9b15afd2bb99993c3240c49b24907f5 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) final;
 | |
|      void resume(ErrorString&, const String& targetId) final;
 | |
|      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/DOM.json b/Source/JavaScriptCore/inspector/protocol/DOM.json
 | |
| index f3a7753702995ebc54312ead0b0c028a58bb19b9..869e06b61f31356dd10c38fc5cae519fa40c2b9e 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": [
 | |
| @@ -508,7 +528,9 @@
 | |
|              "description": "Resolves JavaScript node object for given node id.",
 | |
|              "targetTypes": ["page"],
 | |
|              "parameters": [
 | |
| -                { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to resolve." },
 | |
| +                { "name": "nodeId", "$ref": "NodeId", "optional": true, "description": "Id of the node to resolve." },
 | |
| +                { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "Source element handle." },
 | |
| +                { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Specifies in which execution context to adopt to." },
 | |
|                  { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }
 | |
|              ],
 | |
|              "returns": [
 | |
| @@ -575,6 +597,45 @@
 | |
|              "parameters": [
 | |
|                  { "name": "allow", "type": "boolean" }
 | |
|              ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "describeNode",
 | |
| +            "description": "Returns node description.",
 | |
| +            "parameters": [
 | |
| +                { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." }
 | |
| +            ],
 | |
| +            "returns": [
 | |
| +                { "name": "contentFrameId", "$ref": "Network.FrameId", "optional": true, "description": "Frame ID for frame owner elements." },
 | |
| +                { "name": "ownerFrameId", "$ref": "Network.FrameId", "optional": true, "description": "ID of the owning frame element." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +          "name": "scrollIntoViewIfNeeded",
 | |
| +          "description": "Scrolls the given rect into view if not already in the viewport.",
 | |
| +          "parameters": [
 | |
| +              { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." },
 | |
| +              { "name": "rect", "$ref": "Rect", "optional": true, "description": "Rect relative to the node's border box, in CSS pixels." }
 | |
| +          ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "getContentQuads",
 | |
| +            "description": "Returns quads that describe node position on the page. This method\nmight return multiple quads for inline nodes.",
 | |
| +            "parameters": [
 | |
| +                { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." }
 | |
| +            ],
 | |
| +            "returns": [
 | |
| +                {
 | |
| +                    "name": "quads", "type": "array", "items": { "$ref": "Quad" }, "description": "Quads that describe node layout relative to viewport."
 | |
| +                }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setInputFiles",
 | |
| +            "description": "Sets input files for given <input type=file>",
 | |
| +            "parameters": [
 | |
| +                { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Input element handle." },
 | |
| +                { "name": "files", "type": "array", "items": { "$ref": "FilePayload" }, "description": "Files to set" }
 | |
| +            ]
 | |
|          }
 | |
|      ],
 | |
|      "events": [
 | |
| diff --git a/Source/JavaScriptCore/inspector/protocol/Dialog.json b/Source/JavaScriptCore/inspector/protocol/Dialog.json
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..79edea03fed4e9be5da96e1275e182a479cb7a0a
 | |
| --- /dev/null
 | |
| +++ b/Source/JavaScriptCore/inspector/protocol/Dialog.json
 | |
| @@ -0,0 +1,36 @@
 | |
| +{
 | |
| +    "domain": "Dialog",
 | |
| +    "description": "Actions and events related to alert boxes.",
 | |
| +    "availability": ["web"],
 | |
| +    "types": [
 | |
| +    ],
 | |
| +    "commands": [
 | |
| +        {
 | |
| +            "name": "enable",
 | |
| +            "description": "Enables dialog domain notifications."
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "disable",
 | |
| +            "description": "Disables dialog domain notifications."
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "handleJavaScriptDialog",
 | |
| +            "description": "Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).",
 | |
| +            "parameters": [
 | |
| +                { "name": "accept", "type": "boolean", "description": "Whether to accept or dismiss the dialog."},
 | |
| +                { "name": "promptText", "optional": true, "type": "string", "description": "The text to enter into the dialog prompt before accepting. Used only if this is a prompt dialog."}
 | |
| +            ]
 | |
| +        }
 | |
| +    ],
 | |
| +    "events": [
 | |
| +        {
 | |
| +            "name": "javascriptDialogOpening",
 | |
| +            "description": "Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) is about to open.",
 | |
| +            "parameters": [
 | |
| +                { "name": "type", "type": "string", "description": "Dialog type."},
 | |
| +                { "name": "message", "type": "string", "description": "Message that will be displayed by the dialog."},
 | |
| +                { "name": "defaultPrompt", "optional": true, "type": "string", "description": "Default dialog prompt."}
 | |
| +            ]
 | |
| +        }
 | |
| +    ]
 | |
| +}
 | |
| diff --git a/Source/JavaScriptCore/inspector/protocol/Emulation.json b/Source/JavaScriptCore/inspector/protocol/Emulation.json
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..3f28f8e41b39c517369c8ca69415486a75657489
 | |
| --- /dev/null
 | |
| +++ b/Source/JavaScriptCore/inspector/protocol/Emulation.json
 | |
| @@ -0,0 +1,51 @@
 | |
| +{
 | |
| +    "domain": "Emulation",
 | |
| +    "availability": ["web"],
 | |
| +    "commands": [
 | |
| +        {
 | |
| +            "name": "setDeviceMetricsOverride",
 | |
| +            "description": "Overrides device metrics with provided values.",
 | |
| +            "async": true,
 | |
| +            "parameters": [
 | |
| +                { "name": "width", "type": "integer" },
 | |
| +                { "name": "height", "type": "integer" },
 | |
| +                { "name": "deviceScaleFactor", "type": "number" },
 | |
| +                { "name": "fixedLayout", "type": "boolean" }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setJavaScriptEnabled",
 | |
| +            "description": "Allows to disable script execution for the page.",
 | |
| +            "parameters": [
 | |
| +                { "name": "enabled", "type": "boolean" }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setAuthCredentials",
 | |
| +            "description": "Credentials to use during HTTP authentication.",
 | |
| +            "parameters": [
 | |
| +                { "name": "username", "type": "string", "optional": true },
 | |
| +                { "name": "password", "type": "string", "optional": true }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setActiveAndFocused",
 | |
| +            "description": "Makes page focused for test.",
 | |
| +            "parameters": [
 | |
| +                { "name": "active", "type": "boolean", "optional": true }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "grantPermissions",
 | |
| +            "parameters": [
 | |
| +                { "name": "origin", "type": "string" },
 | |
| +                { "name": "permissions", "type": "array", "items": { "type": "string" } }
 | |
| +            ],
 | |
| +            "description": "Overrides the permissions."
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "resetPermissions",
 | |
| +            "description": "Clears permission overrides."
 | |
| +        }
 | |
| +    ]
 | |
| +}
 | |
| diff --git a/Source/JavaScriptCore/inspector/protocol/Input.json b/Source/JavaScriptCore/inspector/protocol/Input.json
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..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 65ab2092b0ffd0ead3da1ddccd398d4f4179f51a..2d9ef40a20df819193c9a5867fbf6f8f8bf46b48 100644
 | |
| --- a/Source/JavaScriptCore/inspector/protocol/Network.json
 | |
| +++ b/Source/JavaScriptCore/inspector/protocol/Network.json
 | |
| @@ -321,6 +321,13 @@
 | |
|                  { "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network request to fail." },
 | |
|                  { "name": "errorType", "$ref": "ResourceErrorType", "description": "Deliver error reason for the request failure." }
 | |
|              ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setEmulateOfflineState",
 | |
| +            "description": "Emulate offline state overriding the actual state.",
 | |
| +            "parameters": [
 | |
| +                { "name": "offline", "type": "boolean", "description": "True to emulate offline." }
 | |
| +            ]
 | |
|          }
 | |
|      ],
 | |
|      "events": [
 | |
| diff --git a/Source/JavaScriptCore/inspector/protocol/Page.json b/Source/JavaScriptCore/inspector/protocol/Page.json
 | |
| index 3b8fa18bd7e8d95d7e8f95b442afc63e550ce63a..edeabe67bd568be7fbe66781fce61a42644b0ca3 100644
 | |
| --- a/Source/JavaScriptCore/inspector/protocol/Page.json
 | |
| +++ b/Source/JavaScriptCore/inspector/protocol/Page.json
 | |
| @@ -27,7 +27,7 @@
 | |
|          {
 | |
|              "id": "ResourceType",
 | |
|              "type": "string",
 | |
| -            "enum": ["Document", "StyleSheet", "Image", "Font", "Script", "XHR", "Fetch", "Ping", "Beacon", "WebSocket", "Other"],
 | |
| +            "enum": ["Document", "StyleSheet", "Image", "Font", "Script", "XHR", "Fetch", "Ping", "Beacon", "WebSocket", "EventSource", "Other"],
 | |
|              "description": "Resource type as it was perceived by the rendering engine."
 | |
|          },
 | |
|          {
 | |
| @@ -112,6 +112,41 @@
 | |
|                  { "name": "secure", "type": "boolean", "description": "True if cookie is secure." },
 | |
|                  { "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." }
 | |
|              ]
 | |
| +        },
 | |
| +        {
 | |
| +            "id": "AXNode",
 | |
| +            "type": "object",
 | |
| +            "description": "Accessibility Node",
 | |
| +            "properties": [
 | |
| +                { "name": "role", "type": "string", "description": "The role."},
 | |
| +                { "name": "name", "type": "string","optional": true, "description": "A human readable name for the node."},
 | |
| +                { "name": "value", "type": "any", "optional": true, "description": "The current value of the node."},
 | |
| +                { "name": "description", "type": "string", "optional": true, "description": "An additional human readable description of the node."},
 | |
| +                { "name": "keyshortcuts", "type": "string", "optional": true, "description": "Keyboard shortcuts associated with this node."},
 | |
| +                { "name": "roledescription", "type": "string", "optional": true, "description": "A human readable alternative to the role."},
 | |
| +                { "name": "valuetext", "type": "string", "optional": true, "description": "A description of the current value."},
 | |
| +                { "name": "disabled", "type": "boolean", "optional": true, "description": "Whether the node is disabled."},
 | |
| +                { "name": "expanded", "type": "boolean", "optional": true, "description": "Whether the node is expanded or collapsed."},
 | |
| +                { "name": "focused", "type": "boolean", "optional": true, "description": "Whether the node is focused."},
 | |
| +                { "name": "modal", "type": "boolean", "optional": true, "description": "Whether the node is modal."},
 | |
| +                { "name": "multiline", "type": "boolean", "optional": true, "description": "Whether the node text input supports multiline."},
 | |
| +                { "name": "multiselectable", "type": "boolean", "optional": true, "description": "Whether more than one child can be selected."},
 | |
| +                { "name": "readonly", "type": "boolean", "optional": true, "description": "Whether the node is read only."},
 | |
| +                { "name": "required", "type": "boolean", "optional": true, "description": "Whether the node is required."},
 | |
| +                { "name": "selected", "type": "boolean", "optional": true, "description": "Whether the node is selected in its parent node."},
 | |
| +                { "name": "checked", "type": "string", "optional": true, "enum": ["true", "false", "mixed"], "description": "Whether the checkbox is checked, or \"mixed\"."},
 | |
| +                { "name": "pressed", "type": "string", "optional": true, "enum": ["true", "false", "mixed"], "description": "Whether the toggle button is checked, or \"mixed\"."},
 | |
| +                { "name": "level", "type": "integer", "optional": true, "description": "The level of a heading."},
 | |
| +                { "name": "valuemin", "type": "number", "optional": true, "description": "The minimum value in a node."},
 | |
| +                { "name": "valuemax", "type": "number", "optional": true, "description": "The maximum value in a node."},
 | |
| +                { "name": "autocomplete", "type": "string", "optional": true, "description": "What kind of autocomplete is supported by a control."},
 | |
| +                { "name": "haspopup", "type": "string", "optional": true, "description": "What kind of popup is currently being shown for a node."},
 | |
| +                { "name": "invalid", "type": "string", "optional": true, "enum": ["true", "false", "grammar", "spelling"], "description": "Whether and in what way this node's value is invalid."},
 | |
| +                { "name": "orientation", "type": "string", "optional": true, "description": "Whether the node is oriented horizontally or vertically."},
 | |
| +                { "name": "focusable", "type": "boolean", "optional": true, "description": "Whether the node is focusable."},
 | |
| +                { "name": "children", "type": "array", "optional": true, "items": { "$ref": "AXNode"}, "description": "Child AXNodes of this node, if any."},
 | |
| +                { "name": "found", "type": "boolean", "optional": true, "description": "True if this AXNode corresponds with the ObjectId passed into acessibilitySnapshot."}
 | |
| +            ]
 | |
|          }
 | |
|      ],
 | |
|      "commands": [
 | |
| @@ -131,6 +166,14 @@
 | |
|                  { "name": "revalidateAllResources", "type": "boolean", "optional": true, "description": "If true, all cached subresources will be revalidated when the main resource loads. Otherwise, only expired cached subresources will be revalidated (the default behavior for most WebKit clients)." }
 | |
|              ]
 | |
|          },
 | |
| +        {
 | |
| +            "name": "goBack",
 | |
| +            "description": "Goes back in the history."
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "goForward",
 | |
| +            "description": "Goes forward in the history."
 | |
| +        },
 | |
|          {
 | |
|              "name": "navigate",
 | |
|              "description": "Navigates current page to the given URL.",
 | |
| @@ -270,6 +313,20 @@
 | |
|                  { "name": "appearance", "$ref": "Appearance", "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.",
 | |
| @@ -304,6 +361,77 @@
 | |
|              "returns": [
 | |
|                  { "name": "data", "type": "string", "description": "Base64-encoded web archive." }
 | |
|              ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "insertText",
 | |
| +            "description": "Insert text into the current selection of the page.",
 | |
| +            "parameters": [
 | |
| +                { "name": "text", "type": "string", "description": "Text to insert." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "accessibilitySnapshot",
 | |
| +            "description": "Serializes and returns all of the accessibility nodes of the page.",
 | |
| +            "parameters": [
 | |
| +                { "name": "objectId", "type": "string", "optional": true, "description": "Object Id of a node to find in the accessibility tree."}
 | |
| +            ],
 | |
| +            "returns": [
 | |
| +                { "name": "axNode", "$ref": "AXNode", "description": "The root AXNode."}
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setInterceptFileChooserDialog",
 | |
| +            "description": "Intercepts file chooser dialog",
 | |
| +            "parameters": [
 | |
| +                { "name": "enabled", "type": "boolean", "description": "True to enable." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setDefaultBackgroundColorOverride",
 | |
| +            "description": "Sets or clears an override of the default background color of the frame. This override is used if the content does not specify one.",
 | |
| +            "parameters": [
 | |
| +                { "name": "color", "$ref": "DOM.RGBAColor", "optional": true, "description": "RGBA of the default background color. If not specified, any existing override will be cleared." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "createUserWorld",
 | |
| +            "description": "Creates an user world for every loaded frame.",
 | |
| +            "parameters": [
 | |
| +                { "name": "name", "type": "string", "description": "Isolated world name, will be used as an execution context name." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setBypassCSP",
 | |
| +            "description": "Enable page Content Security Policy by-passing.",
 | |
| +            "parameters": [
 | |
| +                { "name": "enabled", "type": "boolean", "description": "Whether to bypass page CSP." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "crash",
 | |
| +            "description": "Crashes the page process"
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setScreenSizeOverride",
 | |
| +            "description": "Overrides screen size with provided values.",
 | |
| +            "parameters": [
 | |
| +                { "name": "width", "type": "integer" },
 | |
| +                { "name": "height", "type": "integer" }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setOrientationOverride",
 | |
| +            "description": "Overrides window.orientation with provided value.",
 | |
| +            "parameters": [
 | |
| +                { "name": "angle", "type": "integer", "optional": true }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setActivityPaused",
 | |
| +            "description": "Pauses page activity (active objects, animations).",
 | |
| +            "parameters": [
 | |
| +                { "name": "paused", "type": "boolean" }
 | |
| +            ]
 | |
|          }
 | |
|      ],
 | |
|      "events": [
 | |
| @@ -311,14 +439,16 @@
 | |
|              "name": "domContentEventFired",
 | |
|              "targetTypes": ["page"],
 | |
|              "parameters": [
 | |
| -                { "name": "timestamp", "type": "number" }
 | |
| +                { "name": "timestamp", "type": "number" },
 | |
| +                { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired DOMContentLoaded event." }
 | |
|              ]
 | |
|          },
 | |
|          {
 | |
|              "name": "loadEventFired",
 | |
|              "targetTypes": ["page"],
 | |
|              "parameters": [
 | |
| -                { "name": "timestamp", "type": "number" }
 | |
| +              { "name": "timestamp", "type": "number" },
 | |
| +              { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired load event." }
 | |
|              ]
 | |
|          },
 | |
|          {
 | |
| @@ -328,6 +458,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.",
 | |
| @@ -367,6 +505,22 @@
 | |
|                  { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has cleared its scheduled navigation." }
 | |
|              ]
 | |
|          },
 | |
| +        {
 | |
| +            "name": "navigatedWithinDocument",
 | |
| +            "description": "Fired when same-document navigation happens, e.g. due to history API usage or anchor navigation.",
 | |
| +            "parameters": [
 | |
| +                {
 | |
| +                    "name": "frameId",
 | |
| +                    "description": "Id of the frame.",
 | |
| +                    "$ref": "Network.FrameId"
 | |
| +                },
 | |
| +                {
 | |
| +                    "name": "url",
 | |
| +                    "description": "Frame's new url.",
 | |
| +                    "type": "string"
 | |
| +                }
 | |
| +            ]
 | |
| +        },
 | |
|          {
 | |
|              "name": "defaultAppearanceDidChange",
 | |
|              "description": "Fired when page's default appearance changes, even if there is a forced appearance.",
 | |
| @@ -375,6 +529,28 @@
 | |
|              "parameters": [
 | |
|                  { "name": "appearance", "$ref": "Appearance", "description": "Name of the appearance that is active (not considering any forced appearance.)" }
 | |
|              ]
 | |
| +        },
 | |
| +        {
 | |
| +          "name": "willRequestOpenWindow",
 | |
| +          "description": "Fired when page tries to open a new window.",
 | |
| +          "parameters": [
 | |
| +              { "name": "url", "type": "string" }
 | |
| +          ]
 | |
| +        },
 | |
| +        {
 | |
| +          "name": "didRequestOpenWindow",
 | |
| +          "description": "Fired after page did try to open a new window.",
 | |
| +          "parameters": [
 | |
| +              { "name": "opened", "type": "boolean" }
 | |
| +          ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "fileChooserOpened",
 | |
| +            "description": "Fired when the page shows file chooser for it's <input type=file>.",
 | |
| +            "parameters": [
 | |
| +                { "name": "frameId", "$ref": "Network.FrameId", "description": "Frame where file chooser is opened." },
 | |
| +                { "name": "element", "$ref": "Runtime.RemoteObject", "description": "Input element." }
 | |
| +            ]
 | |
|          }
 | |
|      ]
 | |
|  }
 | |
| diff --git a/Source/JavaScriptCore/inspector/protocol/Playwright.json b/Source/JavaScriptCore/inspector/protocol/Playwright.json
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..dd4c318ec4b9b49ce937266ba899e54f8e6fa932
 | |
| --- /dev/null
 | |
| +++ b/Source/JavaScriptCore/inspector/protocol/Playwright.json
 | |
| @@ -0,0 +1,244 @@
 | |
| +{
 | |
| +    "domain": "Playwright",
 | |
| +    "availability": ["web"],
 | |
| +    "types": [
 | |
| +        {
 | |
| +            "id": "ContextID",
 | |
| +            "type": "string",
 | |
| +            "description": "Id of Browser context."
 | |
| +        },
 | |
| +        {
 | |
| +            "id": "PageProxyID",
 | |
| +            "type": "string",
 | |
| +            "description": "Id of WebPageProxy."
 | |
| +        },
 | |
| +        {
 | |
| +            "id": "CookieSameSitePolicy",
 | |
| +            "type": "string",
 | |
| +            "enum": ["None", "Lax", "Strict"],
 | |
| +            "description": "Same-Site policy of a cookie."
 | |
| +        },
 | |
| +        {
 | |
| +            "id": "Cookie",
 | |
| +            "type": "object",
 | |
| +            "description": "Cookie object",
 | |
| +            "properties": [
 | |
| +                { "name": "name", "type": "string", "description": "Cookie name." },
 | |
| +                { "name": "value", "type": "string", "description": "Cookie value." },
 | |
| +                { "name": "domain", "type": "string", "description": "Cookie domain." },
 | |
| +                { "name": "path", "type": "string", "description": "Cookie path." },
 | |
| +                { "name": "expires", "type": "number", "description": "Cookie expires." },
 | |
| +                { "name": "httpOnly", "type": "boolean", "description": "True if cookie is http-only." },
 | |
| +                { "name": "secure", "type": "boolean", "description": "True if cookie is secure." },
 | |
| +                { "name": "session", "type": "boolean", "description": "True if cookie is session cookie." },
 | |
| +                { "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "id": "SetCookieParam",
 | |
| +            "type": "object",
 | |
| +            "description": "Cookie object",
 | |
| +            "properties": [
 | |
| +                { "name": "name", "type": "string", "description": "Cookie name." },
 | |
| +                { "name": "value", "type": "string", "description": "Cookie value." },
 | |
| +                { "name": "domain", "type": "string", "description": "Cookie domain." },
 | |
| +                { "name": "path", "type": "string", "description": "Cookie path." },
 | |
| +                { "name": "expires", "type": "number", "optional": true, "description": "Cookie expires." },
 | |
| +                { "name": "httpOnly", "type": "boolean", "optional": true, "description": "True if cookie is http-only." },
 | |
| +                { "name": "secure", "type": "boolean", "optional": true, "description": "True if cookie is secure." },
 | |
| +                { "name": "session", "type": "boolean", "optional": true, "description": "True if cookie is session cookie." },
 | |
| +                { "name": "sameSite", "$ref": "CookieSameSitePolicy", "optional": true, "description": "Cookie Same-Site policy." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "id": "Geolocation",
 | |
| +            "type": "object",
 | |
| +            "description": "Geolocation",
 | |
| +            "properties": [
 | |
| +                { "name": "timestamp", "type": "number", "description": "Mock latitude" },
 | |
| +                { "name": "latitude", "type": "number", "description": "Mock latitude" },
 | |
| +                { "name": "longitude", "type": "number", "description": "Mock longitude" },
 | |
| +                { "name": "accuracy", "type": "number", "description": "Mock accuracy" }
 | |
| +            ]
 | |
| +        }
 | |
| +    ],
 | |
| +    "commands": [
 | |
| +        {
 | |
| +            "name": "enable"
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "disable"
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "close",
 | |
| +            "async": true,
 | |
| +            "description": "Close browser."
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "createContext",
 | |
| +            "description": "Creates new ephemeral browser context.",
 | |
| +            "parameters": [
 | |
| +                { "name": "proxyServer", "type": "string", "optional": true, "description": "Proxy server, similar to the one passed to --proxy-server" },
 | |
| +                { "name": "proxyBypassList", "type": "string", "optional": true, "description": "Proxy bypass list, similar to the one passed to --proxy-bypass-list" }
 | |
| +            ],
 | |
| +            "returns": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "deleteContext",
 | |
| +            "async": true,
 | |
| +            "description": "Deletes browser context previously created with createContect. The command will automatically close all pages that use the context.",
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "description": "Identifier of the context to delete." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "createPage",
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "JSON Inspector Protocol message (command) to be dispatched on the backend." }
 | |
| +            ],
 | |
| +            "returns": [
 | |
| +                { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "navigate",
 | |
| +            "async": true,
 | |
| +            "description": "Navigates current page to the given URL.",
 | |
| +            "parameters": [
 | |
| +                { "name": "url", "type": "string", "description": "URL to navigate the page to." },
 | |
| +                { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." },
 | |
| +                { "name": "frameId", "$ref": "Network.FrameId", "optional": true, "description": "Id of the frame to navigate."},
 | |
| +                { "name": "referrer", "type": "string", "optional": true, "description": "Referrer URL." }
 | |
| +            ],
 | |
| +            "returns": [
 | |
| +                { "name": "loaderId", "$ref": "Network.LoaderId", "optional": true, "description": "Identifier of the loader associated with the navigation." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setIgnoreCertificateErrors",
 | |
| +            "description": "Change whether all certificate errors should be ignored.",
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." },
 | |
| +                { "name": "ignore", "type": "boolean" }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "getAllCookies",
 | |
| +            "description": "Returns all cookies in the given browser context.",
 | |
| +            "async": true,
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
 | |
| +            ],
 | |
| +            "returns": [
 | |
| +                { "name": "cookies", "type": "array", "items": { "$ref": "Cookie" }, "description": "Cookies." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setCookies",
 | |
| +            "description": "Sets cookies in the given browser context.",
 | |
| +            "async": true,
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." },
 | |
| +                { "name": "cookies", "type": "array", "items": { "$ref": "SetCookieParam" }, "description": "Cookies." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "deleteAllCookies",
 | |
| +            "description": "Deletes cookies in the given browser context.",
 | |
| +            "async": true,
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setGeolocationOverride",
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." },
 | |
| +                { "name": "geolocation", "$ref": "Geolocation", "optional": true, "description": "Geolocation to set, if missing emulates position unavailable." }
 | |
| +            ],
 | |
| +            "description": "Overrides the geolocation position or error."
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setLanguages",
 | |
| +            "description": "Allows to set locale language for context.",
 | |
| +            "parameters": [
 | |
| +                { "name": "languages", "type": "array", "items": { "type": "string" } },
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "setDownloadBehavior",
 | |
| +            "description": "Allows to override download behavior.",
 | |
| +            "parameters": [
 | |
| +                { "name": "behavior", "optional": true, "type": "string", "enum": ["allow", "deny"] },
 | |
| +                { "name": "downloadPath", "optional": true, "type": "string" },
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }
 | |
| +            ]
 | |
| +        }
 | |
| +    ],
 | |
| +    "events": [
 | |
| +        {
 | |
| +            "name": "pageProxyCreated",
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." },
 | |
| +                { "name": "pageProxyId", "$ref": "PageProxyID" },
 | |
| +                { "name": "openerId", "$ref": "PageProxyID", "optional": true, "description": "Unique identifier of the opening page. Only set for pages created by window.open()." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "pageProxyDestroyed",
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." },
 | |
| +                { "name": "pageProxyId", "$ref": "PageProxyID" }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "provisionalLoadFailed",
 | |
| +            "description": "Fired when provisional load fails.",
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." },
 | |
| +                { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." },
 | |
| +                { "name": "loaderId", "$ref": "Network.LoaderId", "description": "Identifier of the loader associated with the navigation." },
 | |
| +                { "name": "error", "type": "string", "description": "Localized error string." }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +          "name": "windowOpen",
 | |
| +          "description": "Fired when page opens a new window.",
 | |
| +          "parameters": [
 | |
| +              { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." },
 | |
| +              { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." },
 | |
| +              { "name": "url", "type": "string" },
 | |
| +              { "name": "windowFeatures", "type": "array", "items": { "type": "string" } }
 | |
| +          ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "downloadCreated",
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." },
 | |
| +                { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." },
 | |
| +                { "name": "frameId", "$ref": "Network.FrameId", "description": "Unique identifier of the originating frame." },
 | |
| +                { "name": "uuid", "type": "string" },
 | |
| +                { "name": "url", "type": "string" }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "downloadFilenameSuggested",
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." },
 | |
| +                { "name": "uuid", "type": "string" },
 | |
| +                { "name": "suggestedFilename", "type": "string" }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "downloadFinished",
 | |
| +            "parameters": [
 | |
| +                { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." },
 | |
| +                { "name": "uuid", "type": "string" },
 | |
| +                { "name": "error", "type": "string" }
 | |
| +            ]
 | |
| +        }
 | |
| +    ]
 | |
| +}
 | |
| diff --git a/Source/JavaScriptCore/inspector/protocol/Screencast.json b/Source/JavaScriptCore/inspector/protocol/Screencast.json
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..d0759ea0a9803c13e4f161b87179ba4890ac5c7b
 | |
| --- /dev/null
 | |
| +++ b/Source/JavaScriptCore/inspector/protocol/Screencast.json
 | |
| @@ -0,0 +1,21 @@
 | |
| +{
 | |
| +    "domain": "Screencast",
 | |
| +    "availability": ["web"],
 | |
| +    "commands": [
 | |
| +        {
 | |
| +            "name": "startVideoRecording",
 | |
| +            "description": "Starts recoring video to speified file.",
 | |
| +            "parameters": [
 | |
| +                { "name": "file", "type": "string", "description": "Output file location." },
 | |
| +                { "name": "width", "type": "integer" },
 | |
| +                { "name": "height", "type": "integer" },
 | |
| +                { "name": "scale", "type": "number", "optional": true }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "stopVideoRecording",
 | |
| +            "async": true,
 | |
| +            "description": "Stops recoding video. Returns after the file has been closed."
 | |
| +        }
 | |
| +    ]
 | |
| +}
 | |
| diff --git a/Source/JavaScriptCore/inspector/protocol/Target.json b/Source/JavaScriptCore/inspector/protocol/Target.json
 | |
| index 52920cded24a9c6b0ef6fb4e518664955db4f9fa..bbbabc4e7259088b9404e8cc07eecd6f45077da0 100644
 | |
| --- a/Source/JavaScriptCore/inspector/protocol/Target.json
 | |
| +++ b/Source/JavaScriptCore/inspector/protocol/Target.json
 | |
| @@ -10,7 +10,7 @@
 | |
|              "properties": [
 | |
|                  { "name": "targetId", "type": "string", "description": "Unique identifier for the target." },
 | |
|                  { "name": "type", "type": "string", "enum": ["page", "service-worker", "worker"] },
 | |
| -                { "name": "isProvisional", "type": "boolean", "optional": true, "description": "Whether this is a provisional page target." },
 | |
| +                { "name": "isProvisional", "type": "boolean", "optional": true, "description": "True value indicates that this is a provisional page target i.e. Such target may be created when current page starts cross-origin navigation. Eventually each provisional target is either committed and swaps with the current target or gets destroyed, e.g. in case of load request failure." },
 | |
|                  { "name": "isPaused", "type": "boolean", "optional": true, "description": "Whether the target is paused on start and has to be explicitely resumed by inspector." }
 | |
|              ]
 | |
|          }
 | |
| @@ -37,6 +37,21 @@
 | |
|                  { "name": "targetId", "type": "string" },
 | |
|                  { "name": "message", "type": "string", "description": "JSON Inspector Protocol message (command) to be dispatched on the backend." }
 | |
|              ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "activate",
 | |
| +            "description": "Reveals the target on screen.",
 | |
| +            "parameters": [
 | |
| +                { "name": "targetId", "type": "string" }
 | |
| +            ]
 | |
| +        },
 | |
| +        {
 | |
| +            "name": "close",
 | |
| +            "description": "Closes the target.",
 | |
| +            "parameters": [
 | |
| +                { "name": "targetId", "type": "string" },
 | |
| +                { "name": "runBeforeUnload", "type": "boolean", "optional": true }
 | |
| +            ]
 | |
|          }
 | |
|      ],
 | |
|      "events": [
 | |
| @@ -49,7 +64,8 @@
 | |
|          {
 | |
|              "name": "targetDestroyed",
 | |
|              "parameters": [
 | |
| -                { "name": "targetId", "type": "string" }
 | |
| +                { "name": "targetId", "type": "string" },
 | |
| +                { "name": "crashed", "type": "boolean" }
 | |
|              ]
 | |
|          },
 | |
|          {
 | |
| diff --git a/Source/JavaScriptCore/inspector/protocol/Worker.json b/Source/JavaScriptCore/inspector/protocol/Worker.json
 | |
| index 638612413466efc87b737e8a81042ed07ca12703..6f9e518ff0bfa2a6228675d25b6b785f1ed3022a 100644
 | |
| --- a/Source/JavaScriptCore/inspector/protocol/Worker.json
 | |
| +++ b/Source/JavaScriptCore/inspector/protocol/Worker.json
 | |
| @@ -16,7 +16,7 @@
 | |
|              "description": "Sent after the frontend has sent all initialization messages and can resume this worker. This command is required to allow execution in the worker.",
 | |
|              "parameters": [
 | |
|                  { "name": "workerId", "type": "string" }
 | |
| -            ]            
 | |
| +            ]
 | |
|          },
 | |
|          {
 | |
|              "name": "sendMessageToWorker",
 | |
| @@ -33,7 +33,8 @@
 | |
|              "parameters": [
 | |
|                  { "name": "workerId", "type": "string" },
 | |
|                  { "name": "url", "type": "string" },
 | |
| -                { "name": "name", "type": "string" }
 | |
| +                { "name": "name", "type": "string" },
 | |
| +                { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame this worker belongs to." }
 | |
|              ]
 | |
|          },
 | |
|          {
 | |
| diff --git a/Source/JavaScriptCore/runtime/DateConversion.cpp b/Source/JavaScriptCore/runtime/DateConversion.cpp
 | |
| index 955756ba405f400970610f9a68c7ed42a67cb015..1520c0a1475a90de2795e4ccd8919c1bb1384066 100644
 | |
| --- a/Source/JavaScriptCore/runtime/DateConversion.cpp
 | |
| +++ b/Source/JavaScriptCore/runtime/DateConversion.cpp
 | |
| @@ -100,17 +100,23 @@ String formatDateTime(const GregorianDateTime& t, DateTimeFormat format, bool as
 | |
|              appendNumber<2>(builder, offset / 60);
 | |
|              appendNumber<2>(builder, offset % 60);
 | |
|  
 | |
| -#if OS(WINDOWS)
 | |
| -            TIME_ZONE_INFORMATION timeZoneInformation;
 | |
| -            GetTimeZoneInformation(&timeZoneInformation);
 | |
| -            const WCHAR* winTimeZoneName = t.isDST() ? timeZoneInformation.DaylightName : timeZoneInformation.StandardName;
 | |
| -            String timeZoneName(winTimeZoneName);
 | |
| +            String timeZoneName;
 | |
| +            if (!WTF::timeZoneDisplayNameForAutomation().isEmpty()) {
 | |
| +                timeZoneName = WTF::timeZoneDisplayNameForAutomation();
 | |
| +            } else {
 | |
| + #if OS(WINDOWS)
 | |
| +                TIME_ZONE_INFORMATION timeZoneInformation;
 | |
| +                GetTimeZoneInformation(&timeZoneInformation);
 | |
| +                const WCHAR* winTimeZoneName = t.isDST() ? timeZoneInformation.DaylightName : timeZoneInformation.StandardName;
 | |
| +                timeZoneName = String(winTimeZoneName);
 | |
|  #else
 | |
| -            struct tm gtm = t;
 | |
| -            char timeZoneName[70];
 | |
| -            strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m);
 | |
| +                struct tm gtm = t;
 | |
| +                char tzName[70];
 | |
| +                strftime(tzName, sizeof(tzName), "%Z", >m);
 | |
| +                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 7dfbc367cf4fb4298adf611d12c6ae2f46761385..f3c180ad03478634caa4f5db863bde10c0fc629e 100644
 | |
| --- a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
 | |
| +++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
 | |
| @@ -34,6 +34,7 @@
 | |
|  #include <unicode/ucal.h>
 | |
|  #include <unicode/udatpg.h>
 | |
|  #include <unicode/uenum.h>
 | |
| +#include <wtf/DateMath.h>
 | |
|  #include <wtf/text/StringBuilder.h>
 | |
|  #include <wtf/unicode/icu/ICUHelpers.h>
 | |
|  
 | |
| @@ -102,6 +103,10 @@ static ALWAYS_INLINE bool isUTCEquivalent(StringView timeZone)
 | |
|  // https://tc39.es/ecma402/#sec-defaulttimezone
 | |
|  static String defaultTimeZone()
 | |
|  {
 | |
| +    String tz = WTF::timeZoneForAutomation();
 | |
| +    if (!tz.isEmpty())
 | |
| +        return tz;
 | |
| +
 | |
|      String canonical;
 | |
|  
 | |
|      Vector<UChar, 32> buffer;
 | |
| diff --git a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp
 | |
| index a47d962f61b86f13aae3280de7d480e98ad5d2e8..3d73fdc69cf0f68360c1dabcb456c1d08f3cc383 100644
 | |
| --- a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp
 | |
| +++ b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp
 | |
| @@ -259,3 +259,12 @@ __ZN3rtc17CopyOnWriteBuffer24UnshareAndEnsureCapacityEm
 | |
|  __ZN3rtc6Thread14InvokeInternalERKNS_8LocationENS_12FunctionViewIFvvEEE
 | |
|  __ZN6webrtc18RtpSenderInterface38SetEncoderToPacketizerFrameTransformerEN3rtc13scoped_refptrINS_25FrameTransformerInterfaceEEE
 | |
|  __ZN6webrtc20RtpReceiverInterface40SetDepacketizerToDecoderFrameTransformerEN3rtc13scoped_refptrINS_25FrameTransformerInterfaceEEE
 | |
| +_ARGBToI420
 | |
| +_vpx_codec_enc_config_default
 | |
| +_vpx_codec_enc_init_ver
 | |
| +_vpx_codec_encode
 | |
| +_vpx_codec_err_to_string
 | |
| +_vpx_codec_error
 | |
| +_vpx_codec_get_cx_data
 | |
| +_vpx_codec_iface_name
 | |
| +_vpx_codec_vp8_cx
 | |
| \ No newline at end of file
 | |
| diff --git a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj
 | |
| index 19aaeebf9ef117766a296b11e26fb4859238b483..1374e8409f9a236cfecd8cfb1574ebe60ed2da38 100644
 | |
| --- a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj
 | |
| +++ b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj
 | |
| @@ -16374,7 +16374,7 @@
 | |
|  			);
 | |
|  			runOnlyForDeploymentPostprocessing = 0;
 | |
|  			shellPath = /bin/sh;
 | |
| -			shellScript = "PRIVATE_HEADERS_FOLDER_PATH=usr/local/include\n\nif [[ \"${DEPLOYMENT_LOCATION}\" == \"NO\" ]]; then\n    PRIVATE_HEADERS_PATH=\"${TARGET_BUILD_DIR%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nelse\n    PRIVATE_HEADERS_PATH=\"${DSTROOT}${INSTALL_PATH_PREFIX%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nfi;\n\nmkdir -p \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/webrtc\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/abseil-cpp/absl\" \"${PRIVATE_HEADERS_PATH}\"\n";
 | |
| +			shellScript = "PRIVATE_HEADERS_FOLDER_PATH=usr/local/include\n\nif [[ \"${DEPLOYMENT_LOCATION}\" == \"NO\" ]]; then\n    PRIVATE_HEADERS_PATH=\"${TARGET_BUILD_DIR%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nelse\n    PRIVATE_HEADERS_PATH=\"${DSTROOT}${INSTALL_PATH_PREFIX%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nfi;\n\nmkdir -p \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/webrtc\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/abseil-cpp/absl\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/libyuv/include/\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --exclude \"src\" --exclude \"internal\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/libvpx/source/libvpx/vpx\" \"${PRIVATE_HEADERS_PATH}\"\n";
 | |
|  		};
 | |
|  		5CD286461E6E154E0094FDC8 /* Check for Weak VTables and Externals */ = {
 | |
|  			isa = PBXShellScriptBuildPhase;
 | |
| diff --git a/Source/WTF/wtf/DateMath.cpp b/Source/WTF/wtf/DateMath.cpp
 | |
| index af92f674770349cc8e7be9a53b1cee6e7840e781..f0a960db046292a3505d339a333f03098f3d8418 100644
 | |
| --- a/Source/WTF/wtf/DateMath.cpp
 | |
| +++ b/Source/WTF/wtf/DateMath.cpp
 | |
| @@ -76,9 +76,14 @@
 | |
|  #include <limits>
 | |
|  #include <stdint.h>
 | |
|  #include <time.h>
 | |
| +#include <unicode/ucal.h>
 | |
|  #include <wtf/Assertions.h>
 | |
|  #include <wtf/ASCIICType.h>
 | |
| +#include <wtf/Language.h>
 | |
| +#include <wtf/NeverDestroyed.h>
 | |
| +#include <wtf/ThreadSpecific.h>
 | |
|  #include <wtf/text/StringBuilder.h>
 | |
| +#include <wtf/unicode/UTF8Conversion.h>
 | |
|  
 | |
|  #if OS(WINDOWS)
 | |
|  #include <windows.h>
 | |
| @@ -92,6 +97,18 @@ template<unsigned length> inline bool startsWithLettersIgnoringASCIICase(const c
 | |
|      return equalLettersIgnoringASCIICase(string, lowercaseLetters, length - 1);
 | |
|  }
 | |
|  
 | |
| +struct TimeZoneForAutomation {
 | |
| +    UCalendar* cal;
 | |
| +    String id;
 | |
| +    String displayName;
 | |
| +};
 | |
| +
 | |
| +static TimeZoneForAutomation& innerTimeZoneForAutomation()
 | |
| +{
 | |
| +    static NeverDestroyed<WTF::ThreadSpecific<TimeZoneForAutomation>> timeZoneForAutomation;
 | |
| +    return *timeZoneForAutomation.get();
 | |
| +}
 | |
| +
 | |
|  /* Constants */
 | |
|  
 | |
|  const char* const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
 | |
| @@ -318,6 +335,14 @@ static double calculateDSTOffset(time_t localTime, double utcOffset)
 | |
|  // Returns combined offset in millisecond (UTC + DST).
 | |
|  LocalTimeOffset calculateLocalTimeOffset(double ms, TimeType inputTimeType)
 | |
|  {
 | |
| +    TimeZoneForAutomation& tz = innerTimeZoneForAutomation();
 | |
| +    if (tz.cal) {
 | |
| +        UErrorCode status = U_ZERO_ERROR;
 | |
| +        ucal_setMillis(tz.cal, ms, &status);
 | |
| +        int32_t offset = ucal_get(tz.cal, UCAL_ZONE_OFFSET, &status);
 | |
| +        int32_t dstOffset = ucal_get(tz.cal, UCAL_DST_OFFSET, &status);
 | |
| +        return LocalTimeOffset(dstOffset, offset + dstOffset);
 | |
| +    }
 | |
|  #if HAVE(TM_GMTOFF)
 | |
|      double localToUTCTimeOffset = inputTimeType == LocalTime ? calculateUTCOffset() : 0;
 | |
|  #else
 | |
| @@ -1019,4 +1044,65 @@ String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, u
 | |
|      return stringBuilder.toString();
 | |
|  }
 | |
|  
 | |
| +bool setTimeZoneForAutomation(const String& timeZone)
 | |
| +{
 | |
| +    innerTimeZoneForAutomation().displayName = String();
 | |
| +    if (innerTimeZoneForAutomation().cal) {
 | |
| +        ucal_close(innerTimeZoneForAutomation().cal);
 | |
| +        innerTimeZoneForAutomation().cal = nullptr;
 | |
| +    }
 | |
| +    if (timeZone.isEmpty()) {
 | |
| +        innerTimeZoneForAutomation().id = String();
 | |
| +        return true;
 | |
| +    }
 | |
| +
 | |
| +    // Timezone is ascii.
 | |
| +    Vector<UChar> buffer(timeZone.length());
 | |
| +    UChar* bufferStart = buffer.data();
 | |
| +    CString ctz = timeZone.utf8();
 | |
| +    if (!Unicode::convertUTF8ToUTF16(ctz.data(), ctz.data() + ctz.length(), &bufferStart, bufferStart + timeZone.length()))
 | |
| +        return false;
 | |
| +
 | |
| +    Vector<UChar, 32> canonicalBuffer(32);
 | |
| +    UErrorCode status = U_ZERO_ERROR;
 | |
| +    auto canonicalLength = ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalBuffer.size(), nullptr, &status);
 | |
| +    if (status == U_BUFFER_OVERFLOW_ERROR) {
 | |
| +        status = U_ZERO_ERROR;
 | |
| +        canonicalBuffer.grow(canonicalLength);
 | |
| +        ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalLength, nullptr, &status);
 | |
| +    }
 | |
| +    if (!U_SUCCESS(status))
 | |
| +        return false;
 | |
| +
 | |
| +    UCalendar* cal = ucal_open(canonicalBuffer.data(), canonicalLength, nullptr, UCAL_TRADITIONAL, &status);
 | |
| +    if (!U_SUCCESS(status))
 | |
| +        return false;
 | |
| +
 | |
| +    Vector<UChar, 32> displayNameBuffer(32);
 | |
| +    auto displayNameLength = ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameBuffer.size(), &status);
 | |
| +    if (status == U_BUFFER_OVERFLOW_ERROR) {
 | |
| +        status = U_ZERO_ERROR;
 | |
| +        displayNameBuffer.grow(displayNameLength);
 | |
| +        ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameLength, &status);
 | |
| +    }
 | |
| +    if (!U_SUCCESS(status))
 | |
| +        return false;
 | |
| +
 | |
| +    TimeZoneForAutomation& tzfa = innerTimeZoneForAutomation();
 | |
| +    tzfa.cal = cal;
 | |
| +    tzfa.id = String(canonicalBuffer.data(), canonicalLength);
 | |
| +    tzfa.displayName = String(displayNameBuffer.data(), displayNameLength);
 | |
| +    return true;
 | |
| +}
 | |
| +
 | |
| +String timeZoneForAutomation()
 | |
| +{
 | |
| +    return innerTimeZoneForAutomation().id;
 | |
| +}
 | |
| +
 | |
| +String timeZoneDisplayNameForAutomation()
 | |
| +{
 | |
| +    return innerTimeZoneForAutomation().displayName;
 | |
| +}
 | |
| +
 | |
|  } // namespace WTF
 | |
| diff --git a/Source/WTF/wtf/DateMath.h b/Source/WTF/wtf/DateMath.h
 | |
| index 246ba67c764b629042a7927d24fe89b049d82a0b..68d536878d1f0ba832d1c1d3e36e10b8227bbfac 100644
 | |
| --- a/Source/WTF/wtf/DateMath.h
 | |
| +++ b/Source/WTF/wtf/DateMath.h
 | |
| @@ -389,6 +389,10 @@ inline int dayInMonthFromDayInYear(int dayInYear, bool leapYear)
 | |
|      return d - step;
 | |
|  }
 | |
|  
 | |
| +WTF_EXPORT_PRIVATE bool setTimeZoneForAutomation(const String& timeZone);
 | |
| +WTF_EXPORT_PRIVATE String timeZoneForAutomation();
 | |
| +WTF_EXPORT_PRIVATE String timeZoneDisplayNameForAutomation();
 | |
| +
 | |
|  // Returns combined offset in millisecond (UTC + DST).
 | |
|  WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds, TimeType = UTCTime);
 | |
|  
 | |
| diff --git a/Source/WTF/wtf/PlatformEnable.h b/Source/WTF/wtf/PlatformEnable.h
 | |
| index f70cfc0c471410960d02e2a11205deecf722786f..b95cff9d62e01ac25f0260ca16cd3cbc2917008a 100644
 | |
| --- a/Source/WTF/wtf/PlatformEnable.h
 | |
| +++ b/Source/WTF/wtf/PlatformEnable.h
 | |
| @@ -406,7 +406,7 @@
 | |
|  #endif
 | |
|  
 | |
|  #if !defined(ENABLE_ORIENTATION_EVENTS)
 | |
| -#define ENABLE_ORIENTATION_EVENTS 0
 | |
| +#define ENABLE_ORIENTATION_EVENTS 1
 | |
|  #endif
 | |
|  
 | |
|  #if OS(WINDOWS)
 | |
| diff --git a/Source/WTF/wtf/PlatformHave.h b/Source/WTF/wtf/PlatformHave.h
 | |
| index 7a658805bf95d0b35f9c10e85b18a60dae296dd3..3d343783afa64230c6eac5e62df72f8634fcd048 100644
 | |
| --- a/Source/WTF/wtf/PlatformHave.h
 | |
| +++ b/Source/WTF/wtf/PlatformHave.h
 | |
| @@ -342,7 +342,7 @@
 | |
|  #define HAVE_NSHTTPCOOKIESTORAGE__INITWITHIDENTIFIER_WITH_INACCURATE_NULLABILITY 1
 | |
|  #endif
 | |
|  
 | |
| -#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST)
 | |
| +#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)
 | |
|  #define HAVE_OS_DARK_MODE_SUPPORT 1
 | |
|  #endif
 | |
|  
 | |
| diff --git a/Source/WebCore/Modules/geolocation/Geolocation.cpp b/Source/WebCore/Modules/geolocation/Geolocation.cpp
 | |
| index 6d5be9a591a272cd67d6e9d097b30505bdf8ae5e..8f67ba28c380e844c8e4191ee704466559d88f97 100644
 | |
| --- a/Source/WebCore/Modules/geolocation/Geolocation.cpp
 | |
| +++ b/Source/WebCore/Modules/geolocation/Geolocation.cpp
 | |
| @@ -356,8 +356,9 @@ bool Geolocation::shouldBlockGeolocationRequests()
 | |
|      bool isSecure = SecurityOrigin::isSecure(document()->url());
 | |
|      bool hasMixedContent = !document()->foundMixedContent().isEmpty();
 | |
|      bool isLocalOrigin = securityOrigin()->isLocal();
 | |
| +    bool isPotentiallyTrustworthy = securityOrigin()->isPotentiallyTrustworthy();
 | |
|      if (securityOrigin()->canRequestGeolocation()) {
 | |
| -        if (isLocalOrigin || (isSecure && !hasMixedContent) || isRequestFromIBooks())
 | |
| +        if (isLocalOrigin || isPotentiallyTrustworthy || (isSecure && !hasMixedContent) || isRequestFromIBooks())
 | |
|              return false;
 | |
|      }
 | |
|      
 | |
| diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt
 | |
| index a25286e0a68316e017c9140b90482bde0859102b..81bc29f2b83e739a561cb3e4742df4a64ec64da2 100644
 | |
| --- a/Source/WebCore/SourcesCocoa.txt
 | |
| +++ b/Source/WebCore/SourcesCocoa.txt
 | |
| @@ -670,7 +670,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 c97ef52bf50e48612037ed6ccf57344c0383bcb4..f028574572b2d87733904cc081c96ec0e9a15a5a 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 5265db58382a89060b363156bf8f17f4032b5881..eec588cf50302c89af8b35fe43452a4dd04483b6 100644
 | |
| --- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
 | |
| +++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
 | |
| @@ -5030,6 +5030,14 @@
 | |
|  		EDE3A5000C7A430600956A37 /* ColorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = EDE3A4FF0C7A430600956A37 /* ColorMac.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
|  		EDEC98030AED7E170059137F /* WebCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EDEC98020AED7E170059137F /* WebCorePrefix.h */; };
 | |
|  		EFCC6C8F20FE914400A2321B /* CanvasActivityRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
| +		F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
| +		F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16923AD660C0011CE47 /* Touch.cpp */; };
 | |
| +		F050E16D23AD66630011CE47 /* TouchList.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16B23AD66620011CE47 /* TouchList.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
| +		F050E16E23AD66630011CE47 /* TouchList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16C23AD66630011CE47 /* TouchList.cpp */; };
 | |
| +		F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16F23AD669E0011CE47 /* TouchEvent.cpp */; };
 | |
| +		F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17023AD669F0011CE47 /* TouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
| +		F050E17423AD6A800011CE47 /* DocumentTouch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E17323AD6A800011CE47 /* DocumentTouch.cpp */; };
 | |
| +		F050E17823AD70C50011CE47 /* PlatformTouchPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
|  		F12171F616A8CF0B000053CA /* WebVTTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = F12171F416A8BC63000053CA /* WebVTTElement.h */; };
 | |
|  		F32BDCD92363AACA0073B6AE /* UserGestureEmulationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = F32BDCD72363AACA0073B6AE /* UserGestureEmulationScope.h */; };
 | |
|  		F344C7141125B82C00F26EEE /* InspectorFrontendClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F344C7121125B82C00F26EEE /* InspectorFrontendClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
| @@ -15730,6 +15738,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>"; };
 | |
| @@ -21055,7 +21071,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 */,
 | |
| @@ -26345,7 +26366,9 @@
 | |
|  				B2C3D9EC0D006C1D00EF6F26 /* text */,
 | |
|  				E1EE8B6B2412B2A700E794D6 /* xr */,
 | |
|  				DFDB912CF8E88A6DA1AD264F /* AbortableTaskQueue.h */,
 | |
| +				F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */,
 | |
|  				49AE2D94134EE5F90072920A /* CalculationValue.cpp */,
 | |
| +				F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */,
 | |
|  				49AE2D95134EE5F90072920A /* CalculationValue.h */,
 | |
|  				C330A22113EC196B0000B45B /* ColorChooser.h */,
 | |
|  				C37CDEBC149EF2030042090D /* ColorChooserClient.h */,
 | |
| @@ -28728,6 +28751,7 @@
 | |
|  				BCCFBAE70B5152ED0001F1D7 /* DocumentParser.h */,
 | |
|  				AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */,
 | |
|  				AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */,
 | |
| +				F050E17323AD6A800011CE47 /* DocumentTouch.cpp */,
 | |
|  				6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */,
 | |
|  				6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */,
 | |
|  				6BDB5DC5227CA0EB00919770 /* DocumentStorageAccess.idl */,
 | |
| @@ -29612,6 +29636,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 */,
 | |
| @@ -31493,6 +31518,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 */,
 | |
| @@ -33422,9 +33448,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 */,
 | |
| @@ -34322,6 +34350,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 */,
 | |
| @@ -34389,6 +34418,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 */,
 | |
| @@ -34467,6 +34497,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 */,
 | |
| @@ -34999,6 +35030,7 @@
 | |
|  				2D8B92F1203D13E1009C868F /* UnifiedSource516.cpp in Sources */,
 | |
|  				2D8B92F2203D13E1009C868F /* UnifiedSource517.cpp in Sources */,
 | |
|  				2D8B92F3203D13E1009C868F /* UnifiedSource518.cpp in Sources */,
 | |
| +				F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */,
 | |
|  				2D8B92F4203D13E1009C868F /* UnifiedSource519.cpp in Sources */,
 | |
|  				2D8B92F5203D13E1009C868F /* UnifiedSource520.cpp in Sources */,
 | |
|  				2D8B92F6203D13E1009C868F /* UnifiedSource521.cpp in Sources */,
 | |
| diff --git a/Source/WebCore/accessibility/AccessibilityObject.cpp b/Source/WebCore/accessibility/AccessibilityObject.cpp
 | |
| index 3f800102457083c873d9bf81592bbb085cb70460..387c77e51b8268d39757608faa6f3f1f98ddd442 100644
 | |
| --- a/Source/WebCore/accessibility/AccessibilityObject.cpp
 | |
| +++ b/Source/WebCore/accessibility/AccessibilityObject.cpp
 | |
| @@ -58,6 +58,7 @@
 | |
|  #include "HTMLParserIdioms.h"
 | |
|  #include "HTMLTextAreaElement.h"
 | |
|  #include "HitTestResult.h"
 | |
| +#include "InspectorInstrumentation.h"
 | |
|  #include "LocalizedStrings.h"
 | |
|  #include "MathMLNames.h"
 | |
|  #include "NodeList.h"
 | |
| @@ -3250,10 +3251,15 @@ AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const
 | |
|      
 | |
|      if (useParentData ? m_isIgnoredFromParentData.isPresentationalChildOfAriaRole : isPresentationalChildOfAriaRole())
 | |
|          return AccessibilityObjectInclusion::IgnoreObject;
 | |
| -    
 | |
| -    return accessibilityPlatformIncludesObject();
 | |
| +
 | |
| +    AccessibilityObjectInclusion platformBehavior = accessibilityPlatformIncludesObject();
 | |
| +    if (platformBehavior != AccessibilityObjectInclusion::DefaultBehavior) {
 | |
| +        if (auto* page = this->page())
 | |
| +            InspectorInstrumentation::maybeOverrideDefaultObjectInclusion(*page, platformBehavior);
 | |
| +    }
 | |
| +    return platformBehavior;
 | |
|  }
 | |
| -    
 | |
| +
 | |
|  bool AccessibilityObject::accessibilityIsIgnored() const
 | |
|  {
 | |
|      AXComputedObjectAttributeCache* attributeCache = nullptr;
 | |
| diff --git a/Source/WebCore/css/MediaQueryEvaluator.cpp b/Source/WebCore/css/MediaQueryEvaluator.cpp
 | |
| index 8118b7ab3c50b3ced8120fc106dce9c73141afe4..2aea3ba07eae2a23b6364074d253356165757549 100644
 | |
| --- a/Source/WebCore/css/MediaQueryEvaluator.cpp
 | |
| +++ b/Source/WebCore/css/MediaQueryEvaluator.cpp
 | |
| @@ -388,7 +388,7 @@ static bool deviceAspectRatioEvaluate(CSSValue* value, const CSSToLengthConversi
 | |
|      if (!value)
 | |
|          return true;
 | |
|  
 | |
| -    auto size = screenRect(frame.mainFrame().view()).size();
 | |
| +    auto size = frame.page()->screenSize();
 | |
|      bool result = compareAspectRatioValue(value, size.width(), size.height(), op);
 | |
|      LOG_WITH_STREAM(MediaQueries, stream << "  deviceAspectRatioEvaluate: " << op << " " << aspectRatioValueAsString(value) << " actual screen size " << size << ": " << result);
 | |
|      return result;
 | |
| @@ -506,7 +506,7 @@ static bool deviceHeightEvaluate(CSSValue* value, const CSSToLengthConversionDat
 | |
|      if (!value)
 | |
|          return true;
 | |
|      int length;
 | |
| -    auto height = screenRect(frame.mainFrame().view()).height();
 | |
| +    auto height = frame.page()->screenSize().height();
 | |
|      if (!computeLength(value, !frame.document()->inQuirksMode(), conversionData, length))
 | |
|          return false;
 | |
|  
 | |
| @@ -521,8 +521,10 @@ static bool deviceWidthEvaluate(CSSValue* value, const CSSToLengthConversionData
 | |
|      // assume if we have a device, assume non-zero
 | |
|      if (!value)
 | |
|          return true;
 | |
| +    if (!frame.mainFrame().view())
 | |
| +        return false;
 | |
|      int length;
 | |
| -    auto width = screenRect(frame.mainFrame().view()).width();
 | |
| +    auto width = frame.page()->screenSize().width();
 | |
|      if (!computeLength(value, !frame.document()->inQuirksMode(), conversionData, length))
 | |
|          return false;
 | |
|  
 | |
| diff --git a/Source/WebCore/dom/UserGestureIndicator.cpp b/Source/WebCore/dom/UserGestureIndicator.cpp
 | |
| index dfec93b644f72a51bad0bebf396da61c57f6e428..353833a7614a55566862c196bafc598a475536a1 100644
 | |
| --- a/Source/WebCore/dom/UserGestureIndicator.cpp
 | |
| +++ b/Source/WebCore/dom/UserGestureIndicator.cpp
 | |
| @@ -56,8 +56,7 @@ UserGestureIndicator::UserGestureIndicator(Optional<ProcessingUserGestureState>
 | |
|  
 | |
|      if (state)
 | |
|          currentToken() = UserGestureToken::create(state.value(), gestureType);
 | |
| -
 | |
| -    if (document && currentToken()->processingUserGesture() && state) {
 | |
| +    if (document && state && currentToken()->processingUserGesture()) {
 | |
|          document->updateLastHandledUserGestureTimestamp(currentToken()->startTime());
 | |
|          if (processInteractionStyle == ProcessInteractionStyle::Immediate)
 | |
|              ResourceLoadObserver::shared().logUserInteractionWithReducedTimeResolution(document->topDocument());
 | |
| diff --git a/Source/WebCore/html/FileInputType.cpp b/Source/WebCore/html/FileInputType.cpp
 | |
| index 8f71781a258167280f2ae9a8fcd2b79a7e888f12..c8f4bf45765345fd4abd777e2c4975372325c6f4 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"
 | |
| @@ -204,6 +205,11 @@ void FileInputType::handleDOMActivateEvent(Event& event)
 | |
|      if (input.isDisabledFormControl())
 | |
|          return;
 | |
|  
 | |
| +    bool intercept = false;
 | |
| +    InspectorInstrumentation::runOpenPanel(input.document().frame(), element(), &intercept);
 | |
| +    if (intercept)
 | |
| +        return;
 | |
| +
 | |
|      if (!UserGestureIndicator::processingUserGesture())
 | |
|          return;
 | |
|  
 | |
| diff --git a/Source/WebCore/inspector/InspectorController.cpp b/Source/WebCore/inspector/InspectorController.cpp
 | |
| index a595c13494442c6a69c4f24b1347f057b770211b..0db75363bd708b371e1db1ea81c1b025744bc9e1 100644
 | |
| --- a/Source/WebCore/inspector/InspectorController.cpp
 | |
| +++ b/Source/WebCore/inspector/InspectorController.cpp
 | |
| @@ -371,8 +371,8 @@ void InspectorController::inspect(Node* node)
 | |
|      if (!enabled())
 | |
|          return;
 | |
|  
 | |
| -    if (!hasRemoteFrontend())
 | |
| -        show();
 | |
| +    // HACK: Always attempt to show inspector even if there is a remote connection.
 | |
| +    show();
 | |
|  
 | |
|      ensureDOMAgent().inspect(node);
 | |
|  }
 | |
| @@ -515,4 +515,24 @@ void InspectorController::didComposite(Frame& frame)
 | |
|      InspectorInstrumentation::didComposite(frame);
 | |
|  }
 | |
|  
 | |
| +void InspectorController::pauseWhenShown()
 | |
| +{
 | |
| +    m_pauseWhenShown = true;
 | |
| +}
 | |
| +
 | |
| +void InspectorController::resumeIfPausedInNewWindow()
 | |
| +{
 | |
| +    m_pauseWhenShown = false;
 | |
| +}
 | |
| +
 | |
| +void InspectorController::didShowNewWindow()
 | |
| +{
 | |
| +    if (!m_pauseWhenShown)
 | |
| +        return;
 | |
| +    while (m_pauseWhenShown) {
 | |
| +        if (RunLoop::cycle() == RunLoop::CycleResult::Stop)
 | |
| +            break;
 | |
| +    }
 | |
| +}
 | |
| +
 | |
|  } // namespace WebCore
 | |
| diff --git a/Source/WebCore/inspector/InspectorController.h b/Source/WebCore/inspector/InspectorController.h
 | |
| index bca5ead33d04e3b1f4d67cd335242334e93892ca..bbac092e2c1377d6e1a687e2ea820286b68ec68b 100644
 | |
| --- a/Source/WebCore/inspector/InspectorController.h
 | |
| +++ b/Source/WebCore/inspector/InspectorController.h
 | |
| @@ -101,6 +101,10 @@ public:
 | |
|      WEBCORE_EXPORT void willComposite(Frame&);
 | |
|      WEBCORE_EXPORT void didComposite(Frame&);
 | |
|  
 | |
| +    WEBCORE_EXPORT void pauseWhenShown();
 | |
| +    WEBCORE_EXPORT void resumeIfPausedInNewWindow();
 | |
| +    WEBCORE_EXPORT void didShowNewWindow();
 | |
| +
 | |
|      bool isUnderTest() const { return m_isUnderTest; }
 | |
|      void setIsUnderTest(bool isUnderTest) { m_isUnderTest = isUnderTest; }
 | |
|      WEBCORE_EXPORT void evaluateForTestInFrontend(const String& script);
 | |
| @@ -150,6 +154,7 @@ private:
 | |
|      bool m_isAutomaticInspection { false };
 | |
|      bool m_pauseAfterInitialization = { false };
 | |
|      bool m_didCreateLazyAgents { false };
 | |
| +    bool m_pauseWhenShown { false };
 | |
|  };
 | |
|  
 | |
|  } // namespace WebCore
 | |
| diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp
 | |
| index 191cf8d0e2562c41d03c5830c8ee06b239a8fe89..0417261c688f9e032cba8de38142eafc386725b8 100644
 | |
| --- a/Source/WebCore/inspector/InspectorInstrumentation.cpp
 | |
| +++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp
 | |
| @@ -627,6 +627,12 @@ void InspectorInstrumentation::didFailLoadingImpl(InstrumentingAgents& instrumen
 | |
|          consoleAgent->didFailLoading(identifier, error); // This should come AFTER resource notification, front-end relies on this.
 | |
|  }
 | |
|  
 | |
| +void InspectorInstrumentation::didReceiveMainResourceErrorImpl(InstrumentingAgents& instrumentingAgents, Frame& frame, const ResourceError&)
 | |
| +{
 | |
| +    if (auto* pageRuntimeAgent = instrumentingAgents.enabledPageRuntimeAgent())
 | |
| +        pageRuntimeAgent->didReceiveMainResourceError(frame);
 | |
| +}
 | |
| +
 | |
|  void InspectorInstrumentation::willLoadXHRSynchronouslyImpl(InstrumentingAgents& instrumentingAgents)
 | |
|  {
 | |
|      if (auto* networkAgent = instrumentingAgents.enabledNetworkAgent())
 | |
| @@ -659,20 +665,17 @@ void InspectorInstrumentation::didReceiveScriptResponseImpl(InstrumentingAgents&
 | |
|  
 | |
|  void InspectorInstrumentation::domContentLoadedEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
 | |
|  {
 | |
| -    if (!frame.isMainFrame())
 | |
| -        return;
 | |
| -
 | |
|      if (auto* pageAgent = instrumentingAgents.enabledPageAgent())
 | |
| -        pageAgent->domContentEventFired();
 | |
| +        pageAgent->domContentEventFired(frame);
 | |
|  }
 | |
|  
 | |
|  void InspectorInstrumentation::loadEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame* frame)
 | |
|  {
 | |
| -    if (!frame || !frame->isMainFrame())
 | |
| +    if (!frame)
 | |
|          return;
 | |
|  
 | |
|      if (auto* pageAgent = instrumentingAgents.enabledPageAgent())
 | |
| -        pageAgent->loadEventFired();
 | |
| +        pageAgent->loadEventFired(*frame);
 | |
|  }
 | |
|  
 | |
|  void InspectorInstrumentation::frameDetachedFromParentImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
 | |
| @@ -750,12 +753,6 @@ void InspectorInstrumentation::frameDocumentUpdatedImpl(InstrumentingAgents& ins
 | |
|          pageDOMDebuggerAgent->frameDocumentUpdated(frame);
 | |
|  }
 | |
|  
 | |
| -void InspectorInstrumentation::loaderDetachedFromFrameImpl(InstrumentingAgents& instrumentingAgents, DocumentLoader& loader)
 | |
| -{
 | |
| -    if (auto* inspectorPageAgent = instrumentingAgents.enabledPageAgent())
 | |
| -        inspectorPageAgent->loaderDetachedFromFrame(loader);
 | |
| -}
 | |
| -
 | |
|  void InspectorInstrumentation::frameStartedLoadingImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
 | |
|  {
 | |
|      if (frame.isMainFrame()) {
 | |
| @@ -792,6 +789,12 @@ void InspectorInstrumentation::frameClearedScheduledNavigationImpl(Instrumenting
 | |
|          inspectorPageAgent->frameClearedScheduledNavigation(frame);
 | |
|  }
 | |
|  
 | |
| +void InspectorInstrumentation::didNavigateWithinPageImpl(InstrumentingAgents& instrumentingAgents, Frame& frame)
 | |
| +{
 | |
| +    if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.enabledPageAgent())
 | |
| +        inspectorPageAgent->didNavigateWithinPage(frame);
 | |
| +}
 | |
| +
 | |
|  #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
 | |
|  void InspectorInstrumentation::defaultAppearanceDidChangeImpl(InstrumentingAgents& instrumentingAgents, bool useDarkAppearance)
 | |
|  {
 | |
| @@ -1315,6 +1318,36 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents& ins
 | |
|          layerTreeAgent->renderLayerDestroyed(renderLayer);
 | |
|  }
 | |
|  
 | |
| +void InspectorInstrumentation::runOpenPanelImpl(InstrumentingAgents& instrumentingAgents, HTMLInputElement* element, bool* intercept)
 | |
| +{
 | |
| +    if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent())
 | |
| +        pageAgent->runOpenPanel(element, intercept);
 | |
| +}
 | |
| +
 | |
| +void InspectorInstrumentation::frameAttachedImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) {
 | |
| +    if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent())
 | |
| +        pageAgent->frameAttached(frame);
 | |
| +}
 | |
| +
 | |
| +bool InspectorInstrumentation::shouldBypassCSPImpl(InstrumentingAgents& instrumentingAgents)
 | |
| +{
 | |
| +    if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent())
 | |
| +        return pageAgent->shouldBypassCSP();
 | |
| +    return false;
 | |
| +}
 | |
| +
 | |
| +void InspectorInstrumentation::willCheckNewWindowPolicyImpl(InstrumentingAgents& instrumentingAgents, const URL& url)
 | |
| +{
 | |
| +    if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent())
 | |
| +        pageAgent->willCheckNewWindowPolicy(url);
 | |
| +}
 | |
| +
 | |
| +void InspectorInstrumentation::didCheckNewWindowPolicyImpl(InstrumentingAgents& instrumentingAgents, bool allowed)
 | |
| +{
 | |
| +    if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent())
 | |
| +        pageAgent->didCheckNewWindowPolicy(allowed);
 | |
| +}
 | |
| +
 | |
|  InstrumentingAgents& InspectorInstrumentation::instrumentingAgentsForWorkerGlobalScope(WorkerGlobalScope& workerGlobalScope)
 | |
|  {
 | |
|      return workerGlobalScope.inspectorController().m_instrumentingAgents;
 | |
| @@ -1326,6 +1359,13 @@ InstrumentingAgents& InspectorInstrumentation::instrumentingAgentsForPage(Page&
 | |
|      return page.inspectorController().m_instrumentingAgents.get();
 | |
|  }
 | |
|  
 | |
| +void InspectorInstrumentation::maybeOverrideDefaultObjectInclusion(Page& page, AccessibilityObjectInclusion& inclusion) {
 | |
| +    if (InspectorPageAgent* pageAgent = InspectorInstrumentation::instrumentingAgentsForPage(page).enabledPageAgent()) {
 | |
| +        if (pageAgent->doingAccessibilitySnapshot())
 | |
| +            inclusion = AccessibilityObjectInclusion::DefaultBehavior;
 | |
| +    }
 | |
| +}
 | |
| +
 | |
|  InstrumentingAgents* InspectorInstrumentation::instrumentingAgentsForContext(ScriptExecutionContext& context)
 | |
|  {
 | |
|      if (is<Document>(context))
 | |
| diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h
 | |
| index 730f33251dd0274404adef8f6f3fb6e09cd6fe29..c193eb96be720f1a055b242948f8b388f32c4d41 100644
 | |
| --- a/Source/WebCore/inspector/InspectorInstrumentation.h
 | |
| +++ b/Source/WebCore/inspector/InspectorInstrumentation.h
 | |
| @@ -31,6 +31,7 @@
 | |
|  
 | |
|  #pragma once
 | |
|  
 | |
| +#include "AccessibilityObjectInterface.h"
 | |
|  #include "CSSSelector.h"
 | |
|  #include "CallTracerTypes.h"
 | |
|  #include "CanvasBase.h"
 | |
| @@ -80,6 +81,7 @@ class DOMWrapperWorld;
 | |
|  class Document;
 | |
|  class DocumentLoader;
 | |
|  class EventListener;
 | |
| +class HTMLInputElement;
 | |
|  class HTTPHeaderMap;
 | |
|  class InspectorTimelineAgent;
 | |
|  class InstrumentingAgents;
 | |
| @@ -200,6 +202,7 @@ public:
 | |
|      static void didReceiveData(Frame*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
 | |
|      static void didFinishLoading(Frame*, DocumentLoader*, unsigned long identifier, const NetworkLoadMetrics&, ResourceLoader*);
 | |
|      static void didFailLoading(Frame*, DocumentLoader*, unsigned long identifier, const ResourceError&);
 | |
| +    static void didReceiveMainResourceError(Frame&, const ResourceError&);
 | |
|  
 | |
|      static void willSendRequest(WorkerGlobalScope&, unsigned long identifier, ResourceRequest&);
 | |
|      static void didReceiveResourceResponse(WorkerGlobalScope&, unsigned long identifier, const ResourceResponse&);
 | |
| @@ -226,11 +229,11 @@ public:
 | |
|      static void frameDetachedFromParent(Frame&);
 | |
|      static void didCommitLoad(Frame&, DocumentLoader*);
 | |
|      static void frameDocumentUpdated(Frame&);
 | |
| -    static void loaderDetachedFromFrame(Frame&, DocumentLoader&);
 | |
|      static void frameStartedLoading(Frame&);
 | |
|      static void frameStoppedLoading(Frame&);
 | |
|      static void frameScheduledNavigation(Frame&, Seconds delay);
 | |
|      static void frameClearedScheduledNavigation(Frame&);
 | |
| +    static void didNavigateWithinPage(Frame&);
 | |
|  #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
 | |
|      static void defaultAppearanceDidChange(Page&, bool useDarkAppearance);
 | |
|  #endif
 | |
| @@ -325,6 +328,12 @@ public:
 | |
|      static void layerTreeDidChange(Page*);
 | |
|      static void renderLayerDestroyed(Page*, const RenderLayer&);
 | |
|  
 | |
| +    static void runOpenPanel(Frame*, HTMLInputElement*, bool*);
 | |
| +    static void frameAttached(Frame*);
 | |
| +    static bool shouldBypassCSP(ScriptExecutionContext*);
 | |
| +    static void willCheckNewWindowPolicy(Frame&, const URL&);
 | |
| +    static void didCheckNewWindowPolicy(Frame&, bool allowed);
 | |
| +
 | |
|      static void frontendCreated();
 | |
|      static void frontendDeleted();
 | |
|      static bool hasFrontends() { return InspectorInstrumentationPublic::hasFrontends(); }
 | |
| @@ -340,6 +349,8 @@ public:
 | |
|      static void registerInstrumentingAgents(InstrumentingAgents&);
 | |
|      static void unregisterInstrumentingAgents(InstrumentingAgents&);
 | |
|  
 | |
| +    static void maybeOverrideDefaultObjectInclusion(Page&, AccessibilityObjectInclusion&);
 | |
| +
 | |
|  private:
 | |
|      static void didClearWindowObjectInWorldImpl(InstrumentingAgents&, Frame&, DOMWrapperWorld&);
 | |
|      static bool isDebuggerPausedImpl(InstrumentingAgents&);
 | |
| @@ -426,6 +437,7 @@ private:
 | |
|      static void didReceiveDataImpl(InstrumentingAgents&, unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
 | |
|      static void didFinishLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, const NetworkLoadMetrics&, ResourceLoader*);
 | |
|      static void didFailLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, const ResourceError&);
 | |
| +    static void didReceiveMainResourceErrorImpl(InstrumentingAgents&, Frame&, const ResourceError&);
 | |
|      static void willLoadXHRSynchronouslyImpl(InstrumentingAgents&);
 | |
|      static void didLoadXHRSynchronouslyImpl(InstrumentingAgents&);
 | |
|      static void scriptImportedImpl(InstrumentingAgents&, unsigned long identifier, const String& sourceString);
 | |
| @@ -436,11 +448,11 @@ private:
 | |
|      static void frameDetachedFromParentImpl(InstrumentingAgents&, Frame&);
 | |
|      static void didCommitLoadImpl(InstrumentingAgents&, Frame&, DocumentLoader*);
 | |
|      static void frameDocumentUpdatedImpl(InstrumentingAgents&, Frame&);
 | |
| -    static void loaderDetachedFromFrameImpl(InstrumentingAgents&, DocumentLoader&);
 | |
|      static void frameStartedLoadingImpl(InstrumentingAgents&, Frame&);
 | |
|      static void frameStoppedLoadingImpl(InstrumentingAgents&, Frame&);
 | |
|      static void frameScheduledNavigationImpl(InstrumentingAgents&, Frame&, Seconds delay);
 | |
|      static void frameClearedScheduledNavigationImpl(InstrumentingAgents&, Frame&);
 | |
| +    static void didNavigateWithinPageImpl(InstrumentingAgents&, Frame&);
 | |
|  #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
 | |
|      static void defaultAppearanceDidChangeImpl(InstrumentingAgents&, bool useDarkAppearance);
 | |
|  #endif
 | |
| @@ -531,6 +543,12 @@ private:
 | |
|      static void layerTreeDidChangeImpl(InstrumentingAgents&);
 | |
|      static void renderLayerDestroyedImpl(InstrumentingAgents&, const RenderLayer&);
 | |
|  
 | |
| +    static void runOpenPanelImpl(InstrumentingAgents&, HTMLInputElement*, bool*);
 | |
| +    static void frameAttachedImpl(InstrumentingAgents&, Frame&);
 | |
| +    static bool shouldBypassCSPImpl(InstrumentingAgents&);
 | |
| +    static void willCheckNewWindowPolicyImpl(InstrumentingAgents&, const URL&);
 | |
| +    static void didCheckNewWindowPolicyImpl(InstrumentingAgents&, bool allowed);
 | |
| +
 | |
|      static InstrumentingAgents& instrumentingAgentsForPage(Page&);
 | |
|      static InstrumentingAgents& instrumentingAgentsForWorkerGlobalScope(WorkerGlobalScope&);
 | |
|  
 | |
| @@ -1119,6 +1137,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);
 | |
| @@ -1214,13 +1239,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());
 | |
| @@ -1249,6 +1267,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);
 | |
| +}
 | |
| +
 | |
|  #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
 | |
|  inline void InspectorInstrumentation::defaultAppearanceDidChange(Page& page, bool useDarkAppearance)
 | |
|  {
 | |
| @@ -1723,6 +1748,42 @@ inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const Ren
 | |
|          renderLayerDestroyedImpl(*instrumentingAgents, renderLayer);
 | |
|  }
 | |
|  
 | |
| +inline void InspectorInstrumentation::runOpenPanel(Frame* frame, HTMLInputElement* element, bool* intercept)
 | |
| +{
 | |
| +    FAST_RETURN_IF_NO_FRONTENDS(void());
 | |
| +    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(*frame))
 | |
| +        runOpenPanelImpl(*instrumentingAgents, element, intercept);
 | |
| +}
 | |
| +
 | |
| +inline void InspectorInstrumentation::frameAttached(Frame* frame)
 | |
| +{
 | |
| +    FAST_RETURN_IF_NO_FRONTENDS(void());
 | |
| +    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
 | |
| +        frameAttachedImpl(*instrumentingAgents, *frame);
 | |
| +}
 | |
| +
 | |
| +inline bool InspectorInstrumentation::shouldBypassCSP(ScriptExecutionContext* context)
 | |
| +{
 | |
| +    FAST_RETURN_IF_NO_FRONTENDS(false);
 | |
| +    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
 | |
| +        return shouldBypassCSPImpl(*instrumentingAgents);
 | |
| +    return false;
 | |
| +}
 | |
| +
 | |
| +inline void InspectorInstrumentation::willCheckNewWindowPolicy(Frame& frame, const URL& url)
 | |
| +{
 | |
| +    FAST_RETURN_IF_NO_FRONTENDS(void());
 | |
| +    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
 | |
| +        willCheckNewWindowPolicyImpl(*instrumentingAgents, url);
 | |
| +}
 | |
| +
 | |
| +inline void InspectorInstrumentation::didCheckNewWindowPolicy(Frame& frame, bool allowed)
 | |
| +{
 | |
| +    FAST_RETURN_IF_NO_FRONTENDS(void());
 | |
| +    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
 | |
| +        didCheckNewWindowPolicyImpl(*instrumentingAgents, allowed);
 | |
| +}
 | |
| +
 | |
|  inline InstrumentingAgents* InspectorInstrumentation::instrumentingAgentsForContext(ScriptExecutionContext* context)
 | |
|  {
 | |
|      return context ? instrumentingAgentsForContext(*context) : nullptr;
 | |
| diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp
 | |
| index 8acc1f6dba71a7d3421f135112bcf8bbc70c4128..5645f2a7a61e26f3534aeb6dd281260f50db677b 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);
 | |
| @@ -1337,16 +1359,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;
 | |
|  
 | |
| @@ -1494,18 +1507,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.enabledPageAgent();
 | |
| +    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;
 | |
| +    }
 | |
| +    m_inspectedPage.updateRendering();
 | |
| +    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.
 | |
| +    m_inspectedPage.updateRendering();
 | |
| +
 | |
| +    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)
 | |
| @@ -2670,7 +2812,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())
 | |
| @@ -2679,12 +2821,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)
 | |
| @@ -2705,4 +2851,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 7e6d3f68d3d60caf3d3a01acc380a2605f42d6e3..426716243b178543bc96799401a0a1ce6d6db26a 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.
 | |
| @@ -131,7 +133,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;
 | |
|  #if PLATFORM(IOS_FAMILY)
 | |
|      void setInspectModeEnabled(ErrorString&, bool enabled, const JSON::Object* highlightConfig) override;
 | |
| @@ -154,6 +156,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&);
 | |
| @@ -191,7 +197,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*);
 | |
| @@ -202,12 +208,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();
 | |
| @@ -234,9 +243,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 ddbb5d5347f3beabe3cfab201d6838c896d21e39..25f1798cad5a4ef135a27d3bd5146798d1077a13 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 1ccc5f5de274bd263c8bec5c72fe417ea99534fd..f1c538d44e1a33dc4d5159007392c765cc3920e7 100644
 | |
| --- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp
 | |
| +++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp
 | |
| @@ -44,6 +44,7 @@
 | |
|  #include "DocumentThreadableLoader.h"
 | |
|  #include "FormData.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"
 | |
| @@ -485,8 +487,14 @@ static InspectorPageAgent::ResourceType resourceTypeForLoadType(InspectorInstrum
 | |
|  
 | |
|  void InspectorNetworkAgent::willSendRequest(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse)
 | |
|  {
 | |
| -    auto* cachedResource = loader ? InspectorPageAgent::cachedResource(loader->frame(), request.url()) : nullptr;
 | |
| -    willSendRequest(identifier, loader, request, redirectResponse, resourceTypeForCachedResource(cachedResource));
 | |
| +    InspectorPageAgent::ResourceType resourceType;
 | |
| +    if (request.initiatorIdentifier() == initiatorIdentifierForEventSource()) {
 | |
| +      resourceType = InspectorPageAgent::EventSource;
 | |
| +    } else {
 | |
| +      auto* cachedResource = loader ? InspectorPageAgent::cachedResource(loader->frame(), request.url()) : nullptr;
 | |
| +      resourceType = resourceTypeForCachedResource(cachedResource);
 | |
| +    }
 | |
| +    willSendRequest(identifier, loader, request, redirectResponse, resourceType);
 | |
|  }
 | |
|  
 | |
|  void InspectorNetworkAgent::willSendRequestOfType(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, InspectorInstrumentation::LoadType loadType)
 | |
| @@ -1094,8 +1102,7 @@ bool InspectorNetworkAgent::willIntercept(const ResourceRequest& request)
 | |
|      if (!m_interceptionEnabled)
 | |
|          return false;
 | |
|  
 | |
| -    return shouldIntercept(request.url(), NetworkStage::Request)
 | |
| -        || shouldIntercept(request.url(), NetworkStage::Response);
 | |
| +    return shouldIntercept(request.url(), NetworkStage::Response);
 | |
|  }
 | |
|  
 | |
|  bool InspectorNetworkAgent::shouldInterceptRequest(const ResourceRequest& request)
 | |
| @@ -1179,6 +1186,11 @@ void InspectorNetworkAgent::interceptWithRequest(ErrorString& errorString, const
 | |
|      }
 | |
|  
 | |
|      auto& loader = *pendingRequest->m_loader;
 | |
| +    if (loader.reachedTerminalState()) {
 | |
| +        errorString = "Unable to intercept request, it has already been processed"_s;
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
|      ResourceRequest request = loader.request();
 | |
|      if (url)
 | |
|          request.setURL(URL({ }, *url));
 | |
| @@ -1291,6 +1303,8 @@ void InspectorNetworkAgent::interceptRequestWithResponse(ErrorString& errorStrin
 | |
|      response.setHTTPHeaderFields(WTFMove(explicitHeaders));
 | |
|      response.setHTTPHeaderField(HTTPHeaderName::ContentType, response.mimeType());
 | |
|      loader->didReceiveResponse(response, [loader, buffer = data.releaseNonNull()]() mutable {
 | |
| +        if (loader->reachedTerminalState())
 | |
| +            return;
 | |
|          if (buffer->size())
 | |
|              loader->didReceiveBuffer(WTFMove(buffer), buffer->size(), DataPayloadWholeResource);
 | |
|          loader->didFinishLoading(NetworkLoadMetrics());
 | |
| @@ -1335,6 +1349,11 @@ void InspectorNetworkAgent::interceptRequestWithError(ErrorString& errorString,
 | |
|      loader.didFail(error);
 | |
|  }
 | |
|  
 | |
| +void InspectorNetworkAgent::setEmulateOfflineState(ErrorString&, bool offline)
 | |
| +{
 | |
| +    platformStrategies()->loaderStrategy()->setEmulateOfflineState(offline);
 | |
| +}
 | |
| +
 | |
|  bool InspectorNetworkAgent::shouldTreatAsText(const String& mimeType)
 | |
|  {
 | |
|      return startsWithLettersIgnoringASCIICase(mimeType, "text/")
 | |
| @@ -1376,6 +1395,12 @@ Optional<String> InspectorNetworkAgent::textContentForCachedResource(CachedResou
 | |
|      return WTF::nullopt;
 | |
|  }
 | |
|  
 | |
| +// static
 | |
| +String InspectorNetworkAgent::initiatorIdentifierForEventSource()
 | |
| +{
 | |
| +    return "InspectorNetworkAgent: eventSource"_s;
 | |
| +}
 | |
| +
 | |
|  bool InspectorNetworkAgent::cachedResourceContent(CachedResource& resource, String* result, bool* base64Encoded)
 | |
|  {
 | |
|      ASSERT(result);
 | |
| diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
 | |
| index 3440e71a5ed5ef384620a9f62803751e983db5b1..45e0df5e6d92626ae112d92cffdd745516e4d137 100644
 | |
| --- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
 | |
| +++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h
 | |
| @@ -73,6 +73,7 @@ public:
 | |
|      static Ref<TextResourceDecoder> createTextDecoder(const String& mimeType, const String& textEncodingName);
 | |
|      static Optional<String> textContentForCachedResource(CachedResource&);
 | |
|      static bool cachedResourceContent(CachedResource&, String* result, bool* base64Encoded);
 | |
| +    static String initiatorIdentifierForEventSource();
 | |
|  
 | |
|      // InspectorAgentBase
 | |
|      void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) final;
 | |
| @@ -126,6 +127,7 @@ public:
 | |
|      bool shouldInterceptResponse(const ResourceResponse&);
 | |
|      void interceptResponse(const ResourceResponse&, unsigned long identifier, CompletionHandler<void(const ResourceResponse&, RefPtr<SharedBuffer>)>&&);
 | |
|      void interceptRequest(ResourceLoader&, Function<void(const ResourceRequest&)>&&);
 | |
| +    void setEmulateOfflineState(ErrorString&, bool offline) final;
 | |
|  
 | |
|      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>>&);
 | |
| diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
 | |
| index 539e8105b66e7b2a6a05571a1e1c8cd6bdf27c90..45489cd5e978ac70be8fb33bb3e137ab5eff2d11 100644
 | |
| --- a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
 | |
| +++ b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp
 | |
| @@ -32,19 +32,27 @@
 | |
|  #include "config.h"
 | |
|  #include "InspectorPageAgent.h"
 | |
|  
 | |
| +#include "AXObjectCache.h"
 | |
| +#include "BackForwardController.h"
 | |
|  #include "CachedResource.h"
 | |
|  #include "CachedResourceLoader.h"
 | |
|  #include "Cookie.h"
 | |
|  #include "CookieJar.h"
 | |
| +#include "CustomHeaderFields.h"
 | |
| +#include "CSSAnimationController.h"
 | |
|  #include "DOMWrapperWorld.h"
 | |
|  #include "Document.h"
 | |
| +#include "DocumentTimeline.h"
 | |
|  #include "DocumentLoader.h"
 | |
| +#include "FocusController.h"
 | |
|  #include "Frame.h"
 | |
|  #include "FrameLoadRequest.h"
 | |
|  #include "FrameLoader.h"
 | |
| +#include "FrameLoaderClient.h"
 | |
|  #include "FrameSnapshotting.h"
 | |
|  #include "FrameView.h"
 | |
|  #include "HTMLFrameOwnerElement.h"
 | |
| +#include "HTMLInputElement.h"
 | |
|  #include "HTMLNames.h"
 | |
|  #include "ImageBuffer.h"
 | |
|  #include "InspectorClient.h"
 | |
| @@ -55,19 +63,30 @@
 | |
|  #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 "SVGDocumentExtensions.h"
 | |
|  #include "TextEncoding.h"
 | |
| +#include "TypingCommand.h"
 | |
|  #include "UserGestureIndicator.h"
 | |
|  #include <JavaScriptCore/ContentSearchUtilities.h>
 | |
|  #include <JavaScriptCore/IdentifiersFactory.h>
 | |
| +#include <JavaScriptCore/InjectedScriptManager.h>
 | |
|  #include <JavaScriptCore/RegularExpression.h>
 | |
| +#include <wtf/DateMath.h>
 | |
|  #include <wtf/ListHashSet.h>
 | |
| +#include <wtf/MainThread.h>
 | |
| +#include <wtf/NeverDestroyed.h>
 | |
| +#include <wtf/Ref.h>
 | |
| +#include <wtf/RefPtr.h>
 | |
|  #include <wtf/Stopwatch.h>
 | |
|  #include <wtf/text/Base64.h>
 | |
|  #include <wtf/text/StringBuilder.h>
 | |
| @@ -80,11 +99,15 @@
 | |
|  #include "LegacyWebArchive.h"
 | |
|  #endif
 | |
|  
 | |
| -
 | |
|  namespace WebCore {
 | |
|  
 | |
|  using namespace Inspector;
 | |
|  
 | |
| +static HashMap<String, Ref<DOMWrapperWorld>>& createdUserWorlds() {
 | |
| +    static NeverDestroyed<HashMap<String, Ref<DOMWrapperWorld>>> nameToWorld;
 | |
| +    return nameToWorld;
 | |
| +}
 | |
| +
 | |
|  static bool decodeBuffer(const char* buffer, unsigned size, const String& textEncodingName, String* result)
 | |
|  {
 | |
|      if (buffer) {
 | |
| @@ -236,6 +259,8 @@ Inspector::Protocol::Page::ResourceType InspectorPageAgent::resourceTypeJSON(Ins
 | |
|          return Inspector::Protocol::Page::ResourceType::Beacon;
 | |
|      case WebSocketResource:
 | |
|          return Inspector::Protocol::Page::ResourceType::WebSocket;
 | |
| +    case EventSource:
 | |
| +        return Inspector::Protocol::Page::ResourceType::EventSource;
 | |
|      case OtherResource:
 | |
|          return Inspector::Protocol::Page::ResourceType::Other;
 | |
|  #if ENABLE(APPLICATION_MANIFEST)
 | |
| @@ -325,6 +350,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)
 | |
|  {
 | |
| @@ -358,11 +384,20 @@ void InspectorPageAgent::enable(ErrorString& errorString)
 | |
|  #if ENABLE(DARK_MODE_CSS) || 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.setEnabledPageAgent(nullptr);
 | |
| +    m_interceptFileChooserDialog = false;
 | |
| +    m_bypassCSP = false;
 | |
|  
 | |
|      ErrorString unused;
 | |
|      setShowPaintRects(unused, false);
 | |
| @@ -412,6 +447,18 @@ void InspectorPageAgent::reload(ErrorString&, const bool* optionalReloadFromOrig
 | |
|      m_inspectedPage.mainFrame().loader().reload(reloadOptions);
 | |
|  }
 | |
|  
 | |
| +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&, const String& url)
 | |
|  {
 | |
|      UserGestureIndicator indicator { ProcessingUserGesture };
 | |
| @@ -791,15 +838,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)
 | |
| @@ -807,13 +855,23 @@ void InspectorPageAgent::frameNavigated(Frame& frame)
 | |
|      m_frontendDispatcher->frameNavigated(buildObjectForFrame(&frame));
 | |
|  }
 | |
|  
 | |
| +String InspectorPageAgent::makeFrameID(ProcessIdentifier processID,  FrameIdentifier frameID)
 | |
| +{
 | |
| +    return makeString(processID.toUInt64(), ".", frameID.toUInt64());
 | |
| +}
 | |
| +
 | |
| +static String globalIDForFrame(Frame& frame)
 | |
| +{
 | |
| +    return InspectorPageAgent::makeFrameID(Process::identifier(), *frame.loader().client().frameID());
 | |
| +}
 | |
| +
 | |
|  void InspectorPageAgent::frameDetached(Frame& frame)
 | |
|  {
 | |
| -    auto identifier = m_frameToIdentifier.take(&frame);
 | |
| -    if (identifier.isNull())
 | |
| +    String identifier = globalIDForFrame(frame);
 | |
| +    if (!m_identifierToFrame.take(identifier))
 | |
|          return;
 | |
| +
 | |
|      m_frontendDispatcher->frameDetached(identifier);
 | |
| -    m_identifierToFrame.remove(identifier);
 | |
|  }
 | |
|  
 | |
|  Frame* InspectorPageAgent::frameForId(const String& frameId)
 | |
| @@ -825,20 +883,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)
 | |
| @@ -849,11 +905,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));
 | |
| @@ -874,6 +925,12 @@ void InspectorPageAgent::frameClearedScheduledNavigation(Frame& frame)
 | |
|      m_frontendDispatcher->frameClearedScheduledNavigation(frameId(&frame));
 | |
|  }
 | |
|  
 | |
| +void InspectorPageAgent::didNavigateWithinPage(Frame& frame)
 | |
| +{
 | |
| +    String url = frame.document()->url().string();
 | |
| +    m_frontendDispatcher->navigatedWithinDocument(frameId(&frame), url);
 | |
| +}
 | |
| +
 | |
|  #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
 | |
|  void InspectorPageAgent::defaultAppearanceDidChange(bool useDarkAppearance)
 | |
|  {
 | |
| @@ -933,6 +990,48 @@ void InspectorPageAgent::didRecalculateStyle()
 | |
|      m_overlay->update();
 | |
|  }
 | |
|  
 | |
| +void InspectorPageAgent::runOpenPanel(HTMLInputElement* element, bool* intercept)
 | |
| +{
 | |
| +    if (m_interceptFileChooserDialog) {
 | |
| +        *intercept = true;
 | |
| +    } else {
 | |
| +        return;
 | |
| +    }
 | |
| +    Document& document = element->document();
 | |
| +    auto* frame =  document.frame();
 | |
| +    if (!frame)
 | |
| +        return;
 | |
| +
 | |
| +    auto& state = *mainWorldExecState(frame);
 | |
| +    auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state);
 | |
| +    if (injectedScript.hasNoValue())
 | |
| +        return;
 | |
| +
 | |
| +    m_frontendDispatcher->fileChooserOpened(frameId(frame), injectedScript.wrapObject(InspectorDOMAgent::nodeAsScriptValue(state, element), WTF::String()));
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::frameAttached(Frame& frame)
 | |
| +{
 | |
| +    Frame* parent = frame.tree().parent();
 | |
| +    String parentFrameId = frameId(parent);
 | |
| +    m_frontendDispatcher->frameAttached(frameId(&frame), parent ? &parentFrameId : nullptr);
 | |
| +}
 | |
| +
 | |
| +bool InspectorPageAgent::shouldBypassCSP()
 | |
| +{
 | |
| +    return m_bypassCSP;
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::willCheckNewWindowPolicy(const URL& url)
 | |
| +{
 | |
| +    m_frontendDispatcher->willRequestOpenWindow(url.string());
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::didCheckNewWindowPolicy(bool allowed)
 | |
| +{
 | |
| +    m_frontendDispatcher->didRequestOpenWindow(allowed);
 | |
| +}
 | |
| +
 | |
|  Ref<Inspector::Protocol::Page::Frame> InspectorPageAgent::buildObjectForFrame(Frame* frame)
 | |
|  {
 | |
|      ASSERT_ARG(frame, frame);
 | |
| @@ -1073,6 +1172,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
 | |
| +}
 | |
| +
 | |
| +
 | |
|  #if ENABLE(WEB_ARCHIVE) && USE(CF)
 | |
|  void InspectorPageAgent::archive(ErrorString& errorString, String* data)
 | |
|  {
 | |
| @@ -1087,4 +1209,578 @@ 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.persistentDOMAgent();
 | |
| +        ASSERT(domAgent);
 | |
| +        node = domAgent->nodeForObjectId(*objectId);
 | |
| +        if (!node) {
 | |
| +            errorString = "No Node for objectId"_s;
 | |
| +            return;
 | |
| +        }
 | |
| +    }
 | |
| +
 | |
| +    m_doingAccessibilitySnapshot = true;
 | |
| +    out_axNode = snapshotForAXObject(makeRefPtr(axObject), node);
 | |
| +    m_doingAccessibilitySnapshot = false;
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::setInterceptFileChooserDialog(ErrorString&, bool enabled)
 | |
| +{
 | |
| +    m_interceptFileChooserDialog = enabled;
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::setDefaultBackgroundColorOverride(ErrorString& errorString, const JSON::Object* color)
 | |
| +{
 | |
| +    FrameView* view = m_inspectedPage.mainFrame().view();
 | |
| +    if (!view) {
 | |
| +        errorString = "Internal error: No frame view to set color two"_s;
 | |
| +        return;
 | |
| +    }
 | |
| +    if (!color) {
 | |
| +        view->updateBackgroundRecursively(Optional<Color>());
 | |
| +        return;
 | |
| +    }
 | |
| +    view->updateBackgroundRecursively(InspectorDOMAgent::parseColor(color));
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::createUserWorld(ErrorString& errorString, const String& name)
 | |
| +{
 | |
| +    if (createdUserWorlds().contains(name)) {
 | |
| +        errorString = "World with the given name already exists"_s;
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    Ref<DOMWrapperWorld> world = ScriptController::createWorld(name, ScriptController::WorldType::User);
 | |
| +    ensureUserWorldsExistInAllFrames({world.ptr()});
 | |
| +    createdUserWorlds().set(name, WTFMove(world));
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::ensureUserWorldsExistInAllFrames(const Vector<DOMWrapperWorld*>& worlds)
 | |
| +{
 | |
| +    for (Frame* frame = &m_inspectedPage.mainFrame(); frame; frame = frame->tree().traverseNext()) {
 | |
| +        for (auto* world : worlds)
 | |
| +            frame->windowProxy().jsWindowProxy(*world)->window();
 | |
| +    }
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::setBypassCSP(ErrorString&, bool enabled)
 | |
| +{
 | |
| +    m_bypassCSP = enabled;
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::crash(ErrorString&)
 | |
| +{
 | |
| +    CRASH();
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::setScreenSizeOverride(ErrorString&, int width, int height)
 | |
| +{
 | |
| +    Optional<FloatSize> size;
 | |
| +    if (width && height)
 | |
| +        size = FloatSize(width, height);
 | |
| +    m_inspectedPage.setOverrideScreenSize(size);
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::setOrientationOverride(Inspector::ErrorString& errorString, const int* angle)
 | |
| +{
 | |
| +#if ENABLE(ORIENTATION_EVENTS)
 | |
| +    UNUSED_PARAM(errorString);
 | |
| +    Optional<int> orientation;
 | |
| +    if (angle)
 | |
| +        orientation = *angle;
 | |
| +    m_inspectedPage.setOverrideOrientation(orientation);
 | |
| +#else
 | |
| +    errorString = "Orientation events are disabled in this build";
 | |
| +#endif
 | |
| +}
 | |
| +
 | |
| +void InspectorPageAgent::setActivityPaused(Inspector::ErrorString&, bool paused)
 | |
| +{
 | |
| +    setMainThreadCallbacksPaused(paused);
 | |
| +    bool webAnimationsCSSIntegrationEnabled = RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled();
 | |
| +    for (Frame* frame = &m_inspectedPage.mainFrame(); frame; frame = frame->tree().traverseNext()) {
 | |
| +        ASSERT(frame->document());
 | |
| +        auto& document = *frame->document();
 | |
| +        if (paused) {
 | |
| +            document.suspendScriptedAnimationControllerCallbacks();
 | |
| +            document.suspendActiveDOMObjects(ReasonForSuspension::JavaScriptDebuggerPaused);
 | |
| +            if (webAnimationsCSSIntegrationEnabled) {
 | |
| +                if (auto* timeline = document.existingTimeline())
 | |
| +                    timeline->suspendAnimations();
 | |
| +            }
 | |
| +            if (document.svgExtensions())
 | |
| +                document.accessSVGExtensions().pauseAnimations();
 | |
| +        } else {
 | |
| +            document.resumeActiveDOMObjects(ReasonForSuspension::JavaScriptDebuggerPaused);
 | |
| +            document.resumeScriptedAnimationControllerCallbacks();
 | |
| +            if (webAnimationsCSSIntegrationEnabled) {
 | |
| +                if (auto* timeline = document.existingTimeline())
 | |
| +                    timeline->resumeAnimations();
 | |
| +            }
 | |
| +            if (document.svgExtensions())
 | |
| +                document.accessSVGExtensions().unpauseAnimations();
 | |
| +        }
 | |
| +    }
 | |
| +    if (!webAnimationsCSSIntegrationEnabled) {
 | |
| +      if (paused)
 | |
| +        m_inspectedPage.mainFrame().legacyAnimation().suspendAnimations();
 | |
| +      else
 | |
| +        m_inspectedPage.mainFrame().legacyAnimation().resumeAnimations();
 | |
| +    }
 | |
| +}
 | |
| +
 | |
|  } // namespace WebCore
 | |
| diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.h b/Source/WebCore/inspector/agents/InspectorPageAgent.h
 | |
| index 3bcd0487cfc8766baa01c7804173a15747b47b2d..3b5c230d7e00b9d7e248be8730ab22ab1d4fe40b 100644
 | |
| --- a/Source/WebCore/inspector/agents/InspectorPageAgent.h
 | |
| +++ b/Source/WebCore/inspector/agents/InspectorPageAgent.h
 | |
| @@ -34,17 +34,23 @@
 | |
|  #include "CachedResource.h"
 | |
|  #include "InspectorWebAgentBase.h"
 | |
|  #include "LayoutRect.h"
 | |
| +#include "ProcessIdentifier.h"
 | |
|  #include <JavaScriptCore/InspectorBackendDispatchers.h>
 | |
|  #include <JavaScriptCore/InspectorFrontendDispatchers.h>
 | |
|  #include <wtf/HashMap.h>
 | |
|  #include <wtf/Seconds.h>
 | |
|  #include <wtf/text/WTFString.h>
 | |
|  
 | |
| +namespace Inspector {
 | |
| +class InjectedScriptManager;
 | |
| +}
 | |
| +
 | |
|  namespace WebCore {
 | |
|  
 | |
|  class DOMWrapperWorld;
 | |
|  class DocumentLoader;
 | |
|  class Frame;
 | |
| +class HTMLInputElement;
 | |
|  class InspectorClient;
 | |
|  class InspectorOverlay;
 | |
|  class Page;
 | |
| @@ -71,12 +77,14 @@ public:
 | |
|          PingResource,
 | |
|          BeaconResource,
 | |
|          WebSocketResource,
 | |
| +        EventSource,
 | |
|  #if ENABLE(APPLICATION_MANIFEST)
 | |
|          ApplicationManifestResource,
 | |
|  #endif
 | |
|          OtherResource,
 | |
|      };
 | |
|  
 | |
| +    WEBCORE_EXPORT static String makeFrameID(ProcessIdentifier processID,  FrameIdentifier frameID);
 | |
|      static bool sharedBufferContent(RefPtr<SharedBuffer>&&, const String& textEncodingName, bool withBase64Encode, String* result);
 | |
|      static Vector<CachedResource*> cachedResourcesForFrame(Frame*);
 | |
|      static void resourceContent(ErrorString&, Frame*, const URL&, String* result, bool* base64Encoded);
 | |
| @@ -97,6 +105,8 @@ public:
 | |
|      void enable(ErrorString&) override;
 | |
|      void disable(ErrorString&) override;
 | |
|      void reload(ErrorString&, const bool* optionalReloadFromOrigin, const bool* optionalRevalidateAllResources) override;
 | |
| +    void goBack(ErrorString&) override;
 | |
| +    void goForward(ErrorString&) override;
 | |
|      void navigate(ErrorString&, const String& url) override;
 | |
|      void overrideUserAgent(ErrorString&, const String* value) override;
 | |
|      void overrideSetting(ErrorString&, const String& setting, const bool* value) override;
 | |
| @@ -116,22 +126,35 @@ public:
 | |
|  #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
 | |
|      void setForcedAppearance(ErrorString&, const String&) override;
 | |
|  #endif
 | |
| +    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;
 | |
|  #if ENABLE(WEB_ARCHIVE) && USE(CF)
 | |
|      void archive(ErrorString&, String* data) override;
 | |
|  #endif
 | |
|  
 | |
| +    void insertText(ErrorString&, const String& text) override;
 | |
| +    void accessibilitySnapshot(ErrorString&, const String* objectId, RefPtr<Inspector::Protocol::Page::AXNode>& out_axNode) override;
 | |
| +    void setInterceptFileChooserDialog(ErrorString&, bool enabled) override;
 | |
| +    void setDefaultBackgroundColorOverride(ErrorString&, const JSON::Object*) override;
 | |
| +    void createUserWorld(ErrorString&, const String&) override;
 | |
| +    void setBypassCSP(ErrorString&, bool) override;
 | |
| +    void crash(ErrorString&) override;
 | |
| +    void setScreenSizeOverride(ErrorString&, int width, int height) override;
 | |
| +    void setOrientationOverride(Inspector::ErrorString&, const int* angle) override;
 | |
| +    void setActivityPaused(Inspector::ErrorString&, bool) 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&);
 | |
|  #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT)
 | |
|      void defaultAppearanceDidChange(bool useDarkAppearance);
 | |
|  #endif
 | |
| @@ -142,6 +165,12 @@ public:
 | |
|      void didLayout();
 | |
|      void didScroll();
 | |
|      void didRecalculateStyle();
 | |
| +    void runOpenPanel(HTMLInputElement* element, bool* intercept);
 | |
| +    void frameAttached(Frame&);
 | |
| +    bool shouldBypassCSP();
 | |
| +    void willCheckNewWindowPolicy(const URL&);
 | |
| +    void didCheckNewWindowPolicy(bool allowed);
 | |
| +    bool doingAccessibilitySnapshot() const { return m_doingAccessibilitySnapshot; };
 | |
|  
 | |
|      Frame* frameForId(const String& frameId);
 | |
|      WEBCORE_EXPORT String frameId(Frame*);
 | |
| @@ -150,6 +179,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);
 | |
| @@ -161,17 +191,19 @@ private:
 | |
|      RefPtr<Inspector::PageBackendDispatcher> m_backendDispatcher;
 | |
|  
 | |
|      Page& m_inspectedPage;
 | |
| +    Inspector::InjectedScriptManager& m_injectedScriptManager;
 | |
|      InspectorClient* m_client { nullptr };
 | |
|      InspectorOverlay* m_overlay { nullptr };
 | |
|  
 | |
| -    HashMap<Frame*, String> m_frameToIdentifier;
 | |
|      HashMap<String, Frame*> m_identifierToFrame;
 | |
| -    HashMap<DocumentLoader*, String> m_loaderToIdentifier;
 | |
|      String m_userAgentOverride;
 | |
|      String m_emulatedMedia;
 | |
|      String m_bootstrapScript;
 | |
|      bool m_isFirstLayoutAfterOnLoad { false };
 | |
|      bool m_showPaintRects { false };
 | |
| +    bool m_interceptFileChooserDialog { false };
 | |
| +    bool m_bypassCSP { false };
 | |
| +    bool m_doingAccessibilitySnapshot { false };
 | |
|  };
 | |
|  
 | |
|  } // namespace WebCore
 | |
| diff --git a/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp b/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp
 | |
| index 909c466f87e9bfa8c4c1728c46ad6e7e5907b46e..b4c53ba9dee0e7bb070fe03150339b2abe5efc2c 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().string(), proxy.name());
 | |
| +    ASSERT(is<Document>(proxy.scriptExecutionContext()));
 | |
| +    Document& document = downcast<Document>(*proxy.scriptExecutionContext());
 | |
| +    auto* pageAgent = m_instrumentingAgents.enabledPageAgent();
 | |
| +    m_frontendDispatcher->workerCreated(proxy.identifier(), proxy.url().string(), proxy.name(),
 | |
| +        pageAgent ? pageAgent->frameId(document.frame()) : emptyString());
 | |
|  }
 | |
|  
 | |
|  void InspectorWorkerAgent::disconnectFromWorkerInspectorProxy(WorkerInspectorProxy& proxy)
 | |
| diff --git a/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp b/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp
 | |
| index 50cc98b3fa30e3da1f6e5edd291c9cc663166e71..74d6f7a9a8374ffa92a38ca9244d3fcdc13a585e 100644
 | |
| --- a/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp
 | |
| +++ b/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp
 | |
| @@ -38,6 +38,7 @@
 | |
|  #include "Frame.h"
 | |
|  #include "InspectorPageAgent.h"
 | |
|  #include "InstrumentingAgents.h"
 | |
| +#include "JSDOMWindowBase.h"
 | |
|  #include "Page.h"
 | |
|  #include "PageConsoleClient.h"
 | |
|  #include "PageScriptDebugServer.h"
 | |
| @@ -70,8 +71,11 @@ bool PageDebuggerAgent::enabled() const
 | |
|  
 | |
|  void PageDebuggerAgent::evaluateOnCallFrame(ErrorString& errorString, const String& callFrameId, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, const bool* emulateUserGesture, RefPtr<Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown, Optional<int>& savedResultIndex)
 | |
|  {
 | |
| +    InjectedScript injectedScript = injectedScriptManager().injectedScriptForObjectId(callFrameId);
 | |
| +    JSC::JSGlobalObject* globalObject = injectedScript.globalObject();
 | |
| +    Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr;
 | |
|      auto shouldEmulateUserGesture = emulateUserGesture && *emulateUserGesture;
 | |
| -    UserGestureEmulationScope userGestureScope(m_inspectedPage, shouldEmulateUserGesture);
 | |
| +    UserGestureEmulationScope userGestureScope(m_inspectedPage, shouldEmulateUserGesture, document);
 | |
|  
 | |
|      WebDebuggerAgent::evaluateOnCallFrame(errorString, callFrameId, expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, saveResult, emulateUserGesture, result, wasThrown, savedResultIndex);
 | |
|  }
 | |
| diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
 | |
| index e8ab5f4c89ade4fc85c042b43433b726563abdd2..ce3b87ef1bdcd29c4fff2cfa735b9d1bc76e1f36 100644
 | |
| --- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
 | |
| +++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
 | |
| @@ -35,12 +35,14 @@
 | |
|  #include "DOMWrapperWorld.h"
 | |
|  #include "Document.h"
 | |
|  #include "Frame.h"
 | |
| +#include "FrameLoader.h"
 | |
|  #include "InspectorPageAgent.h"
 | |
|  #include "InstrumentingAgents.h"
 | |
|  #include "JSDOMWindowBase.h"
 | |
|  #include "Page.h"
 | |
|  #include "PageConsoleClient.h"
 | |
|  #include "ScriptController.h"
 | |
| +#include "ScriptSourceCode.h"
 | |
|  #include "ScriptState.h"
 | |
|  #include "SecurityOrigin.h"
 | |
|  #include "UserGestureEmulationScope.h"
 | |
| @@ -106,6 +108,15 @@ void PageRuntimeAgent::didClearWindowObjectInWorld(Frame& frame, DOMWrapperWorld
 | |
|      notifyContextCreated(pageAgent->frameId(&frame), frame.script().globalObject(world), world);
 | |
|  }
 | |
|  
 | |
| +void PageRuntimeAgent::didReceiveMainResourceError(Frame& frame)
 | |
| +{
 | |
| +    if (frame.loader().stateMachine().isDisplayingInitialEmptyDocument()) {
 | |
| +        // Ensure execution context is created for the empty docment to make
 | |
| +        // it usable in case loading failed.
 | |
| +        mainWorldExecState(&frame);
 | |
| +    }
 | |
| +}
 | |
| +
 | |
|  InjectedScript PageRuntimeAgent::injectedScriptForEval(ErrorString& errorString, const int* executionContextId)
 | |
|  {
 | |
|      if (!executionContextId) {
 | |
| @@ -194,13 +205,21 @@ void PageRuntimeAgent::notifyContextCreated(const String& frameId, JSC::JSGlobal
 | |
|  
 | |
|  void PageRuntimeAgent::evaluate(ErrorString& errorString, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, const bool* emulateUserGesture, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown, Optional<int>& savedResultIndex)
 | |
|  {
 | |
| -    UserGestureEmulationScope userGestureScope(m_inspectedPage, asBool(emulateUserGesture));
 | |
| +    InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId);
 | |
| +    if (!errorString.isEmpty())
 | |
| +        return;
 | |
| +    JSC::JSGlobalObject* globalObject = injectedScript.globalObject();
 | |
| +    Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr;
 | |
| +    UserGestureEmulationScope userGestureScope(m_inspectedPage, asBool(emulateUserGesture), document);
 | |
|      InspectorRuntimeAgent::evaluate(errorString, expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, executionContextId, returnByValue, generatePreview, saveResult, emulateUserGesture, result, wasThrown, savedResultIndex);
 | |
|  }
 | |
|  
 | |
|  void PageRuntimeAgent::callFunctionOn(ErrorString& errorString, const String& objectId, const String& expression, const JSON::Array* optionalArguments, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* emulateUserGesture, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown)
 | |
|  {
 | |
| -    UserGestureEmulationScope userGestureScope(m_inspectedPage, asBool(emulateUserGesture));
 | |
| +    InjectedScript injectedScript = injectedScriptManager().injectedScriptForObjectId(objectId);
 | |
| +    JSC::JSGlobalObject* globalObject = injectedScript.globalObject();
 | |
| +    Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr;
 | |
| +    UserGestureEmulationScope userGestureScope(m_inspectedPage, asBool(emulateUserGesture), document);
 | |
|      InspectorRuntimeAgent::callFunctionOn(errorString, objectId, expression, optionalArguments, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, emulateUserGesture, result, wasThrown);
 | |
|  }
 | |
|  
 | |
| diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
 | |
| index 2af3739b7fe7c16faa7d8d2797ce6d010215398d..80bfde6120874e16fb173f707fd0bd8a3e5067a0 100644
 | |
| --- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
 | |
| +++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
 | |
| @@ -63,6 +63,7 @@ public:
 | |
|      // InspectorInstrumentation
 | |
|      void frameNavigated(Frame&);
 | |
|      void didClearWindowObjectInWorld(Frame&, DOMWrapperWorld&);
 | |
| +    void didReceiveMainResourceError(Frame&);
 | |
|  
 | |
|  private:
 | |
|      Inspector::InjectedScript injectedScriptForEval(ErrorString&, const int* executionContextId) override;
 | |
| @@ -73,7 +74,6 @@ private:
 | |
|  
 | |
|      std::unique_ptr<Inspector::RuntimeFrontendDispatcher> m_frontendDispatcher;
 | |
|      RefPtr<Inspector::RuntimeBackendDispatcher> m_backendDispatcher;
 | |
| -
 | |
|      InstrumentingAgents& m_instrumentingAgents;
 | |
|  
 | |
|      Page& m_inspectedPage;
 | |
| diff --git a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp
 | |
| index 633bce6e8f3c0785632eb7f26d172f6016b3efd9..14f531504bb2b96646d1a48092a0b132b0510f55 100644
 | |
| --- a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp
 | |
| +++ b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp
 | |
| @@ -39,9 +39,9 @@
 | |
|  
 | |
|  namespace WebCore {
 | |
|  
 | |
| -UserGestureEmulationScope::UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture)
 | |
| +UserGestureEmulationScope::UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture, Document* document)
 | |
|      : m_pageChromeClient(inspectedPage.chrome().client())
 | |
| -    , m_gestureIndicator(emulateUserGesture ? Optional<ProcessingUserGestureState>(ProcessingUserGesture) : WTF::nullopt)
 | |
| +    , m_gestureIndicator(emulateUserGesture ? Optional<ProcessingUserGestureState>(ProcessingUserGesture) : WTF::nullopt, document)
 | |
|      , m_emulateUserGesture(emulateUserGesture)
 | |
|      , m_userWasInteracting(false)
 | |
|  {
 | |
| diff --git a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h
 | |
| index b94ed78ad3dbea19543c1fd54653f0481e52fb7c..6341c7ff7ef53577f33c19ecad1b8bfbd674d051 100644
 | |
| --- a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h
 | |
| +++ b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h
 | |
| @@ -38,11 +38,12 @@ namespace WebCore {
 | |
|  
 | |
|  class ChromeClient;
 | |
|  class Page;
 | |
| +class Document;
 | |
|  
 | |
|  class UserGestureEmulationScope {
 | |
|      WTF_MAKE_NONCOPYABLE(UserGestureEmulationScope);
 | |
|  public:
 | |
| -    UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture);
 | |
| +    UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture, Document* document);
 | |
|      ~UserGestureEmulationScope();
 | |
|  
 | |
|  private:
 | |
| diff --git a/Source/WebCore/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp
 | |
| index c7a25c86b9f61c8ea00c135973225177bdc4ecbe..3b743ddc18fcf10f860df6489c5aacec4d5af752 100644
 | |
| --- a/Source/WebCore/loader/DocumentLoader.cpp
 | |
| +++ b/Source/WebCore/loader/DocumentLoader.cpp
 | |
| @@ -1304,8 +1304,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 c694e0e9369179d2e7c67637999b9788163ed99f..9f969f0d93e5f8e9a0c94b399a5357734e6b1b6b 100644
 | |
| --- a/Source/WebCore/loader/DocumentLoader.h
 | |
| +++ b/Source/WebCore/loader/DocumentLoader.h
 | |
| @@ -170,9 +170,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 124681f5c7ed386ff50466c228950473387226dd..01011adc50c5e80570e5d80f2d28713f85bd519a 100644
 | |
| --- a/Source/WebCore/loader/FrameLoader.cpp
 | |
| +++ b/Source/WebCore/loader/FrameLoader.cpp
 | |
| @@ -1184,6 +1184,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();
 | |
| @@ -1495,6 +1496,7 @@ void FrameLoader::load(FrameLoadRequest&& request)
 | |
|  
 | |
|  void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, NavigationAction&& action, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler<void()>&& completionHandler)
 | |
|  {
 | |
| +    InspectorInstrumentation::frameScheduledNavigation(m_frame, Seconds(0));
 | |
|      FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadWithNavigationAction: frame load started");
 | |
|  
 | |
|      Ref<DocumentLoader> loader = m_client->createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
 | |
| @@ -1598,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 };
 | |
|  
 | |
| @@ -3150,6 +3154,8 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error)
 | |
|      checkCompleted();
 | |
|      if (m_frame.page())
 | |
|          checkLoadComplete();
 | |
| +
 | |
| +    InspectorInstrumentation::didReceiveMainResourceError(m_frame, error);
 | |
|  }
 | |
|  
 | |
|  void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
 | |
| @@ -3909,9 +3915,6 @@ String FrameLoader::referrer() const
 | |
|  
 | |
|  void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
 | |
|  {
 | |
| -    if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
 | |
| -        return;
 | |
| -
 | |
|      Vector<Ref<DOMWrapperWorld>> worlds;
 | |
|      ScriptController::getAllWorlds(worlds);
 | |
|      for (auto& world : worlds)
 | |
| @@ -3920,13 +3923,13 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
 | |
|  
 | |
|  void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
 | |
|  {
 | |
| -    if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.windowProxy().existingJSWindowProxy(world))
 | |
| -        return;
 | |
| -
 | |
| -    m_client->dispatchDidClearWindowObjectInWorld(world);
 | |
| +    if (m_frame.windowProxy().existingJSWindowProxy(world)) {
 | |
| +        if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
 | |
| +            m_client->dispatchDidClearWindowObjectInWorld(world);
 | |
|  
 | |
| -    if (Page* page = m_frame.page())
 | |
| -        page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
 | |
| +        if (Page* page = m_frame.page())
 | |
| +            page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
 | |
| +    }
 | |
|  
 | |
|      InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
 | |
|  }
 | |
| diff --git a/Source/WebCore/loader/LoaderStrategy.h b/Source/WebCore/loader/LoaderStrategy.h
 | |
| index 579d9038f317d45d27c84a27e3f21cff0ae8fddf..9dc41a6ff78b85e229927409b309e01adce2f27a 100644
 | |
| --- a/Source/WebCore/loader/LoaderStrategy.h
 | |
| +++ b/Source/WebCore/loader/LoaderStrategy.h
 | |
| @@ -80,6 +80,7 @@ public:
 | |
|  
 | |
|      virtual bool isOnLine() const = 0;
 | |
|      virtual void addOnlineStateChangeListener(WTF::Function<void(bool)>&&) = 0;
 | |
| +    virtual void setEmulateOfflineState(bool) {};
 | |
|  
 | |
|      virtual bool shouldPerformSecurityChecks() const { return false; }
 | |
|      virtual bool havePerformedSecurityChecks(const ResourceResponse&) const { return false; }
 | |
| diff --git a/Source/WebCore/loader/PolicyChecker.cpp b/Source/WebCore/loader/PolicyChecker.cpp
 | |
| index 276148a63f36cc46ae0cf2bb535c33f2aa07e30b..998e983870098b620cf154819379aa0b039f7e66 100644
 | |
| --- a/Source/WebCore/loader/PolicyChecker.cpp
 | |
| +++ b/Source/WebCore/loader/PolicyChecker.cpp
 | |
| @@ -46,6 +46,7 @@
 | |
|  #include "HTMLFormElement.h"
 | |
|  #include "HTMLFrameOwnerElement.h"
 | |
|  #include "HTMLPlugInElement.h"
 | |
| +#include "InspectorInstrumentation.h"
 | |
|  #include "Logging.h"
 | |
|  #include <wtf/CompletionHandler.h>
 | |
|  
 | |
| @@ -259,26 +260,32 @@ void FrameLoader::PolicyChecker::checkNewWindowPolicy(NavigationAction&& navigat
 | |
|  
 | |
|      auto blobURLLifetimeExtension = extendBlobURLLifetimeIfNecessary(request, nullptr);
 | |
|  
 | |
| +    InspectorInstrumentation::willCheckNewWindowPolicy(m_frame, request.url());
 | |
|      auto requestIdentifier = PolicyCheckIdentifier::create();
 | |
|      m_frame.loader().client().dispatchDecidePolicyForNewWindowAction(navigationAction, request, formState.get(), frameName, requestIdentifier, [frame = makeRef(m_frame), request,
 | |
|          formState = WTFMove(formState), frameName, navigationAction, function = WTFMove(function), blobURLLifetimeExtension = WTFMove(blobURLLifetimeExtension),
 | |
|          requestIdentifier] (PolicyAction policyAction, PolicyCheckIdentifier responseIdentifier) mutable {
 | |
|  
 | |
| -        if (!responseIdentifier.isValidFor(requestIdentifier))
 | |
| +        if (!responseIdentifier.isValidFor(requestIdentifier)) {
 | |
| +            InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false);
 | |
|              return function({ }, nullptr, { }, { }, ShouldContinuePolicyCheck::No);
 | |
| +        }
 | |
|  
 | |
|          switch (policyAction) {
 | |
|          case PolicyAction::Download:
 | |
|              frame->loader().client().startDownload(request);
 | |
|              FALLTHROUGH;
 | |
|          case PolicyAction::Ignore:
 | |
| +            InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false);
 | |
|              function({ }, nullptr, { }, { }, ShouldContinuePolicyCheck::No);
 | |
|              return;
 | |
|          case PolicyAction::StopAllLoads:
 | |
|              ASSERT_NOT_REACHED();
 | |
| +            InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false);
 | |
|              function({ }, nullptr, { }, { }, ShouldContinuePolicyCheck::No);
 | |
|              return;
 | |
|          case PolicyAction::Use:
 | |
| +            InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), true);
 | |
|              function(request, makeWeakPtr(formState.get()), frameName, navigationAction, ShouldContinuePolicyCheck::Yes);
 | |
|              return;
 | |
|          }
 | |
| diff --git a/Source/WebCore/loader/ProgressTracker.cpp b/Source/WebCore/loader/ProgressTracker.cpp
 | |
| index e24fded2225f1c1918f454017566717e20484eab..30e4b7a986418c4b4f6c799b858b608206e22bb5 100644
 | |
| --- a/Source/WebCore/loader/ProgressTracker.cpp
 | |
| +++ b/Source/WebCore/loader/ProgressTracker.cpp
 | |
| @@ -154,6 +154,8 @@ void ProgressTracker::progressCompleted(Frame& frame)
 | |
|      if (!m_numProgressTrackedFrames || m_originatingProgressFrame == &frame)
 | |
|          finalProgressComplete();
 | |
|  
 | |
| +    InspectorInstrumentation::frameStoppedLoading(frame);
 | |
| +
 | |
|      m_client->didChangeEstimatedProgress();
 | |
|  }
 | |
|  
 | |
| @@ -179,8 +181,6 @@ void ProgressTracker::finalProgressComplete()
 | |
|      frame->loader().client().setMainFrameDocumentReady(true);
 | |
|      m_client->progressFinished(*frame);
 | |
|      frame->loader().loadProgressingStatusChanged();
 | |
| -
 | |
| -    InspectorInstrumentation::frameStoppedLoading(*frame);
 | |
|  }
 | |
|  
 | |
|  void ProgressTracker::incrementProgress(unsigned long identifier, const ResourceResponse& response)
 | |
| diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h
 | |
| index 71e3805992899205536e0bf599ace82f2e56a36a..e33516252fefd5f87144c6cef6916f9c372dd065 100644
 | |
| --- a/Source/WebCore/page/ChromeClient.h
 | |
| +++ b/Source/WebCore/page/ChromeClient.h
 | |
| @@ -277,7 +277,7 @@ public:
 | |
|  #endif
 | |
|  
 | |
|  #if ENABLE(ORIENTATION_EVENTS)
 | |
| -    virtual int deviceOrientation() const = 0;
 | |
| +    virtual int deviceOrientation() const { return 0; }
 | |
|  #endif
 | |
|  
 | |
|  #if ENABLE(INPUT_TYPE_COLOR)
 | |
| diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp
 | |
| index 5e3db4ddbb8a0b4bd9a2264ae5455f5234edaba9..90df915d0506def14f4eac3abedad3a0757a59c1 100644
 | |
| --- a/Source/WebCore/page/EventHandler.cpp
 | |
| +++ b/Source/WebCore/page/EventHandler.cpp
 | |
| @@ -837,9 +837,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;
 | |
| @@ -878,8 +876,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
 | |
| @@ -901,8 +897,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)
 | |
| @@ -923,7 +921,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);
 | |
| @@ -940,6 +940,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
 | |
| @@ -971,6 +973,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())
 | |
| @@ -1062,7 +1066,6 @@ void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResul
 | |
|      m_frame.selection().setSelectionByMouseIfDifferent(newSelection, m_frame.selection().granularity(),
 | |
|          FrameSelection::EndPointsAdjustmentMode::AdjustAtBidiBoundary);
 | |
|  }
 | |
| -#endif // ENABLE(DRAG_SUPPORT)
 | |
|  
 | |
|  void EventHandler::lostMouseCapture()
 | |
|  {
 | |
| @@ -1110,9 +1113,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;
 | |
| @@ -2073,10 +2074,8 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& platformMouseE
 | |
|      
 | |
|      swallowEvent = !dispatchMouseEvent(eventNames().mousemoveEvent, mouseEvent.targetNode(), 0, platformMouseEvent, FireMouseOverOut::Yes);
 | |
|  
 | |
| -#if ENABLE(DRAG_SUPPORT)
 | |
|      if (!swallowEvent)
 | |
|          swallowEvent = handleMouseDraggedEvent(mouseEvent);
 | |
| -#endif
 | |
|  
 | |
|      return swallowEvent;
 | |
|  }
 | |
| diff --git a/Source/WebCore/page/EventHandler.h b/Source/WebCore/page/EventHandler.h
 | |
| index f7a16c1e06299f7a663928ef1193229a5874e032..854dec2823111417c1ce42a2948d0030886e5ac6 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();
 | |
| @@ -364,10 +362,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&);
 | |
|  
 | |
| @@ -464,10 +460,8 @@ private:
 | |
|      void defaultTabEventHandler(KeyboardEvent&);
 | |
|      void defaultArrowEventHandler(FocusDirection, KeyboardEvent&);
 | |
|  
 | |
| -#if ENABLE(DRAG_SUPPORT)
 | |
|      OptionSet<DragSourceAction> updateDragSourceActionsAllowed() const;
 | |
|      bool supportsSelectionUpdatesOnMouseDrag() const;
 | |
| -#endif
 | |
|  
 | |
|      // The following are called at the beginning of handleMouseUp and handleDrag.  
 | |
|      // If they return true it indicates that they have consumed the event.
 | |
| @@ -475,9 +469,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);
 | |
|      
 | |
| @@ -528,10 +523,7 @@ private:
 | |
|      enum SelectionInitiationState { HaveNotStartedSelection, PlacedCaret, ExtendedSelection };
 | |
|      SelectionInitiationState m_selectionInitiationState { HaveNotStartedSelection };
 | |
|  
 | |
| -#if ENABLE(DRAG_SUPPORT)
 | |
|      LayoutPoint m_dragStartPosition;
 | |
| -#endif
 | |
| -
 | |
|      Timer m_hoverTimer;
 | |
|      bool m_hasScheduledCursorUpdate { false };
 | |
|  
 | |
| diff --git a/Source/WebCore/page/EventSource.cpp b/Source/WebCore/page/EventSource.cpp
 | |
| index 757765c3b4872d5a6f92b34e3f2ac67eaaf2dd82..69c4ef67941cee93213ccac1aa04d2cb1db08782 100644
 | |
| --- a/Source/WebCore/page/EventSource.cpp
 | |
| +++ b/Source/WebCore/page/EventSource.cpp
 | |
| @@ -36,6 +36,7 @@
 | |
|  #include "CachedResourceRequestInitiators.h"
 | |
|  #include "ContentSecurityPolicy.h"
 | |
|  #include "EventNames.h"
 | |
| +#include "InspectorNetworkAgent.h"
 | |
|  #include "MessageEvent.h"
 | |
|  #include "ResourceError.h"
 | |
|  #include "ResourceRequest.h"
 | |
| @@ -97,6 +98,7 @@ void EventSource::connect()
 | |
|      ASSERT(!m_requestInFlight);
 | |
|  
 | |
|      ResourceRequest request { m_url };
 | |
| +    request.setInitiatorIdentifier(InspectorNetworkAgent::initiatorIdentifierForEventSource());
 | |
|      request.setHTTPMethod("GET");
 | |
|      request.setHTTPHeaderField(HTTPHeaderName::Accept, "text/event-stream");
 | |
|      request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-cache");
 | |
| diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp
 | |
| index d04fa0c39e0eb9a83ccd864e42ae3042b9928308..b9c1761f676c13822ab20ae0abc979c9629f4cb8 100644
 | |
| --- a/Source/WebCore/page/Frame.cpp
 | |
| +++ b/Source/WebCore/page/Frame.cpp
 | |
| @@ -182,6 +182,7 @@ Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, UniqueRef<FrameLoa
 | |
|  void Frame::init()
 | |
|  {
 | |
|      m_loader->init();
 | |
| +    InspectorInstrumentation::frameAttached(this);
 | |
|  }
 | |
|  
 | |
|  Ref<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, UniqueRef<FrameLoaderClient>&& client)
 | |
| @@ -341,7 +342,7 @@ void Frame::orientationChanged()
 | |
|  int Frame::orientation() const
 | |
|  {
 | |
|      if (m_page)
 | |
| -        return m_page->chrome().client().deviceOrientation();
 | |
| +        return m_page->orientation();
 | |
|      return 0;
 | |
|  }
 | |
|  #endif // ENABLE(ORIENTATION_EVENTS)
 | |
| diff --git a/Source/WebCore/page/FrameSnapshotting.cpp b/Source/WebCore/page/FrameSnapshotting.cpp
 | |
| index 73587787f88a6ad4e4baffb0beb0b87e7782916f..88492f501e6ec9e38455dbe6fd27537bf0ee6970 100644
 | |
| --- a/Source/WebCore/page/FrameSnapshotting.cpp
 | |
| +++ b/Source/WebCore/page/FrameSnapshotting.cpp
 | |
| @@ -114,7 +114,12 @@ std::unique_ptr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRe
 | |
|      std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(imageRect.size(), RenderingMode::Unaccelerated, scaleFactor);
 | |
|      if (!buffer)
 | |
|          return nullptr;
 | |
| +#if !PLATFORM(MAC)
 | |
| +    buffer->context().scale(scaleFactor);
 | |
| +#endif
 | |
|      buffer->context().translate(-imageRect.x(), -imageRect.y());
 | |
| +    if (coordinateSpace != FrameView::ViewCoordinates)
 | |
| +      buffer->context().scale(1 / frame.page()->pageScaleFactor());
 | |
|  
 | |
|      if (!clipRects.isEmpty()) {
 | |
|          Path clipPath;
 | |
| @@ -123,7 +128,10 @@ std::unique_ptr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRe
 | |
|          buffer->context().clipPath(clipPath);
 | |
|      }
 | |
|  
 | |
| -    frame.view()->paintContentsForSnapshot(buffer->context(), imageRect, shouldIncludeSelection, coordinateSpace);
 | |
| +    FloatRect fr = imageRect;
 | |
| +    if (coordinateSpace != FrameView::ViewCoordinates)
 | |
| +      fr.scale(frame.page()->pageScaleFactor());
 | |
| +    frame.view()->paintContentsForSnapshot(buffer->context(), enclosingIntRect(fr), shouldIncludeSelection, coordinateSpace);
 | |
|      return buffer;
 | |
|  }
 | |
|  
 | |
| diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp
 | |
| index 971f555799fdfc4b17b43130ec00175f16389c28..178f2a09f57e5fb2e2f1f650fb93e923f6f1709b 100644
 | |
| --- a/Source/WebCore/page/FrameView.cpp
 | |
| +++ b/Source/WebCore/page/FrameView.cpp
 | |
| @@ -2987,7 +2987,7 @@ void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
 | |
|  
 | |
|  void FrameView::updateBackgroundRecursively(const Optional<Color>& backgroundColor)
 | |
|  {
 | |
| -#if HAVE(OS_DARK_MODE_SUPPORT)
 | |
| +#if HAVE(OS_DARK_MODE_SUPPORT) && (defined(WTF_PLATFORM_MAC) && WTF_PLATFORM_MAC) || (defined(WTF_PLATFORM_IOS_FAMILY) && WTF_PLATFORM_IOS_FAMILY)
 | |
|      Color baseBackgroundColor = backgroundColor.valueOr(RenderTheme::singleton().systemColor(CSSValueAppleSystemControlBackground, styleColorOptions()));
 | |
|  #else
 | |
|      Color baseBackgroundColor = backgroundColor.valueOr(Color::white);
 | |
| diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp
 | |
| index 38fd7b29b53eab484e30963b51c8ae525c5d7a38..37b2a2b8baeba64a50f12c773f2a1072595806c5 100644
 | |
| --- a/Source/WebCore/page/History.cpp
 | |
| +++ b/Source/WebCore/page/History.cpp
 | |
| @@ -260,6 +260,7 @@ ExceptionOr<void> History::stateObjectAdded(RefPtr<SerializedScriptValue>&& data
 | |
|  
 | |
|      if (!urlString.isEmpty())
 | |
|          frame->document()->updateURLForPushOrReplaceState(fullURL);
 | |
| +    InspectorInstrumentation::didNavigateWithinPage(*frame);
 | |
|  
 | |
|      if (stateObjectType == StateObjectType::Push) {
 | |
|          frame->loader().history().pushState(WTFMove(data), title, fullURL.string());
 | |
| diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp
 | |
| index ddab06d8c1358e160d7b25cf3d96cab90dc291a6..9863fbb9ad07bb7b2be32bd5dcc6faa3176ca398 100644
 | |
| --- a/Source/WebCore/page/Page.cpp
 | |
| +++ b/Source/WebCore/page/Page.cpp
 | |
| @@ -90,6 +90,7 @@
 | |
|  #include "PerformanceLoggingClient.h"
 | |
|  #include "PerformanceMonitor.h"
 | |
|  #include "PlatformMediaSessionManager.h"
 | |
| +#include "PlatformScreen.h"
 | |
|  #include "PlatformStrategies.h"
 | |
|  #include "PlugInClient.h"
 | |
|  #include "PluginData.h"
 | |
| @@ -429,6 +430,37 @@ void Page::setOverrideViewportArguments(const Optional<ViewportArguments>& viewp
 | |
|          document->updateViewportArguments();
 | |
|  }
 | |
|  
 | |
| +FloatSize Page::screenSize()
 | |
| +{
 | |
| +    return m_overrideScreenSize.valueOr(screenRect(mainFrame().view()).size());
 | |
| +}
 | |
| +
 | |
| +void Page::setOverrideScreenSize(Optional<FloatSize> size)
 | |
| +{
 | |
| +    if (size == m_overrideScreenSize)
 | |
| +        return;
 | |
| +
 | |
| +    m_overrideScreenSize = size;
 | |
| +    if (auto* document = mainFrame().document())
 | |
| +        document->updateViewportArguments();
 | |
| +}
 | |
| +
 | |
| +#if ENABLE(ORIENTATION_EVENTS)
 | |
| +int Page::orientation() const
 | |
| +{
 | |
| +    return m_overrideOrientation.valueOr(chrome().client().deviceOrientation());
 | |
| +}
 | |
| +
 | |
| +void Page::setOverrideOrientation(Optional<int> orientation)
 | |
| +{
 | |
| +    if (orientation == m_overrideOrientation)
 | |
| +        return;
 | |
| +
 | |
| +    m_overrideOrientation = orientation;
 | |
| +    mainFrame().orientationChanged();
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
|  ScrollingCoordinator* Page::scrollingCoordinator()
 | |
|  {
 | |
|      if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) {
 | |
| diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h
 | |
| index 101a265f470cdb63b2611e64d0e131e392c236de..f75c84a349dbad560d965ea5f81cb0399b7f54e3 100644
 | |
| --- a/Source/WebCore/page/Page.h
 | |
| +++ b/Source/WebCore/page/Page.h
 | |
| @@ -195,6 +195,9 @@ public:
 | |
|      const Optional<ViewportArguments>& overrideViewportArguments() const { return m_overrideViewportArguments; }
 | |
|      WEBCORE_EXPORT void setOverrideViewportArguments(const Optional<ViewportArguments>&);
 | |
|  
 | |
| +    WEBCORE_EXPORT FloatSize screenSize();
 | |
| +    void setOverrideScreenSize(Optional<FloatSize> size);
 | |
| +
 | |
|      static void refreshPlugins(bool reload);
 | |
|      WEBCORE_EXPORT PluginData& pluginData();
 | |
|      void clearPluginData();
 | |
| @@ -743,6 +746,11 @@ public:
 | |
|  
 | |
|      WEBCORE_EXPORT Vector<Ref<Element>> editableElementsInRect(const FloatRect&) const;
 | |
|  
 | |
| +#if ENABLE(ORIENTATION_EVENTS)
 | |
| +    int orientation() const;
 | |
| +    void setOverrideOrientation(Optional<int>);
 | |
| +#endif
 | |
| +
 | |
|  #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY)
 | |
|      DeviceOrientationUpdateProvider* deviceOrientationUpdateProvider() const { return m_deviceOrientationUpdateProvider.get(); }
 | |
|  #endif
 | |
| @@ -1039,6 +1047,11 @@ private:
 | |
|  #endif
 | |
|  
 | |
|      Optional<ViewportArguments> m_overrideViewportArguments;
 | |
| +    Optional<FloatSize> m_overrideScreenSize;
 | |
| +
 | |
| +#if ENABLE(ORIENTATION_EVENTS)
 | |
| +    Optional<int> m_overrideOrientation;
 | |
| +#endif
 | |
|  
 | |
|  #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY)
 | |
|      RefPtr<DeviceOrientationUpdateProvider> m_deviceOrientationUpdateProvider;
 | |
| diff --git a/Source/WebCore/page/Screen.cpp b/Source/WebCore/page/Screen.cpp
 | |
| index a9d228ca404918860c40651994db78a1e76db5ca..1fc3c345308dfed8384d1c02334f2030e879383d 100644
 | |
| --- a/Source/WebCore/page/Screen.cpp
 | |
| +++ b/Source/WebCore/page/Screen.cpp
 | |
| @@ -32,6 +32,7 @@
 | |
|  #include "FloatRect.h"
 | |
|  #include "Frame.h"
 | |
|  #include "FrameView.h"
 | |
| +#include "Page.h"
 | |
|  #include "PlatformScreen.h"
 | |
|  #include "ResourceLoadObserver.h"
 | |
|  #include "RuntimeEnabledFeatures.h"
 | |
| @@ -53,7 +54,7 @@ unsigned Screen::height() const
 | |
|          return 0;
 | |
|      if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled())
 | |
|          ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::Height);
 | |
| -    long height = static_cast<long>(screenRect(frame->view()).height());
 | |
| +    long height = static_cast<long>(frame->page()->screenSize().height());
 | |
|      return static_cast<unsigned>(height);
 | |
|  }
 | |
|  
 | |
| @@ -64,7 +65,7 @@ unsigned Screen::width() const
 | |
|          return 0;
 | |
|      if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled())
 | |
|          ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::Width);
 | |
| -    long width = static_cast<long>(screenRect(frame->view()).width());
 | |
| +    long width = static_cast<long>(frame->page()->screenSize().width());
 | |
|      return static_cast<unsigned>(width);
 | |
|  }
 | |
|  
 | |
| diff --git a/Source/WebCore/page/SocketProvider.cpp b/Source/WebCore/page/SocketProvider.cpp
 | |
| index 803ac83155ff4df1becf75cd4710f6fbf7bbc32a..cc08682748a6d2fdf5d79980cd629812c98aa7ce 100644
 | |
| --- a/Source/WebCore/page/SocketProvider.cpp
 | |
| +++ b/Source/WebCore/page/SocketProvider.cpp
 | |
| @@ -33,7 +33,7 @@ namespace WebCore {
 | |
|      
 | |
|  Ref<SocketStreamHandle> SocketProvider::createSocketStreamHandle(const URL& url, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, const StorageSessionProvider* provider)
 | |
|  {
 | |
| -    return SocketStreamHandleImpl::create(url, client, sessionID, credentialPartition, { }, provider);
 | |
| +    return SocketStreamHandleImpl::create(url, false, client, sessionID, credentialPartition, { }, provider);
 | |
|  }
 | |
|  
 | |
|  RefPtr<ThreadableWebSocketChannel> SocketProvider::createWebSocketChannel(Document&, WebSocketChannelClient&)
 | |
| diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
 | |
| index 664be618eeb9989a3e6cd6b0c16eea8782a6b27f..6a406b116549b8b54a4a834521555470bf5f71a2 100644
 | |
| --- a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
 | |
| +++ b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
 | |
| @@ -297,6 +297,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)
 | |
| @@ -310,6 +312,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) {
 | |
| @@ -326,6 +330,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/Cairo.cmake b/Source/WebCore/platform/Cairo.cmake
 | |
| index fc6c5f3cd046269566822c08a482cc3bd6a883c0..083c03903a3111ee2cb6f9882dd2efe146d7dc35 100644
 | |
| --- a/Source/WebCore/platform/Cairo.cmake
 | |
| +++ b/Source/WebCore/platform/Cairo.cmake
 | |
| @@ -17,6 +17,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS
 | |
|      platform/graphics/cairo/ImageBufferCairoGLSurfaceBackend.h
 | |
|      platform/graphics/cairo/ImageBufferCairoImageSurfaceBackend.h
 | |
|      platform/graphics/cairo/ImageBufferCairoSurfaceBackend.h
 | |
| +    platform/graphics/cairo/ImageBufferUtilitiesCairo.h
 | |
|      platform/graphics/cairo/PlatformContextCairo.h
 | |
|      platform/graphics/cairo/RefPtrCairo.h
 | |
|  )
 | |
| diff --git a/Source/WebCore/platform/PlatformKeyboardEvent.h b/Source/WebCore/platform/PlatformKeyboardEvent.h
 | |
| index f423a4a1d5399326fc48fe4d4a8a8fb9d4df861e..b4b60162d8b0d34113df052b04a1695d481d266e 100644
 | |
| --- a/Source/WebCore/platform/PlatformKeyboardEvent.h
 | |
| +++ b/Source/WebCore/platform/PlatformKeyboardEvent.h
 | |
| @@ -138,6 +138,7 @@ namespace WebCore {
 | |
|          static String keyCodeForHardwareKeyCode(unsigned);
 | |
|          static String keyIdentifierForGdkKeyCode(unsigned);
 | |
|          static int windowsKeyCodeForGdkKeyCode(unsigned);
 | |
| +        static unsigned gdkKeyCodeForWindowsKeyCode(int);
 | |
|          static String singleCharacterString(unsigned);
 | |
|          static bool modifiersContainCapsLock(unsigned);
 | |
|  #endif
 | |
| @@ -147,6 +148,7 @@ namespace WebCore {
 | |
|          static String keyCodeForHardwareKeyCode(unsigned);
 | |
|          static String keyIdentifierForWPEKeyCode(unsigned);
 | |
|          static int windowsKeyCodeForWPEKeyCode(unsigned);
 | |
| +        static unsigned WPEKeyCodeForWindowsKeyCode(int);
 | |
|          static String singleCharacterString(unsigned);
 | |
|  #endif
 | |
|  
 | |
| diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h
 | |
| index 892d8de6d345d91fda80cfa5334c4aa68b757da3..a22497d801a349487be10b15139e9c761a4a3ea5 100644
 | |
| --- a/Source/WebCore/platform/ScrollableArea.h
 | |
| +++ b/Source/WebCore/platform/ScrollableArea.h
 | |
| @@ -110,7 +110,7 @@ public:
 | |
|      void updateScrollSnapState();
 | |
|  
 | |
|  #if ENABLE(TOUCH_EVENTS)
 | |
| -    virtual bool handleTouchEvent(const PlatformTouchEvent&);
 | |
| +    WEBCORE_EXPORT virtual bool handleTouchEvent(const PlatformTouchEvent&);
 | |
|  #endif
 | |
|  
 | |
|  #if PLATFORM(IOS_FAMILY)
 | |
| diff --git a/Source/WebCore/platform/graphics/FontCascade.h b/Source/WebCore/platform/graphics/FontCascade.h
 | |
| index 7d7c5d1f1e06734249f2efce0ecec764e248719a..7cf0a5e8822f9846ee638985b6256c8ec0032d25 100644
 | |
| --- a/Source/WebCore/platform/graphics/FontCascade.h
 | |
| +++ b/Source/WebCore/platform/graphics/FontCascade.h
 | |
| @@ -280,7 +280,8 @@ private:
 | |
|              return true;
 | |
|          if (textRenderingMode == TextRenderingMode::OptimizeSpeed)
 | |
|              return false;
 | |
| -#if PLATFORM(COCOA) || USE(FREETYPE)
 | |
| +        // WIN: quick fix for https://bugs.webkit.org/show_bug.cgi?id=201213
 | |
| +#if PLATFORM(COCOA) || USE(FREETYPE) || PLATFORM(WIN)
 | |
|          return true;
 | |
|  #else
 | |
|          return false;
 | |
| diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp
 | |
| index d79728555b7db9b59cb615c55a7a7a6851cb57c8..61d3cc4b488e35ef9e1afa1ce3ac5f5d60ebe9a7 100644
 | |
| --- a/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp
 | |
| +++ b/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp
 | |
| @@ -48,6 +48,13 @@
 | |
|  #include <wtf/glib/GUniquePtr.h>
 | |
|  #endif
 | |
|  
 | |
| +#if PLATFORM(WPE) || PLATFORM(WIN)
 | |
| +#include <stdio.h> // Needed by jpeglib.h for FILE.
 | |
| +extern "C" {
 | |
| +#include "jpeglib.h"
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
|  namespace WebCore {
 | |
|  
 | |
|  #if !PLATFORM(GTK)
 | |
| @@ -65,8 +72,75 @@ static bool encodeImage(cairo_surface_t* image, const String& mimeType, Vector<u
 | |
|      return cairo_surface_write_to_png_stream(image, writeFunction, output) == CAIRO_STATUS_SUCCESS;
 | |
|  }
 | |
|  
 | |
| -Vector<uint8_t> data(cairo_surface_t* image, const String& mimeType, Optional<double>)
 | |
| +static Vector<uint8_t> encodeJpeg(cairo_surface_t* image, int quality)
 | |
| +{
 | |
| +    if (cairo_surface_get_type(image) != CAIRO_SURFACE_TYPE_IMAGE) {
 | |
| +        fprintf(stderr, "Unexpected cairo surface type: %d\n", cairo_surface_get_type(image));
 | |
| +        return { };
 | |
| +    }
 | |
| +
 | |
| +    if (cairo_image_surface_get_format(image) != CAIRO_FORMAT_ARGB32) {
 | |
| +        fprintf(stderr, "Unexpected surface image format: %d\n", cairo_image_surface_get_format(image));
 | |
| +        return { };
 | |
| +    }
 | |
| +
 | |
| +    struct jpeg_compress_struct info;
 | |
| +    struct jpeg_error_mgr error;
 | |
| +    info.err = jpeg_std_error(&error);
 | |
| +    jpeg_create_compress(&info);
 | |
| +
 | |
| +    unsigned char* bufferPtr = nullptr;
 | |
| +    unsigned long bufferSize;
 | |
| +    jpeg_mem_dest(&info, &bufferPtr, &bufferSize);
 | |
| +    info.image_width = cairo_image_surface_get_width(image);
 | |
| +    info.image_height = cairo_image_surface_get_height(image);
 | |
| +
 | |
| +#ifndef LIBJPEG_TURBO_VERSION
 | |
| +    COMPILE_ASSERT(false, only_libjpeg_turbo_is_supported);
 | |
| +#endif
 | |
| +
 | |
| +#if CPU(LITTLE_ENDIAN)
 | |
| +    info.in_color_space = JCS_EXT_BGRA;
 | |
| +#else
 | |
| +    info.in_color_space = JCS_EXT_ARGB;
 | |
| +#endif
 | |
| +    // # of color components in input image
 | |
| +    info.input_components = 4;
 | |
| +
 | |
| +    jpeg_set_defaults(&info);
 | |
| +    jpeg_set_quality(&info, quality, true);
 | |
| +
 | |
| +    jpeg_start_compress(&info, true);
 | |
| +
 | |
| +    while (info.next_scanline < info.image_height)
 | |
| +    {
 | |
| +        JSAMPROW row = cairo_image_surface_get_data(image) + (info.next_scanline * cairo_image_surface_get_stride(image));
 | |
| +        if (jpeg_write_scanlines(&info, &row, 1) != 1) {
 | |
| +            fprintf(stderr, "JPEG library failed to encode line\n");
 | |
| +            break;
 | |
| +        }
 | |
| +    }
 | |
| +
 | |
| +    jpeg_finish_compress(&info);
 | |
| +    jpeg_destroy_compress(&info);
 | |
| +
 | |
| +    Vector<uint8_t> output;
 | |
| +    output.append(bufferPtr, bufferSize);
 | |
| +    // Cannot use unique_ptr as bufferPtr changes during compression. GUniquePtr would work
 | |
| +    // but it's under GLib and won't work on Windows.
 | |
| +    free(bufferPtr);
 | |
| +    return output;
 | |
| +}
 | |
| +
 | |
| +Vector<uint8_t> data(cairo_surface_t* image, const String& mimeType, Optional<double> quality)
 | |
|  {
 | |
| +    if (mimeType == "image/jpeg") {
 | |
| +        int qualityPercent = 100;
 | |
| +        if (quality)
 | |
| +            qualityPercent = static_cast<int>(*quality * 100.0 + 0.5);
 | |
| +        return encodeJpeg(image, qualityPercent);
 | |
| +    }
 | |
| +
 | |
|      Vector<uint8_t> encodedImage;
 | |
|      if (!image || !encodeImage(image, mimeType, &encodedImage))
 | |
|          return { };
 | |
| diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h
 | |
| index bc87758878d5163a938af8242c7a6800ea9bd13c..3d0751f8dfe1124bbe054daa2fa0c7552fecab32 100644
 | |
| --- a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h
 | |
| +++ b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h
 | |
| @@ -42,7 +42,7 @@ WEBCORE_EXPORT uint8_t verifyImageBufferIsBigEnough(const void* buffer, size_t b
 | |
|  CFStringRef jpegUTI();
 | |
|  RetainPtr<CFStringRef> utiFromImageBufferMIMEType(const String&);
 | |
|  
 | |
| -bool encodeImage(CGImageRef, CFStringRef uti, Optional<double> quality, CFMutableDataRef);
 | |
| +WEBCORE_EXPORT bool encodeImage(CGImageRef, CFStringRef uti, Optional<double> quality, CFMutableDataRef);
 | |
|  
 | |
|  String dataURL(CFDataRef, const String& mimeType);
 | |
|  String dataURL(const ImageData&, const String& mimeType, Optional<double> quality);
 | |
| diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp
 | |
| index 445c7d78a4a1a8cdb0e08a859d3912e5cc62b6c6..93a8006dd5237018b573b976d0bbe28f02b8254f 100644
 | |
| --- a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp
 | |
| +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp
 | |
| @@ -27,7 +27,7 @@
 | |
|  #include "config.h"
 | |
|  #include "GraphicsContextGLOpenGL.h"
 | |
|  
 | |
| -#if ENABLE(GRAPHICS_CONTEXT_GL) && (USE(OPENGL) || (PLATFORM(COCOA) && USE(OPENGL_ES)))
 | |
| +#if !PLATFORM(WIN) && ENABLE(GRAPHICS_CONTEXT_GL) && (USE(OPENGL) || (PLATFORM(COCOA) && USE(OPENGL_ES)))
 | |
|  
 | |
|  #if PLATFORM(IOS_FAMILY)
 | |
|  #include "GraphicsContextGLOpenGLESIOS.h"
 | |
| diff --git a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp
 | |
| index 8121b92a98932789e7ea18ef616462f46e569134..d04569f28c2d35cd756f01d1e637c9e59ca3f5fe 100644
 | |
| --- a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp
 | |
| +++ b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp
 | |
| @@ -172,6 +172,33 @@ static Vector<unsigned> stringIndicesFromClusters(const Vector<WORD>& clusters,
 | |
|      return stringIndices;
 | |
|  }
 | |
|  
 | |
| +static int compactScriptItemsIfNeeded(const UChar* cp, unsigned stringLength, Vector<SCRIPT_ITEM>& items, int numItems, const Font* font)
 | |
| +{
 | |
| +    // https://bugs.webkit.org/show_bug.cgi?id=201214
 | |
| +    // Uniscribe is overly aggressive in separating the runs. It'll split "3d_rotation" into "3", "d", "_" and "rotation" and we
 | |
| +    // will ScriptShape them separately. As a result, a ligature for "3d_rotation" in the Material icon set
 | |
| +    // (https://www.materialui.co/icon/3d-rotation) will not be used. A quick and dirty hack is to glue them back here, only making
 | |
| +    // this apply to the readable characters, digits and _.
 | |
| +
 | |
| +    if (!numItems)
 | |
| +        return numItems;
 | |
| +
 | |
| +    if (font->platformData().isSystemFont() || font->platformData().hasVariations())
 | |
| +        return numItems;
 | |
| +
 | |
| +    bool allGoodCharacters = true;
 | |
| +    for (unsigned i = 0; allGoodCharacters && i < stringLength; ++i) {
 | |
| +        const UChar c = cp[i];
 | |
| +        allGoodCharacters = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_';
 | |
| +    }
 | |
| +    if (!allGoodCharacters)
 | |
| +        return numItems;
 | |
| +
 | |
| +    // Consume entire string into a single run. |items| is at least numItems + 1 long.
 | |
| +    items[1] = items[numItems];
 | |
| +    return 1;
 | |
| +}
 | |
| +
 | |
|  void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned stringLength, unsigned stringLocation, const Font* font)
 | |
|  {
 | |
|      if (!font) {
 | |
| @@ -200,6 +227,8 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp,
 | |
|      }
 | |
|      items.resize(numItems + 1);
 | |
|  
 | |
| +    numItems = compactScriptItemsIfNeeded(cp, stringLength, items, numItems, font);
 | |
| +
 | |
|      for (int i = 0; i < numItems; i++) {
 | |
|          // Determine the string for this item.
 | |
|          const UChar* str = cp + items[i].iCharPos;
 | |
| diff --git a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
 | |
| index 0516e70973e0078de6ad0216375d34dd9ef51a8d..ffd9a02deb5518e0c8c77b156815c11eb4b16829 100644
 | |
| --- a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
 | |
| +++ b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
 | |
| @@ -37,8 +37,10 @@
 | |
|  #include "WindowsKeyboardCodes.h"
 | |
|  #include <gdk/gdk.h>
 | |
|  #include <gdk/gdkkeysyms.h>
 | |
| +#include <wtf/HashMap.h>
 | |
|  #include <wtf/HexNumber.h>
 | |
|  #include <wtf/glib/GUniquePtr.h>
 | |
| +#include <mutex>
 | |
|  
 | |
|  namespace WebCore {
 | |
|  
 | |
| @@ -1294,6 +1296,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode)
 | |
|  
 | |
|  }
 | |
|  
 | |
| +static const HashMap<int, unsigned>& gdkToWindowsKeyCodeMap()
 | |
| +{
 | |
| +    static HashMap<int, unsigned>* result;
 | |
| +    static std::once_flag once;
 | |
| +    std::call_once(
 | |
| +        once,
 | |
| +        [] {
 | |
| +            const unsigned gdkKeyCodes[] = {
 | |
| +                GDK_KEY_Cancel,
 | |
| +                // FIXME: non-keypad keys should take precedence, so we skip GDK_KEY_KP_*
 | |
| +                // GDK_KEY_KP_0,
 | |
| +                // GDK_KEY_KP_1,
 | |
| +                // GDK_KEY_KP_2,
 | |
| +                // GDK_KEY_KP_3,
 | |
| +                // GDK_KEY_KP_4,
 | |
| +                // GDK_KEY_KP_5,
 | |
| +                // GDK_KEY_KP_6,
 | |
| +                // GDK_KEY_KP_7,
 | |
| +                // GDK_KEY_KP_8,
 | |
| +                // GDK_KEY_KP_9,
 | |
| +                // GDK_KEY_KP_Multiply,
 | |
| +                // GDK_KEY_KP_Add,
 | |
| +                // GDK_KEY_KP_Subtract,
 | |
| +                // GDK_KEY_KP_Decimal,
 | |
| +                // GDK_KEY_KP_Divide,
 | |
| +                // GDK_KEY_KP_Page_Up,
 | |
| +                // GDK_KEY_KP_Page_Down,
 | |
| +                // GDK_KEY_KP_End,
 | |
| +                // GDK_KEY_KP_Home,
 | |
| +                // GDK_KEY_KP_Left,
 | |
| +                // GDK_KEY_KP_Up,
 | |
| +                // GDK_KEY_KP_Right,
 | |
| +                // GDK_KEY_KP_Down,
 | |
| +                GDK_KEY_BackSpace,
 | |
| +                // GDK_KEY_ISO_Left_Tab,
 | |
| +                // GDK_KEY_3270_BackTab,
 | |
| +                GDK_KEY_Tab,
 | |
| +                GDK_KEY_Clear,
 | |
| +                // GDK_KEY_ISO_Enter,
 | |
| +                // GDK_KEY_KP_Enter,
 | |
| +                GDK_KEY_Return,
 | |
| +                GDK_KEY_Menu,
 | |
| +                GDK_KEY_Pause,
 | |
| +                GDK_KEY_AudioPause,
 | |
| +                GDK_KEY_Caps_Lock,
 | |
| +                GDK_KEY_Kana_Lock,
 | |
| +                GDK_KEY_Kana_Shift,
 | |
| +                GDK_KEY_Hangul,
 | |
| +                GDK_KEY_Hangul_Hanja,
 | |
| +                GDK_KEY_Kanji,
 | |
| +                GDK_KEY_Escape,
 | |
| +                GDK_KEY_space,
 | |
| +                GDK_KEY_Page_Up,
 | |
| +                GDK_KEY_Page_Down,
 | |
| +                GDK_KEY_End,
 | |
| +                GDK_KEY_Home,
 | |
| +                GDK_KEY_Left,
 | |
| +                GDK_KEY_Up,
 | |
| +                GDK_KEY_Right,
 | |
| +                GDK_KEY_Down,
 | |
| +                GDK_KEY_Select,
 | |
| +                GDK_KEY_Print,
 | |
| +                GDK_KEY_Execute,
 | |
| +                GDK_KEY_Insert,
 | |
| +                GDK_KEY_KP_Insert,
 | |
| +                GDK_KEY_Delete,
 | |
| +                GDK_KEY_KP_Delete,
 | |
| +                GDK_KEY_Help,
 | |
| +                GDK_KEY_0,
 | |
| +                GDK_KEY_parenright,
 | |
| +                GDK_KEY_1,
 | |
| +                GDK_KEY_exclam,
 | |
| +                GDK_KEY_2,
 | |
| +                GDK_KEY_at,
 | |
| +                GDK_KEY_3,
 | |
| +                GDK_KEY_numbersign,
 | |
| +                GDK_KEY_4,
 | |
| +                GDK_KEY_dollar,
 | |
| +                GDK_KEY_5,
 | |
| +                GDK_KEY_percent,
 | |
| +                GDK_KEY_6,
 | |
| +                GDK_KEY_asciicircum,
 | |
| +                GDK_KEY_7,
 | |
| +                GDK_KEY_ampersand,
 | |
| +                GDK_KEY_8,
 | |
| +                GDK_KEY_asterisk,
 | |
| +                GDK_KEY_9,
 | |
| +                GDK_KEY_parenleft,
 | |
| +                GDK_KEY_a,
 | |
| +                GDK_KEY_A,
 | |
| +                GDK_KEY_b,
 | |
| +                GDK_KEY_B,
 | |
| +                GDK_KEY_c,
 | |
| +                GDK_KEY_C,
 | |
| +                GDK_KEY_d,
 | |
| +                GDK_KEY_D,
 | |
| +                GDK_KEY_e,
 | |
| +                GDK_KEY_E,
 | |
| +                GDK_KEY_f,
 | |
| +                GDK_KEY_F,
 | |
| +                GDK_KEY_g,
 | |
| +                GDK_KEY_G,
 | |
| +                GDK_KEY_h,
 | |
| +                GDK_KEY_H,
 | |
| +                GDK_KEY_i,
 | |
| +                GDK_KEY_I,
 | |
| +                GDK_KEY_j,
 | |
| +                GDK_KEY_J,
 | |
| +                GDK_KEY_k,
 | |
| +                GDK_KEY_K,
 | |
| +                GDK_KEY_l,
 | |
| +                GDK_KEY_L,
 | |
| +                GDK_KEY_m,
 | |
| +                GDK_KEY_M,
 | |
| +                GDK_KEY_n,
 | |
| +                GDK_KEY_N,
 | |
| +                GDK_KEY_o,
 | |
| +                GDK_KEY_O,
 | |
| +                GDK_KEY_p,
 | |
| +                GDK_KEY_P,
 | |
| +                GDK_KEY_q,
 | |
| +                GDK_KEY_Q,
 | |
| +                GDK_KEY_r,
 | |
| +                GDK_KEY_R,
 | |
| +                GDK_KEY_s,
 | |
| +                GDK_KEY_S,
 | |
| +                GDK_KEY_t,
 | |
| +                GDK_KEY_T,
 | |
| +                GDK_KEY_u,
 | |
| +                GDK_KEY_U,
 | |
| +                GDK_KEY_v,
 | |
| +                GDK_KEY_V,
 | |
| +                GDK_KEY_w,
 | |
| +                GDK_KEY_W,
 | |
| +                GDK_KEY_x,
 | |
| +                GDK_KEY_X,
 | |
| +                GDK_KEY_y,
 | |
| +                GDK_KEY_Y,
 | |
| +                GDK_KEY_z,
 | |
| +                GDK_KEY_Z,
 | |
| +                GDK_KEY_Meta_L,
 | |
| +                GDK_KEY_Meta_R,
 | |
| +                GDK_KEY_Sleep,
 | |
| +                GDK_KEY_Num_Lock,
 | |
| +                GDK_KEY_Scroll_Lock,
 | |
| +                GDK_KEY_Shift_L,
 | |
| +                GDK_KEY_Shift_R,
 | |
| +                GDK_KEY_Control_L,
 | |
| +                GDK_KEY_Control_R,
 | |
| +                GDK_KEY_Alt_L,
 | |
| +                GDK_KEY_Alt_R,
 | |
| +                GDK_KEY_Back,
 | |
| +                GDK_KEY_Forward,
 | |
| +                GDK_KEY_Refresh,
 | |
| +                GDK_KEY_Stop,
 | |
| +                GDK_KEY_Search,
 | |
| +                GDK_KEY_Favorites,
 | |
| +                GDK_KEY_HomePage,
 | |
| +                GDK_KEY_AudioMute,
 | |
| +                GDK_KEY_AudioLowerVolume,
 | |
| +                GDK_KEY_AudioRaiseVolume,
 | |
| +                GDK_KEY_AudioNext,
 | |
| +                GDK_KEY_AudioPrev,
 | |
| +                GDK_KEY_AudioStop,
 | |
| +                GDK_KEY_AudioMedia,
 | |
| +                GDK_KEY_semicolon,
 | |
| +                GDK_KEY_colon,
 | |
| +                GDK_KEY_plus,
 | |
| +                GDK_KEY_equal,
 | |
| +                GDK_KEY_comma,
 | |
| +                GDK_KEY_less,
 | |
| +                GDK_KEY_minus,
 | |
| +                GDK_KEY_underscore,
 | |
| +                GDK_KEY_period,
 | |
| +                GDK_KEY_greater,
 | |
| +                GDK_KEY_slash,
 | |
| +                GDK_KEY_question,
 | |
| +                GDK_KEY_asciitilde,
 | |
| +                GDK_KEY_quoteleft,
 | |
| +                GDK_KEY_bracketleft,
 | |
| +                GDK_KEY_braceleft,
 | |
| +                GDK_KEY_backslash,
 | |
| +                GDK_KEY_bar,
 | |
| +                GDK_KEY_bracketright,
 | |
| +                GDK_KEY_braceright,
 | |
| +                GDK_KEY_quoteright,
 | |
| +                GDK_KEY_quotedbl,
 | |
| +                GDK_KEY_AudioRewind,
 | |
| +                GDK_KEY_AudioForward,
 | |
| +                GDK_KEY_AudioPlay,
 | |
| +                GDK_KEY_F1,
 | |
| +                GDK_KEY_F2,
 | |
| +                GDK_KEY_F3,
 | |
| +                GDK_KEY_F4,
 | |
| +                GDK_KEY_F5,
 | |
| +                GDK_KEY_F6,
 | |
| +                GDK_KEY_F7,
 | |
| +                GDK_KEY_F8,
 | |
| +                GDK_KEY_F9,
 | |
| +                GDK_KEY_F10,
 | |
| +                GDK_KEY_F11,
 | |
| +                GDK_KEY_F12,
 | |
| +                GDK_KEY_F13,
 | |
| +                GDK_KEY_F14,
 | |
| +                GDK_KEY_F15,
 | |
| +                GDK_KEY_F16,
 | |
| +                GDK_KEY_F17,
 | |
| +                GDK_KEY_F18,
 | |
| +                GDK_KEY_F19,
 | |
| +                GDK_KEY_F20,
 | |
| +                GDK_KEY_F21,
 | |
| +                GDK_KEY_F22,
 | |
| +                GDK_KEY_F23,
 | |
| +                GDK_KEY_F24,
 | |
| +                GDK_KEY_VoidSymbol,
 | |
| +                GDK_KEY_Red,
 | |
| +                GDK_KEY_Green,
 | |
| +                GDK_KEY_Yellow,
 | |
| +                GDK_KEY_Blue,
 | |
| +                GDK_KEY_PowerOff,
 | |
| +                GDK_KEY_AudioRecord,
 | |
| +                GDK_KEY_Display,
 | |
| +                GDK_KEY_Subtitle,
 | |
| +                GDK_KEY_Video
 | |
| +            };
 | |
| +            result = new HashMap<int, unsigned>();
 | |
| +            for (unsigned gdkKeyCode : gdkKeyCodes) {
 | |
| +                int winKeyCode = PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(gdkKeyCode);
 | |
| +                // If several gdk key codes map to the same win key code first one is used.
 | |
| +                result->add(winKeyCode, gdkKeyCode);
 | |
| +            }
 | |
| +        });
 | |
| +    return *result;
 | |
| +}
 | |
| +
 | |
| +unsigned PlatformKeyboardEvent::gdkKeyCodeForWindowsKeyCode(int keycode)
 | |
| +{
 | |
| +    return gdkToWindowsKeyCodeMap().get(keycode);
 | |
| +}
 | |
| +
 | |
|  String PlatformKeyboardEvent::singleCharacterString(unsigned val)
 | |
|  {
 | |
|      switch (val) {
 | |
| diff --git a/Source/WebCore/platform/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/cf/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h
 | |
| index d677280d2b5e7b053a240c155d64bc881f1737bb..1be949e09982b34366d162e6d45ebc51a76dcfb0 100644
 | |
| --- a/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h
 | |
| +++ b/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h
 | |
| @@ -47,7 +47,7 @@ class SocketStreamHandleClient;
 | |
|  
 | |
|  class SocketStreamHandleImpl : public SocketStreamHandle {
 | |
|  public:
 | |
| -    static Ref<SocketStreamHandleImpl> create(const URL& url, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, client, sessionID, credentialPartition, WTFMove(auditData), provider)); }
 | |
| +    static Ref<SocketStreamHandleImpl> create(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, ignoreCertificateErrors, client, sessionID, credentialPartition, WTFMove(auditData), provider)); }
 | |
|  
 | |
|      virtual ~SocketStreamHandleImpl();
 | |
|  
 | |
| @@ -61,7 +61,7 @@ private:
 | |
|      Optional<size_t> platformSendInternal(const uint8_t*, size_t);
 | |
|      bool sendPendingData();
 | |
|  
 | |
| -    WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String& credentialPartition, SourceApplicationAuditToken&&, const StorageSessionProvider*);
 | |
| +    WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, bool ignoreCertificateErrors, SocketStreamHandleClient&, PAL::SessionID, const String& credentialPartition, SourceApplicationAuditToken&&, const StorageSessionProvider*);
 | |
|      void createStreams();
 | |
|      void scheduleStreams();
 | |
|      void chooseProxy();
 | |
| @@ -106,6 +106,7 @@ private:
 | |
|      String m_credentialPartition;
 | |
|      SourceApplicationAuditToken m_auditData;
 | |
|      RefPtr<const StorageSessionProvider> m_storageSessionProvider;
 | |
| +    bool m_ignoreCertificateErrors { false };
 | |
|  
 | |
|      StreamBuffer<uint8_t, 1024 * 1024> m_buffer;
 | |
|      static const unsigned maxBufferSize = 100 * 1024 * 1024;
 | |
| diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp b/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp
 | |
| index 545c28e62f72771de5f3f3e9fed2e8cf6147ed0f..a6fc5f5b3fc62adce2604821bd29f9aed378c24c 100644
 | |
| --- a/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp
 | |
| +++ b/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp
 | |
| @@ -96,7 +96,7 @@ static inline auto callbacksRunLoopMode()
 | |
|  #endif
 | |
|  }
 | |
|  
 | |
| -SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider)
 | |
| +SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider)
 | |
|      : SocketStreamHandle(url, client)
 | |
|      , m_connectingSubstate(New)
 | |
|      , m_connectionType(Unknown)
 | |
| @@ -104,6 +104,7 @@ SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandl
 | |
|      , m_credentialPartition(credentialPartition)
 | |
|      , m_auditData(WTFMove(auditData))
 | |
|      , m_storageSessionProvider(provider)
 | |
| +    , m_ignoreCertificateErrors(ignoreCertificateErrors)
 | |
|  {
 | |
|      LOG(Network, "SocketStreamHandle %p new client %p", this, &m_client);
 | |
|  
 | |
| @@ -360,7 +361,7 @@ void SocketStreamHandleImpl::createStreams()
 | |
|      }
 | |
|  
 | |
|      if (shouldUseSSL()) {
 | |
| -        CFBooleanRef validateCertificateChain = DeprecatedGlobalSettings::allowsAnySSLCertificate() ? kCFBooleanFalse : kCFBooleanTrue;
 | |
| +        CFBooleanRef validateCertificateChain = m_ignoreCertificateErrors || DeprecatedGlobalSettings::allowsAnySSLCertificate() ? kCFBooleanFalse : kCFBooleanTrue;
 | |
|          const void* keys[] = {
 | |
|              kCFStreamSSLPeerName,
 | |
|              kCFStreamSSLLevel,
 | |
| diff --git a/Source/WebCore/platform/network/curl/CookieJarDB.h b/Source/WebCore/platform/network/curl/CookieJarDB.h
 | |
| index 7c0ea47ece4ff0d472ce595c91ea1cfa90b25ca7..1c44229a18fe90f6e5e0c0056dddd09acadfe49b 100644
 | |
| --- a/Source/WebCore/platform/network/curl/CookieJarDB.h
 | |
| +++ b/Source/WebCore/platform/network/curl/CookieJarDB.h
 | |
| @@ -72,7 +72,7 @@ public:
 | |
|      WEBCORE_EXPORT ~CookieJarDB();
 | |
|  
 | |
|  private:
 | |
| -    CookieAcceptPolicy m_acceptPolicy { CookieAcceptPolicy::Always };
 | |
| +    CookieAcceptPolicy m_acceptPolicy { CookieAcceptPolicy::OnlyFromMainDocumentDomain };
 | |
|      String m_databasePath;
 | |
|  
 | |
|      bool m_detectedDatabaseCorruption { false };
 | |
| diff --git a/Source/WebCore/platform/network/curl/CurlStream.cpp b/Source/WebCore/platform/network/curl/CurlStream.cpp
 | |
| index 26dc7bef4b74bc6b4e2e526dec6523c3ad6d3643..c783aa5a7984f3966312e5e0ffd76f93ed6208f8 100644
 | |
| --- a/Source/WebCore/platform/network/curl/CurlStream.cpp
 | |
| +++ b/Source/WebCore/platform/network/curl/CurlStream.cpp
 | |
| @@ -33,7 +33,7 @@
 | |
|  
 | |
|  namespace WebCore {
 | |
|  
 | |
| -CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, URL&& url)
 | |
| +CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, bool ignoreCertificateErrors, URL&& url)
 | |
|      : m_scheduler(scheduler)
 | |
|      , m_streamID(streamID)
 | |
|  {
 | |
| @@ -49,6 +49,9 @@ CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, UR
 | |
|      m_curlHandle->setUrl(urlForConnection);
 | |
|  
 | |
|      m_curlHandle->enableConnectionOnly();
 | |
| +    if (ignoreCertificateErrors)
 | |
| +        m_curlHandle->disableServerTrustEvaluation();
 | |
| +
 | |
|  
 | |
|      auto errorCode = m_curlHandle->perform();
 | |
|      if (errorCode != CURLE_OK) {
 | |
| diff --git a/Source/WebCore/platform/network/curl/CurlStream.h b/Source/WebCore/platform/network/curl/CurlStream.h
 | |
| index 313b0173da5cd404a1e3fcad9573b8ff7c3abd4f..020980a0f61d47e8c7929bfaab2f8394d014766d 100644
 | |
| --- a/Source/WebCore/platform/network/curl/CurlStream.h
 | |
| +++ b/Source/WebCore/platform/network/curl/CurlStream.h
 | |
| @@ -50,12 +50,12 @@ public:
 | |
|          virtual void didFail(CurlStreamID, CURLcode) = 0;
 | |
|      };
 | |
|  
 | |
| -    static std::unique_ptr<CurlStream> create(CurlStreamScheduler& scheduler, CurlStreamID streamID, URL&& url)
 | |
| +    static std::unique_ptr<CurlStream> create(CurlStreamScheduler& scheduler, CurlStreamID streamID, bool ignoreCertificateErrors, URL&& url)
 | |
|      {
 | |
| -        return WTF::makeUnique<CurlStream>(scheduler, streamID, WTFMove(url));
 | |
| +        return WTF::makeUnique<CurlStream>(scheduler, streamID, ignoreCertificateErrors, WTFMove(url));
 | |
|      }
 | |
|  
 | |
| -    CurlStream(CurlStreamScheduler&, CurlStreamID, URL&&);
 | |
| +    CurlStream(CurlStreamScheduler&, CurlStreamID, bool ignoreCertificateErrors, URL&&);
 | |
|      virtual ~CurlStream();
 | |
|  
 | |
|      void send(UniqueArray<uint8_t>&&, size_t);
 | |
| diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp
 | |
| index 3fb8759984aa31a7d44baa2f69afe2fee461ea4f..bb7ad47477d97fa1eaff5d3da6b9a3705ff1e32f 100644
 | |
| --- a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp
 | |
| +++ b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp
 | |
| @@ -40,7 +40,7 @@ CurlStreamScheduler::~CurlStreamScheduler()
 | |
|      ASSERT(isMainThread());
 | |
|  }
 | |
|  
 | |
| -CurlStreamID CurlStreamScheduler::createStream(const URL& url, CurlStream::Client& client)
 | |
| +CurlStreamID CurlStreamScheduler::createStream(const URL& url, bool ignoreCertificateErrors, CurlStream::Client& client)
 | |
|  {
 | |
|      ASSERT(isMainThread());
 | |
|  
 | |
| @@ -51,8 +51,8 @@ CurlStreamID CurlStreamScheduler::createStream(const URL& url, CurlStream::Clien
 | |
|      auto streamID = m_currentStreamID;
 | |
|      m_clientList.add(streamID, &client);
 | |
|  
 | |
| -    callOnWorkerThread([this, streamID, url = url.isolatedCopy()]() mutable {
 | |
| -        m_streamList.add(streamID, CurlStream::create(*this, streamID, WTFMove(url)));
 | |
| +    callOnWorkerThread([this, streamID, ignoreCertificateErrors, url = url.isolatedCopy()]() mutable {
 | |
| +        m_streamList.add(streamID, CurlStream::create(*this, streamID, ignoreCertificateErrors, WTFMove(url)));
 | |
|      });
 | |
|  
 | |
|      return streamID;
 | |
| diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.h b/Source/WebCore/platform/network/curl/CurlStreamScheduler.h
 | |
| index 7d881206c9689f433227969c9b7f9ff268bdaaed..2e8118f11f87fa5f32adcedc165aec8220b36d58 100644
 | |
| --- a/Source/WebCore/platform/network/curl/CurlStreamScheduler.h
 | |
| +++ b/Source/WebCore/platform/network/curl/CurlStreamScheduler.h
 | |
| @@ -38,7 +38,7 @@ public:
 | |
|      CurlStreamScheduler();
 | |
|      virtual ~CurlStreamScheduler();
 | |
|  
 | |
| -    CurlStreamID createStream(const URL&, CurlStream::Client&);
 | |
| +    CurlStreamID createStream(const URL&, bool ignoreCertificateErrors, CurlStream::Client&);
 | |
|      void destroyStream(CurlStreamID);
 | |
|      void send(CurlStreamID, UniqueArray<uint8_t>&&, size_t);
 | |
|  
 | |
| diff --git a/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h
 | |
| index fad4ef9198118f5e6e5ed7d3c14b99e574593451..a2d59843896f252fccdddbb94c5275eec6300f1b 100644
 | |
| --- a/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h
 | |
| +++ b/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h
 | |
| @@ -44,7 +44,7 @@ class StorageSessionProvider;
 | |
|  
 | |
|  class SocketStreamHandleImpl : public SocketStreamHandle, public CurlStream::Client {
 | |
|  public:
 | |
| -    static Ref<SocketStreamHandleImpl> create(const URL& url, SocketStreamHandleClient& client, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, client, provider)); }
 | |
| +    static Ref<SocketStreamHandleImpl> create(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, ignoreCertificateErrors, client, provider)); }
 | |
|  
 | |
|      virtual ~SocketStreamHandleImpl();
 | |
|  
 | |
| @@ -53,7 +53,7 @@ public:
 | |
|      WEBCORE_EXPORT void platformClose() final;
 | |
|  
 | |
|  private:
 | |
| -    WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&, const StorageSessionProvider*);
 | |
| +    WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, bool ignoreCertificateErrors, SocketStreamHandleClient&, const StorageSessionProvider*);
 | |
|  
 | |
|      size_t bufferedAmount() final;
 | |
|      Optional<size_t> platformSendInternal(const uint8_t*, size_t);
 | |
| diff --git a/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp b/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp
 | |
| index cae8c43d60fcf6a3d69c58a7436516f923d227cb..e6b03f378929abbd4437f8507ea2f6c563edcff7 100644
 | |
| --- a/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp
 | |
| +++ b/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp
 | |
| @@ -43,7 +43,7 @@
 | |
|  
 | |
|  namespace WebCore {
 | |
|  
 | |
| -SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandleClient& client, const StorageSessionProvider* provider)
 | |
| +SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, const StorageSessionProvider* provider)
 | |
|      : SocketStreamHandle(url, client)
 | |
|      , m_storageSessionProvider(provider)
 | |
|      , m_scheduler(CurlContext::singleton().streamScheduler())
 | |
| @@ -52,7 +52,7 @@ SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandl
 | |
|      if (m_url.protocolIs("wss") && DeprecatedGlobalSettings::allowsAnySSLCertificate())
 | |
|          CurlContext::singleton().sslHandle().setIgnoreSSLErrors(true);
 | |
|  
 | |
| -    m_streamID = m_scheduler.createStream(m_url, *this);
 | |
| +    m_streamID = m_scheduler.createStream(m_url, ignoreCertificateErrors, *this);
 | |
|  }
 | |
|  
 | |
|  SocketStreamHandleImpl::~SocketStreamHandleImpl()
 | |
| diff --git a/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h
 | |
| index 3ecf866005da6da9cec7c7930e6a4f93cb39d6e0..d81dc9ac0c433e00ab4ad73e206856098ab9230e 100644
 | |
| --- a/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h
 | |
| +++ b/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h
 | |
| @@ -47,7 +47,7 @@ class StorageSessionProvider;
 | |
|  
 | |
|  class SocketStreamHandleImpl final : public SocketStreamHandle {
 | |
|  public:
 | |
| -    static Ref<SocketStreamHandleImpl> create(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider*)
 | |
| +    static Ref<SocketStreamHandleImpl> create(const URL&, bool, SocketStreamHandleClient&, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider*)
 | |
|      {
 | |
|          RELEASE_ASSERT_NOT_REACHED();
 | |
|      }
 | |
| diff --git a/Source/WebCore/platform/win/KeyEventWin.cpp b/Source/WebCore/platform/win/KeyEventWin.cpp
 | |
| index 44737686187a06a92c408ea60b63a48ac8481334..c754a763688b52e7ddd47493296ef9b0c6adc527 100644
 | |
| --- a/Source/WebCore/platform/win/KeyEventWin.cpp
 | |
| +++ b/Source/WebCore/platform/win/KeyEventWin.cpp
 | |
| @@ -239,10 +239,16 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(HWND, WPARAM code, LPARAM keyData,
 | |
|  {
 | |
|  }
 | |
|  
 | |
| -void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type, bool)
 | |
| +void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardsCompatibility)
 | |
|  {
 | |
| -    // No KeyDown events on Windows to disambiguate.
 | |
| -    ASSERT_NOT_REACHED();
 | |
| +    m_type = type;
 | |
| +    if (type == PlatformEvent::RawKeyDown) {
 | |
| +        m_text = String();
 | |
| +        m_unmodifiedText = String();
 | |
| +    } else {
 | |
| +        m_keyIdentifier = String();
 | |
| +        m_windowsVirtualKeyCode = 0;
 | |
| +    }
 | |
|  }
 | |
|  
 | |
|  bool PlatformKeyboardEvent::currentCapsLockState()
 | |
| diff --git a/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp b/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp
 | |
| index d03eaafb306b4dc698004a699256760014061d4b..15bfcb30f6bc6b279b96e55ae46dc44bcfaa4b80 100644
 | |
| --- a/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp
 | |
| +++ b/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp
 | |
| @@ -75,10 +75,10 @@ public:
 | |
|  #endif
 | |
|  
 | |
|  private:
 | |
| -#if USE_OPENXR
 | |
|      void enumerateApiLayerProperties() const;
 | |
|      void enumerateInstanceExtensionProperties() const;
 | |
|  
 | |
| +#if USE_OPENXR
 | |
|      XrInstance m_instance { XR_NULL_HANDLE };
 | |
|  #endif // USE_OPENXR
 | |
|  };
 | |
| @@ -139,10 +139,10 @@ Instance::Impl::Impl()
 | |
|      enumerateApiLayerProperties();
 | |
|      enumerateInstanceExtensionProperties();
 | |
|  
 | |
| +#if USE_OPENXR
 | |
|      static const char* s_applicationName = "WebXR (WebKit)";
 | |
|      static const uint32_t s_applicationVersion = 1;
 | |
|  
 | |
| -#if USE_OPENXR
 | |
|      auto createInfo = createStructure<XrInstanceCreateInfo, XR_TYPE_INSTANCE_CREATE_INFO>();
 | |
|      createInfo.createFlags = 0;
 | |
|      std::memcpy(createInfo.applicationInfo.applicationName, s_applicationName, XR_MAX_APPLICATION_NAME_SIZE);
 | |
| @@ -162,7 +162,9 @@ Instance::Impl::Impl()
 | |
|  
 | |
|  Instance::Impl::~Impl()
 | |
|  {
 | |
| +#if USE_OPENXR
 | |
|      xrDestroyInstance(m_instance);
 | |
| +#endif
 | |
|  }
 | |
|  
 | |
|  #if USE_OPENXR
 | |
| diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.cpp b/Source/WebKit/NetworkProcess/NetworkProcess.cpp
 | |
| index e6135c62c1ccc00dd2cf05d2a7d41591b30e763b..1709e6ac3bf0e90f9ced1a326958319611dcce5f 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"
 | |
| @@ -600,6 +599,41 @@ void NetworkProcess::destroySession(PAL::SessionID sessionID)
 | |
|          webIDBServer->close();
 | |
|  }
 | |
|  
 | |
| +void NetworkProcess::getAllCookies(PAL::SessionID sessionID, CompletionHandler<void(Vector<WebCore::Cookie>&&)>&& completionHandler)
 | |
| +{
 | |
| +    if (auto* networkStorageSession = storageSession(sessionID)) {
 | |
| +        completionHandler(networkStorageSession->getAllCookies());
 | |
| +        return;
 | |
| +    }
 | |
| +    completionHandler({ });
 | |
| +}
 | |
| +
 | |
| +void NetworkProcess::setCookies(PAL::SessionID sessionID, Vector<WebCore::Cookie> cookies, CompletionHandler<void(bool)>&& completionHandler) {
 | |
| +    if (auto* networkStorageSession = storageSession(sessionID)) {
 | |
| +        for (auto cookie : cookies)
 | |
| +            networkStorageSession->setCookie(cookie);
 | |
| +        completionHandler(true);
 | |
| +        return;
 | |
| +    }
 | |
| +    completionHandler(false);
 | |
| +}
 | |
| +
 | |
| +void NetworkProcess::deleteAllCookies(PAL::SessionID sessionID, CompletionHandler<void(bool)>&& completionHandler)
 | |
| +{
 | |
| +    if (auto* networkStorageSession = storageSession(sessionID)) {
 | |
| +        networkStorageSession->deleteAllCookies();
 | |
| +        completionHandler(true);
 | |
| +        return;
 | |
| +    }
 | |
| +    completionHandler(false);
 | |
| +}
 | |
| +
 | |
| +void NetworkProcess::setIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignore)
 | |
| +{
 | |
| +    if (auto* networkSession = this->networkSession(sessionID))
 | |
| +        networkSession->setIgnoreCertificateErrors(ignore);
 | |
| +}
 | |
| +
 | |
|  #if ENABLE(RESOURCE_LOAD_STATISTICS)
 | |
|  void NetworkProcess::dumpResourceLoadStatistics(PAL::SessionID sessionID, CompletionHandler<void(String)>&& completionHandler)
 | |
|  {
 | |
| diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h
 | |
| index 46d9f51dd6a91e6c692729da6163f0abb2d455f2..aa777a5ae392a8249b9eca952079f375c7935287 100644
 | |
| --- a/Source/WebKit/NetworkProcess/NetworkProcess.h
 | |
| +++ b/Source/WebKit/NetworkProcess/NetworkProcess.h
 | |
| @@ -76,6 +76,7 @@ class SessionID;
 | |
|  
 | |
|  namespace WebCore {
 | |
|  class CertificateInfo;
 | |
| +struct Cookie;
 | |
|  class CurlProxySettings;
 | |
|  class DownloadID;
 | |
|  class ProtectionSpace;
 | |
| @@ -204,6 +205,11 @@ public:
 | |
|  
 | |
|      void addWebsiteDataStore(WebsiteDataStoreParameters&&);
 | |
|  
 | |
| +    void getAllCookies(PAL::SessionID, CompletionHandler<void(Vector<WebCore::Cookie>&&)>&&);
 | |
| +    void setCookies(PAL::SessionID, Vector<WebCore::Cookie>, CompletionHandler<void(bool)>&&);
 | |
| +    void deleteAllCookies(PAL::SessionID, CompletionHandler<void(bool)>&&);
 | |
| +    void setIgnoreCertificateErrors(PAL::SessionID, bool);
 | |
| +
 | |
|  #if ENABLE(RESOURCE_LOAD_STATISTICS)
 | |
|      void clearPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
 | |
|      void clearUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
 | |
| diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
 | |
| index 08f07064a8e0ec85bacc0237ad428d57ff9abe7f..bc6691e51e27816be103a9c18341d067c1080fcf 100644
 | |
| --- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
 | |
| +++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
 | |
| @@ -82,6 +82,11 @@ messages -> NetworkProcess LegacyReceiver {
 | |
|  
 | |
|      PreconnectTo(PAL::SessionID sessionID, WebKit::WebPageProxyIdentifier webPageProxyID, WebCore::PageIdentifier webPageID, URL url, String userAgent, enum:uint8_t WebCore::StoredCredentialsPolicy storedCredentialsPolicy, enum:bool Optional<WebKit::NavigatingToAppBoundDomain> isNavigatingToAppBoundDomain);
 | |
|  
 | |
| +    GetAllCookies(PAL::SessionID sessionID) -> (Vector<WebCore::Cookie> cookies) Async
 | |
| +    SetCookies(PAL::SessionID sessionID, Vector<WebCore::Cookie> cookies) -> (bool success) Async
 | |
| +    DeleteAllCookies(PAL::SessionID sessionID) -> (bool success) Async
 | |
| +    SetIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignoreTLSErrors)
 | |
| +
 | |
|  #if ENABLE(RESOURCE_LOAD_STATISTICS)
 | |
|      ClearPrevalentResource(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async
 | |
|      ClearUserInteraction(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async
 | |
| diff --git a/Source/WebKit/NetworkProcess/NetworkSession.h b/Source/WebKit/NetworkProcess/NetworkSession.h
 | |
| index d8d3ecbad8e688506a885640891848a2ba06e43a..62047204ac144fbcdeb5fd35dffa9956a26c43da 100644
 | |
| --- a/Source/WebKit/NetworkProcess/NetworkSession.h
 | |
| +++ b/Source/WebKit/NetworkProcess/NetworkSession.h
 | |
| @@ -138,6 +138,9 @@ public:
 | |
|  
 | |
|      bool isStaleWhileRevalidateEnabled() const { return m_isStaleWhileRevalidateEnabled; }
 | |
|  
 | |
| +    void setIgnoreCertificateErrors(bool ignore) { m_ignoreCertificateErrors = ignore; }
 | |
| +    bool ignoreCertificateErrors() { return m_ignoreCertificateErrors; }
 | |
| +
 | |
|  #if ENABLE(SERVICE_WORKER)
 | |
|      void addSoftUpdateLoader(std::unique_ptr<ServiceWorkerSoftUpdateLoader>&& loader) { m_softUpdateLoaders.add(WTFMove(loader)); }
 | |
|      void removeSoftUpdateLoader(ServiceWorkerSoftUpdateLoader* loader) { m_softUpdateLoaders.remove(loader); }
 | |
| @@ -168,6 +171,7 @@ protected:
 | |
|  #endif
 | |
|      bool m_isStaleWhileRevalidateEnabled { false };
 | |
|      UniqueRef<AdClickAttributionManager> m_adClickAttribution;
 | |
| +    bool m_ignoreCertificateErrors { false };
 | |
|  
 | |
|      HashSet<Ref<NetworkResourceLoader>> m_keptAliveLoads;
 | |
|  
 | |
| diff --git a/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp b/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
 | |
| index d1fa427d82884fc43569d1bf0df7d728921502fc..30450ab01cddfcd406e46ac8e08ac50a2983f7a6 100644
 | |
| --- a/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
 | |
| +++ b/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
 | |
| @@ -43,7 +43,7 @@ Ref<NetworkSocketStream> NetworkSocketStream::create(NetworkProcess& networkProc
 | |
|  NetworkSocketStream::NetworkSocketStream(NetworkProcess& networkProcess, URL&& url, PAL::SessionID sessionID, const String& credentialPartition, WebSocketIdentifier identifier, IPC::Connection& connection, SourceApplicationAuditToken&& auditData)
 | |
|      : m_identifier(identifier)
 | |
|      , m_connection(connection)
 | |
| -    , m_impl(SocketStreamHandleImpl::create(url, *this, sessionID, credentialPartition, WTFMove(auditData), NetworkStorageSessionProvider::create(networkProcess, sessionID).ptr()))
 | |
| +    , m_impl(SocketStreamHandleImpl::create(url, networkProcess.networkSession(sessionID)->ignoreCertificateErrors(), *this, sessionID, credentialPartition, WTFMove(auditData), NetworkStorageSessionProvider::create(networkProcess, sessionID).ptr()))
 | |
|  {
 | |
|  }
 | |
|  
 | |
| diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
 | |
| index 2e1d1cee66929cc11785c081afdf1e8c71f190bb..5c0aac805db6a2cb1425026b3febe0ba1d35b819 100644
 | |
| --- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
 | |
| +++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
 | |
| @@ -657,7 +657,7 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa& session, Se
 | |
|      NegotiatedLegacyTLS negotiatedLegacyTLS = NegotiatedLegacyTLS::No;
 | |
|  
 | |
|      if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
 | |
| -        if (NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(challenge))
 | |
| +        if (sessionCocoa->ignoreCertificateErrors() || sessionCocoa->allowsSpecificHTTPSCertificateForHost(challenge))
 | |
|              return completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
 | |
|  
 | |
|  #if HAVE(TLS_PROTOCOL_VERSION_T)
 | |
| diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp
 | |
| index 00e1a971b1b1e7b918bcde6d28794fbfab91d91c..e118f16b9a51bd5da6e4f393ba5faf695bac430f 100644
 | |
| --- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp
 | |
| +++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp
 | |
| @@ -26,9 +26,13 @@
 | |
|  #include "config.h"
 | |
|  #include "NetworkDataTaskCurl.h"
 | |
|  
 | |
| +#include "APIError.h"
 | |
|  #include "AuthenticationChallengeDisposition.h"
 | |
|  #include "AuthenticationManager.h"
 | |
| +#include "DataReference.h"
 | |
| +#include "Download.h"
 | |
|  #include "NetworkSessionCurl.h"
 | |
| +#include "NetworkProcess.h"
 | |
|  #include <WebCore/AuthenticationChallenge.h>
 | |
|  #include <WebCore/CookieJar.h>
 | |
|  #include <WebCore/CurlRequest.h>
 | |
| @@ -39,6 +43,8 @@
 | |
|  #include <WebCore/SameSiteInfo.h>
 | |
|  #include <WebCore/ShouldRelaxThirdPartyCookieBlocking.h>
 | |
|  #include <WebCore/SynchronousLoaderClient.h>
 | |
| +#include <WebCore/TextEncoding.h>
 | |
| +#include <wtf/FileSystem.h>
 | |
|  
 | |
|  namespace WebKit {
 | |
|  
 | |
| @@ -81,6 +87,8 @@ NetworkDataTaskCurl::NetworkDataTaskCurl(NetworkSession& session, NetworkDataTas
 | |
|          m_curlRequest->setUserPass(m_initialCredential.user(), m_initialCredential.password());
 | |
|          m_curlRequest->setAuthenticationScheme(ProtectionSpaceAuthenticationSchemeHTTPBasic);
 | |
|      }
 | |
| +    if (m_session->ignoreCertificateErrors())
 | |
| +        m_curlRequest->disableServerTrustEvaluation();
 | |
|      m_curlRequest->setStartTime(m_startTime);
 | |
|      m_curlRequest->start();
 | |
|  }
 | |
| @@ -187,7 +195,12 @@ void NetworkDataTaskCurl::curlDidReceiveBuffer(CurlRequest&, Ref<SharedBuffer>&&
 | |
|      auto protectedThis = makeRef(*this);
 | |
|      if (state() == State::Canceling || state() == State::Completed || (!m_client && !isDownload()))
 | |
|          return;
 | |
| -
 | |
| +    if (isDownload()) {
 | |
| +        FileSystem::PlatformFileHandle file = FileSystem::openFile(m_pendingDownloadLocation, FileSystem::FileOpenMode::Write);
 | |
| +        FileSystem::writeToFile(file, buffer->data(), buffer->size());
 | |
| +        FileSystem::closeFile(file);
 | |
| +        return;
 | |
| +    }
 | |
|      m_client->didReceiveData(WTFMove(buffer));
 | |
|  }
 | |
|  
 | |
| @@ -196,6 +209,12 @@ void NetworkDataTaskCurl::curlDidComplete(CurlRequest&, NetworkLoadMetrics&& net
 | |
|      if (state() == State::Canceling || state() == State::Completed || (!m_client && !isDownload()))
 | |
|          return;
 | |
|  
 | |
| +    if (isDownload()) {
 | |
| +        auto* download = m_session->networkProcess().downloadManager().download(m_pendingDownloadID);
 | |
| +        ASSERT(download);
 | |
| +        download->didFinish();
 | |
| +        return;
 | |
| +    }
 | |
|      m_client->didCompleteWithError({ }, WTFMove(networkLoadMetrics));
 | |
|  }
 | |
|  
 | |
| @@ -209,6 +228,13 @@ void NetworkDataTaskCurl::curlDidFailWithError(CurlRequest& request, ResourceErr
 | |
|          return;
 | |
|      }
 | |
|  
 | |
| +    if (isDownload()) {
 | |
| +        auto* download = m_session->networkProcess().downloadManager().download(m_pendingDownloadID);
 | |
| +        ASSERT(download);
 | |
| +        download->didFail(resourceError, IPC::DataReference());
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
|      m_client->didCompleteWithError(resourceError);
 | |
|  }
 | |
|  
 | |
| @@ -245,6 +271,18 @@ void NetworkDataTaskCurl::invokeDidReceiveResponse()
 | |
|              break;
 | |
|          case PolicyAction::Ignore:
 | |
|              break;
 | |
| +        case PolicyAction::Download: {
 | |
| +            FileSystem::deleteFile(m_pendingDownloadLocation);
 | |
| +            auto& downloadManager = m_session->networkProcess().downloadManager();
 | |
| +            auto download = makeUnique<Download>(downloadManager, m_pendingDownloadID, *this, *m_session, suggestedFilename());
 | |
| +            auto* downloadPtr = download.get();
 | |
| +            downloadManager.dataTaskBecameDownloadTask(m_pendingDownloadID, WTFMove(download));
 | |
| +            downloadPtr->didCreateDestination(m_pendingDownloadLocation);
 | |
| +
 | |
| +            if (m_curlRequest)
 | |
| +                m_curlRequest->completeDidReceiveResponse();
 | |
| +            break;
 | |
| +        }
 | |
|          default:
 | |
|              notImplemented();
 | |
|              break;
 | |
| @@ -327,6 +365,8 @@ void NetworkDataTaskCurl::willPerformHTTPRedirection()
 | |
|              m_curlRequest->setUserPass(m_initialCredential.user(), m_initialCredential.password());
 | |
|              m_curlRequest->setAuthenticationScheme(ProtectionSpaceAuthenticationSchemeHTTPBasic);
 | |
|          }
 | |
| +        if (m_session->ignoreCertificateErrors())
 | |
| +            m_curlRequest->disableServerTrustEvaluation();
 | |
|          m_curlRequest->setStartTime(m_startTime);
 | |
|          m_curlRequest->start();
 | |
|  
 | |
| @@ -510,4 +550,16 @@ bool NetworkDataTaskCurl::isThirdPartyRequest(const WebCore::ResourceRequest& re
 | |
|      return !WebCore::areRegistrableDomainsEqual(request.url(), request.firstPartyForCookies());
 | |
|  }
 | |
|  
 | |
| +String NetworkDataTaskCurl::suggestedFilename() const
 | |
| +{
 | |
| +    if (!m_suggestedFilename.isEmpty())
 | |
| +        return m_suggestedFilename;
 | |
| +
 | |
| +    String suggestedFilename = m_response.suggestedFilename();
 | |
| +    if (!suggestedFilename.isEmpty())
 | |
| +        return suggestedFilename;
 | |
| +
 | |
| +    return decodeURLEscapeSequences(m_response.url().lastPathComponent());
 | |
| +}
 | |
| +
 | |
|  } // namespace WebKit
 | |
| diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h
 | |
| index 04f081add9253f2296c026d9548f9b9a97c644f1..65db77501d4eb6dfbb46a4e5f26cae4389f57376 100644
 | |
| --- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h
 | |
| +++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h
 | |
| @@ -84,6 +84,7 @@ private:
 | |
|  
 | |
|      void appendCookieHeader(WebCore::ResourceRequest&);
 | |
|      void handleCookieHeaders(const WebCore::ResourceRequest&, const WebCore::CurlResponse&);
 | |
| +    String suggestedFilename() const override;
 | |
|  
 | |
|      bool isThirdPartyRequest(const WebCore::ResourceRequest&);
 | |
|      bool shouldBlockCookies(const WebCore::ResourceRequest&);
 | |
| diff --git a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
 | |
| index 18a229c1a447148a79abefa88ae80cf53ecf5511..fef9fcd8c99cdddd584096ca73b6048de0f452d8 100644
 | |
| --- a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
 | |
| +++ b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
 | |
| @@ -451,6 +451,8 @@ bool NetworkDataTaskSoup::tlsConnectionAcceptCertificate(GTlsCertificate* certif
 | |
|  {
 | |
|      ASSERT(m_soupRequest);
 | |
|      URL url = soupURIToURL(soup_request_get_uri(m_soupRequest.get()));
 | |
| +    if (m_session->ignoreCertificateErrors())
 | |
| +        return true;
 | |
|      auto error = SoupNetworkSession::checkTLSErrors(url, certificate, tlsErrors);
 | |
|      if (!error)
 | |
|          return true;
 | |
| diff --git a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
 | |
| index 407361f036e79891767d807fbb63c9044b260a70..24773d8f349d441e2b6b1981baa5af170a96b384 100644
 | |
| --- a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
 | |
| +++ b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
 | |
| @@ -106,6 +106,11 @@ static gboolean webSocketAcceptCertificateCallback(GTlsConnection*, GTlsCertific
 | |
|      return !SoupNetworkSession::checkTLSErrors(soupURIToURL(soup_message_get_uri(soupMessage)), certificate, errors);
 | |
|  }
 | |
|  
 | |
| +static gboolean webSocketAcceptCertificateCallbackIgnoreTLSErrors(GTlsConnection*, GTlsCertificate* certificate, GTlsCertificateFlags errors, SoupMessage* soupMessage)
 | |
| +{
 | |
| +    return TRUE;
 | |
| +}
 | |
| +
 | |
|  static void webSocketMessageNetworkEventCallback(SoupMessage* soupMessage, GSocketClientEvent event, GIOStream* connection)
 | |
|  {
 | |
|      if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING)
 | |
| @@ -114,6 +119,14 @@ static void webSocketMessageNetworkEventCallback(SoupMessage* soupMessage, GSock
 | |
|      g_signal_connect(connection, "accept-certificate", G_CALLBACK(webSocketAcceptCertificateCallback), soupMessage);
 | |
|  }
 | |
|  
 | |
| +static void webSocketMessageNetworkEventCallbackIgnoreTLSErrors(SoupMessage* soupMessage, GSocketClientEvent event, GIOStream* connection)
 | |
| +{
 | |
| +    if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING)
 | |
| +        return;
 | |
| +
 | |
| +    g_signal_connect(connection, "accept-certificate", G_CALLBACK(webSocketAcceptCertificateCallbackIgnoreTLSErrors), soupMessage);
 | |
| +}
 | |
| +
 | |
|  std::unique_ptr<WebSocketTask> NetworkSessionSoup::createWebSocketTask(NetworkSocketChannel& channel, const ResourceRequest& request, const String& protocol)
 | |
|  {
 | |
|      GUniquePtr<SoupURI> soupURI = request.createSoupURI();
 | |
| @@ -122,8 +135,12 @@ std::unique_ptr<WebSocketTask> NetworkSessionSoup::createWebSocketTask(NetworkSo
 | |
|  
 | |
|      GRefPtr<SoupMessage> soupMessage = adoptGRef(soup_message_new_from_uri(SOUP_METHOD_GET, soupURI.get()));
 | |
|      request.updateSoupMessage(soupMessage.get(), blobRegistry());
 | |
| -    if (request.url().protocolIs("wss"))
 | |
| -        g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallback), nullptr);
 | |
| +    if (request.url().protocolIs("wss")) {
 | |
| +        if (ignoreCertificateErrors())
 | |
| +          g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallbackIgnoreTLSErrors), nullptr);
 | |
| +        else
 | |
| +          g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallback), nullptr);
 | |
| +    }
 | |
|      return makeUnique<WebSocketTask>(channel, soupSession(), soupMessage.get(), protocol);
 | |
|  }
 | |
|  
 | |
| diff --git a/Source/WebKit/PlatformGTK.cmake b/Source/WebKit/PlatformGTK.cmake
 | |
| index 6cb3df1a60adee7365fa449fb07342eababa61f2..2b98bcc7847554a38fd1a565d6b7bd803284716e 100644
 | |
| --- a/Source/WebKit/PlatformGTK.cmake
 | |
| +++ b/Source/WebKit/PlatformGTK.cmake
 | |
| @@ -448,6 +448,9 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES
 | |
|      ${GSTREAMER_PBUTILS_INCLUDE_DIRS}
 | |
|      ${GTK_INCLUDE_DIRS}
 | |
|      ${LIBSOUP_INCLUDE_DIRS}
 | |
| +# Playwright begin
 | |
| +    ${LIBVPX_INCLUDE_DIRS}
 | |
| +# Playwright end
 | |
|  )
 | |
|  
 | |
|  if (USE_WPE_RENDERER)
 | |
| @@ -501,6 +504,9 @@ if (USE_LIBWEBRTC)
 | |
|      list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES
 | |
|          "${THIRDPARTY_DIR}/libwebrtc/Source/"
 | |
|          "${THIRDPARTY_DIR}/libwebrtc/Source/webrtc"
 | |
| +# Playwright begin
 | |
| +        "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include"
 | |
| +# Playwright end
 | |
|      )
 | |
|  endif ()
 | |
|  
 | |
| diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake
 | |
| index 3b153f122f13040707eea8b0bda91f15185bc1e4..2d24930d725787b9b27c105c78636c6de24b91f4 100644
 | |
| --- a/Source/WebKit/PlatformWPE.cmake
 | |
| +++ b/Source/WebKit/PlatformWPE.cmake
 | |
| @@ -257,6 +257,7 @@ list(APPEND WebKit_INCLUDE_DIRECTORIES
 | |
|      "${WEBKIT_DIR}/UIProcess/API/wpe"
 | |
|      "${WEBKIT_DIR}/UIProcess/CoordinatedGraphics"
 | |
|      "${WEBKIT_DIR}/UIProcess/geoclue"
 | |
| +    "${WEBKIT_DIR}/UIProcess/glib"
 | |
|      "${WEBKIT_DIR}/UIProcess/gstreamer"
 | |
|      "${WEBKIT_DIR}/UIProcess/linux"
 | |
|      "${WEBKIT_DIR}/UIProcess/soup"
 | |
| @@ -287,8 +288,52 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES
 | |
|      ${GSTREAMER_VIDEO_INCLUDE_DIRS}
 | |
|      ${LIBSECCOMP_INCLUDE_DIRS}
 | |
|      ${LIBSOUP_INCLUDE_DIRS}
 | |
| +# Playwright begin
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include"
 | |
| +# Playwright end
 | |
|  )
 | |
|  
 | |
| +# Playwright begin
 | |
| +list(APPEND WebKit_SOURCES
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_common.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_gcc.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_argb.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from_argb.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_jpeg.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_to_argb.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_to_i420.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/cpu_id.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/mjpeg_decoder.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/mjpeg_validate.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/planar_functions.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon64.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_any.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_argb.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_common.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_gcc.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon64.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_any.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_common.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_gcc.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon64.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_any.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_argb.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_common.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_gcc.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon64.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/video_common.cc"
 | |
| +)
 | |
| +# Playwright end
 | |
| +
 | |
|  list(APPEND WebKit_LIBRARIES
 | |
|      Cairo::Cairo
 | |
|      Freetype::Freetype
 | |
| diff --git a/Source/WebKit/PlatformWin.cmake b/Source/WebKit/PlatformWin.cmake
 | |
| index 3b94f4dba2c3b9659a1269bfe030d5d010b5b1bd..dfc890a525c54869118e9828f585e0142bc3acae 100644
 | |
| --- a/Source/WebKit/PlatformWin.cmake
 | |
| +++ b/Source/WebKit/PlatformWin.cmake
 | |
| @@ -59,8 +59,12 @@ list(APPEND WebKit_SOURCES
 | |
|  
 | |
|      UIProcess/WebsiteData/win/WebsiteDataStoreWin.cpp
 | |
|  
 | |
| +    UIProcess/win/InspectorTargetProxyWin.cpp
 | |
| +    UIProcess/win/InspectorPlaywrightAgentClientWin.cpp
 | |
|      UIProcess/win/PageClientImpl.cpp
 | |
|      UIProcess/win/WebContextMenuProxyWin.cpp
 | |
| +    UIProcess/win/WebPageInspectorEmulationAgentWin.cpp
 | |
| +    UIProcess/win/WebPageInspectorInputAgentWin.cpp
 | |
|      UIProcess/win/WebPageProxyWin.cpp
 | |
|      UIProcess/win/WebPopupMenuProxyWin.cpp
 | |
|      UIProcess/win/WebProcessPoolWin.cpp
 | |
| @@ -117,6 +121,56 @@ list(APPEND WebKit_INCLUDE_DIRECTORIES
 | |
|      "${WEBKIT_DIR}/win"
 | |
|  )
 | |
|  
 | |
| +# Playwright begin
 | |
| +list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include"
 | |
| +    "${LIBVPX_CUSTOM_INCLUDE_DIR}"
 | |
| +)
 | |
| +
 | |
| +list(APPEND WebKit_SOURCES
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_common.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_gcc.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_win.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_argb.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from_argb.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_jpeg.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_to_argb.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_to_i420.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/cpu_id.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/mjpeg_decoder.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/mjpeg_validate.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/planar_functions.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon64.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_any.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_argb.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_common.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_gcc.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon64.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_win.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_any.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_common.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_gcc.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon64.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_win.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_any.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_argb.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_common.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_gcc.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon64.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_win.cc"
 | |
| +    "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/video_common.cc"
 | |
| +)
 | |
| +# Playwright end
 | |
| +
 | |
|  set(WebKitCommonIncludeDirectories ${WebKit_INCLUDE_DIRECTORIES})
 | |
|  set(WebKitCommonSystemIncludeDirectories ${WebKit_SYSTEM_INCLUDE_DIRECTORIES})
 | |
|  
 | |
| @@ -169,6 +223,7 @@ if (${WTF_PLATFORM_WIN_CAIRO})
 | |
|          OpenSSL::SSL
 | |
|          mfuuid.lib
 | |
|          strmiids.lib
 | |
| +        ${LIBVPX_CUSTOM_LIBRARY}
 | |
|      )
 | |
|  endif ()
 | |
|  
 | |
| diff --git a/Source/WebKit/Shared/API/c/wpe/WebKit.h b/Source/WebKit/Shared/API/c/wpe/WebKit.h
 | |
| index 898e30b370db8176e886fbbde0cd960e38a64818..74945e06fac0eb14936578de6a599a123364a63a 100644
 | |
| --- a/Source/WebKit/Shared/API/c/wpe/WebKit.h
 | |
| +++ b/Source/WebKit/Shared/API/c/wpe/WebKit.h
 | |
| @@ -78,6 +78,7 @@
 | |
|  // From Source/WebKit/UIProcess/API/C
 | |
|  #include <WebKit/WKBackForwardListItemRef.h>
 | |
|  #include <WebKit/WKBackForwardListRef.h>
 | |
| +#include <WebKit/WKBrowserInspector.h>
 | |
|  #include <WebKit/WKContext.h>
 | |
|  #include <WebKit/WKContextConfigurationRef.h>
 | |
|  #include <WebKit/WKCredential.h>
 | |
| diff --git a/Source/WebKit/Shared/NativeWebKeyboardEvent.h b/Source/WebKit/Shared/NativeWebKeyboardEvent.h
 | |
| index bf64299025afcc1cb784d35dd3ea611d47018b12..5e1e045d1b0dfb327c658e432ebf3a6f8b38ff27 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;
 | |
| @@ -71,19 +72,35 @@ public:
 | |
|  #if USE(APPKIT)
 | |
|      // FIXME: Share iOS's HandledByInputMethod enum here instead of passing a boolean.
 | |
|      NativeWebKeyboardEvent(NSEvent *, bool handledByInputMethod, bool replacesSoftSpace, const Vector<WebCore::KeypressCommand>&);
 | |
| +    NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp, Vector<WebCore::KeypressCommand>&& commands)
 | |
| +        : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp, WTFMove(commands))
 | |
| +    {
 | |
| +    }
 | |
|  #elif PLATFORM(GTK)
 | |
|      NativeWebKeyboardEvent(const NativeWebKeyboardEvent&);
 | |
|      NativeWebKeyboardEvent(GdkEvent*, const String&, Vector<String>&& commands);
 | |
|      NativeWebKeyboardEvent(const String&, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&);
 | |
|      NativeWebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, Vector<String>&& commands, bool isKeypad, OptionSet<Modifier>);
 | |
| +    NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp, Vector<String>&& commands)
 | |
| +        : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp, WTFMove(commands))
 | |
| +    {
 | |
| +    }
 | |
|  #elif PLATFORM(IOS_FAMILY)
 | |
|      enum class HandledByInputMethod : bool { No, Yes };
 | |
|      NativeWebKeyboardEvent(::WebEvent *, HandledByInputMethod);
 | |
|  #elif USE(LIBWPE)
 | |
|      enum class HandledByInputMethod : bool { No, Yes };
 | |
|      NativeWebKeyboardEvent(struct wpe_input_keyboard_event*, const String&, HandledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&);
 | |
| +    NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
 | |
| +        : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp)
 | |
| +    {
 | |
| +    }
 | |
|  #elif PLATFORM(WIN)
 | |
|      NativeWebKeyboardEvent(HWND, UINT message, WPARAM, LPARAM, Vector<MSG>&& pendingCharEvents);
 | |
| +    NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
 | |
| +        : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp)
 | |
| +    {
 | |
| +    }
 | |
|  #endif
 | |
|  
 | |
|  #if USE(APPKIT)
 | |
| diff --git a/Source/WebKit/Shared/NativeWebMouseEvent.h b/Source/WebKit/Shared/NativeWebMouseEvent.h
 | |
| index d6f9902b963bd9a0036a6008d719c3e5b15402c4..8a23efeab7125f86d3b990bb09921ecdbbaaa205 100644
 | |
| --- a/Source/WebKit/Shared/NativeWebMouseEvent.h
 | |
| +++ b/Source/WebKit/Shared/NativeWebMouseEvent.h
 | |
| @@ -77,6 +77,11 @@ public:
 | |
|      NativeWebMouseEvent(HWND, UINT message, WPARAM, LPARAM, bool);
 | |
|  #endif
 | |
|  
 | |
| +#if PLATFORM(GTK) || USE(LIBWPE) || PLATFORM(WIN)
 | |
| +    NativeWebMouseEvent(Type type, Button button, unsigned short buttons, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, float deltaX, float deltaY, float deltaZ, int clickCount, OptionSet<Modifier> modifiers, WallTime timestamp)
 | |
| +       : WebMouseEvent(type, button, buttons, position, globalPosition, deltaX, deltaY, deltaZ, clickCount, modifiers, timestamp) { }
 | |
| +#endif
 | |
| +
 | |
|  #if USE(APPKIT)
 | |
|      NSEvent* nativeEvent() const { return m_nativeEvent.get(); }
 | |
|  #elif PLATFORM(GTK)
 | |
| diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
 | |
| index 5447fca763528a4e99b433e4dfeb8dbf544175f3..2f5aafebfd2dacf061203ca7675258d112746462 100644
 | |
| --- a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
 | |
| +++ b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
 | |
| @@ -1495,6 +1495,9 @@ void ArgumentCoder<WindowFeatures>::encode(Encoder& encoder, const WindowFeature
 | |
|      encoder << windowFeatures.resizable;
 | |
|      encoder << windowFeatures.fullscreen;
 | |
|      encoder << windowFeatures.dialog;
 | |
| +    encoder << windowFeatures.noopener;
 | |
| +    encoder << windowFeatures.noreferrer;
 | |
| +    encoder << windowFeatures.additionalFeatures;
 | |
|  }
 | |
|  
 | |
|  bool ArgumentCoder<WindowFeatures>::decode(Decoder& decoder, WindowFeatures& windowFeatures)
 | |
| @@ -1523,6 +1526,12 @@ bool ArgumentCoder<WindowFeatures>::decode(Decoder& decoder, WindowFeatures& win
 | |
|          return false;
 | |
|      if (!decoder.decode(windowFeatures.dialog))
 | |
|          return false;
 | |
| +    if (!decoder.decode(windowFeatures.noopener))
 | |
| +        return false;
 | |
| +    if (!decoder.decode(windowFeatures.noreferrer))
 | |
| +        return false;
 | |
| +    if (!decoder.decode(windowFeatures.additionalFeatures))
 | |
| +        return false;
 | |
|      return true;
 | |
|  }
 | |
|  
 | |
| diff --git a/Source/WebKit/Shared/WebEvent.h b/Source/WebKit/Shared/WebEvent.h
 | |
| index 4bddad03dc933d8727c5e2fb6cda90d5a5e0b15d..a346623a30b3a7b15669f6e07b0a56c602b80e0d 100644
 | |
| --- a/Source/WebKit/Shared/WebEvent.h
 | |
| +++ b/Source/WebKit/Shared/WebEvent.h
 | |
| @@ -38,6 +38,7 @@
 | |
|  #include <WebCore/KeypressCommand.h>
 | |
|  #include <wtf/EnumTraits.h>
 | |
|  #include <wtf/OptionSet.h>
 | |
| +#include <wtf/RefCounted.h>
 | |
|  #include <wtf/WallTime.h>
 | |
|  #include <wtf/text/WTFString.h>
 | |
|  
 | |
| @@ -253,14 +254,18 @@ public:
 | |
|  
 | |
|  #if USE(APPKIT)
 | |
|      WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, const Vector<WebCore::KeypressCommand>&, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
 | |
| +    WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp, Vector<WebCore::KeypressCommand>&& commands);
 | |
|  #elif PLATFORM(GTK)
 | |
|      WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&, Vector<String>&& commands, bool isKeypad, OptionSet<Modifier>, WallTime timestamp);
 | |
| +    WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp, Vector<String>&& commands);
 | |
|  #elif PLATFORM(IOS_FAMILY)
 | |
|      WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
 | |
|  #elif USE(LIBWPE)
 | |
|      WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<EditingRange>&&, bool isKeypad, OptionSet<Modifier>, WallTime timestamp);
 | |
| +    WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
 | |
|  #else
 | |
|      WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
 | |
| +    WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
 | |
|  #endif
 | |
|  
 | |
|      const String& text() const { return m_text; }
 | |
| diff --git a/Source/WebKit/Shared/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/WebPageCreationParameters.cpp b/Source/WebKit/Shared/WebPageCreationParameters.cpp
 | |
| index e18736f7e372d56c06c030af8a175473bce90baf..214bf11d368d372afbc330875abc4b9764121b4a 100644
 | |
| --- a/Source/WebKit/Shared/WebPageCreationParameters.cpp
 | |
| +++ b/Source/WebKit/Shared/WebPageCreationParameters.cpp
 | |
| @@ -147,6 +147,8 @@ void WebPageCreationParameters::encode(IPC::Encoder& encoder) const
 | |
|      encoder << crossOriginAccessControlCheckEnabled;
 | |
|      encoder << processDisplayName;
 | |
|  
 | |
| +    encoder << shouldPauseInInspectorWhenShown;
 | |
| +
 | |
|      encoder << shouldCaptureAudioInUIProcess;
 | |
|      encoder << shouldCaptureAudioInGPUProcess;
 | |
|      encoder << shouldCaptureVideoInUIProcess;
 | |
| @@ -472,7 +474,10 @@ Optional<WebPageCreationParameters> WebPageCreationParameters::decode(IPC::Decod
 | |
|      if (!processDisplayName)
 | |
|          return WTF::nullopt;
 | |
|      parameters.processDisplayName = WTFMove(*processDisplayName);
 | |
| -    
 | |
| +
 | |
| +    if (!decoder.decode(parameters.shouldPauseInInspectorWhenShown))
 | |
| +        return WTF::nullopt;
 | |
| +
 | |
|      if (!decoder.decode(parameters.shouldCaptureAudioInUIProcess))
 | |
|          return WTF::nullopt;
 | |
|  
 | |
| @@ -493,13 +498,13 @@ Optional<WebPageCreationParameters> WebPageCreationParameters::decode(IPC::Decod
 | |
|  
 | |
|      if (!decoder.decode(parameters.needsInAppBrowserPrivacyQuirks))
 | |
|          return WTF::nullopt;
 | |
| -    
 | |
| +
 | |
|      if (!decoder.decode(parameters.limitsNavigationsToAppBoundDomains))
 | |
|          return WTF::nullopt;
 | |
|      
 | |
|      if (!decoder.decode(parameters.shouldRelaxThirdPartyCookieBlocking))
 | |
|          return WTF::nullopt;
 | |
| -    
 | |
| +
 | |
|  #if PLATFORM(GTK)
 | |
|      if (!decoder.decode(parameters.themeName))
 | |
|          return WTF::nullopt;
 | |
| diff --git a/Source/WebKit/Shared/WebPageCreationParameters.h b/Source/WebKit/Shared/WebPageCreationParameters.h
 | |
| index 992baf499b84f7558c9983f485ec235d099f9ae3..c34c64c4ff6ceafdfb8fc8882a3eb3da6ed8c8e3 100644
 | |
| --- a/Source/WebKit/Shared/WebPageCreationParameters.h
 | |
| +++ b/Source/WebKit/Shared/WebPageCreationParameters.h
 | |
| @@ -230,6 +230,8 @@ struct WebPageCreationParameters {
 | |
|      bool limitsNavigationsToAppBoundDomains { false };
 | |
|      WebCore::ShouldRelaxThirdPartyCookieBlocking shouldRelaxThirdPartyCookieBlocking { WebCore::ShouldRelaxThirdPartyCookieBlocking::No };
 | |
|  
 | |
| +    bool shouldPauseInInspectorWhenShown { false };
 | |
| +
 | |
|  #if PLATFORM(GTK)
 | |
|      String themeName;
 | |
|  #endif
 | |
| diff --git a/Source/WebKit/Shared/WebPreferences.yaml b/Source/WebKit/Shared/WebPreferences.yaml
 | |
| index fad1a9f588621e95e19b1a4fe74ea3023642413d..bf92a79662687f2bf1070ad599cf30e6244b19ae 100644
 | |
| --- a/Source/WebKit/Shared/WebPreferences.yaml
 | |
| +++ b/Source/WebKit/Shared/WebPreferences.yaml
 | |
| @@ -317,7 +317,7 @@ MediaControlsScaleWithPageZoom:
 | |
|  
 | |
|  InspectorStartsAttached:
 | |
|    type: bool
 | |
| -  defaultValue: true
 | |
| +  defaultValue: false
 | |
|    webcoreBinding: none
 | |
|  
 | |
|  ShowsToolTipOverTruncatedText:
 | |
| diff --git a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
 | |
| index c76a9e1f7dae7a31c4048d8f00d849a18ebaff23..1cfd9c7acb69dea69783c42b3f427929509782a4 100644
 | |
| --- a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
 | |
| +++ b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp
 | |
| @@ -50,7 +50,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(Type type, const String& text, co
 | |
|  }
 | |
|  
 | |
|  NativeWebKeyboardEvent::NativeWebKeyboardEvent(const NativeWebKeyboardEvent& event)
 | |
| -    : WebKeyboardEvent(event.type(), event.text(), event.key(), event.code(), event.keyIdentifier(), event.windowsVirtualKeyCode(), event.nativeVirtualKeyCode(), event.handledByInputMethod(), Optional<Vector<WebCore::CompositionUnderline>>(event.preeditUnderlines()), Optional<EditingRange>(event.preeditSelectionRange()), Vector<String>(event.commands()), event.isKeypad(), event.modifiers(), event.timestamp())
 | |
| +    : WebKeyboardEvent(event)
 | |
|      , m_nativeEvent(event.nativeEvent() ? gdk_event_copy(event.nativeEvent()) : nullptr)
 | |
|  {
 | |
|  }
 | |
| diff --git a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
 | |
| index 66fcf27bcdd78e9c4d2b73e1e05830575bc9c05d..656c79494d4224b958ce338c5ebe0f0bfb8d8977 100644
 | |
| --- a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
 | |
| +++ b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp
 | |
| @@ -54,7 +54,7 @@ NativeWebMouseEvent::NativeWebMouseEvent(Type type, Button button, unsigned shor
 | |
|  }
 | |
|  
 | |
|  NativeWebMouseEvent::NativeWebMouseEvent(const NativeWebMouseEvent& event)
 | |
| -    : WebMouseEvent(event.type(), event.button(), event.buttons(), event.position(), event.globalPosition(), event.deltaX(), event.deltaY(), event.deltaZ(), event.clickCount(), event.modifiers(), event.timestamp())
 | |
| +    : WebMouseEvent(event)
 | |
|      , m_nativeEvent(event.nativeEvent() ? gdk_event_copy(const_cast<GdkEvent*>(event.nativeEvent())) : nullptr)
 | |
|  {
 | |
|  }
 | |
| diff --git a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp
 | |
| index 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 5d620b1ad03924b3ffd81d95105d4bf14341d9d4..143bc2905c68665c74991f5add9bb19903c8f87b 100644
 | |
| --- a/Source/WebKit/Sources.txt
 | |
| +++ b/Source/WebKit/Sources.txt
 | |
| @@ -274,16 +274,20 @@ Shared/WebsiteData/WebsiteData.cpp
 | |
|  
 | |
|  UIProcess/AuxiliaryProcessProxy.cpp
 | |
|  UIProcess/BackgroundProcessResponsivenessTimer.cpp
 | |
| +UIProcess/BrowserInspectorPipe.cpp
 | |
|  UIProcess/DeviceIdHashSaltStorage.cpp
 | |
|  UIProcess/DrawingAreaProxy.cpp
 | |
|  UIProcess/FrameLoadState.cpp
 | |
|  UIProcess/GeolocationPermissionRequestManagerProxy.cpp
 | |
|  UIProcess/GeolocationPermissionRequestProxy.cpp
 | |
| +UIProcess/InspectorDialogAgent.cpp
 | |
| +UIProcess/InspectorPlaywrightAgent.cpp
 | |
|  UIProcess/LegacyGlobalSettings.cpp
 | |
|  UIProcess/PageLoadState.cpp
 | |
|  UIProcess/ProcessAssertion.cpp
 | |
|  UIProcess/ProcessThrottler.cpp
 | |
|  UIProcess/ProvisionalPageProxy.cpp
 | |
| +UIProcess/RemoteInspectorPipe.cpp
 | |
|  UIProcess/ResponsivenessTimer.cpp
 | |
|  UIProcess/SuspendedPageProxy.cpp
 | |
|  UIProcess/SystemPreviewController.cpp
 | |
| @@ -320,6 +324,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
 | |
| @@ -439,6 +445,8 @@ UIProcess/Inspector/WebPageDebuggable.cpp
 | |
|  UIProcess/Inspector/WebPageInspectorController.cpp
 | |
|  
 | |
|  UIProcess/Inspector/Agents/InspectorBrowserAgent.cpp
 | |
| +UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
 | |
| +UIProcess/Inspector/Agents/ScreencastEncoder.cpp
 | |
|  
 | |
|  UIProcess/Media/AudioSessionRoutingArbitratorProxy.cpp
 | |
|  UIProcess/Media/MediaUsageManager.cpp
 | |
| diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt
 | |
| index 2519b7ee283a4015acc2a434011d859c4a2c687e..bc88b8e5cd275afa0a9acd20d242c12e4acbcd9d 100644
 | |
| --- a/Source/WebKit/SourcesCocoa.txt
 | |
| +++ b/Source/WebKit/SourcesCocoa.txt
 | |
| @@ -251,6 +251,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
 | |
| @@ -412,6 +413,7 @@ UIProcess/Inspector/ios/WKInspectorHighlightView.mm
 | |
|  UIProcess/Inspector/ios/WKInspectorNodeSearchGestureRecognizer.mm
 | |
|  
 | |
|  UIProcess/Inspector/mac/RemoteWebInspectorProxyMac.mm
 | |
| +UIProcess/Inspector/mac/ScreencastEncoderMac.mm
 | |
|  UIProcess/Inspector/mac/WebInspectorProxyMac.mm
 | |
|  UIProcess/Inspector/mac/WKInspectorViewController.mm
 | |
|  UIProcess/Inspector/mac/WKInspectorWKWebView.mm
 | |
| diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt
 | |
| index 5167ae9ddcbed6c02c10415a0f998fa20a371e77..1e2dd91b3601eff28a514196e578d77443ab6412 100644
 | |
| --- a/Source/WebKit/SourcesGTK.txt
 | |
| +++ b/Source/WebKit/SourcesGTK.txt
 | |
| @@ -135,6 +135,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
 | |
| @@ -251,6 +252,7 @@ UIProcess/WebsiteData/unix/WebsiteDataStoreUnix.cpp
 | |
|  
 | |
|  UIProcess/cairo/BackingStoreCairo.cpp @no-unify
 | |
|  
 | |
| +UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
 | |
|  UIProcess/glib/WebProcessPoolGLib.cpp
 | |
|  UIProcess/glib/WebProcessProxyGLib.cpp
 | |
|  UIProcess/glib/WebsiteDataStoreGLib.cpp @no-unify
 | |
| @@ -266,6 +268,7 @@ UIProcess/gtk/ClipboardGtk3.cpp @no-unify
 | |
|  UIProcess/gtk/ClipboardGtk4.cpp @no-unify
 | |
|  UIProcess/gtk/GestureController.cpp
 | |
|  UIProcess/gtk/HardwareAccelerationManager.cpp
 | |
| +UIProcess/gtk/InspectorTargetProxyGtk.cpp
 | |
|  UIProcess/gtk/KeyBindingTranslator.cpp
 | |
|  UIProcess/gtk/PointerLockManager.cpp @no-unify
 | |
|  UIProcess/gtk/PointerLockManagerWayland.cpp @no-unify
 | |
| @@ -276,6 +279,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 e3f8f47f93dd929da59b356472c20ad9a0c8fb4f..cf7448544afd70457cb1dc9216e8cadc81e4d7e2 100644
 | |
| --- a/Source/WebKit/SourcesWPE.txt
 | |
| +++ b/Source/WebKit/SourcesWPE.txt
 | |
| @@ -125,6 +125,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
 | |
| @@ -202,7 +203,7 @@ UIProcess/Automation/wpe/WebAutomationSessionWPE.cpp
 | |
|  UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
 | |
|  
 | |
|  UIProcess/geoclue/GeoclueGeolocationProvider.cpp
 | |
| -
 | |
| +UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
 | |
|  UIProcess/glib/WebProcessPoolGLib.cpp
 | |
|  UIProcess/glib/WebProcessProxyGLib.cpp
 | |
|  UIProcess/glib/WebsiteDataStoreGLib.cpp @no-unify
 | |
| @@ -227,6 +228,10 @@ UIProcess/linux/MemoryPressureMonitor.cpp
 | |
|  UIProcess/soup/WebCookieManagerProxySoup.cpp
 | |
|  UIProcess/soup/WebProcessPoolSoup.cpp
 | |
|  
 | |
| +UIProcess/wpe/InspectorTargetProxyWPE.cpp
 | |
| +UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp
 | |
| +UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
 | |
| +
 | |
|  UIProcess/wpe/WebPageProxyWPE.cpp
 | |
|  
 | |
|  WebProcess/GPU/media/gstreamer/VideoLayerRemoteGStreamer.cpp
 | |
| diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
 | |
| index 7227587e55153e3d8a13386dedd07de9a5d498be..c870126fc1ccd4cebe6b7a51074f489c83592c28 100644
 | |
| --- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
 | |
| +++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
 | |
| @@ -53,6 +53,9 @@ Ref<ProcessPoolConfiguration> ProcessPoolConfiguration::copy()
 | |
|      copy->m_ignoreSynchronousMessagingTimeoutsForTesting = this->m_ignoreSynchronousMessagingTimeoutsForTesting;
 | |
|      copy->m_attrStyleEnabled = this->m_attrStyleEnabled;
 | |
|      copy->m_overrideLanguages = this->m_overrideLanguages;
 | |
| +#if PLATFORM(MAC)
 | |
| +    copy->m_forceOverlayScrollbars = this->m_forceOverlayScrollbars;
 | |
| +#endif
 | |
|      copy->m_alwaysRunsAtBackgroundPriority = this->m_alwaysRunsAtBackgroundPriority;
 | |
|      copy->m_shouldTakeUIBackgroundAssertion = this->m_shouldTakeUIBackgroundAssertion;
 | |
|      copy->m_shouldCaptureDisplayInUIProcess = this->m_shouldCaptureDisplayInUIProcess;
 | |
| diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
 | |
| index 41ed3857db50b2944c78933f22b5acdb84ddaf3d..f1105988b2b0ccf3e8a87f7d0ed5504be84226b4 100644
 | |
| --- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
 | |
| +++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
 | |
| @@ -98,6 +98,11 @@ public:
 | |
|      const Vector<WTF::String>& overrideLanguages() const { return m_overrideLanguages; }
 | |
|      void setOverrideLanguages(Vector<WTF::String>&& languages) { m_overrideLanguages = WTFMove(languages); }
 | |
|      
 | |
| +#if PLATFORM(MAC)
 | |
| +    bool forceOverlayScrollbars() const { return m_forceOverlayScrollbars; }
 | |
| +    void setForceOverlayScrollbars(bool forceOverlayScrollbars) { m_forceOverlayScrollbars = forceOverlayScrollbars; }
 | |
| +#endif
 | |
| +
 | |
|      bool alwaysRunsAtBackgroundPriority() const { return m_alwaysRunsAtBackgroundPriority; }
 | |
|      void setAlwaysRunsAtBackgroundPriority(bool alwaysRunsAtBackgroundPriority) { m_alwaysRunsAtBackgroundPriority = alwaysRunsAtBackgroundPriority; }
 | |
|  
 | |
| @@ -160,6 +165,9 @@ private:
 | |
|      bool m_ignoreSynchronousMessagingTimeoutsForTesting { false };
 | |
|      bool m_attrStyleEnabled { false };
 | |
|      Vector<WTF::String> m_overrideLanguages;
 | |
| +#if PLATFORM(MAC)
 | |
| +    bool m_forceOverlayScrollbars { false };
 | |
| +#endif
 | |
|      bool m_alwaysRunsAtBackgroundPriority { false };
 | |
|      bool m_shouldTakeUIBackgroundAssertion { true };
 | |
|      bool m_shouldCaptureDisplayInUIProcess { DEFAULT_CAPTURE_DISPLAY_IN_UI_PROCESS };
 | |
| diff --git a/Source/WebKit/UIProcess/API/APIUIClient.h b/Source/WebKit/UIProcess/API/APIUIClient.h
 | |
| index 2e5be65bdfdccb888915d08df86abda741aadcb5..2da7443b8365431d2640ec54a816435986e285d3 100644
 | |
| --- a/Source/WebKit/UIProcess/API/APIUIClient.h
 | |
| +++ b/Source/WebKit/UIProcess/API/APIUIClient.h
 | |
| @@ -97,6 +97,7 @@ public:
 | |
|      virtual void runJavaScriptAlert(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function<void()>&& completionHandler) { completionHandler(); }
 | |
|      virtual void runJavaScriptConfirm(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function<void(bool)>&& completionHandler) { completionHandler(false); }
 | |
|      virtual void runJavaScriptPrompt(WebKit::WebPageProxy&, const WTF::String&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function<void(const WTF::String&)>&& completionHandler) { completionHandler(WTF::String()); }
 | |
| +    virtual void handleJavaScriptDialog(WebKit::WebPageProxy&, bool, const WTF::String&) { }
 | |
|  
 | |
|      virtual void setStatusText(WebKit::WebPageProxy*, const WTF::String&) { }
 | |
|      virtual void mouseDidMoveOverElement(WebKit::WebPageProxy&, const WebKit::WebHitTestResultData&, OptionSet<WebKit::WebEvent::Modifier>, Object*) { }
 | |
| diff --git a/Source/WebKit/UIProcess/API/C/WKContext.cpp b/Source/WebKit/UIProcess/API/C/WKContext.cpp
 | |
| index 8fb8e096d466e2361cdb5203efc9c568c9e69511..ed082f4af22e7f5c6942e8cd8fcc3e24b3883623 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..450033d87fefb743ab7240ce317fae221f91dcf5 100644
 | |
| --- a/Source/WebKit/UIProcess/API/C/WKInspector.cpp
 | |
| +++ b/Source/WebKit/UIProcess/API/C/WKInspector.cpp
 | |
| @@ -28,6 +28,11 @@
 | |
|  
 | |
|  #if !PLATFORM(IOS_FAMILY)
 | |
|  
 | |
| +#if PLATFORM(WIN)
 | |
| +#include "BrowserInspectorPipe.h"
 | |
| +#include "InspectorPlaywrightAgentClientWin.h"
 | |
| +#endif
 | |
| +
 | |
|  #include "WKAPICast.h"
 | |
|  #include "WebInspectorProxy.h"
 | |
|  #include "WebPageProxy.h"
 | |
| @@ -130,4 +135,11 @@ void WKInspectorToggleElementSelection(WKInspectorRef inspectorRef)
 | |
|      toImpl(inspectorRef)->toggleElementSelection();
 | |
|  }
 | |
|  
 | |
| +void WKInspectorInitializeRemoteInspectorPipe(ConfigureDataStoreCallback configureDataStore, CreatePageCallback createPage, QuitCallback quit)
 | |
| +{
 | |
| +#if PLATFORM(WIN)
 | |
| +    initializeBrowserInspectorPipe(makeUnique<InspectorPlaywrightAgentClientWin>(configureDataStore, createPage, quit));
 | |
| +#endif
 | |
| +}
 | |
| +
 | |
|  #endif // !PLATFORM(IOS_FAMILY)
 | |
| diff --git a/Source/WebKit/UIProcess/API/C/WKInspector.h b/Source/WebKit/UIProcess/API/C/WKInspector.h
 | |
| index 026121d114c5fcad84c1396be8d692625beaa3bd..edd6e5cae033124c589959a42522fde07a42fdf6 100644
 | |
| --- a/Source/WebKit/UIProcess/API/C/WKInspector.h
 | |
| +++ b/Source/WebKit/UIProcess/API/C/WKInspector.h
 | |
| @@ -66,6 +66,10 @@ WK_EXPORT void WKInspectorTogglePageProfiling(WKInspectorRef inspector);
 | |
|  WK_EXPORT bool WKInspectorIsElementSelectionActive(WKInspectorRef inspector);
 | |
|  WK_EXPORT void WKInspectorToggleElementSelection(WKInspectorRef inspector);
 | |
|  
 | |
| +typedef void (*ConfigureDataStoreCallback)(WKWebsiteDataStoreRef dataStore);
 | |
| +typedef WKPageRef (*CreatePageCallback)(WKPageConfigurationRef configuration);
 | |
| +typedef void (*QuitCallback)();
 | |
| +WK_EXPORT void WKInspectorInitializeRemoteInspectorPipe(ConfigureDataStoreCallback, CreatePageCallback, QuitCallback);
 | |
|  #ifdef __cplusplus
 | |
|  }
 | |
|  #endif
 | |
| diff --git a/Source/WebKit/UIProcess/API/C/WKPage.cpp b/Source/WebKit/UIProcess/API/C/WKPage.cpp
 | |
| index ba2feecd2885acc45dd153ff502d49f7650f2c6d..9c4bb27242bfa23a91122d899200a1f1ce151fdb 100644
 | |
| --- a/Source/WebKit/UIProcess/API/C/WKPage.cpp
 | |
| +++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp
 | |
| @@ -1689,6 +1689,13 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient
 | |
|              completionHandler(String());
 | |
|          }
 | |
|  
 | |
| +        void handleJavaScriptDialog(WebPageProxy& page, bool accept, const String& value) final {
 | |
| +            if (m_client.handleJavaScriptDialog) {
 | |
| +                m_client.handleJavaScriptDialog(toAPI(&page), accept, toAPI(value.impl()), m_client.base.clientInfo);
 | |
| +                return;
 | |
| +            }
 | |
| +        }
 | |
| +
 | |
|          void setStatusText(WebPageProxy* page, const String& text) final
 | |
|          {
 | |
|              if (!m_client.setStatusText)
 | |
| @@ -1749,6 +1756,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient
 | |
|          {
 | |
|              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/C/WKWebsiteDataStoreRef.cpp b/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
 | |
| index be5030797402d00ba0e0bc371e52c8c1d47b1ca1..eb61db48a546955f39c10b4dfa631a198539ac09 100644
 | |
| --- a/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
 | |
| +++ b/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
 | |
| @@ -31,6 +31,7 @@
 | |
|  #include "ShouldGrandfatherStatistics.h"
 | |
|  #include "WKAPICast.h"
 | |
|  #include "WKDictionary.h"
 | |
| +#include "WKMutableArray.h"
 | |
|  #include "WKNumber.h"
 | |
|  #include "WKRetainPtr.h"
 | |
|  #include "WKSecurityOriginRef.h"
 | |
| @@ -633,7 +634,7 @@ void WKWebsiteDataStoreSetResourceLoadStatisticsToSameSiteStrictCookiesForTestin
 | |
|  void WKWebsiteDataStoreSetAppBoundDomainsForTesting(WKArrayRef originURLsRef, void* context, WKWebsiteDataStoreSetAppBoundDomainsForTestingFunction completionHandler)
 | |
|  {
 | |
|  #if PLATFORM(COCOA)
 | |
| -    RefPtr<API::Array> originURLsArray = toImpl(originURLsRef);
 | |
| +    RefPtr<API::Array> originURLsArray = WebKit::toImpl(originURLsRef);
 | |
|      size_t newSize = originURLsArray ? originURLsArray->size() : 0;
 | |
|      HashSet<WebCore::RegistrableDomain> domains;
 | |
|      domains.reserveInitialCapacity(newSize);
 | |
| @@ -824,7 +825,7 @@ void WKWebsiteDataStoreClearBundleIdentifierInNetworkProcess(WKWebsiteDataStoreR
 | |
|  void WKWebsiteDataStoreGetAllStorageAccessEntries(WKWebsiteDataStoreRef dataStoreRef, WKPageRef pageRef, void* context, WKWebsiteDataStoreGetAllStorageAccessEntriesFunction callback)
 | |
|  {
 | |
|  #if ENABLE(RESOURCE_LOAD_STATISTICS)
 | |
| -    WebKit::toImpl(dataStoreRef)->getAllStorageAccessEntries(toImpl(pageRef)->identifier(), [context, callback] (Vector<String>&& domains) {
 | |
| +    WebKit::toImpl(dataStoreRef)->getAllStorageAccessEntries(WebKit::toImpl(pageRef)->identifier(), [context, callback] (Vector<String>&& domains) {
 | |
|          auto domainArrayRef = WKMutableArrayCreate();
 | |
|          for (auto domain : domains)
 | |
|              WKArrayAppendItem(domainArrayRef, adoptWK(WKStringCreateWithUTF8CString(domain.utf8().data())).get());
 | |
| diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm b/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm
 | |
| index 7b9469ee130d1b62c8b8187bd25748b42c40a352..dab2ff1ebaa7a9c13efe5ae75779f1c8efe19fc0 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>
 | |
| @@ -85,6 +86,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 c0a84a1bfcfba85455988d20a18d381eb273f6da..513868305c4c1884b7effdd09e25fb6b79c0664f 100644
 | |
| --- a/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h
 | |
| +++ b/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h
 | |
| @@ -38,6 +38,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 591428f7f579e76ff01bc94b83f5994af8e48e00..03fc6cf2d3074d9227d7815ac5c72fdb33e8a694 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..5fabe06a3289689246c36dfd96eb9900a48b2b0f
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h
 | |
| @@ -0,0 +1,55 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#import <WebKit/WKFoundation.h>
 | |
| +#import <WebKit/WKProcessPool.h>
 | |
| +#import <WebKit/WKWebsiteDataStore.h>
 | |
| +#import <Foundation/Foundation.h>
 | |
| +
 | |
| +NS_ASSUME_NONNULL_BEGIN
 | |
| +
 | |
| +@class WKWebView;
 | |
| +
 | |
| +WK_CLASS_AVAILABLE(macos(10.14.0))
 | |
| +@interface _WKBrowserContext : NSObject
 | |
| +@property (nonatomic, strong) WKWebsiteDataStore *dataStore;
 | |
| +@property (nonatomic, strong) WKProcessPool *processPool;
 | |
| +@end
 | |
| +
 | |
| +@protocol _WKBrowserInspectorDelegate <NSObject>
 | |
| +- (WKWebView *)createNewPage:(uint64_t)sessionID;
 | |
| +- (_WKBrowserContext *)createBrowserContext:(NSString *)proxyServer WithBypassList:(NSString *)proxyBypassList;
 | |
| +- (void)deleteBrowserContext:(uint64_t)sessionID;
 | |
| +- (void)quit;
 | |
| +@end
 | |
| +
 | |
| +WK_CLASS_AVAILABLE(macos(10.14.0))
 | |
| +@interface _WKBrowserInspector : NSObject
 | |
| ++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless;
 | |
| +@end
 | |
| +
 | |
| +
 | |
| +NS_ASSUME_NONNULL_END
 | |
| +
 | |
| diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..e7143513ea2be8e1cdab5c86a28643fffea626dd
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm
 | |
| @@ -0,0 +1,60 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "_WKBrowserInspector.h"
 | |
| +
 | |
| +#include "BrowserInspectorPipe.h"
 | |
| +#include "InspectorPlaywrightAgentClientMac.h"
 | |
| +#include "PageClientImplMac.h"
 | |
| +#include "WebKit2Initialize.h"
 | |
| +
 | |
| +#import "WKWebView.h"
 | |
| +
 | |
| +using namespace WebKit;
 | |
| +
 | |
| +@implementation _WKBrowserInspector
 | |
| +
 | |
| ++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless
 | |
| +{
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +    InitializeWebKit2();
 | |
| +    PageClientImpl::setHeadless(headless);
 | |
| +    initializeBrowserInspectorPipe(makeUnique<InspectorPlaywrightAgentClientMac>(delegate));
 | |
| +#endif
 | |
| +}
 | |
| +
 | |
| +@end
 | |
| +
 | |
| +@implementation _WKBrowserContext
 | |
| +- (void)dealloc
 | |
| +{
 | |
| +    [_dataStore release];
 | |
| +    [_processPool release];
 | |
| +    _dataStore = nil;
 | |
| +    _processPool = nil;
 | |
| +    [super dealloc];
 | |
| +}
 | |
| +@end
 | |
| diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
 | |
| index df2b919c9ba18cc9cc0471a4334eb85c45e3820e..b5a73c8d6863217da0edb97688d17a7debab3c11 100644
 | |
| --- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
 | |
| +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
 | |
| @@ -62,6 +62,7 @@ WK_CLASS_AVAILABLE(macos(10.10), ios(8.0))
 | |
|  #endif
 | |
|  @property (nonatomic) pid_t presentingApplicationPID WK_API_AVAILABLE(macos(10.13), ios(11.0));
 | |
|  @property (nonatomic) BOOL processSwapsOnNavigation WK_API_AVAILABLE(macos(10.14), ios(12.0));
 | |
| +@property (nonatomic) BOOL forceOverlayScrollbars WK_API_AVAILABLE(macos(10.14));
 | |
|  @property (nonatomic) BOOL alwaysKeepAndReuseSwappedProcesses WK_API_AVAILABLE(macos(10.14), ios(12.0));
 | |
|  @property (nonatomic) BOOL processSwapsOnWindowOpenWithOpener WK_API_AVAILABLE(macos(10.14), ios(12.0));
 | |
|  @property (nonatomic) BOOL prewarmsProcessesAutomatically WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
 | |
| diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
 | |
| index 9c6aa9a080acd3e9e3a4a744141bb5caab9504ba..27f385dd1e823cd59b16d3df6e7bea2742092719 100644
 | |
| --- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
 | |
| +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
 | |
| @@ -231,6 +231,16 @@
 | |
|      return _processPoolConfiguration->processSwapsOnNavigation();
 | |
|  }
 | |
|  
 | |
| +- (void)setForceOverlayScrollbars:(BOOL)force
 | |
| +{
 | |
| +    _processPoolConfiguration->setForceOverlayScrollbars(force);
 | |
| +}
 | |
| +
 | |
| +- (BOOL)forceOverlayScrollbars
 | |
| +{
 | |
| +    return _processPoolConfiguration->forceOverlayScrollbars();
 | |
| +}
 | |
| +
 | |
|  - (void)setPrewarmsProcessesAutomatically:(BOOL)prewarms
 | |
|  {
 | |
|      _processPoolConfiguration->setIsAutomaticProcessWarmingEnabled(prewarms);
 | |
| diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm
 | |
| index 66bf24df826daa8e7284248fd1b728cb5ebff343..d40f4f4be2bf76fa300cb54a06e81ff5a1e18d16 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..54529a23f53cebe6f8a96873ca6c2f31f0481ae0
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp
 | |
| @@ -0,0 +1,158 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "WebKitBrowserInspector.h"
 | |
| +
 | |
| +#include "BrowserInspectorPipe.h"
 | |
| +#include "InspectorPlaywrightAgentClientGLib.h"
 | |
| +#include "WebKitBrowserInspectorPrivate.h"
 | |
| +#include "WebKitWebViewPrivate.h"
 | |
| +#include <wtf/glib/GRefPtr.h>
 | |
| +#include <wtf/glib/WTFGType.h>
 | |
| +
 | |
| +/**
 | |
| + * SECTION: WebKitBrowserInspector
 | |
| + * @Short_description: Access to the WebKit browser inspector
 | |
| + * @Title: WebKitBrowserInspector
 | |
| + *
 | |
| + * The WebKit Browser Inspector is an experimental API that provides
 | |
| + * access to the inspector via the remote debugging protocol. The protocol
 | |
| + * allows to create ephemeral contexts and create pages in them and then
 | |
| + * manipulate them using the inspector commands. This may be useful for
 | |
| + * the browser automation or remote debugging.
 | |
| + *
 | |
| + * Currently the protocol can be exposed to the parent process via a unix
 | |
| + * pipe.
 | |
| + */
 | |
| +
 | |
| +enum {
 | |
| +    CREATE_NEW_PAGE,
 | |
| +    QUIT_APPLICATION,
 | |
| +
 | |
| +    LAST_SIGNAL
 | |
| +};
 | |
| +
 | |
| +struct _WebKitBrowserInspectorPrivate {
 | |
| +    int unused { 0 };
 | |
| +};
 | |
| +
 | |
| +WEBKIT_DEFINE_TYPE(WebKitBrowserInspector, webkit_browser_inspector, G_TYPE_OBJECT)
 | |
| +
 | |
| +static guint signals[LAST_SIGNAL] = { 0, };
 | |
| +
 | |
| +static void webkit_browser_inspector_class_init(WebKitBrowserInspectorClass* findClass)
 | |
| +{
 | |
| +    GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass);
 | |
| +
 | |
| +    /**
 | |
| +     * WebKitBrowserInspector::create-new-page:
 | |
| +     * @inspector: the #WebKitBrowserInspector on which the signal is emitted
 | |
| +     *
 | |
| +     * Emitted when the inspector is requested to create a new page in the provided
 | |
| +     * #WebKitWebContext.
 | |
| +     *
 | |
| +     * This signal is emitted when inspector receives 'Browser.createPage' command
 | |
| +     * from its remote client. If the signal is not handled the command will fail.
 | |
| +     *
 | |
| +     * Returns: %WebKitWebView that contains created page.
 | |
| +     */
 | |
| +    signals[CREATE_NEW_PAGE] = g_signal_new(
 | |
| +        "create-new-page",
 | |
| +        G_TYPE_FROM_CLASS(gObjectClass),
 | |
| +        G_SIGNAL_RUN_LAST,
 | |
| +        G_STRUCT_OFFSET(WebKitBrowserInspectorClass, create_new_page),
 | |
| +        nullptr, nullptr,
 | |
| +        g_cclosure_marshal_generic,
 | |
| +#if PLATFORM(GTK)
 | |
| +        GTK_TYPE_WIDGET,
 | |
| +#else
 | |
| +        WEBKIT_TYPE_WEB_VIEW,
 | |
| +#endif
 | |
| +        1,
 | |
| +        WEBKIT_TYPE_WEB_CONTEXT);
 | |
| +
 | |
| +    /**
 | |
| +     * WebKitBrowserInspector::quit-application:
 | |
| +     * @inspector: the #WebKitBrowserInspector on which the signal is emitted
 | |
| +     *
 | |
| +     * Emitted when the inspector is requested to close the browser application.
 | |
| +     *
 | |
| +     * This signal is emitted when inspector receives 'Browser.close' command
 | |
| +     * from its remote client. If the signal is not handled the command will fail.
 | |
| +     */
 | |
| +    signals[QUIT_APPLICATION] = g_signal_new(
 | |
| +        "quit-application",
 | |
| +        G_TYPE_FROM_CLASS(gObjectClass),
 | |
| +        G_SIGNAL_RUN_LAST,
 | |
| +        G_STRUCT_OFFSET(WebKitBrowserInspectorClass, quit_application),
 | |
| +        nullptr, nullptr,
 | |
| +        g_cclosure_marshal_VOID__VOID,
 | |
| +        G_TYPE_NONE, 0);
 | |
| +}
 | |
| +
 | |
| +WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext* context)
 | |
| +{
 | |
| +    WebKitWebView* newWebView;
 | |
| +    g_signal_emit(webkit_browser_inspector_get_default(), signals[CREATE_NEW_PAGE], 0, context, &newWebView);
 | |
| +    if (!newWebView)
 | |
| +        return nullptr;
 | |
| +    return  &webkitWebViewGetPage(newWebView);
 | |
| +}
 | |
| +
 | |
| +void webkitBrowserInspectorQuitApplication()
 | |
| +{
 | |
| +    g_signal_emit(webkit_browser_inspector_get_default(), signals[QUIT_APPLICATION], 0, NULL);
 | |
| +}
 | |
| +
 | |
| +static gpointer createWebKitBrowserInspector(gpointer)
 | |
| +{
 | |
| +    static GRefPtr<WebKitBrowserInspector> browserInspector = adoptGRef(WEBKIT_BROWSER_INSPECTOR(g_object_new(WEBKIT_TYPE_BROWSER_INSPECTOR, nullptr)));
 | |
| +    return browserInspector.get();
 | |
| +}
 | |
| +
 | |
| +/**
 | |
| + * webkit_browser_inspector_get_default:
 | |
| + *
 | |
| + * Gets the default instance of the browser inspector.
 | |
| + *
 | |
| + * Returns: (transfer none): a #WebKitBrowserInspector
 | |
| + */
 | |
| +WebKitBrowserInspector* webkit_browser_inspector_get_default(void)
 | |
| +{
 | |
| +    static GOnce onceInit = G_ONCE_INIT;
 | |
| +    return WEBKIT_BROWSER_INSPECTOR(g_once(&onceInit, createWebKitBrowserInspector, 0));
 | |
| +}
 | |
| +
 | |
| +/**
 | |
| + * webkit_browser_inspector_initialize_pipe:
 | |
| + *
 | |
| + * Creates browser inspector and configures pipe handler to communicate with
 | |
| + * the parent process.
 | |
| + */
 | |
| +void webkit_browser_inspector_initialize_pipe(const char* defaultProxyURI, const char* const* ignoreHosts)
 | |
| +{
 | |
| +    WebKit::initializeBrowserInspectorPipe(makeUnique<WebKit::InspectorPlaywrightAgentClientGlib>(defaultProxyURI, ignoreHosts));
 | |
| +}
 | |
| diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..e0b1da48465c850f541532ed961d1b778bea6028
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h
 | |
| @@ -0,0 +1,32 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#include "WebKitBrowserInspector.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +
 | |
| +WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext*);
 | |
| +void webkitBrowserInspectorQuitApplication();
 | |
| diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
 | |
| index 2ceb2b4f49f409bbe6e6810115e36d0c84f83b5d..16d2062b746b80ace6f39d779e9c3b8796b581b1 100644
 | |
| --- a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
 | |
| +++ b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
 | |
| @@ -93,6 +93,10 @@ private:
 | |
|      {
 | |
|          webkitWebViewRunJavaScriptPrompt(m_webView, message.utf8(), defaultValue.utf8(), WTFMove(completionHandler));
 | |
|      }
 | |
| +    void handleJavaScriptDialog(WebPageProxy&, bool accept, const String& value) final
 | |
| +    {
 | |
| +        webkitWebViewHandleJavaScriptDialog(m_webView, accept, value);
 | |
| +    }
 | |
|  
 | |
|      bool canRunBeforeUnloadConfirmPanel() const final { return true; }
 | |
|  
 | |
| diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
 | |
| index c4c7d0f6c1261b51d02071a652aa093d1aa3b9d1..3e4a941ea4360b96cf1b8eb808e57ae030f148e6 100644
 | |
| --- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
 | |
| +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
 | |
| @@ -120,8 +120,8 @@ enum {
 | |
|      PROP_LOCAL_STORAGE_DIRECTORY,
 | |
|  #endif
 | |
|      PROP_WEBSITE_DATA_MANAGER,
 | |
| -#if PLATFORM(GTK)
 | |
|      PROP_PSON_ENABLED,
 | |
| +#if PLATFORM(GTK)
 | |
|  #if !USE(GTK4)
 | |
|      PROP_USE_SYSYEM_APPEARANCE_FOR_SCROLLBARS
 | |
|  #endif
 | |
| @@ -206,8 +206,8 @@ struct _WebKitWebContextPrivate {
 | |
|  
 | |
|      RefPtr<WebProcessPool> processPool;
 | |
|      bool clientsDetached;
 | |
| -#if PLATFORM(GTK)
 | |
|      bool psonEnabled;
 | |
| +#if PLATFORM(GTK)
 | |
|  #if !USE(GTK4)
 | |
|      bool useSystemAppearanceForScrollbars;
 | |
|  #endif
 | |
| @@ -307,11 +307,9 @@ WEBKIT_DEFINE_TYPE(WebKitWebContext, webkit_web_context, G_TYPE_OBJECT)
 | |
|  
 | |
|  static const char* injectedBundleDirectory()
 | |
|  {
 | |
| -#if ENABLE(DEVELOPER_MODE)
 | |
|      const char* bundleDirectory = g_getenv("WEBKIT_INJECTED_BUNDLE_PATH");
 | |
|      if (bundleDirectory && g_file_test(bundleDirectory, G_FILE_TEST_IS_DIR))
 | |
|          return bundleDirectory;
 | |
| -#endif
 | |
|  
 | |
|  #if PLATFORM(GTK)
 | |
|      static const char* injectedBundlePath = LIBDIR G_DIR_SEPARATOR_S "webkit2gtk-" WEBKITGTK_API_VERSION_STRING
 | |
| @@ -336,10 +334,10 @@ static void webkitWebContextGetProperty(GObject* object, guint propID, GValue* v
 | |
|      case PROP_WEBSITE_DATA_MANAGER:
 | |
|          g_value_set_object(value, webkit_web_context_get_website_data_manager(context));
 | |
|          break;
 | |
| -#if PLATFORM(GTK)
 | |
|      case PROP_PSON_ENABLED:
 | |
|          g_value_set_boolean(value, context->priv->psonEnabled);
 | |
|          break;
 | |
| +#if PLATFORM(GTK)
 | |
|  #if !USE(GTK4)
 | |
|      case PROP_USE_SYSYEM_APPEARANCE_FOR_SCROLLBARS:
 | |
|          g_value_set_boolean(value, webkit_web_context_get_use_system_appearance_for_scrollbars(context));
 | |
| @@ -366,10 +364,10 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa
 | |
|          context->priv->websiteDataManager = manager ? WEBKIT_WEBSITE_DATA_MANAGER(manager) : nullptr;
 | |
|          break;
 | |
|      }
 | |
| -#if PLATFORM(GTK)
 | |
|      case PROP_PSON_ENABLED:
 | |
|          context->priv->psonEnabled = g_value_get_boolean(value);
 | |
|          break;
 | |
| +#if PLATFORM(GTK)
 | |
|  #if !USE(GTK4)
 | |
|      case PROP_USE_SYSYEM_APPEARANCE_FOR_SCROLLBARS:
 | |
|          webkit_web_context_set_use_system_appearance_for_scrollbars(context, g_value_get_boolean(value));
 | |
| @@ -381,10 +379,19 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa
 | |
|      }
 | |
|  }
 | |
|  
 | |
| +static int webkitWebContext = 0;
 | |
| +
 | |
| +int webkitWebContextExistingCount()
 | |
| +{
 | |
| +    return webkitWebContext;
 | |
| +}
 | |
| +
 | |
|  static void webkitWebContextConstructed(GObject* object)
 | |
|  {
 | |
|      G_OBJECT_CLASS(webkit_web_context_parent_class)->constructed(object);
 | |
|  
 | |
| +    ++webkitWebContext;
 | |
| +
 | |
|      GUniquePtr<char> bundleFilename(g_build_filename(injectedBundleDirectory(), INJECTED_BUNDLE_FILENAME, nullptr));
 | |
|  
 | |
|      WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(object);
 | |
| @@ -392,8 +399,8 @@ static void webkitWebContextConstructed(GObject* object)
 | |
|  
 | |
|      API::ProcessPoolConfiguration configuration;
 | |
|      configuration.setInjectedBundlePath(FileSystem::stringFromFileSystemRepresentation(bundleFilename.get()));
 | |
| -#if PLATFORM(GTK)
 | |
|      configuration.setProcessSwapsOnNavigation(priv->psonEnabled);
 | |
| +#if PLATFORM(GTK)
 | |
|  #if !USE(GTK4)
 | |
|      configuration.setUseSystemAppearanceForScrollbars(priv->useSystemAppearanceForScrollbars);
 | |
|  #endif
 | |
| @@ -405,6 +412,11 @@ static void webkitWebContextConstructed(GObject* object)
 | |
|      if (!webkit_website_data_manager_is_ephemeral(priv->websiteDataManager.get()))
 | |
|          configuration.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) {
 | |
| @@ -439,6 +451,8 @@ static void webkitWebContextConstructed(GObject* object)
 | |
|  
 | |
|  static void webkitWebContextDispose(GObject* object)
 | |
|  {
 | |
| +    --webkitWebContext;
 | |
| +
 | |
|      WebKitWebContextPrivate* priv = WEBKIT_WEB_CONTEXT(object)->priv;
 | |
|      if (!priv->clientsDetached) {
 | |
|          priv->clientsDetached = true;
 | |
| @@ -516,7 +530,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:
 | |
|       *
 | |
| @@ -540,6 +553,7 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass
 | |
|              FALSE,
 | |
|              static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
 | |
|  
 | |
| +#if PLATFORM(GTK)
 | |
|  #if !USE(GTK4)
 | |
|      /**
 | |
|       * WebKitWebContext:use-system-appearance-for-scrollbars:
 | |
| diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h
 | |
| index 78d1578f94793e9e59a3d4d2b33e79ea8530fa04..493cdadac3873508b3efa3048638e73a13f4c976 100644
 | |
| --- a/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h
 | |
| +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h
 | |
| @@ -45,3 +45,4 @@ void webkitWebContextInitializeNotificationPermissions(WebKitWebContext*);
 | |
|  #if ENABLE(REMOTE_INSPECTOR)
 | |
|  void webkitWebContextWillCloseAutomationSession(WebKitWebContext*);
 | |
|  #endif
 | |
| +int webkitWebContextExistingCount();
 | |
| diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
 | |
| index 7b87c43647592c2136ceb8f21ab5152b2cef9f09..d69ba599135333abfa9d72340139dab3d2db4203 100644
 | |
| --- a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
 | |
| +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
 | |
| @@ -31,6 +31,7 @@
 | |
|  #include "WebCertificateInfo.h"
 | |
|  #include "WebContextMenuItem.h"
 | |
|  #include "WebContextMenuItemData.h"
 | |
| +#include "WebPageInspectorController.h"
 | |
|  #include "WebKitAuthenticationRequestPrivate.h"
 | |
|  #include "WebKitBackForwardListPrivate.h"
 | |
|  #include "WebKitContextMenuClient.h"
 | |
| @@ -132,6 +133,7 @@ enum {
 | |
|      CLOSE,
 | |
|  
 | |
|      SCRIPT_DIALOG,
 | |
| +    SCRIPT_DIALOG_HANDLED,
 | |
|  
 | |
|      DECIDE_POLICY,
 | |
|      PERMISSION_REQUEST,
 | |
| @@ -435,6 +437,9 @@ void WebKitWebViewClient::handleDownloadRequest(WKWPE::View&, DownloadProxy& dow
 | |
|  
 | |
|  void WebKitWebViewClient::frameDisplayed(WKWPE::View&)
 | |
|  {
 | |
| +    if (RefPtr<cairo_surface_t> surface = adoptRef(webkitWebViewBackendTakeScreenshot(m_webView->priv->backend.get())))
 | |
| +        getPage(m_webView).inspectorController().didPaint(surface.get());
 | |
| +
 | |
|      {
 | |
|          SetForScope<bool> inFrameDisplayedGuard(m_webView->priv->inFrameDisplayed, true);
 | |
|          for (const auto& callback : m_webView->priv->frameDisplayedCallbacks) {
 | |
| @@ -465,6 +470,7 @@ void WebKitWebViewClient::didReceiveUserMessage(WKWPE::View&, UserMessage&& mess
 | |
|  {
 | |
|      webkitWebViewDidReceiveUserMessage(m_webView, WTFMove(message), WTFMove(completionHandler));
 | |
|  }
 | |
| +
 | |
|  #endif
 | |
|  
 | |
|  static gboolean webkitWebViewLoadFail(WebKitWebView* webView, WebKitLoadEvent, const char* failingURI, GError* error)
 | |
| @@ -1590,6 +1596,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
 | |
| @@ -2470,6 +2485,23 @@ void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const
 | |
|      webkit_script_dialog_unref(webView->priv->currentScriptDialog);
 | |
|  }
 | |
|  
 | |
| +void webkitWebViewHandleJavaScriptDialog(WebKitWebView* webView, bool accept, const String& value) {
 | |
| +    auto* dialog = webView->priv->currentScriptDialog;
 | |
| +#if PLATFORM(WPE)
 | |
| +    dialog->isUserHandled = false;
 | |
| +#endif
 | |
| +    webkit_script_dialog_ref(dialog);
 | |
| +    if (!value.isNull())
 | |
| +        webkitWebViewSetCurrentScriptDialogUserInput(webView, value);
 | |
| +    if (accept)
 | |
| +        webkitWebViewAcceptCurrentScriptDialog(webView);
 | |
| +    else
 | |
| +        webkitWebViewDismissCurrentScriptDialog(webView);
 | |
| +    gboolean returnValue;
 | |
| +    g_signal_emit(webView, signals[SCRIPT_DIALOG_HANDLED], 0, dialog, &returnValue);
 | |
| +    webkit_script_dialog_unref(dialog);
 | |
| +}
 | |
| +
 | |
|  bool webkitWebViewIsShowingScriptDialog(WebKitWebView* webView)
 | |
|  {
 | |
|      if (!webView->priv->currentScriptDialog)
 | |
| diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h
 | |
| index b9e56fc55fd7dfa821f789264b0c15f9b4c7b412..4138d5b42077f735264ac7a168cce329ebaa89c3 100644
 | |
| --- a/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h
 | |
| +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h
 | |
| @@ -60,6 +60,7 @@ void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message, Fun
 | |
|  void webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message, Function<void(bool)>&& completionHandler);
 | |
|  void webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText, Function<void(const String&)>&& completionHandler);
 | |
|  void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView*, const CString& message, Function<void(bool)>&& completionHandler);
 | |
| +void webkitWebViewHandleJavaScriptDialog(WebKitWebView*, bool accept, const String& value);
 | |
|  bool webkitWebViewIsShowingScriptDialog(WebKitWebView*);
 | |
|  bool webkitWebViewIsScriptDialogRunning(WebKitWebView*, WebKitScriptDialog*);
 | |
|  String webkitWebViewGetCurrentScriptDialogMessage(WebKitWebView*);
 | |
| diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
 | |
| index 0aee4bc9380cb47ca4900d8556d51e24d8f14be7..82d1d747a224141e9f006c634b7bfac2f89e5ed0 100644
 | |
| --- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
 | |
| +++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
 | |
| @@ -241,6 +241,8 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool
 | |
|  {
 | |
|      if (wasEventHandled || event.type() != WebEvent::Type::KeyDown || !event.nativeEvent())
 | |
|          return;
 | |
| +    if (!event.nativeEvent())
 | |
| +        return;
 | |
|  
 | |
|      WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(m_viewWidget);
 | |
|      webkitWebViewBaseForwardNextKeyEvent(webkitWebViewBase);
 | |
| diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..9f1a0173a5641d6f158d815b8f7b9ea66f65c26d
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h
 | |
| @@ -0,0 +1,81 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION)
 | |
| +#error "Only <webkit2/webkit2.h> can be included directly."
 | |
| +#endif
 | |
| +
 | |
| +#ifndef WebKitBrowserInspector_h
 | |
| +#define WebKitBrowserInspector_h
 | |
| +
 | |
| +#include <glib-object.h>
 | |
| +#include <webkit2/WebKitDefines.h>
 | |
| +#include <webkit2/WebKitWebView.h>
 | |
| +
 | |
| +G_BEGIN_DECLS
 | |
| +
 | |
| +#define WEBKIT_TYPE_BROWSER_INSPECTOR            (webkit_browser_inspector_get_type())
 | |
| +#define WEBKIT_BROWSER_INSPECTOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspector))
 | |
| +#define WEBKIT_IS_BROWSER_INSPECTOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_BROWSER_INSPECTOR))
 | |
| +#define WEBKIT_BROWSER_INSPECTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass))
 | |
| +#define WEBKIT_IS_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  WEBKIT_TYPE_BROWSER_INSPECTOR))
 | |
| +#define WEBKIT_BROWSER_INSPECTOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass))
 | |
| +
 | |
| +typedef struct _WebKitBrowserInspector        WebKitBrowserInspector;
 | |
| +typedef struct _WebKitBrowserInspectorClass   WebKitBrowserInspectorClass;
 | |
| +typedef struct _WebKitBrowserInspectorPrivate WebKitBrowserInspectorPrivate;
 | |
| +
 | |
| +struct _WebKitBrowserInspector {
 | |
| +    GObject parent;
 | |
| +
 | |
| +    WebKitBrowserInspectorPrivate *priv;
 | |
| +};
 | |
| +
 | |
| +struct _WebKitBrowserInspectorClass {
 | |
| +    GObjectClass parent_class;
 | |
| +
 | |
| +    WebKitWebView *(* create_new_page)           (WebKitBrowserInspector    *browser_inspector,
 | |
| +                                                  WebKitWebContext          *context);
 | |
| +    WebKitWebView *(* quit_application)          (WebKitBrowserInspector    *browser_inspector);
 | |
| +
 | |
| +    void (*_webkit_reserved0) (void);
 | |
| +    void (*_webkit_reserved1) (void);
 | |
| +    void (*_webkit_reserved2) (void);
 | |
| +    void (*_webkit_reserved3) (void);
 | |
| +};
 | |
| +
 | |
| +WEBKIT_API GType
 | |
| +webkit_browser_inspector_get_type                     (void);
 | |
| +
 | |
| +WEBKIT_API WebKitBrowserInspector *
 | |
| +webkit_browser_inspector_get_default                  (void);
 | |
| +
 | |
| +WEBKIT_API void
 | |
| +webkit_browser_inspector_initialize_pipe              (const char* defaultProxyURI,
 | |
| +                                                       const char* const* ignoreHosts);
 | |
| +
 | |
| +G_END_DECLS
 | |
| +
 | |
| +#endif
 | |
| diff --git a/Source/WebKit/UIProcess/API/gtk/webkit2.h b/Source/WebKit/UIProcess/API/gtk/webkit2.h
 | |
| index c358118360a38c7b462227aa4ab8388bd7942c3e..70bdfbda231b481e8c5ac34fe6d8825f2350d71e 100644
 | |
| --- a/Source/WebKit/UIProcess/API/gtk/webkit2.h
 | |
| +++ b/Source/WebKit/UIProcess/API/gtk/webkit2.h
 | |
| @@ -32,6 +32,7 @@
 | |
|  #include <webkit2/WebKitAutomationSession.h>
 | |
|  #include <webkit2/WebKitBackForwardList.h>
 | |
|  #include <webkit2/WebKitBackForwardListItem.h>
 | |
| +#include <webkit2/WebKitBrowserInspector.h>
 | |
|  #include <webkit2/WebKitContextMenu.h>
 | |
|  #include <webkit2/WebKitContextMenuActions.h>
 | |
|  #include <webkit2/WebKitContextMenuItem.h>
 | |
| diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp
 | |
| index c8b41f407774d2337e99cc7f9151ec65be3fc532..22faf21f9a7946a7898cedfc1b6ec1316110a166 100644
 | |
| --- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp
 | |
| +++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp
 | |
| @@ -194,7 +194,7 @@ WebCore::IntPoint PageClientImpl::accessibilityScreenToRootView(const WebCore::I
 | |
|  
 | |
|  WebCore::IntRect PageClientImpl::rootViewToAccessibilityScreen(const WebCore::IntRect& rect)
 | |
|  {
 | |
| -    return rootViewToScreen(rect);    
 | |
| +    return rootViewToScreen(rect);
 | |
|  }
 | |
|  
 | |
|  void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool)
 | |
| diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..cb1a540d341b07581ec87b922b7d007ce45ba989
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h
 | |
| @@ -0,0 +1,81 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#if !defined(__WEBKIT_H_INSIDE__) && !defined(WEBKIT2_COMPILATION)
 | |
| +#error "Only <wpe/webkit.h> can be included directly."
 | |
| +#endif
 | |
| +
 | |
| +#ifndef WebKitBrowserInspector_h
 | |
| +#define WebKitBrowserInspector_h
 | |
| +
 | |
| +#include <glib-object.h>
 | |
| +#include <wpe/WebKitDefines.h>
 | |
| +#include <wpe/WebKitWebView.h>
 | |
| +
 | |
| +G_BEGIN_DECLS
 | |
| +
 | |
| +#define WEBKIT_TYPE_BROWSER_INSPECTOR            (webkit_browser_inspector_get_type())
 | |
| +#define WEBKIT_BROWSER_INSPECTOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspector))
 | |
| +#define WEBKIT_IS_BROWSER_INSPECTOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_BROWSER_INSPECTOR))
 | |
| +#define WEBKIT_BROWSER_INSPECTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass))
 | |
| +#define WEBKIT_IS_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  WEBKIT_TYPE_BROWSER_INSPECTOR))
 | |
| +#define WEBKIT_BROWSER_INSPECTOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass))
 | |
| +
 | |
| +typedef struct _WebKitBrowserInspector        WebKitBrowserInspector;
 | |
| +typedef struct _WebKitBrowserInspectorClass   WebKitBrowserInspectorClass;
 | |
| +typedef struct _WebKitBrowserInspectorPrivate WebKitBrowserInspectorPrivate;
 | |
| +
 | |
| +struct _WebKitBrowserInspector {
 | |
| +    GObject parent;
 | |
| +
 | |
| +    WebKitBrowserInspectorPrivate *priv;
 | |
| +};
 | |
| +
 | |
| +struct _WebKitBrowserInspectorClass {
 | |
| +    GObjectClass parent_class;
 | |
| +
 | |
| +    WebKitWebView *(* create_new_page)           (WebKitBrowserInspector    *browser_inspector,
 | |
| +                                                  WebKitWebContext          *context);
 | |
| +    WebKitWebView *(* quit_application)          (WebKitBrowserInspector    *browser_inspector);
 | |
| +
 | |
| +    void (*_webkit_reserved0) (void);
 | |
| +    void (*_webkit_reserved1) (void);
 | |
| +    void (*_webkit_reserved2) (void);
 | |
| +    void (*_webkit_reserved3) (void);
 | |
| +};
 | |
| +
 | |
| +WEBKIT_API GType
 | |
| +webkit_browser_inspector_get_type                     (void);
 | |
| +
 | |
| +WEBKIT_API WebKitBrowserInspector *
 | |
| +webkit_browser_inspector_get_default                  (void);
 | |
| +
 | |
| +WEBKIT_API void
 | |
| +webkit_browser_inspector_initialize_pipe              (const char* defaultProxyURI,
 | |
| +                                                       const char* const* ignoreHosts);
 | |
| +
 | |
| +G_END_DECLS
 | |
| +
 | |
| +#endif
 | |
| diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp
 | |
| index e0fc205b39095cf8aae201a1dcca520461c60de4..872186ad99a7b82f0c61705ff6c5ae4453e5e1d4 100644
 | |
| --- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp
 | |
| +++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp
 | |
| @@ -54,6 +54,7 @@ struct _WebKitWebViewBackend {
 | |
|      struct wpe_view_backend* backend;
 | |
|      GDestroyNotify notifyCallback;
 | |
|      gpointer notifyCallbackData;
 | |
| +    take_screenshot_callback screenshotCallback;
 | |
|      int referenceCount { 1 };
 | |
|  };
 | |
|  
 | |
| @@ -116,6 +117,19 @@ struct wpe_view_backend* webkit_web_view_backend_get_wpe_backend(WebKitWebViewBa
 | |
|      return viewBackend->backend;
 | |
|  }
 | |
|  
 | |
| +void webkit_web_view_backend_set_screenshot_callback(WebKitWebViewBackend *view_backend, take_screenshot_callback callback)
 | |
| +{
 | |
| +    view_backend->screenshotCallback = callback;
 | |
| +}
 | |
| +
 | |
| +cairo_surface_t* webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend* view_backend)
 | |
| +{
 | |
| +    if (!view_backend->screenshotCallback)
 | |
| +        return nullptr;
 | |
| +
 | |
| +    return view_backend->screenshotCallback(view_backend->notifyCallbackData);
 | |
| +}
 | |
| +
 | |
|  namespace WTF {
 | |
|  
 | |
|  template <> WebKitWebViewBackend* refGPtr(WebKitWebViewBackend* ptr)
 | |
| diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h
 | |
| index 6663964d5abac79e123d90e0351590884c66aa72..13ba5e7c3895c6e4efda95f1f90b9baea1c1bf30 100644
 | |
| --- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h
 | |
| +++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h
 | |
| @@ -27,6 +27,7 @@
 | |
|  #include <glib-object.h>
 | |
|  #include <wpe/WebKitDefines.h>
 | |
|  #include <wpe/wpe.h>
 | |
| +#include <cairo.h>
 | |
|  
 | |
|  G_BEGIN_DECLS
 | |
|  
 | |
| @@ -44,6 +45,12 @@ webkit_web_view_backend_new             (struct wpe_view_backend *backend,
 | |
|  WEBKIT_API struct wpe_view_backend *
 | |
|  webkit_web_view_backend_get_wpe_backend (WebKitWebViewBackend    *view_backend);
 | |
|  
 | |
| +typedef cairo_surface_t* (*take_screenshot_callback)(gpointer              user_data);
 | |
| +
 | |
| +WEBKIT_API void
 | |
| +webkit_web_view_backend_set_screenshot_callback   (WebKitWebViewBackend      *view_backend,
 | |
| +                                                   take_screenshot_callback  callback);
 | |
| +
 | |
|  G_END_DECLS
 | |
|  
 | |
|  #endif /* WebKitWebViewBackend_h */
 | |
| diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h
 | |
| index e4b92ace1531090ae38a7aec3d3d4febf19aee84..43690f9ef4969a39084501613bfc00a77fd5df49 100644
 | |
| --- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h
 | |
| +++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h
 | |
| @@ -31,3 +31,5 @@ template <> void derefGPtr(WebKitWebViewBackend* ptr);
 | |
|  }
 | |
|  
 | |
|  void webkitWebViewBackendUnref(WebKitWebViewBackend*);
 | |
| +
 | |
| +cairo_surface_t* webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend*);
 | |
| diff --git a/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt b/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt
 | |
| index cd29f69d4082b249570ad90e5daa6ee442646179..99a94c8153dba7bb3b2f20a57881cb289a6b36bc 100644
 | |
| --- a/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt
 | |
| +++ b/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt
 | |
| @@ -317,6 +317,8 @@ WEBKIT_TYPE_WEB_VIEW_BACKEND
 | |
|  WebKitWebViewBackend
 | |
|  webkit_web_view_backend_get_wpe_backend
 | |
|  webkit_web_view_backend_new
 | |
| +take_screenshot_callback
 | |
| +webkit_web_view_backend_set_screenshot_callback
 | |
|  
 | |
|  <SUBSECTION Private>
 | |
|  webkit_web_view_backend_get_type
 | |
| diff --git a/Source/WebKit/UIProcess/API/wpe/webkit.h b/Source/WebKit/UIProcess/API/wpe/webkit.h
 | |
| index 27c680d46428d349b0d1119f12da56ff283a60aa..1980aff7d662a1eea450d2db78b41f12a04f715e 100644
 | |
| --- a/Source/WebKit/UIProcess/API/wpe/webkit.h
 | |
| +++ b/Source/WebKit/UIProcess/API/wpe/webkit.h
 | |
| @@ -32,6 +32,7 @@
 | |
|  #include <wpe/WebKitAutomationSession.h>
 | |
|  #include <wpe/WebKitBackForwardList.h>
 | |
|  #include <wpe/WebKitBackForwardListItem.h>
 | |
| +#include <wpe/WebKitBrowserInspector.h>
 | |
|  #include <wpe/WebKitContextMenu.h>
 | |
|  #include <wpe/WebKitContextMenuActions.h>
 | |
|  #include <wpe/WebKitContextMenuItem.h>
 | |
| diff --git a/Source/WebKit/UIProcess/Automation/WebAutomationSession.h b/Source/WebKit/UIProcess/Automation/WebAutomationSession.h
 | |
| index 3627660395cb5f44e77a9f861d42e971dba1bbfc..4a1fb710da6b69be39c5b6bf54ee2b86689d7b5a 100644
 | |
| --- a/Source/WebKit/UIProcess/Automation/WebAutomationSession.h
 | |
| +++ b/Source/WebKit/UIProcess/Automation/WebAutomationSession.h
 | |
| @@ -216,6 +216,8 @@ public:
 | |
|      void markEventAsSynthesizedForAutomation(NSEvent *);
 | |
|  #endif
 | |
|  
 | |
| +    static Optional<String> platformGetBase64EncodedPNGData(const ViewSnapshot&);
 | |
| +
 | |
|  private:
 | |
|      WebPageProxy* webPageProxyForHandle(const String&);
 | |
|      String handleForWebPageProxy(const WebPageProxy&);
 | |
| @@ -264,7 +266,6 @@ private:
 | |
|  
 | |
|      // Get base64-encoded PNG data from a bitmap.
 | |
|      static Optional<String> platformGetBase64EncodedPNGData(const ShareableBitmap::Handle&);
 | |
| -    static Optional<String> platformGetBase64EncodedPNGData(const ViewSnapshot&);
 | |
|  
 | |
|      // Save base64-encoded file contents to a local file path and return the path.
 | |
|      // This reuses the basename of the remote file path so that the filename exposed to DOM API remains the same.
 | |
| diff --git a/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..dc8af6fe1c57bcd62d605fd1daa3da13361858bb
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp
 | |
| @@ -0,0 +1,57 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "BrowserInspectorPipe.h"
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +#include "InspectorPlaywrightAgent.h"
 | |
| +#include "RemoteInspectorPipe.h"
 | |
| +#include <wtf/NeverDestroyed.h>
 | |
| +#include "InspectorPlaywrightAgentClient.h"
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +void initializeBrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client)
 | |
| +{
 | |
| +    class BrowserInspectorPipe {
 | |
| +    public:
 | |
| +        BrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client)
 | |
| +            : m_playwrightAgent(std::move(client))
 | |
| +            , m_remoteInspectorPipe(m_playwrightAgent)
 | |
| +        {
 | |
| +        }
 | |
| +
 | |
| +        InspectorPlaywrightAgent m_playwrightAgent;
 | |
| +        RemoteInspectorPipe m_remoteInspectorPipe;
 | |
| +    };
 | |
| +
 | |
| +    static NeverDestroyed<BrowserInspectorPipe> pipe(std::move(client));
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/BrowserInspectorPipe.h b/Source/WebKit/UIProcess/BrowserInspectorPipe.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..cd66887de171cda7d15a8e4dc6dbff63665dc619
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.h
 | |
| @@ -0,0 +1,38 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class InspectorPlaywrightAgentClient;
 | |
| +
 | |
| +void initializeBrowserInspectorPipe(std::unique_ptr<InspectorPlaywrightAgentClient> client);
 | |
| +
 | |
| +} // namespace WebKit
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm b/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm
 | |
| index c7484a54558b8fbbecd74717c159a915a6114423..2c8809ef697cb9e54356fd9dbb41ea4425ef00e4 100644
 | |
| --- a/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm
 | |
| +++ b/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm
 | |
| @@ -36,7 +36,7 @@ namespace WebKit {
 | |
|  
 | |
|  PageClientImplCocoa::PageClientImplCocoa(WKWebView *webView)
 | |
|      : m_webView { webView }
 | |
| -    , m_alternativeTextUIController { makeUnique<AlternativeTextUIController>() }
 | |
| +    , m_alternativeTextUIController { makeUnique<WebCore::AlternativeTextUIController>() }
 | |
|  {
 | |
|  }
 | |
|  
 | |
| 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 cdefd4287b1f5b2222d50ac6dab195dab236fc34..b8ee75742ce3569aaf668395d8dfe0bc6cafb6f7 100644
 | |
| --- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h
 | |
| +++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h
 | |
| @@ -91,6 +91,7 @@ private:
 | |
|          void runJavaScriptAlert(WebPageProxy&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function<void()>&& completionHandler) final;
 | |
|          void runJavaScriptConfirm(WebPageProxy&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function<void(bool)>&& completionHandler) final;
 | |
|          void runJavaScriptPrompt(WebPageProxy&, const WTF::String&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function<void(const WTF::String&)>&&) final;
 | |
| +        void handleJavaScriptDialog(WebKit::WebPageProxy&, bool accept, const WTF::String&) final;
 | |
|          void presentStorageAccessConfirmDialog(const WTF::String& requestingDomain, const WTF::String& currentDomain, CompletionHandler<void(bool)>&&);
 | |
|          void requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler<void(bool)>&&) final;
 | |
|          void decidePolicyForGeolocationPermissionRequest(WebPageProxy&, WebFrameProxy&, const FrameInfoData&, Function<void(bool)>&) final;
 | |
| @@ -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 49c7142785ec29b446fd956978195a197d39b93f..537a3300b9b2b97001f3811cd85630683316b361 100644
 | |
| --- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
 | |
| +++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
 | |
| @@ -99,6 +99,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:)];
 | |
| @@ -338,6 +339,15 @@ void UIDelegate::UIClient::runJavaScriptPrompt(WebPageProxy& page, const WTF::St
 | |
|      }).get()];
 | |
|  }
 | |
|  
 | |
| +void UIDelegate::UIClient::handleJavaScriptDialog(WebKit::WebPageProxy&, bool accept, const WTF::String& value) {
 | |
| +    if (!m_uiDelegate.m_delegateMethods.webViewHandleJavaScriptDialogValue)
 | |
| +        return;
 | |
| +    auto delegate = m_uiDelegate.m_delegate.get();
 | |
| +    if (!delegate)
 | |
| +        return;
 | |
| +    [delegate webView:m_uiDelegate.m_webView handleJavaScriptDialog:accept value:value];
 | |
| +}
 | |
| +
 | |
|  void UIDelegate::UIClient::requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler<void(bool)>&& completionHandler)
 | |
|  {
 | |
|      auto delegate = m_uiDelegate.m_delegate.get();
 | |
| diff --git a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
 | |
| index 021bacb7b940462fbf5820baa55395a9ed5bb142..f6b6bfbfdd12d6b6eaf6a04b5ee0dba4321ef878 100644
 | |
| --- a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
 | |
| +++ b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
 | |
| @@ -385,7 +385,7 @@ void WebProcessPool::platformInitializeWebProcess(const WebProcessProxy& process
 | |
|      auto screenProperties = WebCore::collectScreenProperties();
 | |
|      parameters.screenProperties = WTFMove(screenProperties);
 | |
|  #if PLATFORM(MAC)
 | |
| -    parameters.useOverlayScrollbars = ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay);
 | |
| +    parameters.useOverlayScrollbars = m_configuration->forceOverlayScrollbars() || ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay);
 | |
|  #endif
 | |
|      
 | |
|  #if PLATFORM(IOS)
 | |
| @@ -676,8 +676,8 @@ void WebProcessPool::registerNotificationObservers()
 | |
|  
 | |
|  #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
 | |
|      m_scrollerStyleNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSPreferredScrollerStyleDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
 | |
| -        auto scrollbarStyle = [NSScroller preferredScrollerStyle];
 | |
| -        sendToAllProcesses(Messages::WebProcess::ScrollerStylePreferenceChanged(scrollbarStyle));
 | |
| +        bool useOverlayScrollbars = m_configuration->forceOverlayScrollbars() || ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay);
 | |
| +        sendToAllProcesses(Messages::WebProcess::ScrollerStylePreferenceChanged(useOverlayScrollbars));
 | |
|      }];
 | |
|  #endif
 | |
|  
 | |
| diff --git a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
 | |
| index d8f25b7ed5194616f064f5e2e1c3ec81490608b3..54048e141a5c23186191718f91fad219d66dbfe6 100644
 | |
| --- a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
 | |
| +++ b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
 | |
| @@ -478,6 +478,9 @@ public:
 | |
|      void provideDataForPasteboard(NSPasteboard *, NSString *type);
 | |
|      NSArray *namesOfPromisedFilesDroppedAtDestination(NSURL *dropDestination);
 | |
|  
 | |
| +// Paywright begin
 | |
| +    RetainPtr<CGImageRef> takeSnapshotForAutomation();
 | |
| +// Paywright end
 | |
|      RefPtr<ViewSnapshot> takeViewSnapshot();
 | |
|      void saveBackForwardSnapshotForCurrentItem();
 | |
|      void saveBackForwardSnapshotForItem(WebBackForwardListItem&);
 | |
| diff --git a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
 | |
| index 1145bd4400770377a68759664ef3db9102048c15..f7f66bdbff9e0656e12d97bfe76f8979d0c408d6 100644
 | |
| --- a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
 | |
| +++ b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
 | |
| @@ -4435,6 +4435,18 @@ static RetainPtr<CGImageRef> takeWindowSnapshot(CGSWindowID windowID, bool captu
 | |
|      return adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, windowID, imageOptions));
 | |
|  }
 | |
|  
 | |
| +// Paywright begin
 | |
| +RetainPtr<CGImageRef> WebViewImpl::takeSnapshotForAutomation() {
 | |
| +    NSWindow *window = [m_view window];
 | |
| +
 | |
| +    CGSWindowID windowID = (CGSWindowID)window.windowNumber;
 | |
| +    if (!windowID || !window.isVisible)
 | |
| +        return nullptr;
 | |
| +
 | |
| +    return takeWindowSnapshot(windowID, true);
 | |
| +}
 | |
| +// Paywright end
 | |
| +
 | |
|  RefPtr<ViewSnapshot> WebViewImpl::takeViewSnapshot()
 | |
|  {
 | |
|      NSWindow *window = [m_view window];
 | |
| diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
 | |
| index 6bbd1cabd27ae2847648a8c2edcf9acfcd556ff5..0c2f1d08becd69a95c13c21d63a57cb5f3facf7b 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>
 | |
| @@ -51,6 +52,14 @@
 | |
|  #include <d3d11_1.h>
 | |
|  #endif
 | |
|  
 | |
| +#if PLATFORM(WIN)
 | |
| +#include "WebPageInspectorController.h"
 | |
| +#include <cairo-win32.h>
 | |
| +#include <windows.h>
 | |
| +#include <WebCore/HWndDC.h>
 | |
| +#include <WebCore/RefPtrCairo.h>
 | |
| +#endif
 | |
| +
 | |
|  namespace WebKit {
 | |
|  using namespace WebCore;
 | |
|  
 | |
| @@ -119,6 +128,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 +146,11 @@ void DrawingAreaProxyCoordinatedGraphics::deviceScaleFactorDidChange()
 | |
|      backingStoreStateDidChange(RespondImmediately);
 | |
|  }
 | |
|  
 | |
| +void DrawingAreaProxyCoordinatedGraphics::waitForSizeUpdate(Function<void ()>&& callback)
 | |
| +{
 | |
| +    m_callbacks.append(WTFMove(callback));
 | |
| +}
 | |
| +
 | |
|  void DrawingAreaProxyCoordinatedGraphics::waitForBackingStoreUpdateOnNextPaint()
 | |
|  {
 | |
|      m_hasReceivedFirstUpdate = true;
 | |
| @@ -238,6 +256,25 @@ void DrawingAreaProxyCoordinatedGraphics::updateAcceleratedCompositingMode(uint6
 | |
|      updateAcceleratedCompositingMode(layerTreeContext);
 | |
|  }
 | |
|  
 | |
| +#if PLATFORM(WIN)
 | |
| +void DrawingAreaProxyCoordinatedGraphics::didCompositeLayersToContext()
 | |
| +{
 | |
| +    HWndDC dc(m_webPageProxy.viewWidget());
 | |
| +    RefPtr<cairo_surface_t> surface = adoptRef(cairo_win32_surface_create(dc));
 | |
| +    if (!surface) {
 | |
| +        fprintf(stderr, "didCompositeLayersToContext() failed to create surface\n");
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    m_webPageProxy.inspectorController().didPaint(surface.get());
 | |
| +}
 | |
| +
 | |
| +void DrawingAreaProxyCoordinatedGraphics::setReportAcceleratedCompositingEnabled(bool enabled)
 | |
| +{
 | |
| +    send(Messages::DrawingArea::SetReportAcceleratedCompositing(enabled));
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
|  #if !PLATFORM(WPE)
 | |
|  void DrawingAreaProxyCoordinatedGraphics::incorporateUpdate(const UpdateInfo& updateInfo)
 | |
|  {
 | |
| diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h
 | |
| index d7695088e7cfc4f638f157338754f9f157489749..9778271c520667e955bc510c6deb591accfbbe47 100644
 | |
| --- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h
 | |
| +++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h
 | |
| @@ -30,6 +30,7 @@
 | |
|  #include "BackingStore.h"
 | |
|  #include "DrawingAreaProxy.h"
 | |
|  #include "LayerTreeContext.h"
 | |
| +#include <wtf/Function.h>
 | |
|  #include <wtf/RunLoop.h>
 | |
|  
 | |
|  namespace WebCore {
 | |
| @@ -49,6 +50,10 @@ public:
 | |
|  
 | |
|      bool isInAcceleratedCompositingMode() const { return !m_layerTreeContext.isEmpty(); }
 | |
|      const LayerTreeContext& layerTreeContext() const { return m_layerTreeContext; }
 | |
| +    void waitForSizeUpdate(Function<void ()>&&);
 | |
| +#if PLATFORM(WIN)
 | |
| +    void setReportAcceleratedCompositingEnabled(bool enabled);
 | |
| +#endif
 | |
|  
 | |
|  private:
 | |
|      // DrawingAreaProxy
 | |
| @@ -63,6 +68,9 @@ private:
 | |
|      void enterAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext&) override;
 | |
|      void exitAcceleratedCompositingMode(uint64_t backingStoreStateID, const UpdateInfo&) override;
 | |
|      void updateAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext&) override;
 | |
| +#if PLATFORM(WIN)
 | |
| +    void didCompositeLayersToContext() override;
 | |
| +#endif
 | |
|  
 | |
|  #if !PLATFORM(WPE)
 | |
|      void incorporateUpdate(const UpdateInfo&);
 | |
| @@ -126,6 +134,8 @@ private:
 | |
|      // For a new Drawing Area don't draw anything until the WebProcess has sent over the first content.
 | |
|      bool m_hasReceivedFirstUpdate { false };
 | |
|  
 | |
| +    Vector<Function<void ()>> m_callbacks;
 | |
| +
 | |
|  #if !PLATFORM(WPE)
 | |
|      bool m_isBackingStoreDiscardable { true };
 | |
|      std::unique_ptr<BackingStore> m_backingStore;
 | |
| diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp
 | |
| index c5de4e7d0f59194f43a023b089e372c58cf8ee06..c0f38eccf578c14d13cb3b42788f988b9917e7ac 100644
 | |
| --- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp
 | |
| +++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp
 | |
| @@ -42,8 +42,10 @@
 | |
|  #include <WebCore/MIMETypeRegistry.h>
 | |
|  #include <WebCore/ResourceResponseBase.h>
 | |
|  #include <wtf/FileSystem.h>
 | |
| +#include <wtf/NeverDestroyed.h>
 | |
|  #include <wtf/text/CString.h>
 | |
|  #include <wtf/text/WTFString.h>
 | |
| +#include <wtf/UUID.h>
 | |
|  
 | |
|  namespace WebKit {
 | |
|  using namespace WebCore;
 | |
| @@ -62,7 +64,10 @@ DownloadProxy::DownloadProxy(DownloadProxyMap& downloadProxyMap, WebsiteDataStor
 | |
|      , m_request(resourceRequest)
 | |
|      , m_originatingPage(makeWeakPtr(originatingPage))
 | |
|      , m_frameInfo(API::FrameInfo::create(FrameInfoData { frameInfoData }, originatingPage))
 | |
| +    , m_uuid(createCanonicalUUIDString())
 | |
|  {
 | |
| +    if (auto* instrumentation = m_dataStore->downloadInstrumentation())
 | |
| +      instrumentation->downloadCreated(*m_dataStore, m_uuid, m_request, frameInfoData, originatingPage);
 | |
|  }
 | |
|  
 | |
|  DownloadProxy::~DownloadProxy()
 | |
| @@ -178,7 +183,21 @@ void DownloadProxy::decideDestinationWithSuggestedFilenameAsync(DownloadID downl
 | |
|  {
 | |
|      if (!m_processPool)
 | |
|          return;
 | |
| -    
 | |
| +
 | |
| +    if (auto* instrumentation = m_dataStore->downloadInstrumentation())
 | |
| +      instrumentation->downloadFilenameSuggested(*m_dataStore, m_uuid, suggestedFilename);
 | |
| +
 | |
| +    if (m_processPool->networkProcess() && m_dataStore->allowDownloadForAutomation()) {
 | |
| +        SandboxExtension::Handle sandboxExtensionHandle;
 | |
| +        String destination;
 | |
| +        if (*m_dataStore->allowDownloadForAutomation()) {
 | |
| +            destination = FileSystem::pathByAppendingComponent(m_dataStore->downloadPathForAutomation(), m_uuid);
 | |
| +            SandboxExtension::createHandle(destination, SandboxExtension::Type::ReadWrite, sandboxExtensionHandle);
 | |
| +        }
 | |
| +        m_processPool->networkProcess()->send(Messages::NetworkProcess::ContinueDecidePendingDownloadDestination(downloadID, destination, sandboxExtensionHandle, true), 0);
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
|      m_processPool->downloadClient().decideDestinationWithSuggestedFilename(*this, ResourceResponseBase::sanitizeSuggestedFilename(suggestedFilename), [this, protectedThis = makeRef(*this), downloadID = downloadID] (AllowOverwrite allowOverwrite, String destination) {
 | |
|          SandboxExtension::Handle sandboxExtensionHandle;
 | |
|          if (!destination.isNull())
 | |
| @@ -206,6 +225,8 @@ void DownloadProxy::didFinish()
 | |
|          return;
 | |
|  
 | |
|      m_processPool->downloadClient().didFinish(*this);
 | |
| +    if (auto* instrumentation = m_dataStore->downloadInstrumentation())
 | |
| +      instrumentation->downloadFinished(*m_dataStore, m_uuid, String());
 | |
|  
 | |
|      // This can cause the DownloadProxy object to be deleted.
 | |
|      m_downloadProxyMap.downloadFinished(*this);
 | |
| @@ -227,6 +248,8 @@ void DownloadProxy::didFail(const ResourceError& error, const IPC::DataReference
 | |
|      m_resumeData = createData(resumeData);
 | |
|  
 | |
|      m_processPool->downloadClient().didFail(*this, error);
 | |
| +    if (auto* instrumentation = m_dataStore->downloadInstrumentation())
 | |
| +      instrumentation->downloadFinished(*m_dataStore, m_uuid, error.localizedDescription());
 | |
|  
 | |
|      // This can cause the DownloadProxy object to be deleted.
 | |
|      m_downloadProxyMap.downloadFinished(*this);
 | |
| @@ -234,9 +257,14 @@ void DownloadProxy::didFail(const ResourceError& error, const IPC::DataReference
 | |
|  
 | |
|  void DownloadProxy::didCancel(const IPC::DataReference& resumeData)
 | |
|  {
 | |
| +    if (!m_processPool)
 | |
| +        return;
 | |
| +
 | |
|      m_resumeData = createData(resumeData);
 | |
|  
 | |
|      m_processPool->downloadClient().didCancel(*this);
 | |
| +    if (auto* instrumentation = m_dataStore->downloadInstrumentation())
 | |
| +      instrumentation->downloadFinished(*m_dataStore, m_uuid, "canceled"_s);
 | |
|  
 | |
|      // This can cause the DownloadProxy object to be deleted.
 | |
|      m_downloadProxyMap.downloadFinished(*this);
 | |
| diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h
 | |
| index b19499a662b48e10e876b403c168dbde9bf9f3ec..2a0384a1936471f27727a6c06905704a4686ddc8 100644
 | |
| --- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h
 | |
| +++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h
 | |
| @@ -133,6 +133,7 @@ private:
 | |
|      Vector<URL> m_redirectChain;
 | |
|      bool m_wasUserInitiated { true };
 | |
|      Ref<API::FrameInfo> m_frameInfo;
 | |
| +    String m_uuid;
 | |
|  };
 | |
|  
 | |
|  } // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.h b/Source/WebKit/UIProcess/DrawingAreaProxy.h
 | |
| index 59cdfdafab1d85ea3a5aecb3cd2293e6dfb1eb8d..37592791af8d1e567ca332423eee00c8567c125f 100644
 | |
| --- a/Source/WebKit/UIProcess/DrawingAreaProxy.h
 | |
| +++ b/Source/WebKit/UIProcess/DrawingAreaProxy.h
 | |
| @@ -75,6 +75,7 @@ public:
 | |
|  
 | |
|      const WebCore::IntSize& size() const { return m_size; }
 | |
|      bool setSize(const WebCore::IntSize&, const WebCore::IntSize& scrollOffset = { });
 | |
| +    void waitForSizeUpdate(Function<void ()>&&);
 | |
|  
 | |
|  #if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER)
 | |
|      // The timeout we use when waiting for a DidUpdateGeometry message.
 | |
| @@ -160,6 +161,9 @@ private:
 | |
|      virtual void update(uint64_t /* backingStoreStateID */, const UpdateInfo&) { }
 | |
|      virtual void didUpdateBackingStoreState(uint64_t /* backingStoreStateID */, const UpdateInfo&, const LayerTreeContext&) { }
 | |
|      virtual void exitAcceleratedCompositingMode(uint64_t /* backingStoreStateID */, const UpdateInfo&) { }
 | |
| +#endif
 | |
| +#if PLATFORM(WIN)
 | |
| +    virtual void didCompositeLayersToContext() { }
 | |
|  #endif
 | |
|      bool m_startedReceivingMessages { false };
 | |
|  };
 | |
| diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in b/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in
 | |
| index b0722e7da81e56530deb570b82ed7cfece970362..1d1463231269363939e4c746a6dada5e29f3fd18 100644
 | |
| --- a/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in
 | |
| +++ b/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in
 | |
| @@ -36,4 +36,7 @@ messages -> DrawingAreaProxy NotRefCounted {
 | |
|      DidUpdateBackingStoreState(uint64_t backingStoreStateID, WebKit::UpdateInfo updateInfo, WebKit::LayerTreeContext context)
 | |
|      ExitAcceleratedCompositingMode(uint64_t backingStoreStateID, WebKit::UpdateInfo updateInfo)
 | |
|  #endif
 | |
| +#if PLATFORM(WIN)
 | |
| +    DidCompositeLayersToContext()
 | |
| +#endif
 | |
|  }
 | |
| diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..3f091aa8ea5e44980f2ea62e26ab860697c6a066
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
 | |
| @@ -0,0 +1,166 @@
 | |
| +/*
 | |
| + * Copyright (C) 2020 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "InspectorScreencastAgent.h"
 | |
| +
 | |
| +#include "PageClient.h"
 | |
| +#include "ScreencastEncoder.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +#include <JavaScriptCore/InspectorFrontendDispatchers.h>
 | |
| +#include <JavaScriptCore/InspectorFrontendRouter.h>
 | |
| +#include <WebCore/NotImplemented.h>
 | |
| +
 | |
| +#if USE(CAIRO)
 | |
| +#include "DrawingAreaProxy.h"
 | |
| +#endif
 | |
| +
 | |
| +#if PLATFORM(WIN)
 | |
| +#include "DrawingAreaProxyCoordinatedGraphics.h"
 | |
| +#endif
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +using namespace Inspector;
 | |
| +
 | |
| +InspectorScreencastAgent::InspectorScreencastAgent(BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page)
 | |
| +    : InspectorAgentBase("Screencast"_s)
 | |
| +    , m_backendDispatcher(ScreencastBackendDispatcher::create(backendDispatcher, this))
 | |
| +    , m_page(page)
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +InspectorScreencastAgent::~InspectorScreencastAgent()
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +void InspectorScreencastAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +void InspectorScreencastAgent::willDestroyFrontendAndBackend(DisconnectReason)
 | |
| +{
 | |
| +    if (!m_encoder)
 | |
| +        return;
 | |
| +
 | |
| +    m_encoder->finish([] { });
 | |
| +    m_encoder = nullptr;
 | |
| +}
 | |
| +
 | |
| +#if USE(CAIRO)
 | |
| +void InspectorScreencastAgent::didPaint(cairo_surface_t* surface)
 | |
| +{
 | |
| +    if (m_encoder)
 | |
| +        m_encoder->encodeFrame(surface, m_page.drawingArea()->size());
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +#if PLATFORM(WIN)
 | |
| +void InspectorScreencastAgent::didCommitProvisionalPage()
 | |
| +{
 | |
| +    if (!m_encoder)
 | |
| +        return;
 | |
| +
 | |
| +    if (auto* drawingArea = m_page.drawingArea())
 | |
| +        static_cast<DrawingAreaProxyCoordinatedGraphics*>(drawingArea)->setReportAcceleratedCompositingEnabled(true);
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +void InspectorScreencastAgent::startVideoRecording(Inspector::ErrorString& errorString, const String& file, int width, int height, const double* scale)
 | |
| +{
 | |
| +    if (m_encoder) {
 | |
| +        errorString = "Already recording"_s;
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    if (width < 10 || width > 10000 || height < 10 || height > 10000) {
 | |
| +        errorString = "Invalid size"_s;
 | |
| +        return;
 | |
| +    }
 | |
| +    Optional<double> optionalScale;
 | |
| +    if (scale) {
 | |
| +        if (*scale <= 0 || *scale > 1) {
 | |
| +            errorString = "Unsupported scale"_s;
 | |
| +            return;
 | |
| +        }
 | |
| +
 | |
| +        optionalScale = *scale;
 | |
| +    }
 | |
| +    m_encoder = ScreencastEncoder::create(errorString, file, WebCore::IntSize(width, height), optionalScale);
 | |
| +    if (!m_encoder)
 | |
| +        return;
 | |
| +
 | |
| +#if PLATFORM(MAC)
 | |
| +    scheduleFrameEncoding();
 | |
| +#endif
 | |
| +#if PLATFORM(WIN)
 | |
| +    if (auto* drawingArea = m_page.drawingArea())
 | |
| +        static_cast<DrawingAreaProxyCoordinatedGraphics*>(drawingArea)->setReportAcceleratedCompositingEnabled(true);
 | |
| +#endif
 | |
| +}
 | |
| +
 | |
| +void InspectorScreencastAgent::stopVideoRecording(Ref<StopVideoRecordingCallback>&& callback)
 | |
| +{
 | |
| +    if (!m_encoder) {
 | |
| +        callback->sendFailure("Not recording"_s);
 | |
| +        return;
 | |
| +    }
 | |
| +#if PLATFORM(WIN)
 | |
| +    if (auto* drawingArea = m_page.drawingArea())
 | |
| +        static_cast<DrawingAreaProxyCoordinatedGraphics*>(drawingArea)->setReportAcceleratedCompositingEnabled(false);
 | |
| +#endif
 | |
| +    m_encoder->finish([protectRef = m_encoder.copyRef(), callback = WTFMove(callback)] {
 | |
| +        callback->sendSuccess();
 | |
| +    });
 | |
| +    m_encoder = nullptr;
 | |
| +}
 | |
| +
 | |
| +#if PLATFORM(MAC)
 | |
| +void InspectorScreencastAgent::scheduleFrameEncoding()
 | |
| +{
 | |
| +    if (!m_encoder)
 | |
| +        return;
 | |
| +
 | |
| +    m_page.callAfterNextPresentationUpdate([agent = makeWeakPtr(this)](CallbackBase::Error error) mutable {
 | |
| +        if (!agent)
 | |
| +            return;
 | |
| +
 | |
| +        if (error == CallbackBase::Error::None) {
 | |
| +            agent->encodeFrame();
 | |
| +        } else {
 | |
| +            fprintf(stderr, "callAfterNextPresentationUpdate failed error= %d\n", error);
 | |
| +        }
 | |
| +        agent->scheduleFrameEncoding();
 | |
| +    });
 | |
| +}
 | |
| +
 | |
| +void InspectorScreencastAgent::encodeFrame()
 | |
| +{
 | |
| +    if (m_encoder)
 | |
| +        m_encoder->encodeFrame(m_page.pageClient().takeSnapshotForAutomation());
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..003ad364d76071ce30d11cce7d1b61a66e2c4d77
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h
 | |
| @@ -0,0 +1,79 @@
 | |
| +/*
 | |
| + * Copyright (C) 2020 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#include <JavaScriptCore/InspectorAgentBase.h>
 | |
| +#include <JavaScriptCore/InspectorBackendDispatchers.h>
 | |
| +
 | |
| +#include <wtf/Forward.h>
 | |
| +#include <wtf/Noncopyable.h>
 | |
| +#include <wtf/WeakPtr.h>
 | |
| +
 | |
| +namespace Inspector {
 | |
| +class BackendDispatcher;
 | |
| +class FrontendChannel;
 | |
| +class FrontendRouter;
 | |
| +class ScreencastFrontendDispatcher;
 | |
| +}
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class ScreencastEncoder;
 | |
| +class WebPageProxy;
 | |
| +
 | |
| +class InspectorScreencastAgent : public Inspector::InspectorAgentBase, public Inspector::ScreencastBackendDispatcherHandler, public CanMakeWeakPtr<InspectorScreencastAgent> {
 | |
| +    WTF_MAKE_NONCOPYABLE(InspectorScreencastAgent);
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    InspectorScreencastAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page);
 | |
| +    ~InspectorScreencastAgent() override;
 | |
| +
 | |
| +    void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
 | |
| +    void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
 | |
| +
 | |
| +#if USE(CAIRO)
 | |
| +    void didPaint(cairo_surface_t*);
 | |
| +#endif
 | |
| +#if PLATFORM(WIN)
 | |
| +    void didCommitProvisionalPage();
 | |
| +#endif
 | |
| +
 | |
| +    void startVideoRecording(Inspector::ErrorString&, const String& file, int width, int height, const double* scale) override;
 | |
| +    void stopVideoRecording(Ref<StopVideoRecordingCallback>&&) override;
 | |
| +
 | |
| +
 | |
| +private:
 | |
| +#if PLATFORM(MAC)
 | |
| +    void scheduleFrameEncoding();
 | |
| +    void encodeFrame();
 | |
| +#endif
 | |
| +
 | |
| +    Ref<Inspector::ScreencastBackendDispatcher> m_backendDispatcher;
 | |
| +    WebPageProxy& m_page;
 | |
| +    RefPtr<ScreencastEncoder> m_encoder;
 | |
| +};
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..5b28d1ba9fe79d35af2e15f97aeb8df31a898a11
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
 | |
| @@ -0,0 +1,442 @@
 | |
| +/*
 | |
| + * Copyright (c) 2010, The WebM Project authors. All rights reserved.
 | |
| + * Copyright (c) 2013 The Chromium Authors. All rights reserved.
 | |
| + * Copyright (C) 2020 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "ScreencastEncoder.h"
 | |
| +
 | |
| +#include <libyuv.h>
 | |
| +#include <vpx/vp8.h>
 | |
| +#include <vpx/vp8cx.h>
 | |
| +#include <vpx/vpx_encoder.h>
 | |
| +#include <wtf/RunLoop.h>
 | |
| +#include <wtf/UniqueArray.h>
 | |
| +#include <wtf/WorkQueue.h>
 | |
| +#include <wtf/text/StringConcatenateNumbers.h>
 | |
| +
 | |
| +#if USE(CAIRO)
 | |
| +#include <WebCore/RefPtrCairo.h>
 | |
| +#endif
 | |
| +
 | |
| +using namespace WebCore;
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +namespace {
 | |
| +// Defines the dimension of a macro block. This is used to compute the active
 | |
| +// map for the encoder.
 | |
| +const int kMacroBlockSize = 16;
 | |
| +
 | |
| +void createImage(unsigned int width, unsigned int height,
 | |
| +                 std::unique_ptr<vpx_image_t>& out_image,
 | |
| +                 std::unique_ptr<uint8_t[]>& out_image_buffer) {
 | |
| +  std::unique_ptr<vpx_image_t> image(new vpx_image_t());
 | |
| +  memset(image.get(), 0, sizeof(vpx_image_t));
 | |
| +
 | |
| +  // libvpx seems to require both to be assigned.
 | |
| +  image->d_w = width;
 | |
| +  image->w = width;
 | |
| +  image->d_h = height;
 | |
| +  image->h = height;
 | |
| +
 | |
| +  // I420
 | |
| +  image->fmt = VPX_IMG_FMT_YV12;
 | |
| +  image->x_chroma_shift = 1;
 | |
| +  image->y_chroma_shift = 1;
 | |
| +
 | |
| +  // libyuv's fast-path requires 16-byte aligned pointers and strides, so pad
 | |
| +  // the Y, U and V planes' strides to multiples of 16 bytes.
 | |
| +  const int y_stride = ((image->w - 1) & ~15) + 16;
 | |
| +  const int uv_unaligned_stride = y_stride >> image->x_chroma_shift;
 | |
| +  const int uv_stride = ((uv_unaligned_stride - 1) & ~15) + 16;
 | |
| +
 | |
| +  // libvpx accesses the source image in macro blocks, and will over-read
 | |
| +  // if the image is not padded out to the next macroblock: crbug.com/119633.
 | |
| +  // Pad the Y, U and V planes' height out to compensate.
 | |
| +  // Assuming macroblocks are 16x16, aligning the planes' strides above also
 | |
| +  // macroblock aligned them.
 | |
| +  static_assert(kMacroBlockSize == 16, "macroblock_size_not_16");
 | |
| +  const int y_rows = ((image->h - 1) & ~(kMacroBlockSize-1)) + kMacroBlockSize;
 | |
| +  const int uv_rows = y_rows >> image->y_chroma_shift;
 | |
| +
 | |
| +  // Allocate a YUV buffer large enough for the aligned data & padding.
 | |
| +  const int buffer_size = y_stride * y_rows + 2*uv_stride * uv_rows;
 | |
| +  std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[buffer_size]);
 | |
| +
 | |
| +  // Reset image value to 128 so we just need to fill in the y plane.
 | |
| +  memset(image_buffer.get(), 128, buffer_size);
 | |
| +
 | |
| +  // Fill in the information for |image_|.
 | |
| +  unsigned char* uchar_buffer =
 | |
| +      reinterpret_cast<unsigned char*>(image_buffer.get());
 | |
| +  image->planes[0] = uchar_buffer;
 | |
| +  image->planes[1] = image->planes[0] + y_stride * y_rows;
 | |
| +  image->planes[2] = image->planes[1] + uv_stride * uv_rows;
 | |
| +  image->stride[0] = y_stride;
 | |
| +  image->stride[1] = uv_stride;
 | |
| +  image->stride[2] = uv_stride;
 | |
| +
 | |
| +  out_image = std::move(image);
 | |
| +  out_image_buffer = std::move(image_buffer);
 | |
| +}
 | |
| +
 | |
| +void mem_put_le16(void *vmem, int val) {
 | |
| +  unsigned char *mem = (unsigned char *)vmem;
 | |
| +
 | |
| +  mem[0] = (unsigned char)((val >> 0) & 0xff);
 | |
| +  mem[1] = (unsigned char)((val >> 8) & 0xff);
 | |
| +}
 | |
| +
 | |
| +void mem_put_le32(void *vmem, int val) {
 | |
| +  unsigned char *mem = (unsigned char *)vmem;
 | |
| +
 | |
| +  mem[0] = (unsigned char)((val >>  0) & 0xff);
 | |
| +  mem[1] = (unsigned char)((val >>  8) & 0xff);
 | |
| +  mem[2] = (unsigned char)((val >> 16) & 0xff);
 | |
| +  mem[3] = (unsigned char)((val >> 24) & 0xff);
 | |
| +}
 | |
| +
 | |
| +void ivf_write_file_header_with_video_info(FILE *outfile, uint32_t fourcc,
 | |
| +                                           int frame_cnt, int frame_width,
 | |
| +                                           int frame_height,
 | |
| +                                           vpx_rational_t timebase) {
 | |
| +  char header[32];
 | |
| +
 | |
| +  header[0] = 'D';
 | |
| +  header[1] = 'K';
 | |
| +  header[2] = 'I';
 | |
| +  header[3] = 'F';
 | |
| +  mem_put_le16(header + 4, 0);              // version
 | |
| +  mem_put_le16(header + 6, 32);             // header size
 | |
| +  mem_put_le32(header + 8, fourcc);         // fourcc
 | |
| +  mem_put_le16(header + 12, frame_width);   // width
 | |
| +  mem_put_le16(header + 14, frame_height);  // height
 | |
| +  mem_put_le32(header + 16, timebase.den);  // rate
 | |
| +  mem_put_le32(header + 20, timebase.num);  // scale
 | |
| +  mem_put_le32(header + 24, frame_cnt);     // length
 | |
| +  mem_put_le32(header + 28, 0);             // unused
 | |
| +
 | |
| +  fwrite(header, 1, 32, outfile);
 | |
| +}
 | |
| +
 | |
| +void ivf_write_file_header(FILE *outfile, const struct vpx_codec_enc_cfg *cfg,
 | |
| +                           uint32_t fourcc, int frame_cnt) {
 | |
| +  ivf_write_file_header_with_video_info(outfile, fourcc, frame_cnt, cfg->g_w,
 | |
| +                                        cfg->g_h, cfg->g_timebase);
 | |
| +}
 | |
| +
 | |
| +void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size) {
 | |
| +  char header[12];
 | |
| +
 | |
| +  mem_put_le32(header, (int)frame_size);
 | |
| +  mem_put_le32(header + 4, (int)(pts & 0xFFFFFFFF));
 | |
| +  mem_put_le32(header + 8, (int)(pts >> 32));
 | |
| +  fwrite(header, 1, 12, outfile);
 | |
| +}
 | |
| +
 | |
| +} // namespace
 | |
| +
 | |
| +class ScreencastEncoder::VPXFrame {
 | |
| +    WTF_MAKE_NONCOPYABLE(VPXFrame);
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +#if USE(CAIRO)
 | |
| +    explicit VPXFrame(RefPtr<cairo_surface_t>&& surface)
 | |
| +        : m_surface(WTFMove(surface))
 | |
| +    { }
 | |
| +#elif PLATFORM(MAC)
 | |
| +    VPXFrame(RetainPtr<CGImageRef> windowImage, Optional<double> scale)
 | |
| +        : m_windowImage(WTFMove(windowImage))
 | |
| +        , m_scale(scale)
 | |
| +    { }
 | |
| +#endif
 | |
| +
 | |
| +    void setDuration(int duration) { m_duration = duration; }
 | |
| +    int duration() const { return m_duration; }
 | |
| +
 | |
| +    void convertToVpxImage(vpx_image_t* image)
 | |
| +    {
 | |
| +#if USE(CAIRO)
 | |
| +        // Convert the updated region to YUV ready for encoding.
 | |
| +        const uint8_t* argb_data = cairo_image_surface_get_data(m_surface.get());
 | |
| +        int argb_stride = cairo_image_surface_get_stride(m_surface.get());
 | |
| +#elif PLATFORM(MAC)
 | |
| +        int argb_stride = image->w * 4;
 | |
| +        UniqueArray<uint8_t> buffer = makeUniqueArray<uint8_t>(argb_stride * image->h);
 | |
| +        uint8_t* argb_data = buffer.get();
 | |
| +        ScreencastEncoder::imageToARGB(m_windowImage.get(), argb_data, image->w, image->h, m_scale);
 | |
| +#endif
 | |
| +        const int y_stride = image->stride[0];
 | |
| +        ASSERT(image->stride[1] == image->stride[2]);
 | |
| +        const int uv_stride = image->stride[1];
 | |
| +        uint8_t* y_data = image->planes[0];
 | |
| +        uint8_t* u_data = image->planes[1];
 | |
| +        uint8_t* v_data = image->planes[2];
 | |
| +
 | |
| +        // TODO: redraw only damaged regions?
 | |
| +        libyuv::ARGBToI420(argb_data, argb_stride,
 | |
| +                            y_data, y_stride,
 | |
| +                            u_data, uv_stride,
 | |
| +                            v_data, uv_stride,
 | |
| +                            image->w, image->h);
 | |
| +    }
 | |
| +
 | |
| +private:
 | |
| +#if USE(CAIRO)
 | |
| +    RefPtr<cairo_surface_t> m_surface;
 | |
| +#elif PLATFORM(MAC)
 | |
| +    RetainPtr<CGImageRef> m_windowImage;
 | |
| +    Optional<double> m_scale;
 | |
| +#endif
 | |
| +    int m_duration = 0;
 | |
| +};
 | |
| +
 | |
| +
 | |
| +class ScreencastEncoder::VPXCodec {
 | |
| +public:
 | |
| +    VPXCodec(uint32_t fourcc, vpx_codec_ctx_t codec, vpx_codec_enc_cfg_t cfg, FILE* file)
 | |
| +        : m_encoderQueue(WorkQueue::create("Screencast encoder"))
 | |
| +        , m_fourcc(fourcc)
 | |
| +        , m_codec(codec)
 | |
| +        , m_cfg(cfg)
 | |
| +        , m_file(file)
 | |
| +    {
 | |
| +        ivf_write_file_header(m_file, &m_cfg, m_fourcc, 0);
 | |
| +
 | |
| +        createImage(cfg.g_w, cfg.g_h, m_image, m_imageBuffer);
 | |
| +    }
 | |
| +
 | |
| +    void encodeFrameAsync(std::unique_ptr<VPXFrame>&& frame)
 | |
| +    {
 | |
| +        m_encoderQueue->dispatch([this, frame = WTFMove(frame)] {
 | |
| +            frame->convertToVpxImage(m_image.get());
 | |
| +            // TODO: figure out why passing duration to the codec results in much
 | |
| +            // worse visual quality and makes video stutter.
 | |
| +            for (int i = 0; i < frame->duration(); i++)
 | |
| +                encodeFrame(m_image.get(), 1);
 | |
| +        });
 | |
| +    }
 | |
| +
 | |
| +    void finishAsync(Function<void()>&& callback)
 | |
| +    {
 | |
| +        m_encoderQueue->dispatch([this, callback = WTFMove(callback)] {
 | |
| +            finish();
 | |
| +            callback();
 | |
| +        });
 | |
| +    }
 | |
| +
 | |
| +private:
 | |
| +    bool encodeFrame(vpx_image_t *img, int duration)
 | |
| +    {
 | |
| +        vpx_codec_iter_t iter = nullptr;
 | |
| +        const vpx_codec_cx_pkt_t *pkt = nullptr;
 | |
| +        int flags = 0;
 | |
| +        const vpx_codec_err_t res = vpx_codec_encode(&m_codec, img, m_pts, duration, flags, VPX_DL_REALTIME);
 | |
| +        if (res != VPX_CODEC_OK) {
 | |
| +            fprintf(stderr, "Failed to encode frame: %s\n", vpx_codec_error(&m_codec));
 | |
| +            return false;
 | |
| +        }
 | |
| +
 | |
| +        bool gotPkts = false;
 | |
| +        while ((pkt = vpx_codec_get_cx_data(&m_codec, &iter)) != nullptr) {
 | |
| +            gotPkts = true;
 | |
| +
 | |
| +            if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
 | |
| +                ivf_write_frame_header(m_file, m_pts, pkt->data.frame.sz);
 | |
| +                if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, m_file) != pkt->data.frame.sz) {
 | |
| +                    fprintf(stderr, "Failed to write compressed frame\n");
 | |
| +                    return 0;
 | |
| +                }
 | |
| +                bool keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
 | |
| +                ++m_frameCount;
 | |
| +                fprintf(stderr, "  #%03d %spts=%" PRId64 " sz=%zd\n", m_frameCount, keyframe ? "[K] " : "", pkt->data.frame.pts, pkt->data.frame.sz);
 | |
| +                m_pts += pkt->data.frame.duration;
 | |
| +            }
 | |
| +        }
 | |
| +
 | |
| +        return gotPkts;
 | |
| +    }
 | |
| +
 | |
| +    void finish()
 | |
| +    {
 | |
| +        // Flush encoder.
 | |
| +        while (encodeFrame(nullptr, 1))
 | |
| +            ++m_frameCount;
 | |
| +
 | |
| +        rewind(m_file);
 | |
| +        // Update total frame count.
 | |
| +        ivf_write_file_header(m_file, &m_cfg, m_fourcc, m_frameCount);
 | |
| +        fclose(m_file);
 | |
| +        fprintf(stderr, "ScreencastEncoder::finish %d frames\n", m_frameCount);
 | |
| +    }
 | |
| +
 | |
| +    Ref<WorkQueue> m_encoderQueue;
 | |
| +    uint32_t m_fourcc { 0 };
 | |
| +    vpx_codec_ctx_t m_codec;
 | |
| +    vpx_codec_enc_cfg_t m_cfg;
 | |
| +    FILE* m_file { nullptr };
 | |
| +    int m_frameCount { 0 };
 | |
| +    int64_t m_pts { 0 };
 | |
| +    std::unique_ptr<uint8_t[]> m_imageBuffer;
 | |
| +    std::unique_ptr<vpx_image_t> m_image;
 | |
| +};
 | |
| +
 | |
| +ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec>&& vpxCodec, IntSize size, Optional<double> scale)
 | |
| +    : m_vpxCodec(WTFMove(vpxCodec))
 | |
| +    , m_size(size)
 | |
| +    , m_scale(scale)
 | |
| +{
 | |
| +    ASSERT(!size.isZero());
 | |
| +}
 | |
| +
 | |
| +ScreencastEncoder::~ScreencastEncoder()
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +static constexpr uint32_t vp8fourcc = 0x30385056;
 | |
| +static constexpr uint32_t vp9fourcc = 0x30395056;
 | |
| +static constexpr int fps = 30;
 | |
| +
 | |
| +RefPtr<ScreencastEncoder> ScreencastEncoder::create(String& errorString, const String& filePath, IntSize size, Optional<double> scale)
 | |
| +{
 | |
| +    const uint32_t fourcc = vp8fourcc;
 | |
| +    vpx_codec_iface_t* codec_interface = vpx_codec_vp8_cx();
 | |
| +    if (!codec_interface) {
 | |
| +        errorString = "Codec not found.";
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    if (size.width() <= 0 || size.height() <= 0 || (size.width() % 2) != 0 || (size.height() % 2) != 0) {
 | |
| +        errorString = makeString("Invalid frame size: "_s, size.width(), "x"_s, size.height());
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    vpx_codec_enc_cfg_t cfg;
 | |
| +    memset(&cfg, 0, sizeof(cfg));
 | |
| +    vpx_codec_err_t error = vpx_codec_enc_config_default(codec_interface, &cfg, 0);
 | |
| +    if (error) {
 | |
| +        errorString = makeString("Failed to get default codec config: "_s, vpx_codec_err_to_string(error));
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    cfg.g_w = size.width();
 | |
| +    cfg.g_h = size.height();
 | |
| +    cfg.g_timebase.num = 1;
 | |
| +    cfg.g_timebase.den = fps;
 | |
| +    cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
 | |
| +
 | |
| +    vpx_codec_ctx_t codec;
 | |
| +    if (vpx_codec_enc_init(&codec, codec_interface, &cfg, 0)) {
 | |
| +        errorString = makeString("Failed to initialize encoder: "_s, vpx_codec_error(&codec));
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    FILE* file = fopen(filePath.utf8().data(), "wb");
 | |
| +    if (!file) {
 | |
| +        errorString = makeString("Failed to open file '", filePath, "' for writing: ", strerror(errno));
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    std::unique_ptr<VPXCodec> vpxCodec(new VPXCodec(fourcc, codec, cfg, file));
 | |
| +    fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface));
 | |
| +    return adoptRef(new ScreencastEncoder(WTFMove(vpxCodec), size, scale));
 | |
| +}
 | |
| +
 | |
| +void ScreencastEncoder::flushLastFrame()
 | |
| +{
 | |
| +    MonotonicTime now = MonotonicTime::now();
 | |
| +    if (m_lastFrameTimestamp) {
 | |
| +        // If previous frame encoding failed for some rason leave the timestampt intact.
 | |
| +        if (!m_lastFrame)
 | |
| +            return;
 | |
| +
 | |
| +        Seconds seconds = now - m_lastFrameTimestamp;
 | |
| +        int duration = 1 + seconds.seconds() * fps; // Duration in timebase units
 | |
| +        m_lastFrame->setDuration(duration);
 | |
| +        m_vpxCodec->encodeFrameAsync(WTFMove(m_lastFrame));
 | |
| +    }
 | |
| +    m_lastFrameTimestamp = now;
 | |
| +}
 | |
| +
 | |
| +#if USE(CAIRO)
 | |
| +void ScreencastEncoder::encodeFrame(cairo_surface_t* drawingAreaSurface, IntSize size)
 | |
| +{
 | |
| +    fprintf(stderr, "ScreencastEncoder::encodeFrame\n");
 | |
| +    flushLastFrame();
 | |
| +    // Note that in WPE drawing area size is updated asynchronously and may differ from acutal
 | |
| +    // size of the surface.
 | |
| +    if (size.isZero()) {
 | |
| +        fprintf(stderr, "Cairo surface size is 0\n");
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    // TODO: adjust device scale factor?
 | |
| +    RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m_size.width(), m_size.height()));
 | |
| +    {
 | |
| +        RefPtr<cairo_t> cr = adoptRef(cairo_create(surface.get()));
 | |
| +
 | |
| +        // TODO: compare to libyuv scale functions?
 | |
| +        cairo_matrix_t transform;
 | |
| +        if (m_scale) {
 | |
| +            cairo_matrix_init_scale(&transform, *m_scale, *m_scale);
 | |
| +            cairo_transform(cr.get(), &transform);
 | |
| +        }
 | |
| +
 | |
| +        // Record top left part of the drawing area that fits into the frame.
 | |
| +        cairo_set_source_surface(cr.get(), drawingAreaSurface, 0, 0);
 | |
| +        cairo_paint(cr.get());
 | |
| +    }
 | |
| +    cairo_surface_flush(surface.get());
 | |
| +
 | |
| +    m_lastFrame = makeUnique<VPXFrame>(WTFMove(surface));
 | |
| +}
 | |
| +#elif PLATFORM(MAC)
 | |
| +void ScreencastEncoder::encodeFrame(RetainPtr<CGImageRef>&& windowImage)
 | |
| +{
 | |
| +    fprintf(stderr, "ScreencastEncoder::encodeFrame\n");
 | |
| +    flushLastFrame();
 | |
| +
 | |
| +    m_lastFrame = makeUnique<VPXFrame>(WTFMove(windowImage), m_scale);
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +void ScreencastEncoder::finish(Function<void()>&& callback)
 | |
| +{
 | |
| +    if (!m_vpxCodec) {
 | |
| +        callback();
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    flushLastFrame();
 | |
| +    m_vpxCodec->finishAsync([callback = WTFMove(callback)] () mutable {
 | |
| +        RunLoop::main().dispatch([callback = WTFMove(callback)] {
 | |
| +            callback();
 | |
| +        });
 | |
| +    });
 | |
| +}
 | |
| +
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..df283ee565b1691c49e68b79f40a72aefca77bf6
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
 | |
| @@ -0,0 +1,75 @@
 | |
| +/*
 | |
| + * Copyright (C) 2020 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#include <WebCore/IntSize.h>
 | |
| +#include <wtf/Forward.h>
 | |
| +#include <wtf/MonotonicTime.h>
 | |
| +#include <wtf/Noncopyable.h>
 | |
| +#include <wtf/ThreadSafeRefCounted.h>
 | |
| +#include <wtf/WeakPtr.h>
 | |
| +
 | |
| +#if USE(CAIRO)
 | |
| +#include <cairo.h>
 | |
| +#endif
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class WebPageProxy;
 | |
| +
 | |
| +class ScreencastEncoder : public ThreadSafeRefCounted<ScreencastEncoder> {
 | |
| +    WTF_MAKE_NONCOPYABLE(ScreencastEncoder);
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    static RefPtr<ScreencastEncoder> create(String& errorString, const String& filePath, WebCore::IntSize, Optional<double> scale);
 | |
| +
 | |
| +    class VPXCodec;
 | |
| +    ScreencastEncoder(std::unique_ptr<VPXCodec>&&, WebCore::IntSize, Optional<double> scale);
 | |
| +    ~ScreencastEncoder();
 | |
| +
 | |
| +#if USE(CAIRO)
 | |
| +    void encodeFrame(cairo_surface_t*, WebCore::IntSize);
 | |
| +#elif PLATFORM(MAC)
 | |
| +    void encodeFrame(RetainPtr<CGImageRef>&&);
 | |
| +#endif
 | |
| +
 | |
| +    void finish(Function<void()>&& callback);
 | |
| +
 | |
| +private:
 | |
| +    void flushLastFrame();
 | |
| +#if PLATFORM(MAC)
 | |
| +    static void imageToARGB(CGImageRef, uint8_t* rgba_data, int width, int height, Optional<double> scale);
 | |
| +#endif
 | |
| +
 | |
| +    std::unique_ptr<VPXCodec> m_vpxCodec;
 | |
| +    const WebCore::IntSize m_size;
 | |
| +    Optional<double> m_scale;
 | |
| +    MonotonicTime m_lastFrameTimestamp;
 | |
| +    class VPXFrame;
 | |
| +    std::unique_ptr<VPXFrame> m_lastFrame;
 | |
| +};
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp
 | |
| index 6928ca2fbfb6939062e3cd14bb7ba6f2fdc87f5f..621b99e233ed5cf504fedbd3ca3209c03bcd611f 100644
 | |
| --- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp
 | |
| +++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp
 | |
| @@ -27,11 +27,10 @@
 | |
|  #include "InspectorTargetProxy.h"
 | |
|  
 | |
|  #include "ProvisionalPageProxy.h"
 | |
| -#include "WebFrameProxy.h"
 | |
| +#include "WebPageInspectorController.h"
 | |
|  #include "WebPageInspectorTarget.h"
 | |
|  #include "WebPageMessages.h"
 | |
|  #include "WebPageProxy.h"
 | |
| -#include "WebProcessProxy.h"
 | |
|  
 | |
|  namespace WebKit {
 | |
|  
 | |
| @@ -39,18 +38,17 @@ using namespace Inspector;
 | |
|  
 | |
|  std::unique_ptr<InspectorTargetProxy> InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type)
 | |
|  {
 | |
| -    return makeUnique<InspectorTargetProxy>(page, targetId, type);
 | |
| +    return makeUnique<InspectorTargetProxy>(page, nullptr, targetId, type);
 | |
|  }
 | |
|  
 | |
| -std::unique_ptr<InspectorTargetProxy> InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId, Inspector::InspectorTargetType type)
 | |
| +std::unique_ptr<InspectorTargetProxy> InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId)
 | |
|  {
 | |
| -    auto target = InspectorTargetProxy::create(provisionalPage.page(), targetId, type);
 | |
| -    target->m_provisionalPage = makeWeakPtr(provisionalPage);
 | |
| -    return target;
 | |
| +    return makeUnique<InspectorTargetProxy>(provisionalPage.page(), &provisionalPage, targetId, Inspector::InspectorTargetType::Page);
 | |
|  }
 | |
|  
 | |
| -InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type)
 | |
| +InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, ProvisionalPageProxy* provisionalPage, const String& targetId, Inspector::InspectorTargetType type)
 | |
|      : m_page(page)
 | |
| +    , m_provisionalPage(makeWeakPtr(provisionalPage))
 | |
|      , m_identifier(targetId)
 | |
|      , m_type(type)
 | |
|  {
 | |
| @@ -97,6 +95,31 @@ void InspectorTargetProxy::didCommitProvisionalTarget()
 | |
|      m_provisionalPage = nullptr;
 | |
|  }
 | |
|  
 | |
| +void InspectorTargetProxy::willResume()
 | |
| +{
 | |
| +    if (m_page.hasRunningProcess())
 | |
| +        m_page.send(Messages::WebPage::ResumeInspectorIfPausedInNewWindow());
 | |
| +}
 | |
| +
 | |
| +void InspectorTargetProxy::activate(String& error)
 | |
| +{
 | |
| +    if (m_type != Inspector::InspectorTargetType::Page)
 | |
| +        return InspectorTarget::activate(error);
 | |
| +
 | |
| +    platformActivate(error);
 | |
| +}
 | |
| +
 | |
| +void InspectorTargetProxy::close(String& error, bool runBeforeUnload)
 | |
| +{
 | |
| +    if (m_type != Inspector::InspectorTargetType::Page)
 | |
| +        return InspectorTarget::close(error, runBeforeUnload);
 | |
| +
 | |
| +    if (runBeforeUnload)
 | |
| +        m_page.tryClose();
 | |
| +    else
 | |
| +        m_page.closePage();
 | |
| +}
 | |
| +
 | |
|  bool InspectorTargetProxy::isProvisional() const
 | |
|  {
 | |
|      return !!m_provisionalPage;
 | |
| diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h
 | |
| index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..79f3ff84327dc075ec96983e04db4b10343b7fae 100644
 | |
| --- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h
 | |
| +++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h
 | |
| @@ -37,13 +37,13 @@ class WebPageProxy;
 | |
|  // NOTE: This UIProcess side InspectorTarget doesn't care about the frontend channel, since
 | |
|  // any target -> frontend messages will be routed to the WebPageProxy with a targetId.
 | |
|  
 | |
| -class InspectorTargetProxy final : public Inspector::InspectorTarget {
 | |
| +class InspectorTargetProxy : public Inspector::InspectorTarget {
 | |
|      WTF_MAKE_FAST_ALLOCATED;
 | |
|      WTF_MAKE_NONCOPYABLE(InspectorTargetProxy);
 | |
|  public:
 | |
|      static std::unique_ptr<InspectorTargetProxy> create(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
 | |
| -    static std::unique_ptr<InspectorTargetProxy> create(ProvisionalPageProxy&, const String& targetId, Inspector::InspectorTargetType);
 | |
| -    InspectorTargetProxy(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
 | |
| +    static std::unique_ptr<InspectorTargetProxy> create(ProvisionalPageProxy&, const String& targetId);
 | |
| +    InspectorTargetProxy(WebPageProxy&, ProvisionalPageProxy*, const String& targetId, Inspector::InspectorTargetType);
 | |
|      ~InspectorTargetProxy() = default;
 | |
|  
 | |
|      Inspector::InspectorTargetType type() const final { return m_type; }
 | |
| @@ -55,12 +55,17 @@ public:
 | |
|      void connect(Inspector::FrontendChannel::ConnectionType) override;
 | |
|      void disconnect() override;
 | |
|      void sendMessageToTargetBackend(const String&) override;
 | |
| +    void activate(String& error) override;
 | |
| +    void close(String& error, bool runBeforeUnload) override;
 | |
|  
 | |
|  private:
 | |
| +    void willResume() override;
 | |
| +    void platformActivate(String& error) const;
 | |
| +
 | |
|      WebPageProxy& m_page;
 | |
| +    WeakPtr<ProvisionalPageProxy> m_provisionalPage;
 | |
|      String m_identifier;
 | |
|      Inspector::InspectorTargetType m_type;
 | |
| -    WeakPtr<ProvisionalPageProxy> m_provisionalPage;
 | |
|  };
 | |
|  
 | |
|  } // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
 | |
| index 1861cff806131196ea49b4f8aca6665beebbf6e8..da16f176bb7273727cea3046d2ec66a81fc53bb9 100644
 | |
| --- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
 | |
| +++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp
 | |
| @@ -26,12 +26,20 @@
 | |
|  #include "config.h"
 | |
|  #include "WebPageInspectorController.h"
 | |
|  
 | |
| +#include "APINavigation.h"
 | |
|  #include "InspectorBrowserAgent.h"
 | |
| +#include "InspectorDialogAgent.h"
 | |
| +#include "InspectorScreencastAgent.h"
 | |
|  #include "ProvisionalPageProxy.h"
 | |
|  #include "WebFrameProxy.h"
 | |
|  #include "WebPageInspectorAgentBase.h"
 | |
| +#include "WebPageInspectorEmulationAgent.h"
 | |
| +#include "WebPageInspectorInputAgent.h"
 | |
|  #include "WebPageInspectorTarget.h"
 | |
|  #include "WebPageProxy.h"
 | |
| +#include "WebPreferences.h"
 | |
| +#include <WebCore/ResourceError.h>
 | |
| +#include <WebCore/WindowFeatures.h>
 | |
|  #include <JavaScriptCore/InspectorAgentBase.h>
 | |
|  #include <JavaScriptCore/InspectorBackendDispatcher.h>
 | |
|  #include <JavaScriptCore/InspectorBackendDispatchers.h>
 | |
| @@ -48,27 +56,104 @@ 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_frontendRouter(FrontendRouter::create())
 | |
|      , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
 | |
|      , m_page(page)
 | |
|  {
 | |
| -    auto targetAgent = makeUnique<InspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
 | |
| -    m_targetAgent = targetAgent.get();
 | |
| -    m_agents.append(WTFMove(targetAgent));
 | |
|  }
 | |
|  
 | |
|  void WebPageInspectorController::init()
 | |
|  {
 | |
| +    auto targetAgent = makeUnique<InspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
 | |
| +    m_targetAgent = targetAgent.get();
 | |
| +    m_agents.append(WTFMove(targetAgent));
 | |
| +    auto emulationAgent = makeUnique<WebPageInspectorEmulationAgent>(m_backendDispatcher.get(), m_page);
 | |
| +    m_emulationAgent = emulationAgent.get();
 | |
| +    m_agents.append(WTFMove(emulationAgent));
 | |
| +    auto inputAgent = makeUnique<WebPageInspectorInputAgent>(m_backendDispatcher.get(), m_page);
 | |
| +    m_inputAgent = inputAgent.get();
 | |
| +    m_agents.append(WTFMove(inputAgent));
 | |
| +    m_agents.append(makeUnique<InspectorDialogAgent>(m_backendDispatcher.get(), m_frontendRouter.get(), m_page));
 | |
| +    auto screencastAgent = makeUnique<InspectorScreencastAgent>(m_backendDispatcher.get(), m_frontendRouter.get(), m_page);
 | |
| +    m_screecastAgent = screencastAgent.get();
 | |
| +    m_agents.append(WTFMove(screencastAgent));
 | |
| +    if (s_observer)
 | |
| +        s_observer->didCreateInspectorController(m_page);
 | |
| +
 | |
| +    // window.open will create page with already running process.
 | |
| +    if (!m_page.hasRunningProcess())
 | |
| +        return;
 | |
|      String pageTargetId = WebPageInspectorTarget::toTargetID(m_page.webPageID());
 | |
|      createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
 | |
|  }
 | |
|  
 | |
| +void WebPageInspectorController::didFinishAttachingToWebProcess()
 | |
| +{
 | |
| +    String pageTargetID = WebPageInspectorTarget::toTargetID(m_page.webPageID());
 | |
| +    // Create target only after attaching to a Web Process first time. Before that
 | |
| +    // we cannot event establish frontend connection.
 | |
| +    if (m_targets.contains(pageTargetID))
 | |
| +        return;
 | |
| +    createInspectorTarget(pageTargetID, Inspector::InspectorTargetType::Page);
 | |
| +}
 | |
| +
 | |
|  void WebPageInspectorController::pageClosed()
 | |
|  {
 | |
| +    String pageTargetId = WebPageInspectorTarget::toTargetID(m_page.webPageID());
 | |
| +    destroyInspectorTarget(pageTargetId);
 | |
| +
 | |
|      disconnectAllFrontends();
 | |
|  
 | |
|      m_agents.discardValues();
 | |
| +
 | |
| +    if (s_observer)
 | |
| +        s_observer->willDestroyInspectorController(m_page);
 | |
| +}
 | |
| +
 | |
| +bool WebPageInspectorController::pageCrashed(ProcessTerminationReason reason)
 | |
| +{
 | |
| +    if (reason != ProcessTerminationReason::Crash)
 | |
| +        return false;
 | |
| +    String targetId = WebPageInspectorTarget::toTargetID(m_page.webPageID());
 | |
| +    auto it = m_targets.find(targetId);
 | |
| +    if (it == m_targets.end())
 | |
| +        return false;
 | |
| +    m_targetAgent->targetCrashed(*it->value);
 | |
| +    m_targets.remove(it);
 | |
| +
 | |
| +    return m_targetAgent->isConnected();
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorController::willCreateNewPage(const WebCore::WindowFeatures& features, const URL& url)
 | |
| +{
 | |
| +    if (s_observer)
 | |
| +        s_observer->willCreateNewPage(m_page, features, url);
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorController::didShowPage()
 | |
| +{
 | |
| +    if (m_frontendRouter->hasFrontends())
 | |
| +        m_emulationAgent->didShowPage();
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorController::didProcessAllPendingKeyboardEvents()
 | |
| +{
 | |
| +    if (m_frontendRouter->hasFrontends())
 | |
| +        m_inputAgent->didProcessAllPendingKeyboardEvents();
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorController::didProcessAllPendingMouseEvents()
 | |
| +{
 | |
| +    if (m_frontendRouter->hasFrontends())
 | |
| +        m_inputAgent->didProcessAllPendingMouseEvents();
 | |
|  }
 | |
|  
 | |
|  bool WebPageInspectorController::hasLocalFrontend() const
 | |
| @@ -82,6 +167,17 @@ void WebPageInspectorController::connectFrontend(Inspector::FrontendChannel& fro
 | |
|  
 | |
|      bool connectingFirstFrontend = !m_frontendRouter->hasFrontends();
 | |
|  
 | |
| +    // HACK: forcefully disconnect remote connections to show local inspector starting with initial
 | |
| +    // agents' state.
 | |
| +    if (frontendChannel.connectionType() == Inspector::FrontendChannel::ConnectionType::Local &&
 | |
| +        !connectingFirstFrontend && !m_frontendRouter->hasLocalFrontend()) {
 | |
| +        disconnectAllFrontends();
 | |
| +        connectingFirstFrontend = true;
 | |
| +    }
 | |
| +
 | |
| +    if (connectingFirstFrontend)
 | |
| +        adjustPageSettings();
 | |
| +
 | |
|      m_frontendRouter->connectFrontend(frontendChannel);
 | |
|  
 | |
|      if (connectingFirstFrontend)
 | |
| @@ -100,8 +196,10 @@ void WebPageInspectorController::disconnectFrontend(FrontendChannel& frontendCha
 | |
|      m_frontendRouter->disconnectFrontend(frontendChannel);
 | |
|  
 | |
|      bool disconnectingLastFrontend = !m_frontendRouter->hasFrontends();
 | |
| -    if (disconnectingLastFrontend)
 | |
| +    if (disconnectingLastFrontend) {
 | |
|          m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectorDestroyed);
 | |
| +        m_pendingNavigations.clear();
 | |
| +    }
 | |
|  
 | |
|      m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
 | |
|  
 | |
| @@ -124,6 +222,8 @@ void WebPageInspectorController::disconnectAllFrontends()
 | |
|      // Disconnect any remaining remote frontends.
 | |
|      m_frontendRouter->disconnectAllFrontends();
 | |
|  
 | |
| +    m_pendingNavigations.clear();
 | |
| +
 | |
|      m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
 | |
|  
 | |
|  #if ENABLE(REMOTE_INSPECTOR)
 | |
| @@ -150,6 +250,66 @@ void WebPageInspectorController::setIndicating(bool indicating)
 | |
|  }
 | |
|  #endif
 | |
|  
 | |
| +#if USE(CAIRO)
 | |
| +void WebPageInspectorController::didPaint(cairo_surface_t* surface)
 | |
| +{
 | |
| +    if (!m_frontendRouter->hasFrontends())
 | |
| +        return;
 | |
| +
 | |
| +    m_screecastAgent->didPaint(surface);
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +
 | |
| +void WebPageInspectorController::navigate(WebCore::ResourceRequest&& request, WebFrameProxy* frame, NavigationHandler&& completionHandler)
 | |
| +{
 | |
| +    auto navigation = m_page.loadRequestForInspector(WTFMove(request), frame);
 | |
| +    if (!navigation) {
 | |
| +        completionHandler("Failed to navigate"_s, 0);
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    m_pendingNavigations.set(navigation->navigationID(), WTFMove(completionHandler));
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorController::didReceivePolicyDecision(WebCore::PolicyAction action, uint64_t navigationID)
 | |
| +{
 | |
| +    if (!m_frontendRouter->hasFrontends())
 | |
| +        return;
 | |
| +
 | |
| +    if (!navigationID)
 | |
| +        return;
 | |
| +
 | |
| +    auto completionHandler = m_pendingNavigations.take(navigationID);
 | |
| +    if (!completionHandler)
 | |
| +        return;
 | |
| +
 | |
| +    if (action == WebCore::PolicyAction::Ignore)
 | |
| +        completionHandler("Navigation cancelled"_s, 0);
 | |
| +    else
 | |
| +        completionHandler(String(), navigationID);
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorController::didDestroyNavigation(uint64_t navigationID)
 | |
| +{
 | |
| +    if (!m_frontendRouter->hasFrontends())
 | |
| +        return;
 | |
| +
 | |
| +    auto completionHandler = m_pendingNavigations.take(navigationID);
 | |
| +    if (!completionHandler)
 | |
| +        return;
 | |
| +
 | |
| +    // Inspector initiated navigation is destroyed before policy check only when it
 | |
| +    // becomes a fragment navigation (which always reuses current navigation).
 | |
| +    completionHandler(String(), 0);
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorController::didFailProvisionalLoadForFrame(uint64_t navigationID, const WebCore::ResourceError& error)
 | |
| +{
 | |
| +    if (s_observer)
 | |
| +        s_observer->didFailProvisionalLoad(m_page, navigationID, error.localizedDescription());
 | |
| +}
 | |
| +
 | |
|  void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
 | |
|  {
 | |
|      addTarget(InspectorTargetProxy::create(m_page, targetId, type));
 | |
| @@ -169,6 +329,33 @@ void WebPageInspectorController::sendMessageToInspectorFrontend(const String& ta
 | |
|      m_targetAgent->sendMessageFromTargetToFrontend(targetId, message);
 | |
|  }
 | |
|  
 | |
| +void WebPageInspectorController::setPauseOnStart(bool shouldPause)
 | |
| +{
 | |
| +    ASSERT(m_frontendRouter->hasFrontends());
 | |
| +    String errorString;
 | |
| +    m_targetAgent->setPauseOnStart(errorString, shouldPause);
 | |
| +}
 | |
| +
 | |
| +bool WebPageInspectorController::shouldPauseLoading() const
 | |
| +{
 | |
| +    if (!m_frontendRouter->hasFrontends())
 | |
| +        return false;
 | |
| +
 | |
| +    if (!m_page.isPageOpenedByDOMShowingInitialEmptyDocument())
 | |
| +        return false;
 | |
| +
 | |
| +    auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_page.webPageID()));
 | |
| +    ASSERT(target);
 | |
| +    return target->isPaused();
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorController::setContinueLoadingCallback(WTF::Function<void()>&& callback)
 | |
| +{
 | |
| +    auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_page.webPageID()));
 | |
| +    ASSERT(target);
 | |
| +    target->setResumeCallback(WTFMove(callback));
 | |
| +}
 | |
| +
 | |
|  bool WebPageInspectorController::shouldPauseLoading(const ProvisionalPageProxy& provisionalPage) const
 | |
|  {
 | |
|      if (!m_frontendRouter->hasFrontends())
 | |
| @@ -188,7 +375,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)
 | |
| @@ -212,6 +399,11 @@ void WebPageInspectorController::didCommitProvisionalPage(WebCore::PageIdentifie
 | |
|          m_targetAgent->targetDestroyed(*target);
 | |
|      m_targets.clear();
 | |
|      m_targets.set(newTarget->identifier(), WTFMove(newTarget));
 | |
| +
 | |
| +#if PLATFORM(WIN)
 | |
| +    if (m_frontendRouter->hasFrontends() && m_screecastAgent)
 | |
| +        m_screecastAgent->didCommitProvisionalPage();
 | |
| +#endif
 | |
|  }
 | |
|  
 | |
|  WebPageAgentContext WebPageInspectorController::webPageAgentContext()
 | |
| @@ -241,4 +433,20 @@ void WebPageInspectorController::addTarget(std::unique_ptr<InspectorTargetProxy>
 | |
|      m_targets.set(target->identifier(), WTFMove(target));
 | |
|  }
 | |
|  
 | |
| +void WebPageInspectorController::adjustPageSettings()
 | |
| +{
 | |
| +    // Set this to true as otherwise updating any preferences will override its
 | |
| +    // value in the Web Process to false (and InspectorController sets it locally
 | |
| +    // to true when frontend is connected).
 | |
| +    m_page.preferences().setDeveloperExtrasEnabled(true);
 | |
| +
 | |
| +    // Navigation to cached pages doesn't fire some of the events (e.g. execution context created)
 | |
| +    // that inspector depends on. So we disable the cache when front-end connects.
 | |
| +    m_page.preferences().setUsesBackForwardCache(false);
 | |
| +
 | |
| +    // Enable popup debugging.
 | |
| +    // TODO: allow to set preferences over the inspector protocol or find a better place for this.
 | |
| +    m_page.preferences().setJavaScriptCanOpenWindowsAutomatically(true);
 | |
| +}
 | |
| +
 | |
|  } // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
 | |
| index c2df3ceb4b69f32060dcbd90d04dc6cb5900de0d..af9c472a1b9137424081b3f1f9fd9448f00be17d 100644
 | |
| --- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
 | |
| +++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h
 | |
| @@ -26,17 +26,31 @@
 | |
|  #pragma once
 | |
|  
 | |
|  #include "InspectorTargetProxy.h"
 | |
| +#include "ProcessTerminationReason.h"
 | |
|  #include <JavaScriptCore/InspectorAgentRegistry.h>
 | |
|  #include <JavaScriptCore/InspectorTargetAgent.h>
 | |
|  #include <WebCore/PageIdentifier.h>
 | |
|  #include <wtf/Forward.h>
 | |
|  #include <wtf/Noncopyable.h>
 | |
|  #include <wtf/text/WTFString.h>
 | |
| +#include <wtf/URL.h>
 | |
| +
 | |
| +#if USE(CAIRO)
 | |
| +#include <cairo.h>
 | |
| +#endif
 | |
|  
 | |
|  namespace Inspector {
 | |
|  class BackendDispatcher;
 | |
|  class FrontendChannel;
 | |
|  class FrontendRouter;
 | |
| +class InspectorTarget;
 | |
| +}
 | |
| +
 | |
| +namespace WebCore {
 | |
| +class ResourceError;
 | |
| +class ResourceRequest;
 | |
| +enum class PolicyAction : uint8_t;
 | |
| +struct WindowFeatures;
 | |
|  }
 | |
|  
 | |
|  namespace WebKit {
 | |
| @@ -44,6 +58,22 @@ namespace WebKit {
 | |
|  class InspectorBrowserAgent;
 | |
|  struct WebPageAgentContext;
 | |
|  
 | |
| +class InspectorScreencastAgent;
 | |
| +class WebFrameProxy;
 | |
| +class WebPageInspectorEmulationAgent;
 | |
| +class WebPageInspectorInputAgent;
 | |
| +
 | |
| +class WebPageInspectorControllerObserver {
 | |
| +public:
 | |
| +    virtual void didCreateInspectorController(WebPageProxy&) = 0;
 | |
| +    virtual void willDestroyInspectorController(WebPageProxy&) = 0;
 | |
| +    virtual void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error) = 0;
 | |
| +    virtual void willCreateNewPage(WebPageProxy&, const WebCore::WindowFeatures&, const URL&) = 0;
 | |
| +
 | |
| +protected:
 | |
| +    virtual ~WebPageInspectorControllerObserver() = default;
 | |
| +};
 | |
| +
 | |
|  class WebPageInspectorController {
 | |
|      WTF_MAKE_NONCOPYABLE(WebPageInspectorController);
 | |
|      WTF_MAKE_FAST_ALLOCATED;
 | |
| @@ -51,7 +81,19 @@ public:
 | |
|      WebPageInspectorController(WebPageProxy&);
 | |
|  
 | |
|      void init();
 | |
| +    void didFinishAttachingToWebProcess();
 | |
| +
 | |
| +    static void setObserver(WebPageInspectorControllerObserver*);
 | |
| +
 | |
|      void pageClosed();
 | |
| +    bool pageCrashed(ProcessTerminationReason);
 | |
| +
 | |
| +    void willCreateNewPage(const WebCore::WindowFeatures&, const URL&);
 | |
| +
 | |
| +    void didShowPage();
 | |
| +
 | |
| +    void didProcessAllPendingKeyboardEvents();
 | |
| +    void didProcessAllPendingMouseEvents();
 | |
|  
 | |
|      bool hasLocalFrontend() const;
 | |
|  
 | |
| @@ -64,11 +106,25 @@ public:
 | |
|  #if ENABLE(REMOTE_INSPECTOR)
 | |
|      void setIndicating(bool);
 | |
|  #endif
 | |
| +#if USE(CAIRO)
 | |
| +    void didPaint(cairo_surface_t*);
 | |
| +#endif
 | |
| +    using NavigationHandler = Function<void(const String&, uint64_t)>;
 | |
| +    void navigate(WebCore::ResourceRequest&&, WebFrameProxy*, NavigationHandler&&);
 | |
| +    void didReceivePolicyDecision(WebCore::PolicyAction action, uint64_t navigationID);
 | |
| +    void didDestroyNavigation(uint64_t navigationID);
 | |
| +
 | |
| +    void didFailProvisionalLoadForFrame(uint64_t navigationID, const WebCore::ResourceError& error);
 | |
|  
 | |
|      void createInspectorTarget(const String& targetId, Inspector::InspectorTargetType);
 | |
|      void destroyInspectorTarget(const String& targetId);
 | |
|      void sendMessageToInspectorFrontend(const String& targetId, const String& message);
 | |
|  
 | |
| +    void setPauseOnStart(bool);
 | |
| +
 | |
| +    bool shouldPauseLoading() const;
 | |
| +    void setContinueLoadingCallback(WTF::Function<void()>&&);
 | |
| +
 | |
|      bool shouldPauseLoading(const ProvisionalPageProxy&) const;
 | |
|      void setContinueLoadingCallback(const ProvisionalPageProxy&, WTF::Function<void()>&&);
 | |
|  
 | |
| @@ -84,6 +140,7 @@ private:
 | |
|      void createLazyAgents();
 | |
|  
 | |
|      void addTarget(std::unique_ptr<InspectorTargetProxy>&&);
 | |
| +    void adjustPageSettings();
 | |
|  
 | |
|      Ref<Inspector::FrontendRouter> m_frontendRouter;
 | |
|      Ref<Inspector::BackendDispatcher> m_backendDispatcher;
 | |
| @@ -92,11 +149,17 @@ private:
 | |
|      WebPageProxy& m_page;
 | |
|  
 | |
|      Inspector::InspectorTargetAgent* m_targetAgent;
 | |
| +    WebPageInspectorEmulationAgent* m_emulationAgent { nullptr };
 | |
| +    WebPageInspectorInputAgent* m_inputAgent { nullptr };
 | |
| +    InspectorScreencastAgent* m_screecastAgent { nullptr };
 | |
|      HashMap<String, std::unique_ptr<InspectorTargetProxy>> m_targets;
 | |
|  
 | |
|      InspectorBrowserAgent* m_enabledBrowserAgent;
 | |
|  
 | |
|      bool m_didCreateLazyAgents { false };
 | |
| +    HashMap<uint64_t, NavigationHandler> m_pendingNavigations;
 | |
| +
 | |
| +    static WebPageInspectorControllerObserver* s_observer;
 | |
|  };
 | |
|  
 | |
|  } // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/Inspector/mac/ScreencastEncoderMac.mm b/Source/WebKit/UIProcess/Inspector/mac/ScreencastEncoderMac.mm
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..aa06bdfb5170428ace1143ae52b413ac6b987040
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/Inspector/mac/ScreencastEncoderMac.mm
 | |
| @@ -0,0 +1,51 @@
 | |
| +/*
 | |
| + * Copyright (C) 2020 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "ScreencastEncoder.h"
 | |
| +
 | |
| +#include <CoreGraphics/CoreGraphics.h>
 | |
| +#include <wtf/RetainPtr.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +void ScreencastEncoder::imageToARGB(CGImageRef image, uint8_t* argb_data, int width, int height, Optional<double> scale)
 | |
| +{
 | |
| +    size_t bitsPerComponent = 8;
 | |
| +    size_t bytesPerPixel = 4;
 | |
| +    size_t bytesPerRow = bytesPerPixel * width;
 | |
| +    RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
 | |
| +    RetainPtr<CGContextRef> context = adoptCF(CGBitmapContextCreate(argb_data, width, height, bitsPerComponent, bytesPerRow, colorSpace.get(), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little));
 | |
| +    if (scale) {
 | |
| +        CGContextScaleCTM(context.get(), *scale, *scale);
 | |
| +        // Ensure that top-left cornder stays in place.
 | |
| +        CGContextTranslateCTM(context.get(), 0, ((1 - *scale) / *scale) * height);
 | |
| +    }
 | |
| +    size_t imageWidth = CGImageGetWidth(image);
 | |
| +    size_t imageHeight = CGImageGetHeight(image);
 | |
| +    CGContextDrawImage(context.get(), CGRectMake(0, 0, imageWidth, imageHeight), image);
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/InspectorDialogAgent.cpp b/Source/WebKit/UIProcess/InspectorDialogAgent.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..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/InspectorPlaywrightAgent.cpp b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..cea80a8f37fe56b3dc6eb3b36744c70c43a74282
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp
 | |
| @@ -0,0 +1,819 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "InspectorPlaywrightAgent.h"
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +#include "APIPageConfiguration.h"
 | |
| +#include "FrameInfoData.h"
 | |
| +#include "InspectorPlaywrightAgentClient.h"
 | |
| +#include "InspectorTargetProxy.h"
 | |
| +#include "NetworkProcessMessages.h"
 | |
| +#include "NetworkProcessProxy.h"
 | |
| +#include "PageClient.h"
 | |
| +#include "WebAutomationSession.h"
 | |
| +#include "WebGeolocationManagerProxy.h"
 | |
| +#include "WebGeolocationPosition.h"
 | |
| +#include "WebPageInspectorController.h"
 | |
| +#include "WebPageInspectorTarget.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +#include "WebProcessPool.h"
 | |
| +#include "WebProcessProxy.h"
 | |
| +#include <WebCore/FrameIdentifier.h>
 | |
| +#include <WebCore/GeolocationPositionData.h>
 | |
| +#include <WebCore/InspectorPageAgent.h>
 | |
| +#include <WebCore/ProcessIdentifier.h>
 | |
| +#include <WebCore/ResourceRequest.h>
 | |
| +#include <WebCore/WindowFeatures.h>
 | |
| +#include <JavaScriptCore/InspectorBackendDispatcher.h>
 | |
| +#include <JavaScriptCore/InspectorFrontendChannel.h>
 | |
| +#include <JavaScriptCore/InspectorFrontendRouter.h>
 | |
| +#include <pal/SessionID.h>
 | |
| +#include <stdlib.h>
 | |
| +#include <wtf/HashMap.h>
 | |
| +#include <wtf/HexNumber.h>
 | |
| +#include <wtf/URL.h>
 | |
| +
 | |
| +
 | |
| +using namespace Inspector;
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class InspectorPlaywrightAgent::PageProxyChannel : public FrontendChannel {
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    PageProxyChannel(FrontendChannel& frontendChannel, String browserContextID, String pageProxyID, WebPageProxy& page)
 | |
| +        : m_browserContextID(browserContextID)
 | |
| +        , m_pageProxyID(pageProxyID)
 | |
| +        , m_frontendChannel(frontendChannel)
 | |
| +        , m_page(page)
 | |
| +    {
 | |
| +    }
 | |
| +
 | |
| +    ~PageProxyChannel() override = default;
 | |
| +
 | |
| +    void dispatchMessageFromFrontend(const String& message)
 | |
| +    {
 | |
| +        m_page.inspectorController().dispatchMessageFromFrontend(message);
 | |
| +    }
 | |
| +
 | |
| +    WebPageProxy& page() { return m_page; }
 | |
| +
 | |
| +    void disconnect()
 | |
| +    {
 | |
| +        m_page.inspectorController().disconnectFrontend(*this);
 | |
| +    }
 | |
| +
 | |
| +private:
 | |
| +    ConnectionType connectionType() const override { return m_frontendChannel.connectionType(); }
 | |
| +    void sendMessageToFrontend(const String& message) override
 | |
| +    {
 | |
| +        m_frontendChannel.sendMessageToFrontend(addTabIdToMessage(message));
 | |
| +    }
 | |
| +
 | |
| +    String addTabIdToMessage(const String& message) {
 | |
| +        RefPtr<JSON::Value> parsedMessage;
 | |
| +        if (!JSON::Value::parseJSON(message, parsedMessage))
 | |
| +            return message;
 | |
| +
 | |
| +        RefPtr<JSON::Object> messageObject;
 | |
| +        if (!parsedMessage->asObject(messageObject))
 | |
| +            return message;
 | |
| +
 | |
| +        messageObject->setString("browserContextId"_s, m_browserContextID);
 | |
| +        messageObject->setString("pageProxyId"_s, m_pageProxyID);
 | |
| +        return messageObject->toJSONString();
 | |
| +    }
 | |
| +
 | |
| +    String m_browserContextID;
 | |
| +    String m_pageProxyID;
 | |
| +    FrontendChannel& m_frontendChannel;
 | |
| +    WebPageProxy& m_page;
 | |
| +};
 | |
| +
 | |
| +namespace {
 | |
| +
 | |
| +String toBrowserContextIDProtocolString(const PAL::SessionID& sessionID)
 | |
| +{
 | |
| +    StringBuilder builder;
 | |
| +    builder.append(hex(sessionID.toUInt64(), 16));
 | |
| +    return builder.toString();
 | |
| +}
 | |
| +
 | |
| +String toPageProxyIDProtocolString(const WebPageProxy& page)
 | |
| +{
 | |
| +    return makeString(page.identifier().toUInt64());
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static RefPtr<JSON::ArrayOf<String>> getEnabledWindowFeatures(const WebCore::WindowFeatures& features) {
 | |
| +  auto result = JSON::ArrayOf<String>::create();
 | |
| +  if (features.x)
 | |
| +    result->addItem("left=" + String::number(*features.x));
 | |
| +  if (features.y)
 | |
| +    result->addItem("top=" + String::number(*features.y));
 | |
| +  if (features.width)
 | |
| +    result->addItem("width=" + String::number(*features.width));
 | |
| +  if (features.height)
 | |
| +    result->addItem("height=" + String::number(*features.height));
 | |
| +  if (features.menuBarVisible)
 | |
| +    result->addItem("menubar");
 | |
| +  if (features.toolBarVisible)
 | |
| +    result->addItem("toolbar");
 | |
| +  if (features.statusBarVisible)
 | |
| +    result->addItem("status");
 | |
| +  if (features.locationBarVisible)
 | |
| +    result->addItem("location");
 | |
| +  if (features.scrollbarsVisible)
 | |
| +    result->addItem("scrollbars");
 | |
| +  if (features.resizable)
 | |
| +    result->addItem("resizable");
 | |
| +  if (features.fullscreen)
 | |
| +    result->addItem("fullscreen");
 | |
| +  if (features.dialog)
 | |
| +    result->addItem("dialog");
 | |
| +  if (features.noopener)
 | |
| +    result->addItem("noopener");
 | |
| +  if (features.noreferrer)
 | |
| +    result->addItem("noreferrer");
 | |
| +  for (const auto& additionalFeature : features.additionalFeatures)
 | |
| +    result->addItem(additionalFeature);
 | |
| +  return result;
 | |
| +}
 | |
| +
 | |
| +Inspector::Protocol::Playwright::CookieSameSitePolicy cookieSameSitePolicy(WebCore::Cookie::SameSitePolicy policy)
 | |
| +{
 | |
| +    switch (policy) {
 | |
| +    case WebCore::Cookie::SameSitePolicy::None:
 | |
| +        return Inspector::Protocol::Playwright::CookieSameSitePolicy::None;
 | |
| +    case WebCore::Cookie::SameSitePolicy::Lax:
 | |
| +        return Inspector::Protocol::Playwright::CookieSameSitePolicy::Lax;
 | |
| +    case WebCore::Cookie::SameSitePolicy::Strict:
 | |
| +        return Inspector::Protocol::Playwright::CookieSameSitePolicy::Strict;
 | |
| +    }
 | |
| +    ASSERT_NOT_REACHED();
 | |
| +    return Inspector::Protocol::Playwright::CookieSameSitePolicy::None;
 | |
| +}
 | |
| +
 | |
| +Ref<Inspector::Protocol::Playwright::Cookie> buildObjectForCookie(const WebCore::Cookie& cookie)
 | |
| +{
 | |
| +    return Inspector::Protocol::Playwright::Cookie::create()
 | |
| +        .setName(cookie.name)
 | |
| +        .setValue(cookie.value)
 | |
| +        .setDomain(cookie.domain)
 | |
| +        .setPath(cookie.path)
 | |
| +        .setExpires(cookie.expires.valueOr(-1))
 | |
| +        .setHttpOnly(cookie.httpOnly)
 | |
| +        .setSecure(cookie.secure)
 | |
| +        .setSession(cookie.session)
 | |
| +        .setSameSite(cookieSameSitePolicy(cookie.sameSite))
 | |
| +        .release();
 | |
| +}
 | |
| +
 | |
| +}  // namespace
 | |
| +
 | |
| +Vector<WebPageProxy*> BrowserContext::pages() const {
 | |
| +    Vector<WebPageProxy*> pages;
 | |
| +    for (auto& process : processPool->processes()) {
 | |
| +        for (auto* page : process->pages())
 | |
| +            pages.append(page);
 | |
| +    }
 | |
| +    return pages;
 | |
| +}
 | |
| +
 | |
| +class InspectorPlaywrightAgent::BrowserContextDeletion {
 | |
| +    WTF_MAKE_NONCOPYABLE(BrowserContextDeletion);
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    BrowserContextDeletion(const BrowserContext& context, size_t numberOfPages, Ref<DeleteContextCallback>&& callback)
 | |
| +        : m_browserContext(context)
 | |
| +        , m_numberOfPages(numberOfPages)
 | |
| +        , m_callback(WTFMove(callback)) { }
 | |
| +
 | |
| +    void willDestroyPage(const WebPageProxy& page)
 | |
| +    {
 | |
| +        ASSERT(m_browserContext.dataStore->sessionID() == page.sessionID());
 | |
| +        // Check if new pages have been created during the context destruction and
 | |
| +        // close all of them if necessary.
 | |
| +        if (m_numberOfPages == 1) {
 | |
| +            Vector<WebPageProxy*> pages = m_browserContext.pages();
 | |
| +            size_t numberOfPages = pages.size();
 | |
| +            if (numberOfPages > 1) {
 | |
| +                m_numberOfPages = numberOfPages;
 | |
| +                for (auto* existingPage : pages) {
 | |
| +                    if (existingPage != &page)
 | |
| +                        existingPage->closePage();
 | |
| +                }
 | |
| +            }
 | |
| +        }
 | |
| +        --m_numberOfPages;
 | |
| +        if (m_numberOfPages)
 | |
| +            return;
 | |
| +        m_callback->sendSuccess();
 | |
| +    }
 | |
| +
 | |
| +    bool isFinished() const { return !m_numberOfPages; }
 | |
| +
 | |
| +private:
 | |
| +    BrowserContext m_browserContext;
 | |
| +    size_t m_numberOfPages;
 | |
| +    Ref<DeleteContextCallback> m_callback;
 | |
| +};
 | |
| +
 | |
| +
 | |
| +InspectorPlaywrightAgent::InspectorPlaywrightAgent(std::unique_ptr<InspectorPlaywrightAgentClient> client)
 | |
| +    : m_frontendChannel(nullptr)
 | |
| +    , m_frontendRouter(FrontendRouter::create())
 | |
| +    , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
 | |
| +    , m_client(std::move(client))
 | |
| +    , m_frontendDispatcher(makeUnique<PlaywrightFrontendDispatcher>(m_frontendRouter))
 | |
| +    , m_playwrightDispatcher(PlaywrightBackendDispatcher::create(m_backendDispatcher.get(), this))
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +InspectorPlaywrightAgent::~InspectorPlaywrightAgent()
 | |
| +{
 | |
| +    if (m_frontendChannel)
 | |
| +        disconnectFrontend();
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::connectFrontend(FrontendChannel& frontendChannel)
 | |
| +{
 | |
| +    ASSERT(!m_frontendChannel);
 | |
| +    m_frontendChannel = &frontendChannel;
 | |
| +    WebPageInspectorController::setObserver(this);
 | |
| +
 | |
| +    m_frontendRouter->connectFrontend(frontendChannel);
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::disconnectFrontend()
 | |
| +{
 | |
| +    ASSERT(m_frontendChannel);
 | |
| +
 | |
| +    ErrorString error;
 | |
| +    disable(error);
 | |
| +
 | |
| +    m_frontendRouter->disconnectFrontend(*m_frontendChannel);
 | |
| +    ASSERT(!m_frontendRouter->hasFrontends());
 | |
| +
 | |
| +    WebPageInspectorController::setObserver(nullptr);
 | |
| +    m_frontendChannel = nullptr;
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::dispatchMessageFromFrontend(const String& message)
 | |
| +{
 | |
| +    m_backendDispatcher->dispatch(message, [&](const RefPtr<JSON::Object>& messageObject) {
 | |
| +        RefPtr<JSON::Value> idValue;
 | |
| +        if (!messageObject->getValue("id"_s, idValue))
 | |
| +            return BackendDispatcher::InterceptionResult::Continue;
 | |
| +        RefPtr<JSON::Value> pageProxyIDValue;
 | |
| +        if (!messageObject->getValue("pageProxyId"_s, pageProxyIDValue))
 | |
| +            return BackendDispatcher::InterceptionResult::Continue;
 | |
| +
 | |
| +        String pageProxyID;
 | |
| +        if (!pageProxyIDValue->asString(pageProxyID)) {
 | |
| +            m_backendDispatcher->reportProtocolError(BackendDispatcher::InvalidRequest, "The type of 'pageProxyId' must be string"_s);
 | |
| +            m_backendDispatcher->sendPendingErrors();
 | |
| +            return BackendDispatcher::InterceptionResult::Intercepted;
 | |
| +        }
 | |
| +
 | |
| +        if (auto pageProxyChannel = m_pageProxyChannels.get(pageProxyID)) {
 | |
| +            pageProxyChannel->dispatchMessageFromFrontend(message);
 | |
| +            return BackendDispatcher::InterceptionResult::Intercepted;
 | |
| +        }
 | |
| +
 | |
| +        long requestId = 0;
 | |
| +        if (!idValue->asInteger(requestId)) {
 | |
| +            m_backendDispatcher->reportProtocolError(BackendDispatcher::InvalidRequest, "The type of 'id' must be number"_s);
 | |
| +            m_backendDispatcher->sendPendingErrors();
 | |
| +            return BackendDispatcher::InterceptionResult::Intercepted;
 | |
| +        }
 | |
| +
 | |
| +        m_backendDispatcher->reportProtocolError(requestId, BackendDispatcher::InvalidParams, "Cannot find page proxy with provided 'pageProxyId'"_s);
 | |
| +        m_backendDispatcher->sendPendingErrors();
 | |
| +        return BackendDispatcher::InterceptionResult::Intercepted;
 | |
| +    });
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::didCreateInspectorController(WebPageProxy& page)
 | |
| +{
 | |
| +    if (!m_isEnabled)
 | |
| +        return;
 | |
| +
 | |
| +    ASSERT(m_frontendChannel);
 | |
| +
 | |
| +    String browserContextID = toBrowserContextIDProtocolString(page.sessionID());
 | |
| +    String pageProxyID = toPageProxyIDProtocolString(page);
 | |
| +    auto* opener = page.configuration().relatedPage();
 | |
| +    String openerId;
 | |
| +    if (opener)
 | |
| +        openerId = toPageProxyIDProtocolString(*opener);
 | |
| +
 | |
| +    m_frontendDispatcher->pageProxyCreated(
 | |
| +        browserContextID, pageProxyID, openerId.isNull() ? nullptr : &openerId);
 | |
| +
 | |
| +    // Auto-connect to all new pages.
 | |
| +    auto pageProxyChannel = makeUnique<PageProxyChannel>(*m_frontendChannel, browserContextID, pageProxyID, page);
 | |
| +    page.inspectorController().connectFrontend(*pageProxyChannel);
 | |
| +    // Always pause new targets if controlled remotely.
 | |
| +    page.inspectorController().setPauseOnStart(true);
 | |
| +    m_pageProxyChannels.set(pageProxyID, WTFMove(pageProxyChannel));
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::willDestroyInspectorController(WebPageProxy& page)
 | |
| +{
 | |
| +    if (!m_isEnabled)
 | |
| +        return;
 | |
| +
 | |
| +    m_frontendDispatcher->pageProxyDestroyed(
 | |
| +        toBrowserContextIDProtocolString(page.sessionID()),
 | |
| +        toPageProxyIDProtocolString(page));
 | |
| +
 | |
| +    auto it = m_browserContextDeletions.find(page.sessionID());
 | |
| +    if (it != m_browserContextDeletions.end()) {
 | |
| +        it->value->willDestroyPage(page);
 | |
| +        if (it->value->isFinished())
 | |
| +            m_browserContextDeletions.remove(it);
 | |
| +    }
 | |
| +
 | |
| +    String pageProxyID = toPageProxyIDProtocolString(page);
 | |
| +    auto channelIt = m_pageProxyChannels.find(pageProxyID);
 | |
| +    ASSERT(channelIt != m_pageProxyChannels.end());
 | |
| +    channelIt->value->disconnect();
 | |
| +    m_pageProxyChannels.remove(channelIt);
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::didFailProvisionalLoad(WebPageProxy& page, uint64_t navigationID, const String& error)
 | |
| +{
 | |
| +    if (!m_isEnabled)
 | |
| +        return;
 | |
| +
 | |
| +    m_frontendDispatcher->provisionalLoadFailed(
 | |
| +        toBrowserContextIDProtocolString(page.sessionID()),
 | |
| +        toPageProxyIDProtocolString(page),
 | |
| +        String::number(navigationID), error);
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::willCreateNewPage(WebPageProxy& page, const WebCore::WindowFeatures& features, const URL& url)
 | |
| +{
 | |
| +    if (!m_isEnabled)
 | |
| +        return;
 | |
| +
 | |
| +    m_frontendDispatcher->windowOpen(
 | |
| +        toBrowserContextIDProtocolString(page.sessionID()),
 | |
| +        toPageProxyIDProtocolString(page),
 | |
| +        url.string(),
 | |
| +        getEnabledWindowFeatures(features));
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::enable(ErrorString&)
 | |
| +{
 | |
| +    if (m_isEnabled)
 | |
| +        return;
 | |
| +
 | |
| +    m_isEnabled = true;
 | |
| +    for (auto& pool : WebProcessPool::allProcessPools()) {
 | |
| +        auto* dataStore = pool->websiteDataStore();
 | |
| +        if (dataStore)
 | |
| +            dataStore->setDownloadInstrumentation(this);
 | |
| +        for (auto& process : pool->processes()) {
 | |
| +            for (auto* page : process->pages())
 | |
| +                didCreateInspectorController(*page);
 | |
| +        }
 | |
| +    }
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::disable(ErrorString&)
 | |
| +{
 | |
| +    if (!m_isEnabled)
 | |
| +        return;
 | |
| +
 | |
| +    m_isEnabled = false;
 | |
| +
 | |
| +    for (auto it = m_pageProxyChannels.begin(); it != m_pageProxyChannels.end(); ++it)
 | |
| +        it->value->disconnect();
 | |
| +    m_pageProxyChannels.clear();
 | |
| +
 | |
| +    for (auto& pool : WebProcessPool::allProcessPools()) {
 | |
| +        auto* dataStore = pool->websiteDataStore();
 | |
| +        if (dataStore) {
 | |
| +            dataStore->setDownloadInstrumentation(nullptr);
 | |
| +            dataStore->setDownloadForAutomation(Optional<bool>(), String());
 | |
| +        }
 | |
| +    }
 | |
| +    for (auto& it : m_browserContexts)
 | |
| +        it.value.dataStore->setDownloadInstrumentation(nullptr);
 | |
| +    m_browserContextDeletions.clear();
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::close(Ref<CloseCallback>&& callback)
 | |
| +{
 | |
| +    Vector<WebPageProxy*> pages;
 | |
| +    for (auto& pool : WebProcessPool::allProcessPools()) {
 | |
| +        for (auto& process : pool->processes()) {
 | |
| +            for (auto* page : process->pages())
 | |
| +                pages.append(page);
 | |
| +        }
 | |
| +    }
 | |
| +    for (auto* page : pages)
 | |
| +        page->closePage();
 | |
| +
 | |
| +    if (!WebProcessPool::allProcessPools().size()) {
 | |
| +        m_client->closeBrowser();
 | |
| +        callback->sendSuccess();
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    WebProcessPool::allProcessPools().first()->syncLocalStorage([this, callback = WTFMove(callback)] () {
 | |
| +        if (!callback->isActive())
 | |
| +            return;
 | |
| +
 | |
| +        m_browserContexts.clear();
 | |
| +        if (m_client == nullptr) {
 | |
| +            callback->sendFailure("no platform delegate to close browser");
 | |
| +        } else {
 | |
| +            m_client->closeBrowser();
 | |
| +            callback->sendSuccess();
 | |
| +        }
 | |
| +    });
 | |
| +
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::createContext(ErrorString& errorString, const String* proxyServer, const String* proxyBypassList, String* browserContextID)
 | |
| +{
 | |
| +    BrowserContext browserContext = m_client->createBrowserContext(errorString, proxyServer ? *proxyServer : String(), proxyBypassList ? *proxyBypassList : String());
 | |
| +    if (!errorString.isEmpty())
 | |
| +        return;
 | |
| +    browserContext.processPool->setPrimaryDataStore(*browserContext.dataStore);
 | |
| +    browserContext.processPool->ensureNetworkProcess(browserContext.dataStore.get());
 | |
| +    browserContext.dataStore->setDownloadInstrumentation(this);
 | |
| +
 | |
| +    PAL::SessionID sessionID = browserContext.dataStore->sessionID();
 | |
| +    *browserContextID = toBrowserContextIDProtocolString(sessionID);
 | |
| +    m_browserContexts.set(*browserContextID, browserContext);
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::deleteContext(const String& browserContextID, Ref<DeleteContextCallback>&& callback)
 | |
| +{
 | |
| +    String errorString;
 | |
| +    BrowserContext browserContext = lookupBrowserContext(errorString, &browserContextID);
 | |
| +    if (!errorString.isEmpty()) {
 | |
| +        callback->sendFailure(errorString);
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    Vector<WebPageProxy*> pages = browserContext.pages();
 | |
| +    PAL::SessionID sessionID = browserContext.dataStore->sessionID();
 | |
| +    m_browserContexts.remove(browserContextID);
 | |
| +    if (pages.isEmpty()) {
 | |
| +        callback->sendSuccess();
 | |
| +    } else {
 | |
| +        m_browserContextDeletions.set(sessionID, makeUnique<BrowserContextDeletion>(browserContext, pages.size(), WTFMove(callback)));
 | |
| +        for (auto* page : pages)
 | |
| +            page->closePage();
 | |
| +    }
 | |
| +    m_client->deleteBrowserContext(errorString, sessionID);
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::createPage(ErrorString& errorString, const String* browserContextID, String* pageProxyID)
 | |
| +{
 | |
| +    BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
 | |
| +    if (!errorString.isEmpty())
 | |
| +        return;
 | |
| +    RefPtr<WebPageProxy> page = m_client->createPage(errorString, browserContext);
 | |
| +    if (!page)
 | |
| +        return;
 | |
| +    *pageProxyID = toPageProxyIDProtocolString(*page);
 | |
| +}
 | |
| +
 | |
| +WebFrameProxy* InspectorPlaywrightAgent::frameForID(const String& frameID, String& error)
 | |
| +{
 | |
| +    size_t dotPos = frameID.find(".");
 | |
| +    if (dotPos == notFound) {
 | |
| +        error = "Invalid frame id"_s;
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    if (!frameID.isAllASCII()) {
 | |
| +        error = "Invalid frame id"_s;
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    String processIDString = frameID.left(dotPos);
 | |
| +    uint64_t pid = strtoull(processIDString.ascii().data(), 0, 10);
 | |
| +    auto processID = makeObjectIdentifier<WebCore::ProcessIdentifierType>(pid);
 | |
| +    WebProcessProxy* process = WebProcessProxy::processForIdentifier(processID);
 | |
| +    if (!process) {
 | |
| +        error = "Cannot find web process for the frame id"_s;
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    String frameIDString = frameID.substring(dotPos + 1);
 | |
| +    uint64_t frameIDNumber = strtoull(frameIDString.ascii().data(), 0, 10);
 | |
| +    auto frameIdentifier = makeObjectIdentifier<WebCore::FrameIdentifierType>(frameIDNumber);
 | |
| +    WebFrameProxy* frame = process->webFrame(frameIdentifier);
 | |
| +    if (!frame) {
 | |
| +        error = "Cannot find web frame for the frame id"_s;
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    return frame;
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::navigate(const String& url, const String& pageProxyID, const String* frameID, const String* referrer, Ref<NavigateCallback>&& callback)
 | |
| +{
 | |
| +    auto* pageProxyChannel = m_pageProxyChannels.get(pageProxyID);
 | |
| +    if (!pageProxyChannel) {
 | |
| +        callback->sendFailure("Cannot find page proxy with provided 'pageProxyId'"_s);
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    WebCore::ResourceRequest resourceRequest { url };
 | |
| +
 | |
| +    if (referrer)
 | |
| +        resourceRequest.setHTTPReferrer(*referrer);
 | |
| +
 | |
| +    if (!resourceRequest.url().isValid()) {
 | |
| +        callback->sendFailure("Cannot navigate to invalid URL"_s);
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    WebFrameProxy* frame = nullptr;
 | |
| +    if (frameID) {
 | |
| +        String error;
 | |
| +        frame = frameForID(*frameID, error);
 | |
| +        if (!frame) {
 | |
| +            callback->sendFailure(error);
 | |
| +            return;
 | |
| +        }
 | |
| +
 | |
| +        if (frame->page() != &pageProxyChannel->page()) {
 | |
| +            callback->sendFailure("Frame with specified is not from the specified page"_s);
 | |
| +            return;
 | |
| +        }
 | |
| +    }
 | |
| +
 | |
| +    pageProxyChannel->page().inspectorController().navigate(WTFMove(resourceRequest), frame, [callback = WTFMove(callback)](const String& error, uint64_t navigationID) {
 | |
| +        if (!error.isEmpty()) {
 | |
| +            callback->sendFailure(error);
 | |
| +            return;
 | |
| +        }
 | |
| +
 | |
| +        Optional<String> navigationIDString;
 | |
| +        if (navigationID)
 | |
| +            navigationIDString = String::number(navigationID);
 | |
| +        callback->sendSuccess(navigationIDString);
 | |
| +    });
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::setIgnoreCertificateErrors(ErrorString& errorString, const String* browserContextID, bool ignore)
 | |
| +{
 | |
| +    BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
 | |
| +    if (!errorString.isEmpty())
 | |
| +        return;
 | |
| +
 | |
| +    PAL::SessionID sessionID = browserContext.dataStore->sessionID();
 | |
| +    NetworkProcessProxy* networkProcess = browserContext.processPool->networkProcess();
 | |
| +    networkProcess->send(Messages::NetworkProcess::SetIgnoreCertificateErrors(sessionID, ignore), 0);
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::getAllCookies(const String* browserContextID, Ref<GetAllCookiesCallback>&& callback) {
 | |
| +    String errorString;
 | |
| +    BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
 | |
| +    if (!errorString.isEmpty()) {
 | |
| +        callback->sendFailure(errorString);
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    PAL::SessionID sessionID = browserContext.dataStore->sessionID();
 | |
| +    NetworkProcessProxy* networkProcess = browserContext.processPool->networkProcess();
 | |
| +    networkProcess->sendWithAsyncReply(Messages::NetworkProcess::GetAllCookies(sessionID),
 | |
| +        [callback = WTFMove(callback)](Vector<WebCore::Cookie> allCookies) {
 | |
| +            if (!callback->isActive())
 | |
| +                return;
 | |
| +            auto cookies = JSON::ArrayOf<Inspector::Protocol::Playwright::Cookie>::create();
 | |
| +            for (const auto& cookie : allCookies)
 | |
| +                cookies->addItem(buildObjectForCookie(cookie));
 | |
| +            callback->sendSuccess(WTFMove(cookies));
 | |
| +        }, 0);
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::setCookies(const String* browserContextID, const JSON::Array& in_cookies, Ref<SetCookiesCallback>&& callback) {
 | |
| +    String errorString;
 | |
| +    BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
 | |
| +    if (!errorString.isEmpty()) {
 | |
| +        callback->sendFailure(errorString);
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    NetworkProcessProxy* networkProcess = browserContext.processPool->networkProcess();
 | |
| +    PAL::SessionID sessionID = browserContext.dataStore->sessionID();
 | |
| +
 | |
| +    Vector<WebCore::Cookie> cookies;
 | |
| +    for (unsigned i = 0; i < in_cookies.length(); ++i) {
 | |
| +        RefPtr<JSON::Value> item = in_cookies.get(i);
 | |
| +        RefPtr<JSON::Object> obj;
 | |
| +        if (!item->asObject(obj)) {
 | |
| +            errorString = "Invalid cookie payload format"_s;
 | |
| +            return;
 | |
| +        }
 | |
| +
 | |
| +        WebCore::Cookie cookie;
 | |
| +        if (!obj->getString("name", cookie.name) ||
 | |
| +            !obj->getString("value", cookie.value) ||
 | |
| +            !obj->getString("domain", cookie.domain) ||
 | |
| +            !obj->getString("path", cookie.path)) {
 | |
| +            errorString = "Invalid file payload format"_s;
 | |
| +            return;
 | |
| +        }
 | |
| +
 | |
| +        double expires;
 | |
| +        if (obj->getDouble("expires", expires) && expires != -1)
 | |
| +            cookie.expires = expires;
 | |
| +        obj->getBoolean("httpOnly", cookie.httpOnly);
 | |
| +        obj->getBoolean("secure", cookie.secure);
 | |
| +        obj->getBoolean("session", cookie.session);
 | |
| +        String sameSite;
 | |
| +        if (obj->getString("sameSite", sameSite)) {
 | |
| +            if (sameSite == "None")
 | |
| +                cookie.sameSite = WebCore::Cookie::SameSitePolicy::None;
 | |
| +            if (sameSite == "Lax")
 | |
| +                cookie.sameSite = WebCore::Cookie::SameSitePolicy::Lax;
 | |
| +            if (sameSite == "Strict")
 | |
| +                cookie.sameSite = WebCore::Cookie::SameSitePolicy::Strict;
 | |
| +        }
 | |
| +        cookies.append(WTFMove(cookie));
 | |
| +    }
 | |
| +
 | |
| +    networkProcess->sendWithAsyncReply(Messages::NetworkProcess::SetCookies(sessionID, WTFMove(cookies)),
 | |
| +        [callback = WTFMove(callback)](bool success) {
 | |
| +            if (!callback->isActive())
 | |
| +                return;
 | |
| +
 | |
| +            if (success)
 | |
| +                callback->sendSuccess();
 | |
| +            else
 | |
| +                callback->sendFailure("Internal error: no network storage"_s);
 | |
| +            callback->sendSuccess();
 | |
| +        }, 0);
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::deleteAllCookies(const String* browserContextID, Ref<DeleteAllCookiesCallback>&& callback) {
 | |
| +    String errorString;
 | |
| +    BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
 | |
| +    if (!errorString.isEmpty()) {
 | |
| +        callback->sendFailure(errorString);
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    NetworkProcessProxy* networkProcess = browserContext.processPool->networkProcess();
 | |
| +    PAL::SessionID sessionID = browserContext.dataStore->sessionID();
 | |
| +    networkProcess->sendWithAsyncReply(Messages::NetworkProcess::DeleteAllCookies(sessionID),
 | |
| +        [callback = WTFMove(callback)](bool success) {
 | |
| +            if (!callback->isActive())
 | |
| +                return;
 | |
| +            if (success)
 | |
| +                callback->sendSuccess();
 | |
| +            else
 | |
| +                callback->sendFailure("Internal error: no network storage"_s);
 | |
| +        }, 0);
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::setLanguages(ErrorString& errorString, const JSON::Array& languages, const String* browserContextID)
 | |
| +{
 | |
| +    BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
 | |
| +    if (!errorString.isEmpty())
 | |
| +        return;
 | |
| +
 | |
| +    Vector<String> items;
 | |
| +    for (const auto& value : languages) {
 | |
| +        String language;
 | |
| +        if (!value->asString(language)) {
 | |
| +            errorString = "Language must be a string"_s;
 | |
| +            return;
 | |
| +        }
 | |
| +        items.append(language);
 | |
| +    }
 | |
| +
 | |
| +    browserContext.dataStore->setLanguagesForAutomation(WTFMove(items));
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::setDownloadBehavior(ErrorString& errorString, const String* behavior, const String* downloadPath, const String* browserContextID)
 | |
| +{
 | |
| +    BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
 | |
| +    if (!errorString.isEmpty())
 | |
| +        return;
 | |
| +    Optional<bool> allow;
 | |
| +    if (behavior && *behavior == "allow"_s)
 | |
| +      allow = true;
 | |
| +    if (behavior && *behavior == "deny"_s)
 | |
| +      allow = false;
 | |
| +    browserContext.dataStore->setDownloadForAutomation(allow, downloadPath ? *downloadPath : String());
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::setGeolocationOverride(ErrorString& errorString, const String* browserContextID, const JSON::Object* geolocation)
 | |
| +{
 | |
| +    BrowserContext browserContext = lookupBrowserContext(errorString, browserContextID);
 | |
| +    if (!errorString.isEmpty())
 | |
| +        return;
 | |
| +    auto* geoManager = browserContext.processPool->supplement<WebGeolocationManagerProxy>();
 | |
| +    if (!geoManager) {
 | |
| +        errorString = "Internal error: geolocation manager is not available."_s;
 | |
| +        return;
 | |
| +    }
 | |
| +    if (geolocation) {
 | |
| +        double timestamp = 0;
 | |
| +        double latitude = 0;
 | |
| +        double longitude = 0;
 | |
| +        double accuracy = 0;
 | |
| +        if (!geolocation->getDouble("timestamp"_s, timestamp) ||
 | |
| +            !geolocation->getDouble("latitude"_s, latitude) ||
 | |
| +            !geolocation->getDouble("longitude"_s, longitude) ||
 | |
| +            !geolocation->getDouble("accuracy"_s, accuracy)) {
 | |
| +            errorString = "Invalid geolocation format"_s;
 | |
| +            return;
 | |
| +        }
 | |
| +        auto position = WebGeolocationPosition::create(WebCore::GeolocationPositionData(timestamp, latitude, longitude, accuracy));
 | |
| +        geoManager->providerDidChangePosition(&position.get());
 | |
| +    } else {
 | |
| +        geoManager->providerDidFailToDeterminePosition("Position unavailable"_s);
 | |
| +    }
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::downloadCreated(const WebsiteDataStore& dataStore, const String& uuid, const WebCore::ResourceRequest& request, const FrameInfoData& frameInfoData, WebPageProxy* page)
 | |
| +{
 | |
| +    if (!m_isEnabled)
 | |
| +        return;
 | |
| +    String frameID = WebCore::InspectorPageAgent::makeFrameID(page->process().coreProcessIdentifier(), frameInfoData.frameID ? *frameInfoData.frameID : page->mainFrame()->frameID());
 | |
| +    m_frontendDispatcher->downloadCreated(
 | |
| +        toBrowserContextIDProtocolString(dataStore.sessionID()),
 | |
| +        toPageProxyIDProtocolString(*page),
 | |
| +        frameID,
 | |
| +        uuid, request.url().string());
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::downloadFilenameSuggested(const WebsiteDataStore& dataStore, const String& uuid, const String& suggestedFilename)
 | |
| +{
 | |
| +    if (!m_isEnabled)
 | |
| +        return;
 | |
| +    m_frontendDispatcher->downloadFilenameSuggested(
 | |
| +        toBrowserContextIDProtocolString(dataStore.sessionID()),
 | |
| +        uuid, suggestedFilename);
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgent::downloadFinished(const WebsiteDataStore& dataStore, const String& uuid, const String& error)
 | |
| +{
 | |
| +    if (!m_isEnabled)
 | |
| +        return;
 | |
| +    m_frontendDispatcher->downloadFinished(
 | |
| +        toBrowserContextIDProtocolString(dataStore.sessionID()),
 | |
| +        uuid, error);
 | |
| +}
 | |
| +
 | |
| +BrowserContext InspectorPlaywrightAgent::lookupBrowserContext(ErrorString& errorString, const String* browserContextID)
 | |
| +{
 | |
| +    if (!browserContextID) {
 | |
| +        BrowserContext context;
 | |
| +        if (!WebProcessPool::allProcessPools().size()) {
 | |
| +            errorString = "Browser started with no default context"_s;
 | |
| +            return context;
 | |
| +        }
 | |
| +        auto* pool = WebProcessPool::allProcessPools().first();
 | |
| +        context.processPool = pool;
 | |
| +        context.dataStore = pool->websiteDataStore();
 | |
| +        return context;
 | |
| +    }
 | |
| +
 | |
| +    BrowserContext browserContext = m_browserContexts.get(*browserContextID);
 | |
| +    if (!browserContext.processPool)
 | |
| +        errorString = "Could not find browser context for given id"_s;
 | |
| +    return browserContext;
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..7b1b0c063c792ce7dddf338242d1914539cae76d
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h
 | |
| @@ -0,0 +1,119 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +#include "InspectorPlaywrightAgentClient.h"
 | |
| +#include <JavaScriptCore/InspectorBackendDispatchers.h>
 | |
| +#include "WebPageInspectorController.h"
 | |
| +#include "WebProcessPool.h"
 | |
| +#include <wtf/HashMap.h>
 | |
| +#include <wtf/Forward.h>
 | |
| +#include <wtf/Noncopyable.h>
 | |
| +
 | |
| +namespace Inspector {
 | |
| +class BackendDispatcher;
 | |
| +class FrontendChannel;
 | |
| +class FrontendRouter;
 | |
| +class PlaywrightFrontendDispatcher;
 | |
| +}
 | |
| +
 | |
| +namespace PAL {
 | |
| +class SessionID;
 | |
| +}
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class WebFrameProxy;
 | |
| +
 | |
| +class InspectorPlaywrightAgent final
 | |
| +    : public WebPageInspectorControllerObserver
 | |
| +    , public Inspector::PlaywrightBackendDispatcherHandler
 | |
| +    , public DownloadInstrumentation {
 | |
| +    WTF_MAKE_NONCOPYABLE(InspectorPlaywrightAgent);
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    explicit InspectorPlaywrightAgent(std::unique_ptr<InspectorPlaywrightAgentClient> client);
 | |
| +    ~InspectorPlaywrightAgent() override;
 | |
| +
 | |
| +    // Transport
 | |
| +    void connectFrontend(Inspector::FrontendChannel&);
 | |
| +    void disconnectFrontend();
 | |
| +    void dispatchMessageFromFrontend(const String& message);
 | |
| +
 | |
| +private:
 | |
| +    class BrowserContextDeletion;
 | |
| +    class PageProxyChannel;
 | |
| +    class TargetHandler;
 | |
| +
 | |
| +    // WebPageInspectorControllerObserver
 | |
| +    void didCreateInspectorController(WebPageProxy&) override;
 | |
| +    void willDestroyInspectorController(WebPageProxy&) override;
 | |
| +    void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error) override;
 | |
| +    void willCreateNewPage(WebPageProxy&, const WebCore::WindowFeatures&, const URL&) override;
 | |
| +
 | |
| +    // PlaywrightDispatcherHandler
 | |
| +    void enable(Inspector::ErrorString&) override;
 | |
| +    void disable(Inspector::ErrorString&) override;
 | |
| +    void close(Ref<CloseCallback>&&) override;
 | |
| +    void createContext(Inspector::ErrorString&, const String* proxyServer, const String* proxyBypassList, String* browserContextID) override;
 | |
| +    void deleteContext(const String& browserContextID, Ref<DeleteContextCallback>&& callback) override;
 | |
| +    void createPage(Inspector::ErrorString&, const String* browserContextID, String* pageProxyID) override;
 | |
| +    void navigate(const String& url, const String& pageProxyID, const String* frameId, const String* referrer, Ref<NavigateCallback>&&) override;
 | |
| +    void setIgnoreCertificateErrors(Inspector::ErrorString&, const String* browserContextID, bool ignore) override;
 | |
| +
 | |
| +    void getAllCookies(const String* browserContextID, Ref<GetAllCookiesCallback>&&) override;
 | |
| +    void setCookies(const String* browserContextID, const JSON::Array& in_cookies, Ref<SetCookiesCallback>&&) override;
 | |
| +    void deleteAllCookies(const String* browserContextID, Ref<DeleteAllCookiesCallback>&&) override;
 | |
| +
 | |
| +    void setGeolocationOverride(Inspector::ErrorString&, const String* browserContextID, const JSON::Object* geolocation) override;
 | |
| +    void setLanguages(Inspector::ErrorString&, const JSON::Array& languages, const String* browserContextID) override;
 | |
| +    void setDownloadBehavior(Inspector::ErrorString&, const String* behavior, const String* downloadPath, const String* browserContextID) override;
 | |
| +
 | |
| +    // DownloadInstrumentation
 | |
| +    void downloadCreated(const WebsiteDataStore&, const String& uuid, const WebCore::ResourceRequest&, const FrameInfoData& frameInfoData, WebPageProxy* page) override;
 | |
| +    void downloadFilenameSuggested(const WebsiteDataStore&, const String& uuid, const String& suggestedFilename) override;
 | |
| +    void downloadFinished(const WebsiteDataStore&, const String& uuid, const String& error) override;
 | |
| +
 | |
| +    BrowserContext lookupBrowserContext(Inspector::ErrorString&, const String* browserContextID);
 | |
| +    WebFrameProxy* frameForID(const String& frameID, String& error);
 | |
| +
 | |
| +    Inspector::FrontendChannel* m_frontendChannel { nullptr };
 | |
| +    Ref<Inspector::FrontendRouter> m_frontendRouter;
 | |
| +    Ref<Inspector::BackendDispatcher> m_backendDispatcher;
 | |
| +    std::unique_ptr<InspectorPlaywrightAgentClient> m_client;
 | |
| +    std::unique_ptr<Inspector::PlaywrightFrontendDispatcher> m_frontendDispatcher;
 | |
| +    Ref<Inspector::PlaywrightBackendDispatcher> m_playwrightDispatcher;
 | |
| +    HashMap<String, std::unique_ptr<PageProxyChannel>> m_pageProxyChannels;
 | |
| +    HashMap<String, BrowserContext> m_browserContexts;
 | |
| +    HashMap<PAL::SessionID, std::unique_ptr<BrowserContextDeletion>> m_browserContextDeletions;
 | |
| +    bool m_isEnabled { false };
 | |
| +};
 | |
| +
 | |
| +} // namespace WebKit
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h b/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..b254875dc7404aed56680db05bac65b6d5f9c50a
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h
 | |
| @@ -0,0 +1,56 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +#include <pal/SessionID.h>
 | |
| +#include <wtf/Forward.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class WebsiteDataStore;
 | |
| +class WebPageProxy;
 | |
| +class WebProcessPool;
 | |
| +
 | |
| +struct BrowserContext {
 | |
| +    Vector<WebPageProxy*> pages() const;
 | |
| +    RefPtr<WebsiteDataStore> dataStore;
 | |
| +    RefPtr<WebProcessPool> processPool;
 | |
| +};
 | |
| +
 | |
| +class InspectorPlaywrightAgentClient {
 | |
| +public:
 | |
| +    virtual ~InspectorPlaywrightAgentClient() = default;
 | |
| +    virtual RefPtr<WebKit::WebPageProxy> createPage(WTF::String& error, const BrowserContext& context) = 0;
 | |
| +    virtual void closeBrowser() = 0;
 | |
| +    virtual BrowserContext createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) = 0;
 | |
| +    virtual void deleteBrowserContext(WTF::String& error, PAL::SessionID) = 0;
 | |
| +};
 | |
| +
 | |
| +} // namespace WebKit
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp
 | |
| index 7a14cfba15c103a2d4fe263fa49d25af3c396ec2..3ee0e154349661632799057c71f1d1f1551c2d69 100644
 | |
| --- a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp
 | |
| +++ b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp
 | |
| @@ -96,8 +96,11 @@ void ProcessLauncher::launchProcess()
 | |
|  
 | |
|      STARTUPINFO startupInfo { };
 | |
|      startupInfo.cb = sizeof(startupInfo);
 | |
| -    startupInfo.dwFlags = STARTF_USESHOWWINDOW;
 | |
| +    startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
 | |
|      startupInfo.wShowWindow = SW_HIDE;
 | |
| +    startupInfo.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
 | |
| +    startupInfo.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
 | |
| +    startupInfo.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
 | |
|      PROCESS_INFORMATION processInformation { };
 | |
|      BOOL result = ::CreateProcess(0, commandLine.data(), 0, 0, true, 0, 0, 0, &startupInfo, &processInformation);
 | |
|  
 | |
| diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h
 | |
| index 2e66628ab5c708fff1210e587cd4a8529b80e816..059df8d50dc61d44d62081aa264823bfb6232ee8 100644
 | |
| --- a/Source/WebKit/UIProcess/PageClient.h
 | |
| +++ b/Source/WebKit/UIProcess/PageClient.h
 | |
| @@ -247,7 +247,7 @@ public:
 | |
|      virtual void showSafeBrowsingWarning(const SafeBrowsingWarning&, CompletionHandler<void(Variant<ContinueUnsafeLoad, URL>&&)>&& completionHandler) { completionHandler(ContinueUnsafeLoad::Yes); }
 | |
|      virtual void clearSafeBrowsingWarning() { }
 | |
|      virtual void clearSafeBrowsingWarningIfForMainFrameNavigation() { }
 | |
| -    
 | |
| +
 | |
|  #if ENABLE(DRAG_SUPPORT)
 | |
|  #if PLATFORM(GTK)
 | |
|      virtual void startDrag(WebCore::SelectionData&&, OptionSet<WebCore::DragOperation>, RefPtr<ShareableBitmap>&& dragImage) = 0;
 | |
| @@ -286,6 +286,11 @@ public:
 | |
|      virtual void selectionDidChange() = 0;
 | |
|  #endif
 | |
|  
 | |
| +// Paywright begin
 | |
| +#if PLATFORM(COCOA)
 | |
| +    virtual RetainPtr<CGImageRef> takeSnapshotForAutomation() = 0;
 | |
| +#endif
 | |
| +// Paywright end
 | |
|  #if PLATFORM(COCOA) || PLATFORM(GTK)
 | |
|      virtual RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&) = 0;
 | |
|  #endif
 | |
| @@ -346,7 +351,7 @@ public:
 | |
|      virtual void setTextIndicator(Ref<WebCore::TextIndicator>, WebCore::TextIndicatorWindowLifetime) = 0;
 | |
|      virtual void clearTextIndicator(WebCore::TextIndicatorWindowDismissalAnimation) = 0;
 | |
|      virtual void setTextIndicatorAnimationProgress(float) = 0;
 | |
| -    
 | |
| +
 | |
|      virtual void didPerformDictionaryLookup(const WebCore::DictionaryPopupInfo&) = 0;
 | |
|  #endif
 | |
|  
 | |
| @@ -476,7 +481,7 @@ public:
 | |
|      virtual bool hasSafeBrowsingWarning() const { return false; }
 | |
|  
 | |
|      virtual void setMouseEventPolicy(WebCore::MouseEventPolicy) { }
 | |
| -    
 | |
| +
 | |
|  #if PLATFORM(MAC)
 | |
|      virtual void didPerformImmediateActionHitTest(const WebHitTestResultData&, bool contentPreventsDefault, API::Object*) = 0;
 | |
|      virtual NSObject *immediateActionAnimationControllerForHitTestResult(RefPtr<API::HitTestResult>, uint64_t, RefPtr<API::Object>) = 0;
 | |
| diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..adcc4b59f90670f162bb2a798582723532e37ee0
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp
 | |
| @@ -0,0 +1,221 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "RemoteInspectorPipe.h"
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +#include "InspectorPlaywrightAgent.h"
 | |
| +#include <JavaScriptCore/InspectorFrontendChannel.h>
 | |
| +#include <wtf/MainThread.h>
 | |
| +#include <wtf/RunLoop.h>
 | |
| +#include <wtf/UniqueArray.h>
 | |
| +#include <wtf/Vector.h>
 | |
| +#include <wtf/WorkQueue.h>
 | |
| +
 | |
| +#if OS(UNIX)
 | |
| +#include <stdio.h>
 | |
| +#include <unistd.h>
 | |
| +#endif
 | |
| +
 | |
| +#if PLATFORM(WIN)
 | |
| +#include <io.h>
 | |
| +#endif
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +namespace {
 | |
| +
 | |
| +const int readFD = 3;
 | |
| +const int writeFD = 4;
 | |
| +
 | |
| +const size_t kWritePacketSize = 1 << 16;
 | |
| +
 | |
| +#if PLATFORM(WIN)
 | |
| +HANDLE readHandle;
 | |
| +HANDLE writeHandle;
 | |
| +#endif
 | |
| +
 | |
| +size_t ReadBytes(void* buffer, size_t size, bool exact_size)
 | |
| +{
 | |
| +    size_t bytesRead = 0;
 | |
| +    while (bytesRead < size) {
 | |
| +#if PLATFORM(WIN)
 | |
| +        DWORD sizeRead = 0;
 | |
| +        bool hadError = !ReadFile(readHandle, static_cast<char*>(buffer) + bytesRead,
 | |
| +            size - bytesRead, &sizeRead, nullptr);
 | |
| +#else
 | |
| +        int sizeRead = read(readFD, static_cast<char*>(buffer) + bytesRead,
 | |
| +            size - bytesRead);
 | |
| +        if (sizeRead < 0 && errno == EINTR)
 | |
| +            continue;
 | |
| +        bool hadError = sizeRead <= 0;
 | |
| +#endif
 | |
| +        if (hadError) {
 | |
| +            return 0;
 | |
| +        }
 | |
| +        bytesRead += sizeRead;
 | |
| +        if (!exact_size)
 | |
| +            break;
 | |
| +    }
 | |
| +    return bytesRead;
 | |
| +}
 | |
| +
 | |
| +void WriteBytes(const char* bytes, size_t size)
 | |
| +{
 | |
| +    size_t totalWritten = 0;
 | |
| +    while (totalWritten < size) {
 | |
| +        size_t length = size - totalWritten;
 | |
| +        if (length > kWritePacketSize)
 | |
| +            length = kWritePacketSize;
 | |
| +#if PLATFORM(WIN)
 | |
| +        DWORD bytesWritten = 0;
 | |
| +        bool hadError = !WriteFile(writeHandle, bytes + totalWritten, static_cast<DWORD>(length), &bytesWritten, nullptr);
 | |
| +#else
 | |
| +        int bytesWritten = write(writeFD, bytes + totalWritten, length);
 | |
| +        if (bytesWritten < 0 && errno == EINTR)
 | |
| +            continue;
 | |
| +        bool hadError = bytesWritten <= 0;
 | |
| +#endif
 | |
| +        if (hadError)
 | |
| +            return;
 | |
| +        totalWritten += bytesWritten;
 | |
| +    }
 | |
| +}
 | |
| +
 | |
| +}  // namespace
 | |
| +
 | |
| +class RemoteInspectorPipe::RemoteFrontendChannel : public Inspector::FrontendChannel {
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +
 | |
| +public:
 | |
| +    RemoteFrontendChannel()
 | |
| +        : m_senderQueue(WorkQueue::create("Inspector pipe writer"))
 | |
| +    {
 | |
| +    }
 | |
| +
 | |
| +    ~RemoteFrontendChannel() override = default;
 | |
| +
 | |
| +    ConnectionType connectionType() const override
 | |
| +    {
 | |
| +        return ConnectionType::Remote;
 | |
| +    }
 | |
| +
 | |
| +    void sendMessageToFrontend(const String& message) override
 | |
| +    {
 | |
| +        m_senderQueue->dispatch([message = message.isolatedCopy()]() {
 | |
| +            WriteBytes(message.ascii().data(), message.length());
 | |
| +            WriteBytes("\0", 1);
 | |
| +        });
 | |
| +    }
 | |
| +
 | |
| +private:
 | |
| +    Ref<WorkQueue> m_senderQueue;
 | |
| +};
 | |
| +
 | |
| +RemoteInspectorPipe::RemoteInspectorPipe(InspectorPlaywrightAgent& playwrightAgent)
 | |
| +    : m_playwrightAgent(playwrightAgent)
 | |
| +{
 | |
| +    // Initialize main loop before creating WorkQueue
 | |
| +    WTF::RunLoop::initializeMain();
 | |
| +    m_remoteFrontendChannel = makeUnique<RemoteFrontendChannel>();
 | |
| +    start();
 | |
| +}
 | |
| +
 | |
| +RemoteInspectorPipe::~RemoteInspectorPipe()
 | |
| +{
 | |
| +    stop();
 | |
| +}
 | |
| +
 | |
| +bool RemoteInspectorPipe::start()
 | |
| +{
 | |
| +    if (m_receiverThread)
 | |
| +        return true;
 | |
| +
 | |
| +#if PLATFORM(WIN)
 | |
| +    readHandle = reinterpret_cast<HANDLE>(_get_osfhandle(readFD));
 | |
| +    writeHandle = reinterpret_cast<HANDLE>(_get_osfhandle(writeFD));
 | |
| +#endif
 | |
| +
 | |
| +    m_playwrightAgent.connectFrontend(*m_remoteFrontendChannel);
 | |
| +    m_terminated = false;
 | |
| +    m_receiverThread = Thread::create("Inspector pipe reader", [this] {
 | |
| +        workerRun();
 | |
| +    });
 | |
| +    return true;
 | |
| +}
 | |
| +
 | |
| +void RemoteInspectorPipe::stop()
 | |
| +{
 | |
| +    if (!m_receiverThread)
 | |
| +        return;
 | |
| +
 | |
| +    m_playwrightAgent.disconnectFrontend();
 | |
| +
 | |
| +    m_terminated = true;
 | |
| +    m_receiverThread->waitForCompletion();
 | |
| +    m_receiverThread = nullptr;
 | |
| +}
 | |
| +
 | |
| +void RemoteInspectorPipe::workerRun()
 | |
| +{
 | |
| +    const size_t bufSize = 256 * 1024;
 | |
| +    auto buffer = makeUniqueArray<char>(bufSize);
 | |
| +    Vector<char> line;
 | |
| +    while (!m_terminated) {
 | |
| +        size_t size = ReadBytes(buffer.get(), bufSize, false);
 | |
| +        if (!size)
 | |
| +            break;
 | |
| +        size_t start = 0;
 | |
| +        size_t end = line.size();
 | |
| +        line.append(buffer.get(), size);
 | |
| +        while (true) {
 | |
| +            for (; end < line.size(); ++end) {
 | |
| +                if (line[end] == '\0')
 | |
| +                    break;
 | |
| +            }
 | |
| +            if (end == line.size())
 | |
| +                break;
 | |
| +
 | |
| +            if (end > start) {
 | |
| +                String message = String::fromUTF8(line.data() + start, end - start);
 | |
| +                RunLoop::main().dispatch([this, message] {
 | |
| +                    if (!m_terminated)
 | |
| +                        m_playwrightAgent.dispatchMessageFromFrontend(message);
 | |
| +                });
 | |
| +            }
 | |
| +            ++end;
 | |
| +            start = end;
 | |
| +        }
 | |
| +        if (start != 0 && start < line.size())
 | |
| +            memmove(line.data(), line.data() + start, line.size() - start);
 | |
| +        line.shrink(line.size() - start);
 | |
| +    }
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.h b/Source/WebKit/UIProcess/RemoteInspectorPipe.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..6d04f9290135069359ce6bf8726546482fd1dc95
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.h
 | |
| @@ -0,0 +1,65 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +#include <wtf/Ref.h>
 | |
| +#include <wtf/RefPtr.h>
 | |
| +#include <wtf/Threading.h>
 | |
| +
 | |
| +namespace Inspector {
 | |
| +class FrontendChannel;
 | |
| +}
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class InspectorPlaywrightAgent;
 | |
| +
 | |
| +class RemoteInspectorPipe {
 | |
| +    WTF_MAKE_NONCOPYABLE(RemoteInspectorPipe);
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    explicit RemoteInspectorPipe(InspectorPlaywrightAgent&);
 | |
| +    ~RemoteInspectorPipe();
 | |
| +
 | |
| +private:
 | |
| +    class RemoteFrontendChannel;
 | |
| +
 | |
| +    bool start();
 | |
| +    void stop();
 | |
| +
 | |
| +    void workerRun();
 | |
| +
 | |
| +    RefPtr<Thread> m_receiverThread;
 | |
| +    std::atomic<bool> m_terminated { false };
 | |
| +    std::unique_ptr<Inspector::FrontendChannel> m_remoteFrontendChannel;
 | |
| +    InspectorPlaywrightAgent& m_playwrightAgent;
 | |
| +};
 | |
| +
 | |
| +} // namespace WebKit
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h b/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h
 | |
| index ff90d3de4349c9a3385c20c059729b8e22ebe2e5..d5c4f2cd715551ddef6f5af93ada65cbe78ad213 100644
 | |
| --- a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h
 | |
| +++ b/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h
 | |
| @@ -28,6 +28,7 @@
 | |
|  #if ENABLE(WEB_AUTHN)
 | |
|  
 | |
|  #include "LocalConnection.h"
 | |
| +#include <WebCore/AuthenticatorAssertionResponse.h>
 | |
|  #include <WebCore/MockWebAuthenticationConfiguration.h>
 | |
|  
 | |
|  namespace WebKit {
 | |
| diff --git a/Source/WebKit/UIProcess/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..3983c25682b06bbbf9ae9fde95b5b9c349ae6abe
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp
 | |
| @@ -0,0 +1,145 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "WebPageInspectorEmulationAgent.h"
 | |
| +
 | |
| +#include "APIPageConfiguration.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +#include "WebPreferences.h"
 | |
| +#include "PageClient.h"
 | |
| +#include <JavaScriptCore/InspectorFrontendRouter.h>
 | |
| +#include <WebCore/Credential.h>
 | |
| +
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +using namespace Inspector;
 | |
| +
 | |
| +WebPageInspectorEmulationAgent::WebPageInspectorEmulationAgent(BackendDispatcher& backendDispatcher, WebPageProxy& page)
 | |
| +    : InspectorAgentBase("Emulation"_s)
 | |
| +    , m_backendDispatcher(EmulationBackendDispatcher::create(backendDispatcher, this))
 | |
| +    , m_page(page)
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +WebPageInspectorEmulationAgent::~WebPageInspectorEmulationAgent()
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::willDestroyFrontendAndBackend(DisconnectReason)
 | |
| +{
 | |
| +   m_commandsToRunWhenShown.clear();
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref<SetDeviceMetricsOverrideCallback>&& callback)
 | |
| +{
 | |
| +#if PLATFORM(GTK)
 | |
| +    // On gtk, fixed layout doesn't work with compositing enabled
 | |
| +    // FIXME: This turns off compositing forever, even if fixedLayout is disabled.
 | |
| +    if (fixedlayout) {
 | |
| +        auto copy = m_page.preferences().copy();
 | |
| +        copy->setAcceleratedCompositingEnabled(false);
 | |
| +        m_page.setPreferences(copy);
 | |
| +    }
 | |
| +#endif
 | |
| +
 | |
| +    m_page.setCustomDeviceScaleFactor(deviceScaleFactor);
 | |
| +    m_page.setUseFixedLayout(fixedlayout);
 | |
| +    if (!m_page.pageClient().isViewVisible() && m_page.configuration().relatedPage()) {
 | |
| +        m_commandsToRunWhenShown.append([this, width, height, callback = WTFMove(callback)]() mutable {
 | |
| +            setSize(width, height, WTFMove(callback));
 | |
| +        });
 | |
| +    } else {
 | |
| +        setSize(width, height, WTFMove(callback));
 | |
| +    }
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::setSize(int width, int height, Ref<SetDeviceMetricsOverrideCallback>&& callback)
 | |
| +{
 | |
| +    platformSetSize(width, height, [callback = WTFMove(callback)](const String& error) {
 | |
| +        if (error.isEmpty())
 | |
| +            callback->sendSuccess();
 | |
| +        else
 | |
| +            callback->sendFailure(error);
 | |
| +    });
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::setJavaScriptEnabled(ErrorString&, bool enabled)
 | |
| +{
 | |
| +    auto copy = m_page.preferences().copy();
 | |
| +    copy->setJavaScriptEnabled(enabled);
 | |
| +    m_page.setPreferences(copy);
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::setAuthCredentials(Inspector::ErrorString&, const String* username, const String* password)
 | |
| +{
 | |
| +    if (username && password)
 | |
| +        m_page.setAuthCredentialsForAutomation(WebCore::Credential(*username, *password, CredentialPersistencePermanent));
 | |
| +    else
 | |
| +        m_page.setAuthCredentialsForAutomation(Optional<WebCore::Credential>());
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::setActiveAndFocused(Inspector::ErrorString&, const bool* active)
 | |
| +{
 | |
| +    Optional<bool> value;
 | |
| +    if (active)
 | |
| +      value = *active;
 | |
| +    m_page.setActiveForAutomation(value);
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::grantPermissions(Inspector::ErrorString& errorString, const String& origin, const JSON::Array& values)
 | |
| +{
 | |
| +    HashSet<String> set;
 | |
| +    for (const auto& value : values) {
 | |
| +        String name;
 | |
| +        if (!value->asString(name)) {
 | |
| +            errorString = "Permission must be a string"_s;
 | |
| +            return;
 | |
| +        }
 | |
| +        set.add(name);
 | |
| +    }
 | |
| +    m_permissions.set(origin, WTFMove(set));
 | |
| +    m_page.setPermissionsForAutomation(m_permissions);
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::resetPermissions(Inspector::ErrorString&)
 | |
| +{
 | |
| +    m_permissions.clear();
 | |
| +    m_page.setPermissionsForAutomation(m_permissions);
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::didShowPage()
 | |
| +{
 | |
| +    for (auto& command : m_commandsToRunWhenShown)
 | |
| +        command();
 | |
| +    m_commandsToRunWhenShown.clear();
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..5ae0ce152f06b8316dbfbbbb2efd1990a31687d0
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h
 | |
| @@ -0,0 +1,75 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#include <JavaScriptCore/InspectorAgentBase.h>
 | |
| +#include <JavaScriptCore/InspectorBackendDispatchers.h>
 | |
| +
 | |
| +#include <wtf/Forward.h>
 | |
| +#include <wtf/Function.h>
 | |
| +#include <wtf/Noncopyable.h>
 | |
| +#include <wtf/Vector.h>
 | |
| +
 | |
| +namespace Inspector {
 | |
| +class BackendDispatcher;
 | |
| +class FrontendChannel;
 | |
| +class FrontendRouter;
 | |
| +}
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class WebPageProxy;
 | |
| +
 | |
| +class WebPageInspectorEmulationAgent : public Inspector::InspectorAgentBase, public Inspector::EmulationBackendDispatcherHandler {
 | |
| +    WTF_MAKE_NONCOPYABLE(WebPageInspectorEmulationAgent);
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    WebPageInspectorEmulationAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page);
 | |
| +    ~WebPageInspectorEmulationAgent() override;
 | |
| +
 | |
| +    void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
 | |
| +    void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
 | |
| +
 | |
| +    void setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref<SetDeviceMetricsOverrideCallback>&&) override;
 | |
| +    void setJavaScriptEnabled(Inspector::ErrorString&, bool enabled) override;
 | |
| +    void setAuthCredentials(Inspector::ErrorString&, const String*, const String*) override;
 | |
| +    void setActiveAndFocused(Inspector::ErrorString&, const bool*) override;
 | |
| +    void grantPermissions(Inspector::ErrorString&, const String& origin, const JSON::Array& permissions) override;
 | |
| +    void resetPermissions(Inspector::ErrorString&) override;
 | |
| +
 | |
| +    void didShowPage();
 | |
| +
 | |
| +private:
 | |
| +    void setSize(int width, int height, Ref<SetDeviceMetricsOverrideCallback>&& callback);
 | |
| +    void platformSetSize(int width, int height, Function<void (const String& error)>&&);
 | |
| +
 | |
| +    Ref<Inspector::EmulationBackendDispatcher> m_backendDispatcher;
 | |
| +    WebPageProxy& m_page;
 | |
| +    Vector<Function<void()>> m_commandsToRunWhenShown;
 | |
| +    HashMap<String, HashSet<String>> m_permissions;
 | |
| +};
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..5d19607e019489b33318be50ccdc94c2fcfae914
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp
 | |
| @@ -0,0 +1,282 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "WebPageInspectorInputAgent.h"
 | |
| +
 | |
| +#include "NativeWebKeyboardEvent.h"
 | |
| +#include "NativeWebMouseEvent.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +#include <wtf/MathExtras.h>
 | |
| +#include <wtf/HexNumber.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +using namespace Inspector;
 | |
| +
 | |
| +namespace {
 | |
| +
 | |
| +template<class T>
 | |
| +class CallbackList {
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    ~CallbackList()
 | |
| +    {
 | |
| +        for (const auto& callback : m_callbacks)
 | |
| +            callback->sendFailure("Page closed");
 | |
| +    }
 | |
| +
 | |
| +    void append(Ref<T>&& callback)
 | |
| +    {
 | |
| +        m_callbacks.append(WTFMove(callback));
 | |
| +    }
 | |
| +
 | |
| +    void sendSuccess()
 | |
| +    {
 | |
| +        for (const auto& callback : m_callbacks)
 | |
| +            callback->sendSuccess();
 | |
| +        m_callbacks.clear();
 | |
| +    }
 | |
| +
 | |
| +private:
 | |
| +    Vector<Ref<T>> m_callbacks;
 | |
| +};
 | |
| +
 | |
| +} // namespace
 | |
| +
 | |
| +class WebPageInspectorInputAgent::KeyboardCallbacks : public CallbackList<Inspector::InputBackendDispatcherHandler::DispatchKeyEventCallback> {
 | |
| +};
 | |
| +
 | |
| +class WebPageInspectorInputAgent::MouseCallbacks : public CallbackList<Inspector::InputBackendDispatcherHandler::DispatchMouseEventCallback> {
 | |
| +};
 | |
| +
 | |
| +WebPageInspectorInputAgent::WebPageInspectorInputAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page)
 | |
| +    : InspectorAgentBase("Input"_s)
 | |
| +    , m_backendDispatcher(InputBackendDispatcher::create(backendDispatcher, this))
 | |
| +    , m_page(page)
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +WebPageInspectorInputAgent::~WebPageInspectorInputAgent() = default;
 | |
| +
 | |
| +void WebPageInspectorInputAgent::didProcessAllPendingKeyboardEvents()
 | |
| +{
 | |
| +    m_keyboardCallbacks->sendSuccess();
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorInputAgent::didProcessAllPendingMouseEvents()
 | |
| +{
 | |
| +    m_mouseCallbacks->sendSuccess();
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorInputAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
 | |
| +{
 | |
| +    m_keyboardCallbacks = makeUnique<KeyboardCallbacks>();
 | |
| +    m_mouseCallbacks = makeUnique<MouseCallbacks>();
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorInputAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
 | |
| +{
 | |
| +    m_keyboardCallbacks = nullptr;
 | |
| +    m_mouseCallbacks = nullptr;
 | |
| +}
 | |
| +
 | |
| +static String keyIdentifierForKey(const String& key)
 | |
| +{
 | |
| +    if (key.length() == 1)
 | |
| +        return makeString("U+", hex(toASCIIUpper(key.characterAt(0)), 4));
 | |
| +    if (key == "Delete")
 | |
| +        return "U+007F";
 | |
| +    if (key == "Backspace")
 | |
| +        return "U+0008";
 | |
| +    if (key == "ArrowUp")
 | |
| +        return "Up";
 | |
| +    if (key == "ArrowDown")
 | |
| +        return "Down";
 | |
| +    if (key == "ArrowLeft")
 | |
| +        return "Left";
 | |
| +    if (key == "ArrowRight")
 | |
| +        return "Right";
 | |
| +    if (key == "Tab")
 | |
| +        return "U+0009";
 | |
| +    if (key == "Pause")
 | |
| +        return "Pause";
 | |
| +    if (key == "ScrollLock")
 | |
| +        return "Scroll";
 | |
| +    return key;
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorInputAgent::dispatchKeyEvent(const String& type, 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);
 | |
| +      }
 | |
| +    }
 | |
| +
 | |
| +    String keyIdentifier = keyIdentifierForKey(eventKey);
 | |
| +
 | |
| +    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,
 | |
| +        keyIdentifier,
 | |
| +        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..20311d530090b0229010957a96fc60f44b4823fe
 | |
| --- /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, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& commands, WallTime timestamp);
 | |
| +#if PLATFORM(WPE)
 | |
| +    void platformDispatchMouseEvent(WebMouseEvent::Type type, int x, int y, WebMouseEvent::Button button, OptionSet<WebEvent::Modifier> modifiers);
 | |
| +#endif
 | |
| +#if PLATFORM(MAC)
 | |
| +    void platformDispatchMouseEvent(const String& type, int x, int y, 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 4037ceef8668619ae52f1aa1a4b2783818d9c091..df126d71a13b80595fccfa586b23b78c6a6feeeb 100644
 | |
| --- a/Source/WebKit/UIProcess/WebPageProxy.cpp
 | |
| +++ b/Source/WebKit/UIProcess/WebPageProxy.cpp
 | |
| @@ -953,6 +953,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason)
 | |
|      m_pageLoadState.didSwapWebProcesses();
 | |
|      if (reason != ProcessLaunchReason::InitialProcess)
 | |
|          m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
 | |
| +    m_inspectorController->didFinishAttachingToWebProcess();
 | |
|  }
 | |
|  
 | |
|  void WebPageProxy::didAttachToRunningProcess()
 | |
| @@ -1274,6 +1275,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)
 | |
| @@ -1739,6 +1755,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());
 | |
| @@ -1881,6 +1922,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())
 | |
| @@ -2845,7 +2905,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();
 | |
| @@ -2878,7 +2938,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
 | |
| @@ -3307,6 +3367,7 @@ void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, A
 | |
|  
 | |
|  void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, RefPtr<API::WebsitePolicies>&& websitePolicies, Ref<PolicyDecisionSender>&& sender, Optional<SandboxExtension::Handle> sandboxExtensionHandle, WillContinueLoadInNewProcess willContinueLoadInNewProcess)
 | |
|  {
 | |
| +    m_inspectorController->didReceivePolicyDecision(action, navigation ? navigation->navigationID() : 0);
 | |
|      if (!hasRunningProcess()) {
 | |
|          sender->send(PolicyDecision { sender->identifier(), isNavigatingToAppBoundDomain(), PolicyAction::Ignore, 0, DownloadID(), WTF::nullopt });
 | |
|          return;
 | |
| @@ -4009,6 +4070,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;
 | |
| @@ -4427,6 +4493,7 @@ void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
 | |
|  
 | |
|      // FIXME: Message check the navigationID.
 | |
|      m_navigationState->didDestroyNavigation(navigationID);
 | |
| +    m_inspectorController->didDestroyNavigation(navigationID);
 | |
|  }
 | |
|  
 | |
|  void WebPageProxy::didStartProvisionalLoadForFrame(FrameIdentifier frameID, FrameInfoData&& frameInfo, ResourceRequest&& request, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData)
 | |
| @@ -4649,6 +4716,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;
 | |
| @@ -5090,7 +5159,14 @@ void WebPageProxy::decidePolicyForNavigationActionAsync(FrameIdentifier frameID,
 | |
|      NavigationActionData&& navigationActionData, FrameInfoData&& originatingFrameInfo, Optional<WebPageProxyIdentifier> originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&& request,
 | |
|      IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData& userData, uint64_t listenerID)
 | |
|  {
 | |
| -    decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, WTFMove(navigationActionData), WTFMove(originatingFrameInfo), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
 | |
| +    if (m_inspectorController->shouldPauseLoading()) {
 | |
| +        m_inspectorController->setContinueLoadingCallback([this, protectedThis = makeRef(*this), frameID, frameInfo = WTFMove(frameInfo), identifier, navigationID, navigationActionData = WTFMove(navigationActionData),
 | |
| +                originatingFrameInfo = WTFMove(originatingFrameInfo), originatingPageID, originalRequest, request = WTFMove(request), requestBody = WTFMove(requestBody), redirectResponse = WTFMove(redirectResponse), userData, listenerID] () mutable {
 | |
| +            decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, WTFMove(navigationActionData), WTFMove(originatingFrameInfo), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
 | |
| +        });
 | |
| +    } else {
 | |
| +        decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, WTFMove(navigationActionData), WTFMove(originatingFrameInfo), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
 | |
| +    }
 | |
|  }
 | |
|  
 | |
|  void WebPageProxy::decidePolicyForNavigationActionAsyncShared(Ref<WebProcessProxy>&& process, PageIdentifier webPageID, FrameIdentifier frameID, FrameInfoData&& frameInfo,
 | |
| @@ -5595,6 +5671,7 @@ void WebPageProxy::createNewPage(FrameInfoData&& originatingFrameInfoData, Optio
 | |
|      auto* originatingPage = m_process->webPage(*originatingPageID);
 | |
|      auto originatingFrameInfo = API::FrameInfo::create(WTFMove(originatingFrameInfoData), originatingPage);
 | |
|      auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : URL();
 | |
| +    m_inspectorController->willCreateNewPage(windowFeatures, request.url());
 | |
|      auto completionHandler = [this, protectedThis = makeRef(*this), mainFrameURL, request, reply = WTFMove(reply)] (RefPtr<WebPageProxy> newPage) mutable {
 | |
|          if (!newPage) {
 | |
|              reply(WTF::nullopt, WTF::nullopt);
 | |
| @@ -5624,6 +5701,7 @@ void WebPageProxy::createNewPage(FrameInfoData&& originatingFrameInfoData, Optio
 | |
|  void WebPageProxy::showPage()
 | |
|  {
 | |
|      m_uiClient->showPage(this);
 | |
| +    m_inspectorController->didShowPage();
 | |
|  }
 | |
|  
 | |
|  void WebPageProxy::exitFullscreenImmediately()
 | |
| @@ -5678,6 +5756,8 @@ void WebPageProxy::runJavaScriptAlert(FrameIdentifier frameID, FrameInfoData&& f
 | |
|          if (auto* automationSession = process().processPool().automationSession())
 | |
|              automationSession->willShowJavaScriptDialog(*this);
 | |
|      }
 | |
| +    if (m_inspectorDialogAgent)
 | |
| +        m_inspectorDialogAgent->javascriptDialogOpening("alert"_s, message);
 | |
|      m_uiClient->runJavaScriptAlert(*this, message, frame, WTFMove(frameInfo), WTFMove(reply));
 | |
|  }
 | |
|  
 | |
| @@ -5695,6 +5775,8 @@ void WebPageProxy::runJavaScriptConfirm(FrameIdentifier frameID, FrameInfoData&&
 | |
|          if (auto* automationSession = process().processPool().automationSession())
 | |
|              automationSession->willShowJavaScriptDialog(*this);
 | |
|      }
 | |
| +    if (m_inspectorDialogAgent)
 | |
| +        m_inspectorDialogAgent->javascriptDialogOpening("confirm"_s, message);
 | |
|  
 | |
|      m_uiClient->runJavaScriptConfirm(*this, message, frame, WTFMove(frameInfo), WTFMove(reply));
 | |
|  }
 | |
| @@ -5713,6 +5795,8 @@ void WebPageProxy::runJavaScriptPrompt(FrameIdentifier frameID, FrameInfoData&&
 | |
|          if (auto* automationSession = process().processPool().automationSession())
 | |
|              automationSession->willShowJavaScriptDialog(*this);
 | |
|      }
 | |
| +    if (m_inspectorDialogAgent)
 | |
| +        m_inspectorDialogAgent->javascriptDialogOpening("prompt"_s, message, &defaultValue);
 | |
|  
 | |
|      m_uiClient->runJavaScriptPrompt(*this, message, defaultValue, frame, WTFMove(frameInfo), WTFMove(reply));
 | |
|  }
 | |
| @@ -5868,6 +5952,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(FrameIdentifier frameID, FrameInf
 | |
|              return;
 | |
|          }
 | |
|      }
 | |
| +    if (m_inspectorDialogAgent)
 | |
| +        m_inspectorDialogAgent->javascriptDialogOpening("beforeunload"_s, message);
 | |
|  
 | |
|      // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer and the tryClose timer.
 | |
|      m_process->stopResponsivenessTimer();
 | |
| @@ -6925,6 +7011,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
 | |
|              if (auto* automationSession = process().processPool().automationSession())
 | |
|                  automationSession->mouseEventsFlushedForPage(*this);
 | |
|              didFinishProcessingAllPendingMouseEvents();
 | |
| +            m_inspectorController->didProcessAllPendingMouseEvents();
 | |
|          }
 | |
|  
 | |
|          break;
 | |
| @@ -6951,7 +7038,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();
 | |
|  
 | |
| @@ -6971,7 +7057,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);
 | |
| @@ -6980,6 +7065,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
 | |
|          if (!canProcessMoreKeyEvents) {
 | |
|              if (auto* automationSession = process().processPool().automationSession())
 | |
|                  automationSession->keyboardEventsFlushedForPage(*this);
 | |
| +            m_inspectorController->didProcessAllPendingKeyboardEvents();
 | |
|          }
 | |
|          break;
 | |
|      }
 | |
| @@ -7425,8 +7511,10 @@ static bool shouldReloadAfterProcessTermination(ProcessTerminationReason reason)
 | |
|  void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason)
 | |
|  {
 | |
|      RELEASE_LOG_ERROR_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
 | |
| @@ -7693,6 +7781,7 @@ void WebPageProxy::resetStateAfterProcessExited(ProcessTerminationReason termina
 | |
|  
 | |
|  WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& process, DrawingAreaProxy& drawingArea, RefPtr<API::WebsitePolicies>&& websitePolicies)
 | |
|  {
 | |
| +
 | |
|      WebPageCreationParameters parameters;
 | |
|  
 | |
|      parameters.processDisplayName = configuration().processDisplayName();
 | |
| @@ -7845,6 +7934,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc
 | |
|      parameters.limitsNavigationsToAppBoundDomains = m_limitsNavigationsToAppBoundDomains;
 | |
|      parameters.shouldRelaxThirdPartyCookieBlocking = m_configuration->shouldRelaxThirdPartyCookieBlocking();
 | |
|  
 | |
| +    parameters.shouldPauseInInspectorWhenShown = m_inspectorController->shouldPauseLoading();
 | |
| +
 | |
|  #if PLATFORM(GTK)
 | |
|      parameters.themeName = pageClient().themeName();
 | |
|  #endif
 | |
| @@ -7916,6 +8007,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)
 | |
| @@ -8001,7 +8100,8 @@ void WebPageProxy::requestGeolocationPermissionForFrame(GeolocationIdentifier ge
 | |
|      MESSAGE_CHECK(m_process, frame);
 | |
|  
 | |
|      // FIXME: Geolocation should probably be using toString() as its string representation instead of databaseIdentifier().
 | |
| -    auto origin = API::SecurityOrigin::create(frameInfo.securityOrigin.securityOrigin());
 | |
| +    auto securityOrigin = frameInfo.securityOrigin.securityOrigin();
 | |
| +    auto origin = API::SecurityOrigin::create(securityOrigin);
 | |
|      auto request = m_geolocationPermissionRequestManager.createRequest(geolocationID);
 | |
|      Function<void(bool)> completionHandler = [request = WTFMove(request)](bool allowed) {
 | |
|          if (allowed)
 | |
| @@ -8010,6 +8110,14 @@ void WebPageProxy::requestGeolocationPermissionForFrame(GeolocationIdentifier ge
 | |
|              request->deny();
 | |
|      };
 | |
|  
 | |
| +    auto permissions = m_permissionsForAutomation.find(securityOrigin->toString());
 | |
| +    if (permissions == m_permissionsForAutomation.end())
 | |
| +      permissions = m_permissionsForAutomation.find("*");
 | |
| +    if (permissions != m_permissionsForAutomation.end()) {
 | |
| +        completionHandler(permissions->value.contains("geolocation"));
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
|      // FIXME: Once iOS migrates to the new WKUIDelegate SPI, clean this up
 | |
|      // and make it one UIClient call that calls the completionHandler with false
 | |
|      // if there is no delegate instead of returning the completionHandler
 | |
| diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h
 | |
| index 2edf44f59d498a8201a8ac7898493b5213e25da1..0f1644b556b26c5c2ffe7cc8c0e2a8938c9433d9 100644
 | |
| --- a/Source/WebKit/UIProcess/WebPageProxy.h
 | |
| +++ b/Source/WebKit/UIProcess/WebPageProxy.h
 | |
| @@ -37,6 +37,7 @@
 | |
|  #include "GeolocationIdentifier.h"
 | |
|  #include "GeolocationPermissionRequestManagerProxy.h"
 | |
|  #include "HiddenPageThrottlingAutoIncreasesCounter.h"
 | |
| +#include "InspectorDialogAgent.h"
 | |
|  #include "LayerTreeContext.h"
 | |
|  #include "MessageSender.h"
 | |
|  #include "NotificationPermissionRequestManagerProxy.h"
 | |
| @@ -505,6 +506,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();
 | |
| @@ -579,6 +582,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>&&);
 | |
|  
 | |
| @@ -604,6 +612,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);
 | |
| @@ -1093,6 +1102,7 @@ public:
 | |
|  #endif
 | |
|  
 | |
|      void pageScaleFactorDidChange(double);
 | |
| +    void viewScaleFactorDidChange(double);
 | |
|      void pluginScaleFactorDidChange(double);
 | |
|      void pluginZoomFactorDidChange(double);
 | |
|  
 | |
| @@ -1413,6 +1423,8 @@ public:
 | |
|  
 | |
|  #if PLATFORM(COCOA) || PLATFORM(GTK)
 | |
|      RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&);
 | |
| +#elif PLATFORM(WPE)
 | |
| +    RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&) { return nullptr; }
 | |
|  #endif
 | |
|  
 | |
|  #if ENABLE(WEB_CRYPTO)
 | |
| @@ -2395,6 +2407,7 @@ private:
 | |
|      String m_overrideContentSecurityPolicy;
 | |
|  
 | |
|      RefPtr<WebInspectorProxy> m_inspector;
 | |
| +    InspectorDialogAgent* m_inspectorDialogAgent { nullptr };
 | |
|  
 | |
|  #if ENABLE(FULLSCREEN_API)
 | |
|      std::unique_ptr<WebFullScreenManagerProxy> m_fullScreenManager;
 | |
| @@ -2823,6 +2836,9 @@ private:
 | |
|          RefPtr<API::Object> messageBody;
 | |
|      };
 | |
|      Vector<InjectedBundleMessage> m_pendingInjectedBundleMessages;
 | |
| +    Optional<WebCore::Credential> m_credentialsForAutomation;
 | |
| +    HashMap<String, HashSet<String>> m_permissionsForAutomation;
 | |
| +    Optional<bool> m_activeForAutomation;
 | |
|          
 | |
|  #if PLATFORM(IOS_FAMILY) && ENABLE(DEVICE_ORIENTATION)
 | |
|      std::unique_ptr<WebDeviceOrientationUpdateProviderProxy> m_webDeviceOrientationUpdateProviderProxy;
 | |
| diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in
 | |
| index 83508e89e45608f2a4ff1119bc91e2e2550d4059..2633b9958022d179ee34c846480e9689bb042e88 100644
 | |
| --- a/Source/WebKit/UIProcess/WebPageProxy.messages.in
 | |
| +++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in
 | |
| @@ -29,6 +29,7 @@ messages -> WebPageProxy {
 | |
|      RunJavaScriptConfirm(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, String message) -> (bool result) Synchronous
 | |
|      RunJavaScriptPrompt(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, String message, String defaultValue) -> (String result) Synchronous
 | |
|      MouseDidMoveOverElement(struct WebKit::WebHitTestResultData hitTestResultData, uint32_t modifiers, WebKit::UserData userData)
 | |
| +    LogToStderr(String text)
 | |
|  
 | |
|  #if ENABLE(NETSCAPE_PLUGIN_API)
 | |
|      UnavailablePluginButtonClicked(uint32_t pluginUnavailabilityReason, String mimeType, String pluginURLString, String pluginspageAttributeURLString, String frameURLString, String pageURLString)
 | |
| @@ -204,6 +205,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 34376f90b1037a50dc8240508ada979f29367331..5ec1c3414ac5c6c06367ef8e748a3b0e923c454f 100644
 | |
| --- a/Source/WebKit/UIProcess/WebProcessPool.cpp
 | |
| +++ b/Source/WebKit/UIProcess/WebProcessPool.cpp
 | |
| @@ -1029,7 +1029,10 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa
 | |
|  #endif
 | |
|  
 | |
|      parameters.cacheModel = LegacyGlobalSettings::singleton().cacheModel();
 | |
| -    parameters.overrideLanguages = configuration().overrideLanguages();
 | |
| +    if (websiteDataStore && websiteDataStore->languagesForAutomation().size())
 | |
| +        parameters.overrideLanguages = websiteDataStore->languagesForAutomation();
 | |
| +    else
 | |
| +        parameters.overrideLanguages = configuration().overrideLanguages();
 | |
|  
 | |
|      parameters.urlSchemesRegisteredAsEmptyDocument = copyToVector(m_schemesToRegisterAsEmptyDocument);
 | |
|      parameters.urlSchemesRegisteredAsSecure = copyToVector(LegacyGlobalSettings::singleton().schemesToRegisterAsSecure());
 | |
| diff --git a/Source/WebKit/UIProcess/WebProcessPool.h b/Source/WebKit/UIProcess/WebProcessPool.h
 | |
| index 5c60a32f978017fc5ae2d84e31273cea15a4d24c..a856ada5dd9ee83b136a0745c90bdf426dc88370 100644
 | |
| --- a/Source/WebKit/UIProcess/WebProcessPool.h
 | |
| +++ b/Source/WebKit/UIProcess/WebProcessPool.h
 | |
| @@ -717,8 +717,8 @@ private:
 | |
|  
 | |
|      HashMap<uint64_t, RefPtr<DictionaryCallback>> m_dictionaryCallbacks;
 | |
|  
 | |
| -#if USE(SOUP)
 | |
| -    bool m_ignoreTLSErrors { true };
 | |
| +#if USE(SOUP) || PLATFORM(COCOA) || PLATFORM(WIN)
 | |
| +    bool m_ignoreTLSErrors { false };
 | |
|  #endif
 | |
|  
 | |
|      bool m_memoryCacheDisabled { false };
 | |
| diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
 | |
| index 52c9f9402c3aebc366eb9c3da820ba30d772b4f7..40ecb72ec756c903fba170876cafb1dabf652c17 100644
 | |
| --- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
 | |
| +++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
 | |
| @@ -2453,6 +2453,17 @@ void WebsiteDataStore::renameOriginInWebsiteData(URL&& oldName, URL&& newName, O
 | |
|      }
 | |
|  }
 | |
|  
 | |
| +void WebsiteDataStore::setLanguagesForAutomation(Vector<String>&& languages)
 | |
| +{
 | |
| +    m_languagesForAutomation = WTFMove(languages);
 | |
| +}
 | |
| +
 | |
| +void WebsiteDataStore::setDownloadForAutomation(Optional<bool> allow, const String& downloadPath)
 | |
| +{
 | |
| +    m_allowDownloadForAutomation = allow;
 | |
| +    m_downloadPathForAutomation = downloadPath;
 | |
| +}
 | |
| +
 | |
|  #if PLATFORM(COCOA)
 | |
|  void WebsiteDataStore::forwardAppBoundDomainsToITPIfInitialized(CompletionHandler<void()>&& completionHandler)
 | |
|  {
 | |
| diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
 | |
| index 964c6315e38f5e0a0303febce45b1e975054f0b4..6b6c4f18b617d0a87d05a17db739808929dff2a6 100644
 | |
| --- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
 | |
| +++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
 | |
| @@ -83,6 +83,7 @@ class WebResourceLoadStatisticsStore;
 | |
|  enum class CacheModel : uint8_t;
 | |
|  enum class WebsiteDataFetchOption;
 | |
|  enum class WebsiteDataType;
 | |
| +struct FrameInfoData;
 | |
|  struct WebsiteDataRecord;
 | |
|  struct WebsiteDataStoreParameters;
 | |
|  
 | |
| @@ -96,6 +97,16 @@ enum class StorageAccessPromptStatus;
 | |
|  struct PluginModuleInfo;
 | |
|  #endif
 | |
|  
 | |
| +class WebsiteDataStore;
 | |
| +
 | |
| +class DownloadInstrumentation {
 | |
| +public:
 | |
| +    virtual void downloadCreated(const WebsiteDataStore&, const String& uuid, const WebCore::ResourceRequest&, const FrameInfoData& frameInfoData, WebPageProxy* page) = 0;
 | |
| +    virtual void downloadFilenameSuggested(const WebsiteDataStore&, const String& uuid, const String& suggestedFilename) = 0;
 | |
| +    virtual void downloadFinished(const WebsiteDataStore&, const String& uuid, const String& error) = 0;
 | |
| +    virtual ~DownloadInstrumentation() = default;
 | |
| +};
 | |
| +
 | |
|  class WebsiteDataStore : public API::ObjectImpl<API::Object::Type::WebsiteDataStore>, public Identified<WebsiteDataStore>, public CanMakeWeakPtr<WebsiteDataStore>  {
 | |
|  public:
 | |
|      static Ref<WebsiteDataStore> defaultDataStore();
 | |
| @@ -290,6 +301,14 @@ public:
 | |
|      static WTF::String defaultJavaScriptConfigurationDirectory();
 | |
|      static bool http3Enabled();
 | |
|  
 | |
| +    void setLanguagesForAutomation(Vector<String>&&);
 | |
| +    Vector<String>& languagesForAutomation() { return m_languagesForAutomation; };
 | |
| +    void setDownloadForAutomation(Optional<bool> allow, const String& downloadPath);
 | |
| +    Optional<bool> allowDownloadForAutomation() { return m_allowDownloadForAutomation; };
 | |
| +    String downloadPathForAutomation() { return m_downloadPathForAutomation; };
 | |
| +    void setDownloadInstrumentation(DownloadInstrumentation* instrumentation) { m_downloadInstrumentation = instrumentation; };
 | |
| +    DownloadInstrumentation* downloadInstrumentation() { return m_downloadInstrumentation; };
 | |
| +
 | |
|      void resetQuota(CompletionHandler<void()>&&);
 | |
|      void hasAppBoundSession(CompletionHandler<void(bool)>&&) const;
 | |
|      void clearAppBoundSession(CompletionHandler<void()>&&);
 | |
| @@ -390,6 +409,11 @@ private:
 | |
|  
 | |
|      RefPtr<API::HTTPCookieStore> m_cookieStore;
 | |
|  
 | |
| +    Vector<String> m_languagesForAutomation;
 | |
| +    Optional<bool> m_allowDownloadForAutomation;
 | |
| +    String m_downloadPathForAutomation;
 | |
| +    DownloadInstrumentation* m_downloadInstrumentation { nullptr };
 | |
| +
 | |
|  #if HAVE(APP_SSO)
 | |
|      UniqueRef<SOAuthorizationCoordinator> m_soAuthorizationCoordinator;
 | |
|  #endif
 | |
| diff --git a/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp b/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp
 | |
| index dc0a70b8824afdc7ec3dd1f69f4d9b51942924f6..9642cf27c33ec4b707bd588e0d2670770f9718bf 100644
 | |
| --- a/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp
 | |
| +++ b/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp
 | |
| @@ -27,9 +27,11 @@
 | |
|  #include "config.h"
 | |
|  #include "BackingStore.h"
 | |
|  
 | |
| +#include "DrawingAreaProxyCoordinatedGraphics.h"
 | |
|  #include "ShareableBitmap.h"
 | |
|  #include "UpdateInfo.h"
 | |
|  #include "WebPageProxy.h"
 | |
| +#include "WebPageInspectorController.h"
 | |
|  #include <WebCore/BackingStoreBackendCairoImpl.h>
 | |
|  #include <WebCore/CairoUtilities.h>
 | |
|  #include <WebCore/GraphicsContextImplCairo.h>
 | |
| @@ -72,6 +74,7 @@ void BackingStore::paint(cairo_t* context, const IntRect& rect)
 | |
|      cairo_rectangle(context, rect.x(), rect.y(), rect.width(), rect.height());
 | |
|      cairo_fill(context);
 | |
|      cairo_restore(context);
 | |
| +    m_webPageProxy.inspectorController().didPaint(m_backend->surface());
 | |
|  }
 | |
|  
 | |
|  void BackingStore::incorporateUpdate(ShareableBitmap* bitmap, const UpdateInfo& updateInfo)
 | |
| diff --git a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp
 | |
| index 7ba39332bce6e28f0f4b2f7acf636f835c54f486..7c3d8125df147b6049075491b12cce1dc84bf514 100644
 | |
| --- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp
 | |
| +++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp
 | |
| @@ -60,6 +60,8 @@ void GeoclueGeolocationProvider::start(UpdateNotifyFunction&& updateNotifyFuncti
 | |
|      m_isRunning = true;
 | |
|      m_cancellable = adoptGRef(g_cancellable_new());
 | |
|      if (!m_manager) {
 | |
| +        g_cancellable_cancel(m_cancellable_start.get());
 | |
| +        m_cancellable_start = adoptGRef(g_cancellable_new());
 | |
|          g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr,
 | |
|              "org.freedesktop.GeoClue2", "/org/freedesktop/GeoClue2/Manager", "org.freedesktop.GeoClue2.Manager", m_cancellable.get(),
 | |
|              [](GObject*, GAsyncResult* result, gpointer userData) {
 | |
| @@ -91,6 +93,12 @@ void GeoclueGeolocationProvider::stop()
 | |
|      g_cancellable_cancel(m_cancellable.get());
 | |
|      m_cancellable = nullptr;
 | |
|      stopClient();
 | |
| +    g_cancellable_cancel(m_cancellable_start.get());
 | |
| +    m_cancellable_start = nullptr;
 | |
| +    g_cancellable_cancel(m_cancellable_setup.get());
 | |
| +    m_cancellable_setup = nullptr;
 | |
| +    g_cancellable_cancel(m_cancellable_create.get());
 | |
| +    m_cancellable_create = nullptr;
 | |
|      destroyManagerLater();
 | |
|  }
 | |
|  
 | |
| @@ -153,6 +161,8 @@ void GeoclueGeolocationProvider::createClient(const char* clientPath)
 | |
|          return;
 | |
|      }
 | |
|  
 | |
| +    g_cancellable_cancel(m_cancellable_create.get());
 | |
| +    m_cancellable_create = adoptGRef(g_cancellable_new());
 | |
|      g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr,
 | |
|          "org.freedesktop.GeoClue2", clientPath, "org.freedesktop.GeoClue2.Client", m_cancellable.get(),
 | |
|          [](GObject*, GAsyncResult* result, gpointer userData) {
 | |
| diff --git a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h
 | |
| index 31d29091985f34a65134a2b0e7cb3ace1dae441d..571ceac8a4b291fa6e91eb8b17065c0aba908ac3 100644
 | |
| --- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h
 | |
| +++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h
 | |
| @@ -71,6 +71,9 @@ private:
 | |
|      GRefPtr<GDBusProxy> m_manager;
 | |
|      GRefPtr<GDBusProxy> m_client;
 | |
|      GRefPtr<GCancellable> m_cancellable;
 | |
| +    GRefPtr<GCancellable> m_cancellable_start;
 | |
| +    GRefPtr<GCancellable> m_cancellable_setup;
 | |
| +    GRefPtr<GCancellable> m_cancellable_create;
 | |
|      UpdateNotifyFunction m_updateNotifyFunction;
 | |
|      RunLoop::Timer<GeoclueGeolocationProvider> m_destroyManagerLaterTimer;
 | |
|  };
 | |
| diff --git a/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..a3d37d491f79d4022788e87025f988c71538346f
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp
 | |
| @@ -0,0 +1,146 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "InspectorPlaywrightAgentClientGLib.h"
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +#include "InspectorPlaywrightAgent.h"
 | |
| +#include "WebKitBrowserInspectorPrivate.h"
 | |
| +#include "WebKitWebContextPrivate.h"
 | |
| +#include "WebKitWebsiteDataManagerPrivate.h"
 | |
| +#include "WebKitWebViewPrivate.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +#include <wtf/HashMap.h>
 | |
| +#include <wtf/RefPtr.h>
 | |
| +#include <wtf/text/StringView.h>
 | |
| +#include <wtf/text/WTFString.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +static WebCore::SoupNetworkProxySettings parseRawProxySettings(const String& proxyServer, const char* const* ignoreHosts)
 | |
| +{
 | |
| +    WebCore::SoupNetworkProxySettings settings;
 | |
| +    if (proxyServer.isEmpty())
 | |
| +        return settings;
 | |
| +
 | |
| +    settings.mode = WebCore::SoupNetworkProxySettings::Mode::Custom;
 | |
| +    settings.defaultProxyURL = proxyServer.utf8();
 | |
| +    settings.ignoreHosts.reset(g_strdupv(const_cast<char**>(ignoreHosts)));
 | |
| +    return settings;
 | |
| +}
 | |
| +
 | |
| +static WebCore::SoupNetworkProxySettings parseProxySettings(const String& proxyServer, const String& proxyBypassList)
 | |
| +{
 | |
| +    Vector<const char*> ignoreHosts;
 | |
| +    if (!proxyBypassList.isEmpty()) {
 | |
| +        Vector<String> tokens = proxyBypassList.split(',');
 | |
| +        Vector<CString> protectTokens;
 | |
| +        for (String token : tokens) {
 | |
| +            CString cstr = token.utf8();
 | |
| +            ignoreHosts.append(cstr.data());
 | |
| +            protectTokens.append(WTFMove(cstr));
 | |
| +        }
 | |
| +    }
 | |
| +    return parseRawProxySettings(proxyServer, ignoreHosts.data());
 | |
| +}
 | |
| +
 | |
| +InspectorPlaywrightAgentClientGlib::InspectorPlaywrightAgentClientGlib(const WTF::String& proxyURI, const char* const* ignoreHosts)
 | |
| +    : m_proxySettings(parseRawProxySettings(proxyURI, ignoreHosts))
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +RefPtr<WebPageProxy> InspectorPlaywrightAgentClientGlib::createPage(WTF::String& error, const BrowserContext& browserContext)
 | |
| +{
 | |
| +    auto sessionID = browserContext.dataStore->sessionID();
 | |
| +    WebKitWebContext* context = m_idToContext.get(sessionID);
 | |
| +    if (!context && !browserContext.dataStore->isPersistent()) {
 | |
| +        ASSERT_NOT_REACHED();
 | |
| +        error = "Context with provided id not found";
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    RefPtr<WebPageProxy> page = webkitBrowserInspectorCreateNewPageInContext(context);
 | |
| +    if (page == nullptr) {
 | |
| +        error = "Failed to create new page in the context";
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    if (context == nullptr && sessionID != page->sessionID()) {
 | |
| +        ASSERT_NOT_REACHED();
 | |
| +        error = " Failed to create new page in default context";
 | |
| +        return nullptr;
 | |
| +    }
 | |
| +
 | |
| +    return page;
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgentClientGlib::closeBrowser()
 | |
| +{
 | |
| +    m_idToContext.clear();
 | |
| +    webkitBrowserInspectorQuitApplication();
 | |
| +    if (webkitWebContextExistingCount() > 1)
 | |
| +        fprintf(stderr, "LEAK: %d contexts are still alive when closing browser\n", webkitWebContextExistingCount());
 | |
| +}
 | |
| +
 | |
| +static PAL::SessionID sessionIDFromContext(WebKitWebContext* context)
 | |
| +{
 | |
| +    WebKitWebsiteDataManager* data_manager = webkit_web_context_get_website_data_manager(context);
 | |
| +    WebsiteDataStore& websiteDataStore = webkitWebsiteDataManagerGetDataStore(data_manager);
 | |
| +    return websiteDataStore.sessionID();
 | |
| +}
 | |
| +
 | |
| +BrowserContext InspectorPlaywrightAgentClientGlib::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList)
 | |
| +{
 | |
| +    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));
 | |
| +
 | |
| +    if (!proxyServer.isEmpty()) {
 | |
| +        WebCore::SoupNetworkProxySettings contextProxySettings = parseProxySettings(proxyServer, proxyBypassList);
 | |
| +        browserContext.processPool->setNetworkProxySettings(contextProxySettings);
 | |
| +    } else {
 | |
| +        browserContext.processPool->setNetworkProxySettings(m_proxySettings);
 | |
| +    }
 | |
| +    return browserContext;
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgentClientGlib::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
 | |
| +{
 | |
| +    m_idToContext.remove(sessionID);
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..63ff73901ceb50771820709e91796fb42f58e651
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h
 | |
| @@ -0,0 +1,60 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +#include "InspectorPlaywrightAgentClient.h"
 | |
| +#include <WebCore/SoupNetworkProxySettings.h>
 | |
| +#include "WebKitWebContext.h"
 | |
| +#include <wtf/Forward.h>
 | |
| +#include <wtf/HashMap.h>
 | |
| +#include <wtf/glib/GRefPtr.h>
 | |
| +#include <wtf/text/StringHash.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class InspectorPlaywrightAgentClientGlib : public InspectorPlaywrightAgentClient {
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    InspectorPlaywrightAgentClientGlib(const WTF::String& proxyURI, const char* const* ignoreHosts);
 | |
| +    ~InspectorPlaywrightAgentClientGlib() override = default;
 | |
| +
 | |
| +    RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
 | |
| +    void closeBrowser() override;
 | |
| +    BrowserContext createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) override;
 | |
| +    void deleteBrowserContext(WTF::String& error, PAL::SessionID) override;
 | |
| +
 | |
| +private:
 | |
| +    WebKitWebContext* findContext(WTF::String& error, PAL::SessionID);
 | |
| +
 | |
| +    HashMap<PAL::SessionID, GRefPtr<WebKitWebContext>> m_idToContext;
 | |
| +    WebCore::SoupNetworkProxySettings m_proxySettings;
 | |
| +};
 | |
| +
 | |
| +} // namespace API
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.cpp b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.cpp
 | |
| index be19b6007c9c0fbfffb859e40fd34751493fe7d1..ce214fb7e22f8623aff6e2487cecd0272b21c478 100644
 | |
| --- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.cpp
 | |
| +++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.cpp
 | |
| @@ -31,6 +31,7 @@
 | |
|  #include "DrawingAreaProxyCoordinatedGraphics.h"
 | |
|  #include "LayerTreeContext.h"
 | |
|  #include "WebPageProxy.h"
 | |
| +#include "WebPageInspectorController.h"
 | |
|  #include <WebCore/CairoUtilities.h>
 | |
|  #include <WebCore/PlatformDisplayX11.h>
 | |
|  #include <WebCore/XErrorTrapper.h>
 | |
| @@ -256,6 +257,8 @@ bool AcceleratedBackingStoreX11::paint(cairo_t* cr, const IntRect& clipRect)
 | |
|  
 | |
|      cairo_restore(cr);
 | |
|  
 | |
| +    m_webPage.inspectorController().didPaint(m_surface.get());
 | |
| +
 | |
|      cairo_surface_flush(m_surface.get());
 | |
|  
 | |
|      return true;
 | |
| diff --git a/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp b/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..8a86cc348bc210b71bb463dcb3057f575ad7c1d3
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp
 | |
| @@ -0,0 +1,44 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "InspectorTargetProxy.h"
 | |
| +
 | |
| +#include "WebPageProxy.h"
 | |
| +#include <WebCore/GtkUtilities.h>
 | |
| +#include <gtk/gtk.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +void InspectorTargetProxy::platformActivate(String& error) const
 | |
| +{
 | |
| +    GtkWidget* parent = gtk_widget_get_toplevel(m_page.viewWidget());
 | |
| +    if (WebCore::widgetIsOnscreenToplevelWindow(parent))
 | |
| +        gtk_window_present(GTK_WINDOW(parent));
 | |
| +    else
 | |
| +        error = "The view is not on screen";
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..e5e25acebabb76a05a77db02a99f1267bd99a3af
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp
 | |
| @@ -0,0 +1,69 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "DrawingAreaProxyCoordinatedGraphics.h"
 | |
| +#include "WebPageInspectorEmulationAgent.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +#include <WebCore/IntSize.h>
 | |
| +#include <gtk/gtk.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
 | |
| +{
 | |
| +    GtkWidget* viewWidget = m_page.viewWidget();
 | |
| +    GtkWidget* window = gtk_widget_get_toplevel(viewWidget);
 | |
| +    if (!window) {
 | |
| +        callback("Cannot find parent window"_s);
 | |
| +        return;
 | |
| +    }
 | |
| +    if (!GTK_IS_WINDOW(window)) {
 | |
| +        callback("Toplevel is not a window"_s);
 | |
| +        return;
 | |
| +    }
 | |
| +    GtkAllocation viewAllocation;
 | |
| +    gtk_widget_get_allocation(viewWidget, &viewAllocation);
 | |
| +    if (viewAllocation.width == width && viewAllocation.height == height) {
 | |
| +        callback(String());
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    GtkAllocation windowAllocation;
 | |
| +    gtk_widget_get_allocation(window, &windowAllocation);
 | |
| +
 | |
| +    width += windowAllocation.width - viewAllocation.width;
 | |
| +    height += windowAllocation.height - viewAllocation.height;
 | |
| +
 | |
| +    if (auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(m_page.drawingArea())) {
 | |
| +        drawingArea->waitForSizeUpdate([callback = WTFMove(callback)]() {
 | |
| +            callback(String());
 | |
| +        });
 | |
| +    } else {
 | |
| +        callback("No backing store for window"_s);
 | |
| +    }
 | |
| +    gtk_window_resize(GTK_WINDOW(window), width, height);
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..d0f9827544994e450e24e3f7a427c35eeff94d67
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp
 | |
| @@ -0,0 +1,105 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "WebPageInspectorInputAgent.h"
 | |
| +
 | |
| +#include "KeyBindingTranslator.h"
 | |
| +#include "NativeWebKeyboardEvent.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +#include <WebCore/PlatformKeyboardEvent.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +static Vector<String> commandsForKeyEvent(GdkEventType type, unsigned keyVal, unsigned state)
 | |
| +{
 | |
| +    ASSERT(type == GDK_KEY_PRESS || type == GDK_KEY_RELEASE);
 | |
| +
 | |
| +    GUniquePtr<GdkEvent> event(gdk_event_new(type));
 | |
| +    event->key.keyval = keyVal;
 | |
| +    event->key.time = GDK_CURRENT_TIME;
 | |
| +    event->key.state = state;
 | |
| +    // When synthesizing an event, an invalid hardware_keycode value can cause it to be badly processed by GTK+.
 | |
| +    GUniqueOutPtr<GdkKeymapKey> keys;
 | |
| +    int keysCount;
 | |
| +    if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyVal, &keys.outPtr(), &keysCount) && keysCount)
 | |
| +        event->key.hardware_keycode = keys.get()[0].keycode;
 | |
| +    return KeyBindingTranslator().commandsForKeyEvent(&event->key);
 | |
| +}
 | |
| +
 | |
| +static unsigned modifiersToEventState(OptionSet<WebEvent::Modifier> modifiers)
 | |
| +{
 | |
| +    unsigned state = 0;
 | |
| +    if (modifiers.contains(WebEvent::Modifier::ControlKey))
 | |
| +        state |= GDK_CONTROL_MASK;
 | |
| +    if (modifiers.contains(WebEvent::Modifier::ShiftKey))
 | |
| +        state |= GDK_SHIFT_MASK;
 | |
| +    if (modifiers.contains(WebEvent::Modifier::AltKey))
 | |
| +        state |= GDK_META_MASK;
 | |
| +    if (modifiers.contains(WebEvent::Modifier::CapsLockKey))
 | |
| +        state |= GDK_LOCK_MASK;
 | |
| +    return state;
 | |
| +}
 | |
| +
 | |
| +void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& macCommands, WallTime timestamp)
 | |
| +{
 | |
| +    Vector<String> commands;
 | |
| +    const guint keyVal = WebCore::PlatformKeyboardEvent::gdkKeyCodeForWindowsKeyCode(windowsVirtualKeyCode);
 | |
| +    if (keyVal) {
 | |
| +        GdkEventType event = GDK_NOTHING;
 | |
| +        switch (type)
 | |
| +        {
 | |
| +        case WebKeyboardEvent::KeyDown:
 | |
| +            event = GDK_KEY_PRESS;
 | |
| +            break;
 | |
| +        case WebKeyboardEvent::KeyUp:
 | |
| +            event = GDK_KEY_RELEASE;
 | |
| +            break;
 | |
| +        default:
 | |
| +            fprintf(stderr, "Unsupported event type = %d\n", type);
 | |
| +            break;
 | |
| +        }
 | |
| +        unsigned state = modifiersToEventState(modifiers);
 | |
| +        commands = commandsForKeyEvent(event, keyVal, state);
 | |
| +    }
 | |
| +    NativeWebKeyboardEvent event(
 | |
| +        type,
 | |
| +        text,
 | |
| +        unmodifiedText,
 | |
| +        key,
 | |
| +        code,
 | |
| +        keyIdentifier,
 | |
| +        windowsVirtualKeyCode,
 | |
| +        nativeVirtualKeyCode,
 | |
| +        isAutoRepeat,
 | |
| +        isKeypad,
 | |
| +        isSystemKey,
 | |
| +        modifiers,
 | |
| +        timestamp,
 | |
| +        WTFMove(commands));
 | |
| +    m_page.handleKeyboardEvent(event);
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
 | |
| index 3879abd15a643b0cbe266f9f521ba1e66def7d33..2efc4edc234266d26a15efc26a4e0d28937ca697 100644
 | |
| --- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
 | |
| +++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
 | |
| @@ -445,6 +445,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
 | |
|      
 | |
|  void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
 | |
|  {
 | |
| +    if (!event.nativeEvent())
 | |
| +        return;
 | |
|      [m_contentView _didHandleKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled];
 | |
|  }
 | |
|  
 | |
| diff --git a/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..bce31b16fe37dc2a981389a6160e4094bf2b0f74
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h
 | |
| @@ -0,0 +1,51 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#include "InspectorPlaywrightAgentClient.h"
 | |
| +#include <wtf/Forward.h>
 | |
| +
 | |
| +OBJC_PROTOCOL(_WKBrowserInspectorDelegate);
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class InspectorPlaywrightAgentClientMac : public InspectorPlaywrightAgentClient {
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    InspectorPlaywrightAgentClientMac(_WKBrowserInspectorDelegate* delegate);
 | |
| +    ~InspectorPlaywrightAgentClientMac() override = default;
 | |
| +
 | |
| +    RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
 | |
| +    void closeBrowser() override;
 | |
| +    BrowserContext createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) override;
 | |
| +    void deleteBrowserContext(WTF::String& error, PAL::SessionID) override;
 | |
| +
 | |
| +private:
 | |
| +    _WKBrowserInspectorDelegate* delegate_;
 | |
| +};
 | |
| +
 | |
| +
 | |
| +} // namespace API
 | |
| diff --git a/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..600a1687094f5a209f24dc951206ba7faf4de991
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm
 | |
| @@ -0,0 +1,77 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#import "config.h"
 | |
| +#import "InspectorPlaywrightAgentClientMac.h"
 | |
| +
 | |
| +#import <wtf/RefPtr.h>
 | |
| +#import <wtf/text/WTFString.h>
 | |
| +#import "WebPageProxy.h"
 | |
| +#import "WebProcessPool.h"
 | |
| +#import "WebsiteDataStore.h"
 | |
| +#import "_WKBrowserInspector.h"
 | |
| +#import "WKProcessPoolInternal.h"
 | |
| +#import "WKWebsiteDataStoreInternal.h"
 | |
| +#import "WKWebView.h"
 | |
| +#import "WKWebViewInternal.h"
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +InspectorPlaywrightAgentClientMac::InspectorPlaywrightAgentClientMac(_WKBrowserInspectorDelegate* delegate)
 | |
| +  : delegate_(delegate)
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +RefPtr<WebPageProxy> InspectorPlaywrightAgentClientMac::createPage(WTF::String& error, const BrowserContext& browserContext)
 | |
| +{
 | |
| +    auto sessionID = browserContext.dataStore->sessionID();
 | |
| +    WKWebView *webView = [delegate_ createNewPage:sessionID.toUInt64()];
 | |
| +    if (!webView) {
 | |
| +        error = "Internal error: can't create page in given context"_s;
 | |
| +        return nil;
 | |
| +    }
 | |
| +    return [webView _page].get();
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgentClientMac::closeBrowser()
 | |
| +{
 | |
| +    [delegate_ quit];
 | |
| +}
 | |
| +
 | |
| +BrowserContext InspectorPlaywrightAgentClientMac::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList)
 | |
| +{
 | |
| +    _WKBrowserContext* wkBrowserContext = [[delegate_ createBrowserContext:proxyServer WithBypassList:proxyBypassList] autorelease];
 | |
| +    BrowserContext browserContext;
 | |
| +    browserContext.processPool = &static_cast<WebProcessPool&>([[wkBrowserContext processPool] _apiObject]);
 | |
| +    browserContext.dataStore = &static_cast<WebsiteDataStore&>([[wkBrowserContext dataStore] _apiObject]);
 | |
| +    return browserContext;
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgentClientMac::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
 | |
| +{
 | |
| +    [delegate_ deleteBrowserContext:sessionID.toUInt64()];
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm b/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..721826c8c98fc85b68a4f45deaee69c1219a7254
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm
 | |
| @@ -0,0 +1,42 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#import "config.h"
 | |
| +#import "InspectorTargetProxy.h"
 | |
| +#import "WebPageProxy.h"
 | |
| +
 | |
| +#if PLATFORM(MAC)
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +void InspectorTargetProxy::platformActivate(String& error) const
 | |
| +{
 | |
| +    NSWindow* window = m_page.platformWindow();
 | |
| +    [window makeKeyAndOrderFront:nil];
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| +
 | |
| +#endif
 | |
| diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.h b/Source/WebKit/UIProcess/mac/PageClientImplMac.h
 | |
| index 53203c0bab7e8fc2f1b75d340c055c938590050e..207c96011155c51a398c3cb46b7beb3295990d5c 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();
 | |
|  
 | |
| @@ -154,6 +156,9 @@ private:
 | |
|      void updateAcceleratedCompositingMode(const LayerTreeContext&) override;
 | |
|      void didFirstLayerFlush(const LayerTreeContext&) override;
 | |
|  
 | |
| +// Paywright begin
 | |
| +    RetainPtr<CGImageRef> takeSnapshotForAutomation() override;
 | |
| +// Paywright end
 | |
|      RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&) override;
 | |
|      void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&) override;
 | |
|  #if ENABLE(MAC_GESTURE_EVENTS)
 | |
| @@ -201,6 +206,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 7b7e66c79edaf84a8a14756524e16c26e57896c6..868c8bc1e3b74e3318c56e568a18d768bc8ccd27 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/RetainPtr.h>
 | |
|  #import <wtf/text/CString.h>
 | |
| @@ -103,6 +104,13 @@ namespace WebKit {
 | |
|  
 | |
|  using namespace WebCore;
 | |
|  
 | |
| +static bool _headless = false;
 | |
| +
 | |
| +// static
 | |
| +void PageClientImpl::setHeadless(bool headless) {
 | |
| +    _headless = true;
 | |
| +}
 | |
| +
 | |
|  PageClientImpl::PageClientImpl(NSView *view, WKWebView *webView)
 | |
|      : PageClientImplCocoa(webView)
 | |
|      , m_view(view)
 | |
| @@ -156,6 +164,9 @@ NSWindow *PageClientImpl::activeWindow() const
 | |
|  
 | |
|  bool PageClientImpl::isViewWindowActive()
 | |
|  {
 | |
| +    if (_headless)
 | |
| +        return true;
 | |
| +
 | |
|      ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
 | |
|      NSWindow *activeViewWindow = activeWindow();
 | |
|      return activeViewWindow.isKeyWindow || [NSApp keyWindow] == activeViewWindow;
 | |
| @@ -163,6 +174,9 @@ bool PageClientImpl::isViewWindowActive()
 | |
|  
 | |
|  bool PageClientImpl::isViewFocused()
 | |
|  {
 | |
| +    if (_headless)
 | |
| +        return true;
 | |
| +
 | |
|      // FIXME: This is called from the WebPageProxy constructor before we have a WebViewImpl.
 | |
|      // Once WebViewImpl and PageClient merge, this won't be a problem.
 | |
|      if (!m_impl)
 | |
| @@ -186,6 +200,9 @@ void PageClientImpl::makeFirstResponder()
 | |
|      
 | |
|  bool PageClientImpl::isViewVisible()
 | |
|  {
 | |
| +    if (_headless)
 | |
| +        return true;
 | |
| +
 | |
|      NSView *activeView = this->activeView();
 | |
|      NSWindow *activeViewWindow = activeWindow();
 | |
|  
 | |
| @@ -269,7 +286,8 @@ void PageClientImpl::didRelaunchProcess()
 | |
|  
 | |
|  void PageClientImpl::preferencesDidChange()
 | |
|  {
 | |
| -    m_impl->preferencesDidChange();
 | |
| +    if (m_impl)
 | |
| +        m_impl->preferencesDidChange();
 | |
|  }
 | |
|  
 | |
|  void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip)
 | |
| @@ -445,6 +463,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);
 | |
|  }
 | |
|  
 | |
| @@ -562,6 +582,12 @@ CALayer *PageClientImpl::acceleratedCompositingRootLayer() const
 | |
|      return m_impl->acceleratedCompositingRootLayer();
 | |
|  }
 | |
|  
 | |
| +// Paywright begin
 | |
| +RetainPtr<CGImageRef> PageClientImpl::takeSnapshotForAutomation() {
 | |
| +    return m_impl->takeSnapshotForAutomation();
 | |
| +}
 | |
| +// Paywright begin
 | |
| +
 | |
|  RefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot(Optional<WebCore::IntRect>&&)
 | |
|  {
 | |
|      return m_impl->takeViewSnapshot();
 | |
| @@ -740,6 +766,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);
 | |
| @@ -906,6 +939,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..78bd14ef515e4022dbc251945d60248a791d50b3
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm
 | |
| @@ -0,0 +1,124 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#import "config.h"
 | |
| +#import "NativeWebMouseEvent.h"
 | |
| +#import "WebPageInspectorInputAgent.h"
 | |
| +#import "WebPageProxy.h"
 | |
| +#import <WebCore/IntPoint.h>
 | |
| +#import <WebCore/IntSize.h>
 | |
| +#import "NativeWebKeyboardEvent.h"
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +using namespace WebCore;
 | |
| +
 | |
| +void WebPageInspectorInputAgent::platformDispatchMouseEvent(const String& type, int x, int y, 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, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& commands, WallTime timestamp)
 | |
| +{
 | |
| +    Vector<WebCore::KeypressCommand> macCommands;
 | |
| +    for (const String& command : commands) {
 | |
| +      m_page.registerKeypressCommandName(command);
 | |
| +      macCommands.append(WebCore::KeypressCommand(command.utf8().data()));
 | |
| +    }
 | |
| +    if (text.length() > 0 && macCommands.size() == 0)
 | |
| +      macCommands.append(WebCore::KeypressCommand("insertText:", text));
 | |
| +    NativeWebKeyboardEvent event(
 | |
| +        type,
 | |
| +        text,
 | |
| +        unmodifiedText,
 | |
| +        key,
 | |
| +        code,
 | |
| +        keyIdentifier,
 | |
| +        windowsVirtualKeyCode,
 | |
| +        nativeVirtualKeyCode,
 | |
| +        isAutoRepeat,
 | |
| +        isKeypad,
 | |
| +        isSystemKey,
 | |
| +        modifiers,
 | |
| +        timestamp,
 | |
| +        WTFMove(macCommands));
 | |
| +    m_page.handleKeyboardEvent(event);
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..4e5910f0f1d1b237b7c5637ccbc4fe3f374ff391
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp
 | |
| @@ -0,0 +1,90 @@
 | |
| +/*
 | |
| + * Copyright (C) 2020 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "InspectorPlaywrightAgentClientWin.h"
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +#include "APIPageConfiguration.h"
 | |
| +#include "APIProcessPoolConfiguration.h"
 | |
| +#include "InspectorPlaywrightAgent.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +#include "WebsiteDataStore.h"
 | |
| +#include "WebPreferences.h"
 | |
| +#include "WebProcessPool.h"
 | |
| +#include "WebView.h"
 | |
| +#include "WKAPICast.h"
 | |
| +#include <WebCore/CurlProxySettings.h>
 | |
| +#include <wtf/HashMap.h>
 | |
| +#include <wtf/RefPtr.h>
 | |
| +#include <wtf/text/StringView.h>
 | |
| +#include <wtf/text/WTFString.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +InspectorPlaywrightAgentClientWin::InspectorPlaywrightAgentClientWin(ConfigureDataStoreCallback configureDataStore, CreatePageCallback createPage, QuitCallback quit)
 | |
| +    : m_configureDataStore(configureDataStore)
 | |
| +    , m_createPage(createPage)
 | |
| +    , m_quit(quit)
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +RefPtr<WebPageProxy> InspectorPlaywrightAgentClientWin::createPage(WTF::String& error, const BrowserContext& context)
 | |
| +{
 | |
| +    auto conf = API::PageConfiguration::create();
 | |
| +    conf->setProcessPool(context.processPool.get());
 | |
| +    conf->setWebsiteDataStore(context.dataStore.get());
 | |
| +    return toImpl(m_createPage(toAPI(&conf.get())));
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgentClientWin::closeBrowser()
 | |
| +{
 | |
| +    m_quit();
 | |
| +}
 | |
| +
 | |
| +BrowserContext InspectorPlaywrightAgentClientWin::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList)
 | |
| +{
 | |
| +    auto config = API::ProcessPoolConfiguration::create();
 | |
| +    BrowserContext browserContext;
 | |
| +    browserContext.processPool = WebKit::WebProcessPool::create(config);
 | |
| +    browserContext.dataStore = WebKit::WebsiteDataStore::createNonPersistent();
 | |
| +    m_configureDataStore(toAPI(browserContext.dataStore.get()));
 | |
| +    if (!proxyServer.isEmpty()) {
 | |
| +        URL proxyURL = URL(URL(), proxyServer);
 | |
| +        WebCore::CurlProxySettings settings(WTFMove(proxyURL), String(proxyBypassList));
 | |
| +        browserContext.dataStore->setNetworkProxySettings(WTFMove(settings));
 | |
| +    }
 | |
| +    PAL::SessionID sessionID = browserContext.dataStore->sessionID();
 | |
| +    return browserContext;
 | |
| +}
 | |
| +
 | |
| +void InspectorPlaywrightAgentClientWin::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID)
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.h b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.h
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..e18db39e5e9fe3e70658b4596c636eac083222b4
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.h
 | |
| @@ -0,0 +1,60 @@
 | |
| +/*
 | |
| + * Copyright (C) 2020 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#pragma once
 | |
| +
 | |
| +#if ENABLE(REMOTE_INSPECTOR)
 | |
| +
 | |
| +#include "InspectorPlaywrightAgentClient.h"
 | |
| +#include <WebKit/WKInspector.h>
 | |
| +#include <wtf/Forward.h>
 | |
| +#include <wtf/text/StringHash.h>
 | |
| +
 | |
| +typedef void (*ConfigureDataStoreCallback)(WKWebsiteDataStoreRef dataStore);
 | |
| +typedef WKPageRef (*CreatePageCallback)(WKPageConfigurationRef configuration);
 | |
| +typedef void (*QuitCallback)();
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +class InspectorPlaywrightAgentClientWin : public InspectorPlaywrightAgentClient {
 | |
| +    WTF_MAKE_FAST_ALLOCATED;
 | |
| +public:
 | |
| +    InspectorPlaywrightAgentClientWin(ConfigureDataStoreCallback, CreatePageCallback, QuitCallback);
 | |
| +    ~InspectorPlaywrightAgentClientWin() override = default;
 | |
| +
 | |
| +    RefPtr<WebPageProxy> createPage(WTF::String& error, const BrowserContext&) override;
 | |
| +    void closeBrowser() override;
 | |
| +    BrowserContext createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) override;
 | |
| +    void deleteBrowserContext(WTF::String& error, PAL::SessionID) override;
 | |
| +
 | |
| +private:
 | |
| +    ConfigureDataStoreCallback m_configureDataStore;
 | |
| +    CreatePageCallback m_createPage;
 | |
| +    QuitCallback m_quit;
 | |
| +};
 | |
| +
 | |
| +} // namespace API
 | |
| +
 | |
| +#endif // ENABLE(REMOTE_INSPECTOR)
 | |
| diff --git a/Source/WebKit/UIProcess/win/InspectorTargetProxyWin.cpp b/Source/WebKit/UIProcess/win/InspectorTargetProxyWin.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..135a60361fa8fbf907382625e7c8dd4ea64ceb94
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/win/InspectorTargetProxyWin.cpp
 | |
| @@ -0,0 +1,36 @@
 | |
| +/*
 | |
| + * Copyright (C) 2020 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "InspectorTargetProxy.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +void InspectorTargetProxy::platformActivate(String& error) const
 | |
| +{
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp b/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..62b841fe1d0de2296e1c61e328cff564f5aa1c0f
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp
 | |
| @@ -0,0 +1,58 @@
 | |
| +/*
 | |
| + * Copyright (C) 2020 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "WebPageInspectorEmulationAgent.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
 | |
| +{
 | |
| +    HWND viewHwnd = m_page.viewWidget();
 | |
| +    HWND windowHwnd = GetAncestor(viewHwnd, GA_ROOT);
 | |
| +    RECT viewRect;
 | |
| +    RECT windowRect;
 | |
| +
 | |
| +    if (!windowHwnd || !GetWindowRect(windowHwnd, &windowRect)) {
 | |
| +        callback("Could not retrieve window size");
 | |
| +        return;
 | |
| +    }
 | |
| +    if (!GetWindowRect(viewHwnd, &viewRect)) {
 | |
| +        callback("Could retrieve view size");
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    width += windowRect.right - windowRect.left - viewRect.right + viewRect.left;
 | |
| +    height += windowRect.bottom - windowRect.top - viewRect.bottom + viewRect.top;
 | |
| +
 | |
| +    if (!SetWindowPos(windowHwnd, 0, 0, 0, width, height, SWP_NOCOPYBITS | SWP_NOSENDCHANGING | SWP_NOMOVE)) {
 | |
| +        callback("Could not resize window");
 | |
| +        return;
 | |
| +    }
 | |
| +    callback(String());
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/win/WebPageInspectorInputAgentWin.cpp b/Source/WebKit/UIProcess/win/WebPageInspectorInputAgentWin.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..5cf8a010e9809e6a95741cdb7c2cbeb445ab638b
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/win/WebPageInspectorInputAgentWin.cpp
 | |
| @@ -0,0 +1,55 @@
 | |
| +/*
 | |
| + * Copyright (C) 2020 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "WebPageInspectorInputAgent.h"
 | |
| +
 | |
| +#include "NativeWebKeyboardEvent.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +#include <WebCore/PlatformKeyboardEvent.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& macCommands, WallTime timestamp)
 | |
| +{
 | |
| +    NativeWebKeyboardEvent event(
 | |
| +        type,
 | |
| +        text,
 | |
| +        unmodifiedText,
 | |
| +        key,
 | |
| +        code,
 | |
| +        keyIdentifier,
 | |
| +        windowsVirtualKeyCode,
 | |
| +        nativeVirtualKeyCode,
 | |
| +        isAutoRepeat,
 | |
| +        isKeypad,
 | |
| +        isSystemKey,
 | |
| +        modifiers,
 | |
| +        timestamp);
 | |
| +    m_page.handleKeyboardEvent(event);
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..7453194ca6f032ba86a4c67f5bf12688ab6ec1be
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp
 | |
| @@ -0,0 +1,40 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "InspectorTargetProxy.h"
 | |
| +
 | |
| +#include "WebPageProxy.h"
 | |
| +#include <wpe/wpe.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +void InspectorTargetProxy::platformActivate(String& error) const
 | |
| +{
 | |
| +    struct wpe_view_backend* backend = m_page.viewBackend();
 | |
| +    wpe_view_backend_add_activity_state(backend, wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window);
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..5dc76aa302cb574307059e66a1b73730efe920da
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp
 | |
| @@ -0,0 +1,41 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "WebPageInspectorEmulationAgent.h"
 | |
| +
 | |
| +#include "WebPageProxy.h"
 | |
| +#include <wpe/wpe.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function<void (const String& error)>&& callback)
 | |
| +{
 | |
| +    struct wpe_view_backend* backend = m_page.viewBackend();
 | |
| +    wpe_view_backend_dispatch_set_size(backend, width, height);
 | |
| +    callback(String());
 | |
| +}
 | |
| +
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..c3d7cacea987ba2b094d5022c670705ef6ced129
 | |
| --- /dev/null
 | |
| +++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp
 | |
| @@ -0,0 +1,55 @@
 | |
| +/*
 | |
| + * Copyright (C) 2019 Microsoft Corporation.
 | |
| + *
 | |
| + * Redistribution and use in source and binary forms, with or without
 | |
| + * modification, are permitted provided that the following conditions
 | |
| + * are met:
 | |
| + * 1. Redistributions of source code must retain the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer.
 | |
| + * 2. Redistributions in binary form must reproduce the above copyright
 | |
| + *    notice, this list of conditions and the following disclaimer in the
 | |
| + *    documentation and/or other materials provided with the distribution.
 | |
| + *
 | |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| + */
 | |
| +
 | |
| +#include "config.h"
 | |
| +#include "WebPageInspectorInputAgent.h"
 | |
| +
 | |
| +#include "NativeWebKeyboardEvent.h"
 | |
| +#include "WebPageProxy.h"
 | |
| +#include <WebCore/PlatformKeyboardEvent.h>
 | |
| +#include <wpe/wpe.h>
 | |
| +
 | |
| +namespace WebKit {
 | |
| +
 | |
| +void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<WebEvent::Modifier> modifiers, Vector<String>& macCommands, WallTime timestamp)
 | |
| +{
 | |
| +    NativeWebKeyboardEvent event(
 | |
| +        type,
 | |
| +        text,
 | |
| +        unmodifiedText,
 | |
| +        key,
 | |
| +        code,
 | |
| +        keyIdentifier,
 | |
| +        windowsVirtualKeyCode,
 | |
| +        nativeVirtualKeyCode,
 | |
| +        isAutoRepeat,
 | |
| +        isKeypad,
 | |
| +        isSystemKey,
 | |
| +        modifiers,
 | |
| +        timestamp);
 | |
| +    m_page.handleKeyboardEvent(event);
 | |
| +}
 | |
| + 
 | |
| +} // namespace WebKit
 | |
| diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
 | |
| index e94fe6ecc22840e9f11a03ef12c247dfaa82c299..79f73cc00f100d477243e601831d8470b760027e 100644
 | |
| --- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj
 | |
| +++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
 | |
| @@ -1779,6 +1779,18 @@
 | |
|  		CEE4AE2B1A5DCF430002F49B /* UIKitSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE4AE2A1A5DCF430002F49B /* UIKitSPI.h */; };
 | |
|  		D3B9484711FF4B6500032B39 /* WebPopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = D3B9484311FF4B6500032B39 /* WebPopupMenu.h */; };
 | |
|  		D3B9484911FF4B6500032B39 /* WebSearchPopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */; };
 | |
| +		D71A94322370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */; };
 | |
| +		D71A94342370E07A002C4D9E /* InspectorPlaywrightAgentClient.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */; };
 | |
| +		D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */; };
 | |
| +		D71A94422371F67E002C4D9E /* WebPageInspectorEmulationAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */; };
 | |
| +		D71A94432371F67E002C4D9E /* WebPageInspectorInputAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */; };
 | |
| +		D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94492372290B002C4D9E /* _WKBrowserInspector.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
| +		D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */; };
 | |
| +		D76D6888238DBD81008D314B /* InspectorDialogAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D76D6887238DBD80008D314B /* InspectorDialogAgent.h */; };
 | |
| +		D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */; };
 | |
| +		D79902B2236E9404005D6F7E /* InspectorTargetProxyMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */; };
 | |
| +		D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */; };
 | |
| +		D7EB04E72372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */; };
 | |
|  		DF462E0F23F22F5500EFF35F /* WKHTTPCookieStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
|  		DF462E1223F338BE00EFF35F /* WKContentWorldPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
|  		E105FE5418D7B9DE008F57A8 /* EditingRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E105FE5318D7B9DE008F57A8 /* EditingRange.h */; };
 | |
| @@ -1832,6 +1844,9 @@
 | |
|  		E5CB07DC20E1678F0022C183 /* WKFormColorControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E5CB07DA20E1678F0022C183 /* WKFormColorControl.h */; };
 | |
|  		ECA680D81E690E2500731D20 /* WebProcessCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = ECA680D71E690DF800731D20 /* WebProcessCocoa.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
|  		ED82A7F2128C6FAF004477B3 /* WKBundlePageOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A22F0FF1289FCD90085E74F /* WKBundlePageOverlay.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
| +		F303B849249A8D640031DE5C /* ScreencastEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */; };
 | |
| +		F33C7AC7249AD79C0018BE41 /* libwebrtc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */; };
 | |
| +		F3867F0A24607D4E008F0F31 /* InspectorScreencastAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */; };
 | |
|  		F409BA181E6E64BC009DA28E /* WKDragDestinationAction.h in Headers */ = {isa = PBXBuildFile; fileRef = F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */; settings = {ATTRIBUTES = (Private, ); }; };
 | |
|  		F42D634122A0EFDF00D2FB3A /* WebAutocorrectionData.h in Headers */ = {isa = PBXBuildFile; fileRef = F42D633F22A0EFD300D2FB3A /* WebAutocorrectionData.h */; };
 | |
|  		F430E9422247335F005FE053 /* WebsiteMetaViewportPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = F430E941224732A9005FE053 /* WebsiteMetaViewportPolicy.h */; };
 | |
| @@ -5253,6 +5268,19 @@
 | |
|  		D3B9484311FF4B6500032B39 /* WebPopupMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPopupMenu.h; sourceTree = "<group>"; };
 | |
|  		D3B9484411FF4B6500032B39 /* WebSearchPopupMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSearchPopupMenu.cpp; sourceTree = "<group>"; };
 | |
|  		D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSearchPopupMenu.h; sourceTree = "<group>"; };
 | |
| +		D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBrowserInspector.h; sourceTree = "<group>"; };
 | |
| +		D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorPlaywrightAgentClientMac.h; sourceTree = "<group>"; };
 | |
| +		D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorPlaywrightAgentClient.h; sourceTree = "<group>"; };
 | |
| +		D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteInspectorPipe.h; sourceTree = "<group>"; };
 | |
| +		D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorEmulationAgent.h; sourceTree = "<group>"; };
 | |
| +		D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorInputAgent.h; sourceTree = "<group>"; };
 | |
| +		D71A94492372290B002C4D9E /* _WKBrowserInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKBrowserInspector.h; sourceTree = "<group>"; };
 | |
| +		D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrowserInspectorPipe.h; sourceTree = "<group>"; };
 | |
| +		D76D6887238DBD80008D314B /* InspectorDialogAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDialogAgent.h; sourceTree = "<group>"; };
 | |
| +		D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorEmulationAgentMac.mm; sourceTree = "<group>"; };
 | |
| +		D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorTargetProxyMac.mm; sourceTree = "<group>"; };
 | |
| +		D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorInputAgentMac.mm; sourceTree = "<group>"; };
 | |
| +		D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorPlaywrightAgentClientMac.mm; sourceTree = "<group>"; };
 | |
|  		DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKHTTPCookieStorePrivate.h; sourceTree = "<group>"; };
 | |
|  		DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContentWorldPrivate.h; sourceTree = "<group>"; };
 | |
|  		DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebWheelEvent.h; sourceTree = "<group>"; };
 | |
| @@ -5357,6 +5385,12 @@
 | |
|  		ECA680D71E690DF800731D20 /* WebProcessCocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebProcessCocoa.h; sourceTree = "<group>"; };
 | |
|  		ECBFC1DB1E6A4D66000300C7 /* ExtraPublicSymbolsForTAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtraPublicSymbolsForTAPI.h; sourceTree = "<group>"; };
 | |
|  		F036978715F4BF0500C3A80E /* WebColorPicker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebColorPicker.cpp; sourceTree = "<group>"; };
 | |
| +		F303B847249A8D3A0031DE5C /* ScreencastEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScreencastEncoder.cpp; sourceTree = "<group>"; };
 | |
| +		F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreencastEncoder.h; sourceTree = "<group>"; };
 | |
| +		F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; path = libwebrtc.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 | |
| +		F3867F0324607D2B008F0F31 /* InspectorScreencastAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorScreencastAgent.cpp; sourceTree = "<group>"; };
 | |
| +		F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorScreencastAgent.h; sourceTree = "<group>"; };
 | |
| +		F3970344249BD4CE003E1A22 /* ScreencastEncoderMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScreencastEncoderMac.mm; sourceTree = "<group>"; };
 | |
|  		F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDragDestinationAction.h; sourceTree = "<group>"; };
 | |
|  		F40D1B68220BDC0F00B49A01 /* WebAutocorrectionContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebAutocorrectionContext.h; path = ios/WebAutocorrectionContext.h; sourceTree = "<group>"; };
 | |
|  		F41056612130699A0092281D /* APIAttachmentCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = APIAttachmentCocoa.mm; sourceTree = "<group>"; };
 | |
| @@ -5447,6 +5481,7 @@
 | |
|  				3766F9EF189A1244003CF19B /* QuartzCore.framework in Frameworks */,
 | |
|  				37694525184FC6B600CDE21F /* Security.framework in Frameworks */,
 | |
|  				37BEC4DD1948FC6A008B4286 /* WebCore.framework in Frameworks */,
 | |
| +				F33C7AC7249AD79C0018BE41 /* libwebrtc.dylib in Frameworks */,
 | |
|  			);
 | |
|  			runOnlyForDeploymentPostprocessing = 0;
 | |
|  		};
 | |
| @@ -7186,6 +7221,7 @@
 | |
|  		37C4C08318149C2A003688B9 /* Cocoa */ = {
 | |
|  			isa = PBXGroup;
 | |
|  			children = (
 | |
| +				D71A94492372290B002C4D9E /* _WKBrowserInspector.h */,
 | |
|  				1A43E826188F38E2009E4D30 /* Deprecated */,
 | |
|  				37A5E01218BBF937000A081E /* _WKActivatedElementInfo.h */,
 | |
|  				37A5E01118BBF937000A081E /* _WKActivatedElementInfo.mm */,
 | |
| @@ -8087,6 +8123,7 @@
 | |
|  		5750F3292032D4E300389347 /* Frameworks */ = {
 | |
|  			isa = PBXGroup;
 | |
|  			children = (
 | |
| +				F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */,
 | |
|  				5750F32A2032D4E500389347 /* LocalAuthentication.framework */,
 | |
|  				570DAAB0230273D200E8FC04 /* NearField.framework */,
 | |
|  			);
 | |
| @@ -8483,6 +8520,10 @@
 | |
|  			children = (
 | |
|  				9197940423DBC4BB00257892 /* InspectorBrowserAgent.cpp */,
 | |
|  				9197940323DBC4BB00257892 /* InspectorBrowserAgent.h */,
 | |
| +				F3867F0324607D2B008F0F31 /* InspectorScreencastAgent.cpp */,
 | |
| +				F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */,
 | |
| +				F303B847249A8D3A0031DE5C /* ScreencastEncoder.cpp */,
 | |
| +				F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */,
 | |
|  			);
 | |
|  			path = Agents;
 | |
|  			sourceTree = "<group>";
 | |
| @@ -8491,6 +8532,7 @@
 | |
|  			isa = PBXGroup;
 | |
|  			children = (
 | |
|  				A5D3504D1D78F0D2005124A9 /* RemoteWebInspectorProxyMac.mm */,
 | |
| +				F3970344249BD4CE003E1A22 /* ScreencastEncoderMac.mm */,
 | |
|  				1CA8B935127C774E00576C2B /* WebInspectorProxyMac.mm */,
 | |
|  				994BADF11F7D77EA00B571E7 /* WKInspectorViewController.h */,
 | |
|  				994BADF21F7D77EB00B571E7 /* WKInspectorViewController.mm */,
 | |
| @@ -8916,6 +8958,12 @@
 | |
|  		BC032DC310F438260058C15A /* UIProcess */ = {
 | |
|  			isa = PBXGroup;
 | |
|  			children = (
 | |
| +				D76D6887238DBD80008D314B /* InspectorDialogAgent.h */,
 | |
| +				D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */,
 | |
| +				D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */,
 | |
| +				D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */,
 | |
| +				D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */,
 | |
| +				D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */,
 | |
|  				BC032DC410F4387C0058C15A /* API */,
 | |
|  				512F588D12A8836F00629530 /* Authentication */,
 | |
|  				9955A6E81C79809000EB6A93 /* Automation */,
 | |
| @@ -9196,6 +9244,7 @@
 | |
|  		BC0C376610F807660076D7CB /* C */ = {
 | |
|  			isa = PBXGroup;
 | |
|  			children = (
 | |
| +				D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */,
 | |
|  				5123CF18133D25E60056F800 /* cg */,
 | |
|  				6EE849C41368D9040038D481 /* mac */,
 | |
|  				BCB63477116BF10600603215 /* WebKit2_C.h */,
 | |
| @@ -9796,6 +9845,11 @@
 | |
|  		BCCF085C113F3B7500C650C5 /* mac */ = {
 | |
|  			isa = PBXGroup;
 | |
|  			children = (
 | |
| +				D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */,
 | |
| +				D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */,
 | |
| +				D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */,
 | |
| +				D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */,
 | |
| +				D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */,
 | |
|  				B878B613133428DC006888E9 /* CorrectionPanel.h */,
 | |
|  				B878B614133428DC006888E9 /* CorrectionPanel.mm */,
 | |
|  				C1817362205844A900DFDA65 /* DisplayLink.cpp */,
 | |
| @@ -10578,6 +10632,7 @@
 | |
|  				991F492F23A812C60054642B /* _WKInspectorDebuggableInfo.h in Headers */,
 | |
|  				99036AE223A949CF0000B06A /* _WKInspectorDebuggableInfoInternal.h in Headers */,
 | |
|  				9197940C23DBC50300257892 /* _WKInspectorDelegate.h in Headers */,
 | |
| +				D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */,
 | |
|  				5CAFDE472130846A00B1F7E1 /* _WKInspectorInternal.h in Headers */,
 | |
|  				9979CA58237F49F10039EC05 /* _WKInspectorPrivate.h in Headers */,
 | |
|  				A5C0F0AB2000658200536536 /* _WKInspectorWindow.h in Headers */,
 | |
| @@ -10818,6 +10873,7 @@
 | |
|  				1A14F8E21D74C834006CBEC6 /* FrameInfoData.h in Headers */,
 | |
|  				1AE00D611831792100087DD7 /* FrameLoadState.h in Headers */,
 | |
|  				5C121E842410208D00486F9B /* FrameTreeNodeData.h in Headers */,
 | |
| +				F303B849249A8D640031DE5C /* ScreencastEncoder.h in Headers */,
 | |
|  				2D4AF0892044C3C4006C8817 /* FrontBoardServicesSPI.h in Headers */,
 | |
|  				CD78E1151DB7D7ED0014A2DE /* FullscreenClient.h in Headers */,
 | |
|  				CD19D2EA2046406F0017074A /* FullscreenTouchSecheuristic.h in Headers */,
 | |
| @@ -10830,6 +10886,7 @@
 | |
|  				BC06F43A12DBCCFB002D78DE /* GeolocationPermissionRequestProxy.h in Headers */,
 | |
|  				2DA944A41884E4F000ED86DB /* GestureTypes.h in Headers */,
 | |
|  				2DA049B8180CCD0A00AAFA9E /* GraphicsLayerCARemote.h in Headers */,
 | |
| +				D71A94342370E07A002C4D9E /* InspectorPlaywrightAgentClient.h in Headers */,
 | |
|  				C0CE72AD1247E78D00BC0EC4 /* HandleMessage.h in Headers */,
 | |
|  				1AC75A1B1B3368270056745B /* HangDetectionDisabler.h in Headers */,
 | |
|  				57AC8F50217FEED90055438C /* HidConnection.h in Headers */,
 | |
| @@ -10958,8 +11015,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 */,
 | |
| @@ -11043,6 +11102,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 */,
 | |
|  				1A0C227E2451130A00ED614D /* QuickLookThumbnailingSoftLink.h in Headers */,
 | |
| @@ -11339,6 +11399,7 @@
 | |
|  				A543E30D215C8A9000279CD9 /* WebPageInspectorTargetController.h in Headers */,
 | |
|  				A543E307215AD13700279CD9 /* WebPageInspectorTargetFrontendChannel.h in Headers */,
 | |
|  				C0CE72A11247E71D00BC0EC4 /* WebPageMessages.h in Headers */,
 | |
| +				F3867F0A24607D4E008F0F31 /* InspectorScreencastAgent.h in Headers */,
 | |
|  				2D5C9D0619C81D8F00B3C5C1 /* WebPageOverlay.h in Headers */,
 | |
|  				46C392292316EC4D008EED9B /* WebPageProxyIdentifier.h in Headers */,
 | |
|  				BCBD3915125BB1A800D2C29F /* WebPageProxyMessages.h in Headers */,
 | |
| @@ -11470,6 +11531,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 */,
 | |
| @@ -11522,6 +11584,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 */,
 | |
| @@ -11672,6 +11735,7 @@
 | |
|  				1AB8A1F818400BB800E9AE69 /* WKPageContextMenuClient.h in Headers */,
 | |
|  				8372DB251A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h in Headers */,
 | |
|  				1AB8A1F418400B8F00E9AE69 /* WKPageFindClient.h in Headers */,
 | |
| +				D71A94322370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h in Headers */,
 | |
|  				1AB8A1F618400B9D00E9AE69 /* WKPageFindMatchesClient.h in Headers */,
 | |
|  				1AB8A1F018400B0000E9AE69 /* WKPageFormClient.h in Headers */,
 | |
|  				BC7B633712A45ABA00D174A4 /* WKPageGroup.h in Headers */,
 | |
| @@ -12731,6 +12795,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 */,
 | |
| @@ -12742,6 +12807,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 */,
 | |
| @@ -12766,6 +12832,7 @@
 | |
|  				1A2D8439127F65D5001EB962 /* NPObjectMessageReceiverMessageReceiver.cpp in Sources */,
 | |
|  				2D92A792212B6AD400F493FD /* NPObjectProxy.cpp in Sources */,
 | |
|  				2D92A793212B6AD400F493FD /* NPRemoteObjectMap.cpp in Sources */,
 | |
| +				D7EB04E72372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm in Sources */,
 | |
|  				2D913447212CF9F000128AFD /* NPRuntimeObjectMap.cpp in Sources */,
 | |
|  				2D913448212CF9F000128AFD /* NPRuntimeUtilities.cpp in Sources */,
 | |
|  				2D92A794212B6AD400F493FD /* NPVariantData.cpp in Sources */,
 | |
| @@ -13049,6 +13116,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 6a7eca6018f62c1b8a2a42b33d565f896a613fea..e3d9f2a32de767f22b332204e48409a6605a387a 100644
 | |
| --- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
 | |
| +++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
 | |
| @@ -227,6 +227,11 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou
 | |
|      }
 | |
|  #endif
 | |
|  
 | |
| +    if (m_emulateOfflineState) {
 | |
| +        scheduleInternallyFailedLoad(resourceLoader);
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
|      if (!tryLoadingUsingURLSchemeHandler(resourceLoader, trackingParameters)) {
 | |
|          WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be scheduled with the NetworkProcess");
 | |
|  
 | |
| @@ -766,7 +771,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)
 | |
| @@ -777,6 +782,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;
 | |
|  
 | |
| @@ -785,6 +795,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 283afab34d2d73235219f9aad80f6028a9b6faef..bbe4f258383dc21574cc3b5769deae721d5f427d 100644
 | |
| --- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h
 | |
| +++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h
 | |
| @@ -88,6 +88,7 @@ public:
 | |
|      bool isOnLine() const final;
 | |
|      void addOnlineStateChangeListener(Function<void(bool)>&&) final;
 | |
|      void setOnLineState(bool);
 | |
| +    void setEmulateOfflineState(bool) final;
 | |
|  
 | |
|  private:
 | |
|      void scheduleLoad(WebCore::ResourceLoader&, WebCore::CachedResource*, bool shouldClearReferrerOnHTTPSToHTTPRedirect);
 | |
| @@ -126,6 +127,7 @@ private:
 | |
|      HashMap<unsigned long, PreconnectCompletionHandler> m_preconnectCompletionHandlers;
 | |
|      Vector<Function<void(bool)>> m_onlineStateChangeListeners;
 | |
|      bool m_isOnLine { true };
 | |
| +    bool m_emulateOfflineState { false };
 | |
|  };
 | |
|  
 | |
|  } // namespace WebKit
 | |
| diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
 | |
| index 22f9c46ecdf08834321840ffe71a5114616a3357..cf551cd6111e86421e7311c403715d62917abe25 100644
 | |
| --- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
 | |
| +++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
 | |
| @@ -385,6 +385,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);
 | |
|  }
 | |
| @@ -775,6 +777,13 @@ bool WebChromeClient::canShowDataListSuggestionLabels() const
 | |
|  
 | |
|  #endif
 | |
|  
 | |
| +#if ENABLE(ORIENTATION_EVENTS) && !PLATFORM(IOS_FAMILY)
 | |
| +int WebChromeClient::deviceOrientation() const {
 | |
| +    // Only overrides are supported for non-iOS platforms.
 | |
| +    return 0;
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
|  void WebChromeClient::runOpenPanel(Frame& frame, FileChooser& fileChooser)
 | |
|  {
 | |
|      if (m_page.activeOpenPanelResultListener())
 | |
| diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
 | |
| index 0587c38861b0b77beaa9dcc911895305e4fa155e..3b89b5dd5fedc50d108a0fb539ea4a41f0d12159 100644
 | |
| --- a/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
 | |
| +++ b/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
 | |
| @@ -1538,13 +1538,6 @@ void WebFrameLoaderClient::transitionToCommittedForNewPage()
 | |
|      if (webPage->scrollPinningBehavior() != DoNotPin)
 | |
|          view->setScrollPinningBehavior(webPage->scrollPinningBehavior());
 | |
|  
 | |
| -#if USE(COORDINATED_GRAPHICS)
 | |
| -    if (shouldUseFixedLayout) {
 | |
| -        view->setDelegatesScrolling(shouldUseFixedLayout);
 | |
| -        view->setPaintsEntireContents(shouldUseFixedLayout);
 | |
| -        return;
 | |
| -    }
 | |
| -#endif
 | |
|  }
 | |
|  
 | |
|  void WebFrameLoaderClient::didRestoreFromBackForwardCache()
 | |
| diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
 | |
| index 564126e14e22882e7896fcff3e6d32f722eec47b..430a64b83ad0e99772d8708ef37ff87671f99ec6 100644
 | |
| --- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
 | |
| +++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
 | |
| @@ -37,6 +37,7 @@
 | |
|  #include "WebPreferencesKeys.h"
 | |
|  #include <WebCore/Frame.h>
 | |
|  #include <WebCore/GraphicsContext.h>
 | |
| +#include <WebCore/InspectorController.h>
 | |
|  #include <WebCore/Page.h>
 | |
|  #include <WebCore/PageOverlayController.h>
 | |
|  #include <WebCore/Settings.h>
 | |
| @@ -122,6 +123,16 @@ void DrawingAreaCoordinatedGraphics::scroll(const IntRect& scrollRect, const Int
 | |
|          ASSERT(m_scrollRect.isEmpty());
 | |
|          ASSERT(m_scrollOffset.isEmpty());
 | |
|          ASSERT(m_dirtyRegion.isEmpty());
 | |
| +// Playwright begin
 | |
| +#if !PLATFORM(WIN)
 | |
| +        if (m_webPage.mainFrameView() && m_webPage.mainFrameView()->useFixedLayout()) {
 | |
| +            IntRect visibleRect;
 | |
| +            visibleRect.move(-scrollDelta.width(), -scrollDelta.height());
 | |
| +            m_layerTreeHost->scrollNonCompositedContents(visibleRect);
 | |
| +            return;
 | |
| +        }
 | |
| +#endif
 | |
| +// Playwright end
 | |
|          m_layerTreeHost->scrollNonCompositedContents(scrollRect);
 | |
|          return;
 | |
|      }
 | |
| @@ -247,6 +258,7 @@ void DrawingAreaCoordinatedGraphics::updatePreferences(const WebPreferencesStore
 | |
|          settings.setAcceleratedCompositingEnabled(false);
 | |
|      }
 | |
|  #endif
 | |
| +
 | |
|      settings.setForceCompositingMode(store.getBoolValueForKey(WebPreferencesKey::forceCompositingModeKey()));
 | |
|      // Fixed position elements need to be composited and create stacking contexts
 | |
|      // in order to be scrolled by the ScrollingCoordinator.
 | |
| diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp
 | |
| index 8685e23d0d468601c459954775fe6f565b0ce7ac..f9d49292837bf390b81eadeaebe2d4d599bc236c 100644
 | |
| --- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp
 | |
| +++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp
 | |
| @@ -166,8 +166,16 @@ void LayerTreeHost::setViewOverlayRootLayer(GraphicsLayer* viewOverlayRootLayer)
 | |
|  void LayerTreeHost::scrollNonCompositedContents(const IntRect& rect)
 | |
|  {
 | |
|      auto* frameView = m_webPage.mainFrameView();
 | |
| +
 | |
| +// Playwright begin
 | |
| +#if PLATFORM(WIN)
 | |
|      if (!frameView || !frameView->delegatesScrolling())
 | |
| +        return
 | |
| +#else
 | |
| +    if (!frameView)
 | |
|          return;
 | |
| +#endif
 | |
| +// Playwright end
 | |
|  
 | |
|      m_viewportController.didScroll(rect.location());
 | |
|      if (m_isDiscardable)
 | |
| diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp
 | |
| index 87b864636e3b863425a6259f0e52864bbc9f5148..0ae141af6a821e4aea3f257c825b90c94e3883c7 100644
 | |
| --- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp
 | |
| +++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp
 | |
| @@ -29,6 +29,7 @@
 | |
|  
 | |
|  #if USE(GRAPHICS_LAYER_TEXTURE_MAPPER)
 | |
|  
 | |
| +#include "DrawingArea.h"
 | |
|  #include "WebPage.h"
 | |
|  #include <GLES2/gl2.h>
 | |
|  #include <WebCore/Document.h>
 | |
| @@ -72,6 +73,8 @@ void LayerTreeHost::compositeLayersToContext()
 | |
|      m_textureMapper->endPainting();
 | |
|  
 | |
|      m_context->swapBuffers();
 | |
| +    if (auto* drawingArea = m_webPage.drawingArea())
 | |
| +        drawingArea->didCompositeLayersToContext();
 | |
|  }
 | |
|  
 | |
|  bool LayerTreeHost::flushPendingLayerChanges()
 | |
| diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp
 | |
| index 97429e9769d2accf3d99949e2f6ca8a4e8acece9..ae2fc8308acf53931e00c2ed9a1563f464fb4975 100644
 | |
| --- a/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp
 | |
| +++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp
 | |
| @@ -27,6 +27,7 @@
 | |
|  #include "DrawingArea.h"
 | |
|  
 | |
|  #include "DrawingAreaMessages.h"
 | |
| +#include "DrawingAreaProxyMessages.h"
 | |
|  #include "WebPage.h"
 | |
|  #include "WebPageCreationParameters.h"
 | |
|  #include "WebProcess.h"
 | |
| @@ -89,6 +90,14 @@ RefPtr<WebCore::DisplayRefreshMonitor> DrawingArea::createDisplayRefreshMonitor(
 | |
|  }
 | |
|  #endif
 | |
|  
 | |
| +#if PLATFORM(WIN)
 | |
| +void DrawingArea::didCompositeLayersToContext()
 | |
| +{
 | |
| +    if (m_isReportingAcceleratedCompositing)
 | |
| +        send(Messages::DrawingAreaProxy::DidCompositeLayersToContext());
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
|  void DrawingArea::removeMessageReceiverIfNeeded()
 | |
|  {
 | |
|      if (m_hasRemovedMessageReceiver)
 | |
| diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.h b/Source/WebKit/WebProcess/WebPage/DrawingArea.h
 | |
| index ce7758d0b9468d9b7f6f845b4deaf5671274fecd..59a40482dad05dad593997c23a0b5125a961c164 100644
 | |
| --- a/Source/WebKit/WebProcess/WebPage/DrawingArea.h
 | |
| +++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.h
 | |
| @@ -144,6 +144,9 @@ public:
 | |
|      virtual void didChangeViewportAttributes(WebCore::ViewportAttributes&&) = 0;
 | |
|      virtual void deviceOrPageScaleFactorChanged() = 0;
 | |
|  #endif
 | |
| +#if PLATFORM(WIN)
 | |
| +    void didCompositeLayersToContext();
 | |
| +#endif
 | |
|  
 | |
|      virtual void adoptLayersFromDrawingArea(DrawingArea&) { }
 | |
|      virtual void adoptDisplayRefreshMonitorsFromDrawingArea(DrawingArea&) { }
 | |
| @@ -171,6 +174,9 @@ private:
 | |
|  #if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER)
 | |
|      virtual void updateBackingStoreState(uint64_t /*backingStoreStateID*/, bool /*respondImmediately*/, float /*deviceScaleFactor*/, const WebCore::IntSize& /*size*/,
 | |
|                                           const WebCore::IntSize& /*scrollOffset*/) { }
 | |
| +#endif
 | |
| +#if PLATFORM(WIN)
 | |
| +    void setReportAcceleratedCompositing(bool enabled) { m_isReportingAcceleratedCompositing = enabled; }
 | |
|  #endif
 | |
|      virtual void didUpdate() { }
 | |
|  
 | |
| @@ -186,6 +192,9 @@ private:
 | |
|  #endif
 | |
|  
 | |
|      bool m_hasRemovedMessageReceiver { false };
 | |
| +#if PLATFORM(WIN)
 | |
| +    bool m_isReportingAcceleratedCompositing { false };
 | |
| +#endif
 | |
|  };
 | |
|  
 | |
|  } // namespace WebKit
 | |
| diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.messages.in b/Source/WebKit/WebProcess/WebPage/DrawingArea.messages.in
 | |
| index f207e107e95270a7f9189cba9ab677534aa22792..cb7d776279c97db54eae7748019c47846193923f 100644
 | |
| --- a/Source/WebKit/WebProcess/WebPage/DrawingArea.messages.in
 | |
| +++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.messages.in
 | |
| @@ -24,6 +24,9 @@ messages -> DrawingArea NotRefCounted {
 | |
|  #if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER)
 | |
|      UpdateBackingStoreState(uint64_t backingStoreStateID, bool respondImmediately, float deviceScaleFactor, WebCore::IntSize size, WebCore::IntSize scrollOffset)
 | |
|  #endif
 | |
| +#if PLATFORM(WIN)
 | |
| +    SetReportAcceleratedCompositing(bool enabled)
 | |
| +#endif
 | |
|  
 | |
|      DidUpdate()
 | |
|  
 | |
| 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 0965d2c00720e1570331d30e108e5e1dbab35591..89aea1f3fb9b712c272fb9b96f9777f8a8a1aef0 100644
 | |
| --- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp
 | |
| +++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
 | |
| @@ -773,6 +773,9 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters)
 | |
|      send(Messages::WebPageProxy::DidCreateContextForVisibilityPropagation(m_contextForVisibilityPropagation->contextID()));
 | |
|  #endif
 | |
|  
 | |
| +    if (parameters.shouldPauseInInspectorWhenShown)
 | |
| +        m_page->inspectorController().pauseWhenShown();
 | |
| +
 | |
|      updateThrottleState();
 | |
|  }
 | |
|  
 | |
| @@ -1532,6 +1535,22 @@ void WebPage::platformDidReceiveLoadParameters(const LoadParameters& loadParamet
 | |
|  }
 | |
|  #endif
 | |
|  
 | |
| +void WebPage::loadRequestInFrameForInspector(LoadParameters&& loadParameters, WebCore::FrameIdentifier frameID)
 | |
| +{
 | |
| +    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
 | |
| +    if (!frame) {
 | |
| +        send(Messages::WebPageProxy::DidDestroyNavigation(loadParameters.navigationID));
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    // FIXME: use m_pendingNavigationID instead?
 | |
| +    m_pendingFrameNavigationID = loadParameters.navigationID;
 | |
| +
 | |
| +    FrameLoadRequest frameLoadRequest { *frame->coreFrame(), loadParameters.request };
 | |
| +    frame->coreFrame()->loader().load(WTFMove(frameLoadRequest));
 | |
| +    ASSERT(!m_pendingFrameNavigationID);
 | |
| +}
 | |
| +
 | |
|  void WebPage::loadRequest(LoadParameters&& loadParameters)
 | |
|  {
 | |
|      setIsNavigatingToAppBoundDomain(loadParameters.isNavigatingToAppBoundDomain);
 | |
| @@ -1738,17 +1757,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())
 | |
| @@ -1765,20 +1780,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));
 | |
| @@ -1786,7 +1799,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg
 | |
|      send(Messages::WebPageProxy::DidChangeViewportProperties(attr));
 | |
|  #endif
 | |
|  }
 | |
| -#endif
 | |
|  
 | |
|  void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
 | |
|  {
 | |
| @@ -2085,6 +2097,7 @@ void WebPage::scaleView(double scale)
 | |
|      }
 | |
|  
 | |
|      m_page->setViewScaleFactor(scale);
 | |
| +    send(Messages::WebPageProxy::ViewScaleFactorDidChange(scale));
 | |
|      scalePage(pageScale, scrollPositionAtNewScale);
 | |
|  }
 | |
|  
 | |
| @@ -2189,17 +2202,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)
 | |
| @@ -3084,6 +3093,11 @@ void WebPage::sendMessageToTargetBackend(const String& targetId, const String& m
 | |
|      m_inspectorTargetController->sendMessageToTargetBackend(targetId, message);
 | |
|  }
 | |
|  
 | |
| +void WebPage::resumeInspectorIfPausedInNewWindow()
 | |
| +{
 | |
| +    m_page->inspectorController().resumeIfPausedInNewWindow();
 | |
| +}
 | |
| +
 | |
|  void WebPage::insertNewlineInQuotedContent()
 | |
|  {
 | |
|      Frame& frame = m_page->focusController().focusedOrMainFrame();
 | |
| @@ -3324,6 +3338,7 @@ void WebPage::didCompletePageTransition()
 | |
|  void WebPage::show()
 | |
|  {
 | |
|      send(Messages::WebPageProxy::ShowPage());
 | |
| +    m_page->inspectorController().didShowNewWindow();
 | |
|  }
 | |
|  
 | |
|  void WebPage::setShouldFireEvents(bool shouldFireEvents)
 | |
| @@ -6419,6 +6434,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 0495602f0e36506fd3a686984423f8222c74b926..0db6e61f8730a7a1cfbc64fcdc65466ec52c2497 100644
 | |
| --- a/Source/WebKit/WebProcess/WebPage/WebPage.h
 | |
| +++ b/Source/WebKit/WebProcess/WebPage/WebPage.h
 | |
| @@ -1167,6 +1167,7 @@ public:
 | |
|      void connectInspector(const String& targetId, Inspector::FrontendChannel::ConnectionType);
 | |
|      void disconnectInspector(const String& targetId);
 | |
|      void sendMessageToTargetBackend(const String& targetId, const String& message);
 | |
| +    void resumeInspectorIfPausedInNewWindow();
 | |
|  
 | |
|      void insertNewlineInQuotedContent();
 | |
|  
 | |
| @@ -1436,6 +1437,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&&);
 | |
| @@ -1588,9 +1590,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);
 | |
| @@ -2057,6 +2057,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 16af317e8846f5f3f96c080b4caa875a6a4000d4..989727ac97daf431a620c295b4ce23010d528607 100644
 | |
| --- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
 | |
| +++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
 | |
| @@ -133,6 +133,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType
 | |
|      ConnectInspector(String targetId, Inspector::FrontendChannel::ConnectionType connectionType)
 | |
|      DisconnectInspector(String targetId)
 | |
|      SendMessageToTargetBackend(String targetId, String message)
 | |
| +    ResumeInspectorIfPausedInNewWindow();
 | |
|  
 | |
|  #if ENABLE(REMOTE_INSPECTOR)
 | |
|      SetIndicating(bool indicating);
 | |
| @@ -173,6 +174,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 692e231e6e6d607bbb9cfc14132a97a79de18197..760eae48b53c6569d0e3caeb2352b5686ccba17c 100644
 | |
| --- a/Source/WebKit/WebProcess/WebProcess.cpp
 | |
| +++ b/Source/WebKit/WebProcess/WebProcess.cpp
 | |
| @@ -81,6 +81,7 @@
 | |
|  #include "WebsiteData.h"
 | |
|  #include "WebsiteDataStoreParameters.h"
 | |
|  #include "WebsiteDataType.h"
 | |
| +#include <JavaScriptCore/IdentifiersFactory.h>
 | |
|  #include <JavaScriptCore/JSLock.h>
 | |
|  #include <JavaScriptCore/MemoryStatistics.h>
 | |
|  #include <JavaScriptCore/WasmFaultSignalHandler.h>
 | |
| @@ -284,6 +285,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 9fcd43bd1fe68d96674f90ccb974bbe3312c01f9..330921f916ead6b0ddac45ed24df16b4ef6334a7 100644
 | |
| --- a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
 | |
| +++ b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
 | |
| @@ -4214,7 +4214,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 299cb1ca7934ba8aaa3d620cf61594be640b039a..f768038894b2fac417e20467dcebca85c6e2c06b 100644
 | |
| --- a/Source/WebKitLegacy/mac/WebView/WebView.mm
 | |
| +++ b/Source/WebKitLegacy/mac/WebView/WebView.mm
 | |
| @@ -4494,7 +4494,7 @@ IGNORE_WARNINGS_END
 | |
|  }
 | |
|  #endif // PLATFORM(IOS_FAMILY)
 | |
|  
 | |
| -#if ENABLE(TOUCH_EVENTS)
 | |
| +#if ENABLE(IOS_TOUCH_EVENTS)
 | |
|  
 | |
|  - (NSArray *)_touchEventRegions
 | |
|  {
 | |
| @@ -4536,7 +4536,7 @@ IGNORE_WARNINGS_END
 | |
|      }).autorelease();
 | |
|  }
 | |
|  
 | |
| -#endif // ENABLE(TOUCH_EVENTS)
 | |
| +#endif // ENABLE(IOS_TOUCH_EVENTS)
 | |
|  
 | |
|  // For backwards compatibility with the WebBackForwardList API, we honor both
 | |
|  // a per-WebView and a per-preferences setting for whether to use the back/forward cache.
 | |
| diff --git a/Source/cmake/FindLibVPX.cmake b/Source/cmake/FindLibVPX.cmake
 | |
| new file mode 100644
 | |
| index 0000000000000000000000000000000000000000..dd6a53e2d57318489b7e49dd7373706d5d9dc387
 | |
| --- /dev/null
 | |
| +++ b/Source/cmake/FindLibVPX.cmake
 | |
| @@ -0,0 +1,25 @@
 | |
| +# Find LibVPX
 | |
| +
 | |
| +find_package(PkgConfig QUIET)
 | |
| +pkg_check_modules(PC_LIBVPX REQUIRED vpx)
 | |
| +
 | |
| +find_path(LIBVPX_INCLUDE_DIRS
 | |
| +    NAMES vpx/vp8.h
 | |
| +    HINTS ${PC_LIBVPX_INCLUDEDIR}
 | |
| +          ${PC_LIBVPX_INCLUDE_DIRS}
 | |
| +)
 | |
| +
 | |
| +find_library(LIBVPX_LIBRARIES
 | |
| +    NAMES vpx
 | |
| +    HINTS ${PC_LIBVPX_LIBDIR}
 | |
| +          ${PC_LIBVPX_LIBRARY_DIRS}
 | |
| +)
 | |
| +
 | |
| +include(FindPackageHandleStandardArgs)
 | |
| +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibVPX REQUIRED_VARS LIBVPX_INCLUDE_DIRS LIBVPX_LIBRARIES
 | |
| +                                         VERSION_VAR   PC_LIBVPX_VERSION)
 | |
| +
 | |
| +mark_as_advanced(
 | |
| +    LIBVPX_INCLUDE_DIRS
 | |
| +    LIBVPX_LIBRARIES
 | |
| +)
 | |
| diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake
 | |
| index a3e5519e987e8840d9a86b296a31e247e920b1c3..483c06a6a04c37d4f0a4048c64fbe544ba4eac4a 100644
 | |
| --- a/Source/cmake/OptionsGTK.cmake
 | |
| +++ b/Source/cmake/OptionsGTK.cmake
 | |
| @@ -6,6 +6,8 @@ WEBKIT_OPTION_DEFINE(USE_GTK4 "Whether to enable usage of GTK4 instead of GTK3."
 | |
|  
 | |
|  SET_PROJECT_VERSION(2 29 1)
 | |
|  
 | |
| +set(ENABLE_WEBKIT_LEGACY OFF)
 | |
| +
 | |
|  if (USE_GTK4)
 | |
|      set(WEBKITGTK_API_VERSION 5.0)
 | |
|      set(GTK_MINIMUM_VERSION 3.98.5)
 | |
| @@ -55,6 +57,10 @@ find_package(EGL)
 | |
|  find_package(OpenGL)
 | |
|  find_package(OpenGLES2)
 | |
|  
 | |
| +# Playwright begin
 | |
| +find_package(LibVPX REQUIRED)
 | |
| +# Playwright end
 | |
| +
 | |
|  include(GStreamerDefinitions)
 | |
|  
 | |
|  SET_AND_EXPOSE_TO_BUILD(USE_ATK TRUE)
 | |
| @@ -198,6 +204,13 @@ if (USE_GTK4)
 | |
|  WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETSCAPE_PLUGIN_API PRIVATE OFF)
 | |
|  endif ()
 | |
|  
 | |
| +# 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 1e32f16e9d2cb73f267ceb19c6aed46236b81587..2d1440b013ff6d7ada5bb76b7063da8d5d925214 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)
 | |
|  
 | |
| @@ -76,13 +77,21 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBGL2 PRIVATE OFF)
 | |
|  WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_RTC PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
 | |
|  WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBXR PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
 | |
|  
 | |
| +# Playwright
 | |
| +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_APPLICATION_MANIFEST PRIVATE ON)
 | |
| +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TRAILING_WORD PRIVATE ON)
 | |
| +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PRIVATE ON)
 | |
| +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DARK_MODE_CSS PRIVATE ON)
 | |
| +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON)
 | |
| +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LEGACY_CSS_VENDOR_PREFIXES PRIVATE ON)
 | |
| +
 | |
|  # Public options specific to the WPE port. Do not add any options here unless
 | |
|  # there is a strong reason we should support changing the value of the option,
 | |
|  # and the option is not relevant to any other WebKit ports.
 | |
|  WEBKIT_OPTION_DEFINE(ENABLE_GTKDOC "Whether or not to use generate gtkdoc." PUBLIC OFF)
 | |
|  WEBKIT_OPTION_DEFINE(USE_OPENJPEG "Whether to enable support for JPEG2000 images." PUBLIC ON)
 | |
|  WEBKIT_OPTION_DEFINE(USE_WOFF2 "Whether to enable support for WOFF2 Web Fonts." PUBLIC ON)
 | |
| -WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC ${DEVELOPER_MODE})
 | |
| +WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC OFF)
 | |
|  WEBKIT_OPTION_DEFINE(USE_SYSTEMD "Whether to enable journald logging" PUBLIC ON)
 | |
|  
 | |
|  # Private options specific to the WPE port.
 | |
| diff --git a/Source/cmake/OptionsWin.cmake b/Source/cmake/OptionsWin.cmake
 | |
| index 4047a1d6df94f3c57337875c390eae447bcfc3ea..7fb9b0927ce187fc060ae84408b5130351f45520 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 ()
 | |
|  
 | |
| @@ -91,6 +92,13 @@ if (${WTF_PLATFORM_WIN_CAIRO})
 | |
|      WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBDRIVER PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
 | |
|      WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_CRYPTO PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
 | |
|  
 | |
| +    # Playwright
 | |
| +    WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_CONIC_GRADIENTS PRIVATE ON)
 | |
| +    WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TRAILING_WORD PRIVATE ON)
 | |
| +    WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DARK_MODE_CSS PRIVATE ON)
 | |
| +    WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON)
 | |
| +    WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_EVENTS PRIVATE ON)
 | |
| +
 | |
|      # FIXME: Implement plugin process on Modern WebKit. https://bugs.webkit.org/show_bug.cgi?id=185313
 | |
|      WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETSCAPE_PLUGIN_API PRIVATE OFF)
 | |
|  else ()
 | |
| diff --git a/Source/cmake/OptionsWinCairo.cmake b/Source/cmake/OptionsWinCairo.cmake
 | |
| index 113170ce21145fc53a3c804822ef20fa9d89de8b..855ff101965bf1dd652d58903db0c143c3f389e6 100644
 | |
| --- a/Source/cmake/OptionsWinCairo.cmake
 | |
| +++ b/Source/cmake/OptionsWinCairo.cmake
 | |
| @@ -31,6 +31,29 @@ if (WebP_FOUND)
 | |
|      SET_AND_EXPOSE_TO_BUILD(USE_WEBP ON)
 | |
|  endif ()
 | |
|  
 | |
| +# Playwright begin
 | |
| +if (NOT LIBVPX_PACKAGE_PATH)
 | |
| +    set(LIBVPX_PACKAGE_PATH "C:\\vcpkg\\packages\\libvpx_x64-windows")
 | |
| +endif()
 | |
| +file(TO_CMAKE_PATH "${LIBVPX_PACKAGE_PATH}" LIBVPX_PACKAGE_PATH)
 | |
| +message(STATUS "Using LIBVPX_PACKAGE_PATH = ${LIBVPX_PACKAGE_PATH}")
 | |
| +
 | |
| +find_library(LIBVPX_CUSTOM_LIBRARY vpxmd.lib
 | |
| +    HINTS ${LIBVPX_PACKAGE_PATH}/lib
 | |
| +    REQIRED
 | |
| +    NO_DEFAULT_PATH
 | |
| +)
 | |
| +message(STATUS "Found LIBVPX_CUSTOM_LIBRARY = ${LIBVPX_CUSTOM_LIBRARY}")
 | |
| +
 | |
| +find_path(LIBVPX_CUSTOM_INCLUDE_DIR
 | |
| +    NAMES vpx/vp8.h
 | |
| +    HINTS ${LIBVPX_PACKAGE_PATH}/include
 | |
| +    REQUIRED
 | |
| +    NO_DEFAULT_PATH
 | |
| +)
 | |
| +message(STATUS "Found LIBVPX_CUSTOM_INCLUDE_DIR = ${LIBVPX_CUSTOM_INCLUDE_DIR}")
 | |
| +# Playwright end
 | |
| +
 | |
|  # TODO: Add a check for HAVE_RSA_PSS for support of CryptoAlgorithmRSA_PSS
 | |
|  # https://bugs.webkit.org/show_bug.cgi?id=206635
 | |
|  
 | |
| diff --git a/Tools/MiniBrowser/gtk/BrowserTab.c b/Tools/MiniBrowser/gtk/BrowserTab.c
 | |
| index 3845eabba3e964f9e11bb0ffcb8726fd4ea96fc4..630a6e395298bd9c03c1b131f984b0a8444d2051 100644
 | |
| --- a/Tools/MiniBrowser/gtk/BrowserTab.c
 | |
| +++ b/Tools/MiniBrowser/gtk/BrowserTab.c
 | |
| @@ -160,6 +160,11 @@ static void loadChanged(WebKitWebView *webView, WebKitLoadEvent loadEvent, Brows
 | |
|  #endif
 | |
|  }
 | |
|  
 | |
| +static gboolean loadFailed()
 | |
| +{
 | |
| +    return TRUE;
 | |
| +}
 | |
| +
 | |
|  static GtkWidget *createInfoBarQuestionMessage(const char *title, const char *text)
 | |
|  {
 | |
|      GtkWidget *dialog = gtk_info_bar_new_with_buttons("No", GTK_RESPONSE_NO, "Yes", GTK_RESPONSE_YES, NULL);
 | |
| @@ -623,6 +628,7 @@ static void browserTabConstructed(GObject *gObject)
 | |
|      g_signal_connect(tab->webView, "notify::is-loading", G_CALLBACK(isLoadingChanged), tab);
 | |
|      g_signal_connect(tab->webView, "decide-policy", G_CALLBACK(decidePolicy), tab);
 | |
|      g_signal_connect(tab->webView, "load-changed", G_CALLBACK(loadChanged), tab);
 | |
| +    g_signal_connect(tab->webView, "load-failed", G_CALLBACK(loadFailed), tab);
 | |
|      g_signal_connect(tab->webView, "load-failed-with-tls-errors", G_CALLBACK(loadFailedWithTLSerrors), tab);
 | |
|      g_signal_connect(tab->webView, "permission-request", G_CALLBACK(decidePermissionRequest), tab);
 | |
|      g_signal_connect(tab->webView, "run-color-chooser", G_CALLBACK(runColorChooserCallback), tab);
 | |
| diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.c b/Tools/MiniBrowser/gtk/BrowserWindow.c
 | |
| index 5cd84dac3d349cc61199cb22bce3a816706c2250..71f02a0453e85162529748caa03aa1f3e561c777 100644
 | |
| --- a/Tools/MiniBrowser/gtk/BrowserWindow.c
 | |
| +++ b/Tools/MiniBrowser/gtk/BrowserWindow.c
 | |
| @@ -1312,6 +1312,12 @@ static gboolean browserWindowDeleteEvent(GtkWidget *widget, GdkEventAny* event)
 | |
|  }
 | |
|  #endif
 | |
|  
 | |
| +static void zeroPreferredSize(GtkWidget* widget, gint* minimumSize, gint* naturalSize)
 | |
| +{
 | |
| +    *minimumSize = 10;
 | |
| +    *naturalSize = 10;
 | |
| +}
 | |
| +
 | |
|  static void browser_window_class_init(BrowserWindowClass *klass)
 | |
|  {
 | |
|      GObjectClass *gobjectClass = G_OBJECT_CLASS(klass);
 | |
| @@ -1325,6 +1331,14 @@ static void browser_window_class_init(BrowserWindowClass *klass)
 | |
|      GtkWidgetClass *widgetClass = GTK_WIDGET_CLASS(klass);
 | |
|      widgetClass->delete_event = browserWindowDeleteEvent;
 | |
|  #endif
 | |
| +
 | |
| +// Playwrigth begin
 | |
| +    // Override preferred (which is minimum :-) size to 0 so that we can
 | |
| +    // emulate arbitrary resolution.
 | |
| +    GtkWidgetClass* browserWidgetClass = GTK_WIDGET_CLASS(klass);
 | |
| +    browserWidgetClass->get_preferred_width = zeroPreferredSize;
 | |
| +    browserWidgetClass->get_preferred_height = zeroPreferredSize;
 | |
| +// Playwrigth end
 | |
|  }
 | |
|  
 | |
|  /* Public API. */
 | |
| diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.h b/Tools/MiniBrowser/gtk/BrowserWindow.h
 | |
| index 62629b4c1c25ae82bd797b39bbf9de0331f8eed2..5de7900a29b0e629f1ac404bbb0dc5b4e605294d 100644
 | |
| --- a/Tools/MiniBrowser/gtk/BrowserWindow.h
 | |
| +++ b/Tools/MiniBrowser/gtk/BrowserWindow.h
 | |
| @@ -37,7 +37,7 @@ G_BEGIN_DECLS
 | |
|  #define BROWSER_IS_WINDOW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), BROWSER_TYPE_WINDOW))
 | |
|  #define BROWSER_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  BROWSER_TYPE_WINDOW))
 | |
|  #define BROWSER_WINDOW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  BROWSER_TYPE_WINDOW, BrowserWindowClass))
 | |
| -#define BROWSER_DEFAULT_URL            "http://www.webkitgtk.org/"
 | |
| +#define BROWSER_DEFAULT_URL            "about:blank"
 | |
|  #define BROWSER_ABOUT_SCHEME           "minibrowser-about"
 | |
|  
 | |
|  typedef struct _BrowserWindow        BrowserWindow;
 | |
| diff --git a/Tools/MiniBrowser/gtk/main.c b/Tools/MiniBrowser/gtk/main.c
 | |
| index 1cea60b87e1e9445d309e720d00632becd016fac..28b23907f86dd214bd5bd21c78258cd3e14be375 100644
 | |
| --- a/Tools/MiniBrowser/gtk/main.c
 | |
| +++ b/Tools/MiniBrowser/gtk/main.c
 | |
| @@ -55,7 +55,12 @@ static const char *cookiesPolicy;
 | |
|  static const char *proxy;
 | |
|  static gboolean darkMode;
 | |
|  static gboolean enableITP;
 | |
| +static gboolean inspectorPipe;
 | |
| +static gboolean headless;
 | |
| +static gboolean noStartupWindow;
 | |
| +static const char *userDataDir;
 | |
|  static gboolean printVersion;
 | |
| +static GtkApplication *browserApplication = NULL;
 | |
|  
 | |
|  typedef enum {
 | |
|      MINI_BROWSER_ERROR_INVALID_ABOUT_PATH
 | |
| @@ -147,6 +152,10 @@ static const GOptionEntry commandLineOptions[] =
 | |
|      { "content-filter", 0, 0, G_OPTION_ARG_FILENAME, &contentFilter, "JSON with content filtering rules", "FILE" },
 | |
|      { "enable-itp", 0, 0, G_OPTION_ARG_NONE, &enableITP, "Enable Intelligent Tracking Prevention (ITP)", NULL },
 | |
|      { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WebKitGTK version", NULL },
 | |
| +    { "inspector-pipe", 0, 0, G_OPTION_ARG_NONE, &inspectorPipe, "Open pipe connection to the remote inspector", NULL },
 | |
| +    { "user-data-dir", 0, 0, G_OPTION_ARG_STRING, &userDataDir, "Default profile persistence folder location", NULL },
 | |
| +    { "headless", 0, 0, G_OPTION_ARG_NONE, &headless, "Noop headless operation", NULL },
 | |
| +    { "no-startup-window", 0, 0, G_OPTION_ARG_NONE, &noStartupWindow, "Do not open default page", NULL },
 | |
|      { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL…]" },
 | |
|      { 0, 0, 0, 0, 0, 0, 0 }
 | |
|  };
 | |
| @@ -527,6 +536,41 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul
 | |
|      g_main_loop_quit(data->mainLoop);
 | |
|  }
 | |
|  
 | |
| +static WebKitWebContext *persistentWebContext = NULL;
 | |
| +
 | |
| +static WebKitWebView *createNewPage(WebKitBrowserInspector *browser_inspector, WebKitWebContext *context)
 | |
| +{
 | |
| +    if (context == NULL)
 | |
| +        context = persistentWebContext;
 | |
| +
 | |
| +    WebKitWebView *newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
 | |
| +        "web-context", context,
 | |
| +        "is-ephemeral", webkit_web_context_is_ephemeral(context),
 | |
| +        "is-controlled-by-automation", TRUE,
 | |
| +        NULL));
 | |
| +    GtkWidget *newWindow = browser_window_new(NULL, context);
 | |
| +    gtk_window_set_application(GTK_WINDOW(newWindow), browserApplication);
 | |
| +    browser_window_append_view(BROWSER_WINDOW(newWindow), newWebView);
 | |
| +    gtk_widget_grab_focus(GTK_WIDGET(newWebView));
 | |
| +    gtk_widget_show(GTK_WIDGET(newWindow));
 | |
| +    webkit_web_view_load_uri(newWebView, "about:blank");
 | |
| +    return newWebView;
 | |
| +}
 | |
| +
 | |
| +static void quitBroserApplication(WebKitBrowserInspector* browser_inspector)
 | |
| +{
 | |
| +    g_application_release(G_APPLICATION(browserApplication));
 | |
| +}
 | |
| +
 | |
| +static void configureBrowserInspectorPipe()
 | |
| +{
 | |
| +    WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default();
 | |
| +    g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL);
 | |
| +    g_signal_connect(browserInspector, "quit-application", G_CALLBACK(quitBroserApplication), NULL);
 | |
| + 
 | |
| +    webkit_browser_inspector_initialize_pipe(proxy, ignoreHosts);
 | |
| +}
 | |
| +
 | |
|  static void startup(GApplication *application)
 | |
|  {
 | |
|      const char *actionAccels[] = {
 | |
| @@ -557,13 +601,33 @@ static void startup(GApplication *application)
 | |
|  
 | |
|  static void activate(GApplication *application, WebKitSettings *webkitSettings)
 | |
|  {
 | |
| -    WebKitWebsiteDataManager *manager = (privateMode || automationMode) ? webkit_website_data_manager_new_ephemeral() : webkit_website_data_manager_new(NULL);
 | |
| +    if (inspectorPipe)
 | |
| +        configureBrowserInspectorPipe();
 | |
| +
 | |
| +    if (noStartupWindow) {
 | |
| +        // Reference the application, it will be released in quitBroserApplication.
 | |
| +        g_application_hold(application);
 | |
| +        g_clear_object(&webkitSettings);
 | |
| +        return;
 | |
| +    }
 | |
| +
 | |
| +    WebKitWebsiteDataManager *manager;
 | |
| +    if (userDataDir) {
 | |
| +        manager = webkit_website_data_manager_new("base-data-directory", userDataDir, "base-cache-directory", userDataDir, NULL);
 | |
| +        cookiesFile = g_build_filename(userDataDir, "cookies.txt", NULL);
 | |
| +    } else if (inspectorPipe || privateMode || automationMode) {
 | |
| +        manager = webkit_website_data_manager_new_ephemeral();
 | |
| +    } else {
 | |
| +        manager = webkit_website_data_manager_new(NULL);
 | |
| +    }
 | |
|      webkit_website_data_manager_set_itp_enabled(manager, enableITP);
 | |
| +
 | |
|      WebKitWebContext *webContext = g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, "process-swap-on-cross-site-navigation-enabled", TRUE,
 | |
|  #if !GTK_CHECK_VERSION(3, 98, 0)
 | |
|          "use-system-appearance-for-scrollbars", FALSE,
 | |
|  #endif
 | |
|          NULL);
 | |
| +    persistentWebContext = webContext;
 | |
|      g_object_unref(manager);
 | |
|  
 | |
|      if (cookiesPolicy) {
 | |
| @@ -582,7 +646,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings)
 | |
|      }
 | |
|  
 | |
|      if (proxy) {
 | |
| -        WebKitNetworkProxySettings *webkitProxySettings = webkit_network_proxy_settings_new(proxy, ignoreHosts);
 | |
| +        WebKitNetworkProxySettings* webkitProxySettings = webkit_network_proxy_settings_new(proxy, ignoreHosts);
 | |
|          webkit_web_context_set_network_proxy_settings(webContext, WEBKIT_NETWORK_PROXY_MODE_CUSTOM, webkitProxySettings);
 | |
|          webkit_network_proxy_settings_free(webkitProxySettings);
 | |
|      }
 | |
| @@ -648,9 +712,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings)
 | |
|              WebKitWebView *webView = createBrowserTab(mainWindow, webkitSettings, userContentManager, defaultWebsitePolicies);
 | |
|              if (!i)
 | |
|                  firstTab = GTK_WIDGET(webView);
 | |
| -            gchar *url = argumentToURL(uriArguments[i]);
 | |
| -            webkit_web_view_load_uri(webView, url);
 | |
| -            g_free(url);
 | |
| +            webkit_web_view_load_uri(webView, uriArguments[i]);
 | |
|          }
 | |
|      } else {
 | |
|          WebKitWebView *webView = createBrowserTab(mainWindow, webkitSettings, userContentManager, defaultWebsitePolicies);
 | |
| @@ -726,9 +788,11 @@ int main(int argc, char *argv[])
 | |
|      }
 | |
|  
 | |
|      GtkApplication *application = gtk_application_new(NULL, G_APPLICATION_FLAGS_NONE);
 | |
| +    browserApplication = application;
 | |
|      g_signal_connect(application, "startup", G_CALLBACK(startup), NULL);
 | |
|      g_signal_connect(application, "activate", G_CALLBACK(activate), webkitSettings);
 | |
|      g_application_run(G_APPLICATION(application), 0, NULL);
 | |
| +    browserApplication = NULL;
 | |
|      g_object_unref(application);
 | |
|  
 | |
|      return 0;
 | |
| diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp
 | |
| index d6c164fba8deef343b22d598030479e160841d68..71e269134f264d3e703405ab9755d984643ac95f 100644
 | |
| --- a/Tools/MiniBrowser/wpe/main.cpp
 | |
| +++ b/Tools/MiniBrowser/wpe/main.cpp
 | |
| @@ -43,6 +43,9 @@ static gboolean headlessMode;
 | |
|  static gboolean privateMode;
 | |
|  static gboolean automationMode;
 | |
|  static gboolean ignoreTLSErrors;
 | |
| +static gboolean inspectorPipe;
 | |
| +static gboolean noStartupWindow;
 | |
| +static const char* userDataDir;
 | |
|  static const char* contentFilter;
 | |
|  static const char* cookiesFile;
 | |
|  static const char* cookiesPolicy;
 | |
| @@ -66,6 +69,9 @@ static const GOptionEntry commandLineOptions[] =
 | |
|      { "bg-color", 0, 0, G_OPTION_ARG_STRING, &bgColor, "Window background color. Default: white", "COLOR" },
 | |
|      { "enable-itp", 0, 0, G_OPTION_ARG_NONE, &enableITP, "Enable Intelligent Tracking Prevention (ITP)", nullptr },
 | |
|      { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WPE version", nullptr },
 | |
| +    { "inspector-pipe", 'v', 0, G_OPTION_ARG_NONE, &inspectorPipe, "Expose remote debugging protocol over pipe", nullptr },
 | |
| +    { "user-data-dir", 0, 0, G_OPTION_ARG_STRING, &userDataDir, "Default profile persistence folder location", "FILE" },
 | |
| +    { "no-startup-window", 0, 0, G_OPTION_ARG_NONE, &noStartupWindow, "Do not open default page", nullptr },
 | |
|      { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, nullptr, "[URL]" },
 | |
|      { nullptr, 0, 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr }
 | |
|  };
 | |
| @@ -150,13 +156,34 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul
 | |
|      g_main_loop_quit(data->mainLoop);
 | |
|  }
 | |
|  
 | |
| +static gboolean webViewLoadFailed()
 | |
| +{
 | |
| +    return TRUE;
 | |
| +}
 | |
| +
 | |
|  static void webViewClose(WebKitWebView* webView, gpointer)
 | |
|  {
 | |
|      // Hash table key delete func takes care of unref'ing the view
 | |
|      g_hash_table_remove(openViews, webView);
 | |
|  }
 | |
|  
 | |
| -static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer)
 | |
| +static gboolean scriptDialog(WebKitWebView*, WebKitScriptDialog* dialog, gpointer)
 | |
| +{
 | |
| +    if (inspectorPipe)
 | |
| +        webkit_script_dialog_ref(dialog);
 | |
| +    return TRUE;
 | |
| +}
 | |
| +
 | |
| +static gboolean scriptDialogHandled(WebKitWebView*, WebKitScriptDialog* dialog, gpointer)
 | |
| +{
 | |
| +    if (inspectorPipe)
 | |
| +        webkit_script_dialog_unref(dialog);
 | |
| +    return TRUE;
 | |
| +}
 | |
| +
 | |
| +static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer);
 | |
| +
 | |
| +static WebKitWebView* createWebViewImpl(WebKitWebView* webView, WebKitWebContext *webContext)
 | |
|  {
 | |
|      auto backend = createViewBackend(1280, 720);
 | |
|      struct wpe_view_backend* wpeBackend = backend->backend();
 | |
| @@ -168,17 +195,66 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi
 | |
|              delete static_cast<WPEToolingBackends::ViewBackend*>(data);
 | |
|          }, backend.release());
 | |
|  
 | |
| -    auto* newWebView = webkit_web_view_new_with_related_view(viewBackend, webView);
 | |
| -    webkit_web_view_set_settings(newWebView, webkit_web_view_get_settings(webView));
 | |
| +// Playwright begin
 | |
| +    if (headlessMode) {
 | |
| +        webkit_web_view_backend_set_screenshot_callback(viewBackend,
 | |
| +            [](gpointer data) {
 | |
| +                return static_cast<WPEToolingBackends::HeadlessViewBackend*>(data)->snapshot();
 | |
| +            });
 | |
| +    }
 | |
| +// Playwright end
 | |
| +    WebKitWebView* newWebView;
 | |
| +    if (webView) {
 | |
| +        newWebView = webkit_web_view_new_with_related_view(viewBackend, webView);
 | |
| +    } else {
 | |
| +        newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
 | |
| +            "backend", viewBackend,
 | |
| +            "web-context", webContext,
 | |
| +            nullptr));
 | |
| +    }
 | |
|  
 | |
|      g_signal_connect(newWebView, "create", G_CALLBACK(createWebView), nullptr);
 | |
|      g_signal_connect(newWebView, "close", G_CALLBACK(webViewClose), nullptr);
 | |
|  
 | |
|      g_hash_table_add(openViews, newWebView);
 | |
|  
 | |
| +    g_signal_connect(newWebView, "load-failed", G_CALLBACK(webViewLoadFailed), nullptr);
 | |
| +    g_signal_connect(newWebView, "script-dialog", G_CALLBACK(scriptDialog), nullptr);
 | |
| +    g_signal_connect(newWebView, "script-dialog-handled", G_CALLBACK(scriptDialogHandled), nullptr);
 | |
| +    g_signal_connect(newWebView, "create", G_CALLBACK(createWebView), nullptr);
 | |
|      return newWebView;
 | |
|  }
 | |
|  
 | |
| +static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer)
 | |
| +{
 | |
| +    return createWebViewImpl(webView, nullptr);
 | |
| +}
 | |
| +
 | |
| +static WebKitWebContext *persistentWebContext = NULL;
 | |
| +
 | |
| +static WebKitWebView* createNewPage(WebKitBrowserInspector*, WebKitWebContext *webContext)
 | |
| +{
 | |
| +    if (!webContext)
 | |
| +        webContext = persistentWebContext;
 | |
| +    WebKitWebView* webView = createWebViewImpl(nullptr, webContext);
 | |
| +    webkit_web_view_load_uri(webView, "about:blank");
 | |
| +    return webView;
 | |
| +}
 | |
| +
 | |
| +static void quitBroserApplication(WebKitBrowserInspector* browser_inspector, gpointer data)
 | |
| +{
 | |
| +    GMainLoop* mainLoop = static_cast<GMainLoop*>(data);
 | |
| +    g_main_loop_quit(mainLoop);
 | |
| +}
 | |
| +
 | |
| +static void configureBrowserInspector(GMainLoop* mainLoop)
 | |
| +{
 | |
| +    WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default();
 | |
| +    g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL);
 | |
| +    g_signal_connect(browserInspector, "quit-application", G_CALLBACK(quitBroserApplication), mainLoop);
 | |
| +    webkit_browser_inspector_initialize_pipe(proxy, ignoreHosts);
 | |
| +}
 | |
| +
 | |
|  int main(int argc, char *argv[])
 | |
|  {
 | |
|  #if ENABLE_DEVELOPER_MODE
 | |
| @@ -213,6 +289,16 @@ int main(int argc, char *argv[])
 | |
|      }
 | |
|  
 | |
|      auto* loop = g_main_loop_new(nullptr, FALSE);
 | |
| +    if (inspectorPipe)
 | |
| +        configureBrowserInspector(loop);
 | |
| +
 | |
| +    openViews = g_hash_table_new_full(nullptr, nullptr, g_object_unref, nullptr);
 | |
| +
 | |
| +    if (noStartupWindow) {
 | |
| +        g_main_loop_run(loop);
 | |
| +        g_main_loop_unref(loop);
 | |
| +        return 0;
 | |
| +    }
 | |
|  
 | |
|      auto backend = createViewBackend(1280, 720);
 | |
|      struct wpe_view_backend* wpeBackend = backend->backend();
 | |
| @@ -222,9 +308,19 @@ int main(int argc, char *argv[])
 | |
|          return 1;
 | |
|      }
 | |
|  
 | |
| -    auto* manager = (privateMode || automationMode) ? webkit_website_data_manager_new_ephemeral() : webkit_website_data_manager_new(nullptr);
 | |
| +    WebKitWebsiteDataManager *manager;
 | |
| +    if (userDataDir) {
 | |
| +        manager = webkit_website_data_manager_new("base-data-directory", userDataDir, "base-cache-directory", userDataDir, NULL);
 | |
| +        cookiesFile = g_build_filename(userDataDir, "cookies.txt", NULL);
 | |
| +    } else if (inspectorPipe || privateMode || automationMode) {
 | |
| +        manager = webkit_website_data_manager_new_ephemeral();
 | |
| +    } else {
 | |
| +        manager = webkit_website_data_manager_new(NULL);
 | |
| +    }
 | |
|      webkit_website_data_manager_set_itp_enabled(manager, enableITP);
 | |
| -    auto* webContext = webkit_web_context_new_with_website_data_manager(manager);
 | |
| +
 | |
| +    WebKitWebContext *webContext = WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, "process-swap-on-cross-site-navigation-enabled", TRUE, NULL));
 | |
| +    persistentWebContext = webContext;
 | |
|      g_object_unref(manager);
 | |
|  
 | |
|      if (cookiesPolicy) {
 | |
| @@ -243,7 +339,7 @@ int main(int argc, char *argv[])
 | |
|      }
 | |
|  
 | |
|      if (proxy) {
 | |
| -        auto* webkitProxySettings = webkit_network_proxy_settings_new(proxy, ignoreHosts);
 | |
| +        WebKitNetworkProxySettings* webkitProxySettings = webkit_network_proxy_settings_new(proxy, ignoreHosts);
 | |
|          webkit_web_context_set_network_proxy_settings(webContext, WEBKIT_NETWORK_PROXY_MODE_CUSTOM, webkitProxySettings);
 | |
|          webkit_network_proxy_settings_free(webkitProxySettings);
 | |
|      }
 | |
| @@ -289,7 +385,14 @@ int main(int argc, char *argv[])
 | |
|      auto* viewBackend = webkit_web_view_backend_new(wpeBackend, [](gpointer data) {
 | |
|          delete static_cast<WPEToolingBackends::ViewBackend*>(data);
 | |
|      }, backend.release());
 | |
| -
 | |
| +// Playwright begin
 | |
| +    if (headlessMode) {
 | |
| +        webkit_web_view_backend_set_screenshot_callback(viewBackend,
 | |
| +            [](gpointer data) {
 | |
| +                return static_cast<WPEToolingBackends::HeadlessViewBackend*>(data)->snapshot();
 | |
| +            });
 | |
| +    }
 | |
| +// Playwright end
 | |
|      auto* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
 | |
|          "backend", viewBackend,
 | |
|          "web-context", webContext,
 | |
| @@ -306,8 +409,6 @@ int main(int argc, char *argv[])
 | |
|          backendPtr->setAccessibleChild(ATK_OBJECT(accessible));
 | |
|  #endif
 | |
|  
 | |
| -    openViews = g_hash_table_new_full(nullptr, nullptr, g_object_unref, nullptr);
 | |
| -
 | |
|      webkit_web_context_set_automation_allowed(webContext, automationMode);
 | |
|      g_signal_connect(webContext, "automation-started", G_CALLBACK(automationStartedCallback), webView);
 | |
|      g_signal_connect(webView, "permission-request", G_CALLBACK(decidePermissionRequest), nullptr);
 | |
| @@ -323,16 +424,9 @@ int main(int argc, char *argv[])
 | |
|          webkit_web_view_set_background_color(webView, &color);
 | |
|  
 | |
|      if (uriArguments) {
 | |
| -        const char* uri = uriArguments[0];
 | |
| -        if (g_str_equal(uri, "about:gpu"))
 | |
| -            uri = "webkit://gpu";
 | |
| -
 | |
| -        GFile* file = g_file_new_for_commandline_arg(uri);
 | |
| -        char* url = g_file_get_uri(file);
 | |
| -        g_object_unref(file);
 | |
| -        webkit_web_view_load_uri(webView, url);
 | |
| -        g_free(url);
 | |
| -    } else if (automationMode)
 | |
| +        // Playwright: avoid weird url transformation like http://trac.webkit.org/r240840
 | |
| +        webkit_web_view_load_uri(webView, uriArguments[0]);
 | |
| +    } else if (automationMode || inspectorPipe)
 | |
|          webkit_web_view_load_uri(webView, "about:blank");
 | |
|      else
 | |
|          webkit_web_view_load_uri(webView, "https://wpewebkit.org");
 | |
| @@ -342,8 +436,7 @@ int main(int argc, char *argv[])
 | |
|      g_hash_table_destroy(openViews);
 | |
|  
 | |
|  
 | |
| -    if (privateMode || automationMode)
 | |
| -        g_object_unref(webContext);
 | |
| +    g_object_unref(webContext);
 | |
|      g_main_loop_unref(loop);
 | |
|  
 | |
|      return 0;
 | |
| diff --git a/Tools/PlatformWin.cmake b/Tools/PlatformWin.cmake
 | |
| index 44301d5fef9c977dc0228b9de1ae75263efd9014..0c8c7e176a6e02ca04872cdd362d0a8927728557 100644
 | |
| --- a/Tools/PlatformWin.cmake
 | |
| +++ b/Tools/PlatformWin.cmake
 | |
| @@ -10,4 +10,5 @@ endif ()
 | |
|  
 | |
|  if (ENABLE_WEBKIT)
 | |
|      add_subdirectory(WebKitTestRunner)
 | |
| +    add_subdirectory(Playwright/win)
 | |
|  endif ()
 | |
| diff --git a/Tools/Scripts/build-webkit b/Tools/Scripts/build-webkit
 | |
| index 0500097b2d4935909840b278a476000d0287a20c..572d483fcfbee9c71c8aa87e24d9c28cd8939381 100755
 | |
| --- a/Tools/Scripts/build-webkit
 | |
| +++ b/Tools/Scripts/build-webkit
 | |
| @@ -249,7 +249,7 @@ if (isAppleCocoaWebKit()) {
 | |
|      push @projects, ("Source/WebKit");
 | |
|  
 | |
|      if (!isEmbeddedWebKit()) {
 | |
| -        push @projects, ("Tools/MiniBrowser");
 | |
| +        push @projects, ("Tools/Playwright");
 | |
|  
 | |
|          # WebInspectorUI must come after JavaScriptCore and WebCore but before WebKit and WebKit2
 | |
|          my $webKitIndex = first { $projects[$_] eq "Source/WebKitLegacy" } 0..$#projects;
 | |
| diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp
 | |
| index 908ee7c691cab06482f6182b65d31c524bb9f23f..c40917d4e66ab86212187b56c4e5108175e11f0e 100644
 | |
| --- a/Tools/WebKitTestRunner/TestController.cpp
 | |
| +++ b/Tools/WebKitTestRunner/TestController.cpp
 | |
| @@ -730,7 +730,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/wpe/backends/HeadlessViewBackend.cpp b/Tools/wpe/backends/HeadlessViewBackend.cpp
 | |
| index d0af19a9aba9aeab8aa3acb2f8c1129f83e07cd7..b32f3eb1495f5f21f059a9eca236bbbf9584b682 100644
 | |
| --- a/Tools/wpe/backends/HeadlessViewBackend.cpp
 | |
| +++ b/Tools/wpe/backends/HeadlessViewBackend.cpp
 | |
| @@ -148,27 +148,24 @@ void HeadlessViewBackend::updateSnapshot(struct wpe_fdo_shm_exported_buffer* exp
 | |
|              return;
 | |
|      }
 | |
|  
 | |
| -    uint32_t bufferStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width);
 | |
| -    uint8_t* buffer = new uint8_t[bufferStride * m_height];
 | |
| -    memset(buffer, 0, bufferStride * m_height);
 | |
| +    uint32_t width = std::max(0, wl_shm_buffer_get_width(shmBuffer));
 | |
| +    uint32_t height = std::max(0, wl_shm_buffer_get_height(shmBuffer));
 | |
| +    if (!width || !height) {
 | |
| +        fprintf(stderr, "HeadlessViewBackend::updateSnapshot shmBuffer is empty: %ux%u\n", width, height);
 | |
| +        return;
 | |
| +    }
 | |
|  
 | |
| +    uint32_t bufferStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
 | |
| +    uint32_t stride = std::max(0, wl_shm_buffer_get_stride(shmBuffer));
 | |
| +    if (bufferStride != stride) {
 | |
| +        fprintf(stderr, "bufferStride != stride: %u != %u\n", bufferStride, stride);
 | |
| +        return;
 | |
| +    }
 | |
| +    uint8_t* buffer = new uint8_t[bufferStride * height];
 | |
|      {
 | |
| -        uint32_t width = std::min<uint32_t>(m_width, std::max(0, wl_shm_buffer_get_width(shmBuffer)));
 | |
| -        uint32_t height = std::min<uint32_t>(m_height, std::max(0, wl_shm_buffer_get_height(shmBuffer)));
 | |
| -        uint32_t stride = std::max(0, wl_shm_buffer_get_stride(shmBuffer));
 | |
| -
 | |
|          wl_shm_buffer_begin_access(shmBuffer);
 | |
|          auto* data = static_cast<uint8_t*>(wl_shm_buffer_get_data(shmBuffer));
 | |
| -
 | |
| -        for (uint32_t y = 0; y < height; ++y) {
 | |
| -            for (uint32_t x = 0; x < width; ++x) {
 | |
| -                buffer[bufferStride * y + 4 * x + 0] = data[stride * y + 4 * x + 0];
 | |
| -                buffer[bufferStride * y + 4 * x + 1] = data[stride * y + 4 * x + 1];
 | |
| -                buffer[bufferStride * y + 4 * x + 2] = data[stride * y + 4 * x + 2];
 | |
| -                buffer[bufferStride * y + 4 * x + 3] = data[stride * y + 4 * x + 3];
 | |
| -            }
 | |
| -        }
 | |
| -
 | |
| +        memcpy(buffer, data, bufferStride * height);
 | |
|          wl_shm_buffer_end_access(shmBuffer);
 | |
|      }
 | |
|  
 | |
| @@ -176,7 +173,7 @@ void HeadlessViewBackend::updateSnapshot(struct wpe_fdo_shm_exported_buffer* exp
 | |
|          cairo_surface_destroy(m_snapshot);
 | |
|  
 | |
|      m_snapshot = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32,
 | |
| -        m_width, m_height, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width));
 | |
| +        width, height, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width));
 | |
|  
 | |
|      static cairo_user_data_key_t bufferKey;
 | |
|      cairo_surface_set_user_data(m_snapshot, &bufferKey, buffer,
 |