diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/inspector/remote | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/inspector/remote')
10 files changed, 1003 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/inspector/remote/RemoteAutomationTarget.cpp b/Source/JavaScriptCore/inspector/remote/RemoteAutomationTarget.cpp new file mode 100644 index 000000000..565218c69 --- /dev/null +++ b/Source/JavaScriptCore/inspector/remote/RemoteAutomationTarget.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "RemoteAutomationTarget.h" + +#if ENABLE(REMOTE_INSPECTOR) + +#include "RemoteInspector.h" + +namespace Inspector { + +void RemoteAutomationTarget::setIsPaired(bool paired) +{ + if (m_paired == paired) + return; + + m_paired = paired; + + update(); +} + +} // namespace Inspector + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/JavaScriptCore/inspector/remote/RemoteAutomationTarget.h b/Source/JavaScriptCore/inspector/remote/RemoteAutomationTarget.h new file mode 100644 index 000000000..0b174fd75 --- /dev/null +++ b/Source/JavaScriptCore/inspector/remote/RemoteAutomationTarget.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +#include "RemoteControllableTarget.h" +#include <wtf/text/WTFString.h> + +namespace Inspector { + +class FrontendChannel; + +class JS_EXPORT_PRIVATE RemoteAutomationTarget : public RemoteControllableTarget { +public: + virtual ~RemoteAutomationTarget() { } + + bool isPaired() const { return m_paired; } + void setIsPaired(bool); + + virtual String name() const = 0; + RemoteControllableTarget::Type type() const override { return RemoteControllableTarget::Type::Automation; } + bool remoteControlAllowed() const override { return !m_paired; }; + +private: + bool m_paired { false }; +}; + +} // namespace Inspector + +SPECIALIZE_TYPE_TRAITS_CONTROLLABLE_TARGET(Inspector::RemoteAutomationTarget, Automation) + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/JavaScriptCore/inspector/remote/RemoteConnectionToTarget.h b/Source/JavaScriptCore/inspector/remote/RemoteConnectionToTarget.h new file mode 100644 index 000000000..99596e5c8 --- /dev/null +++ b/Source/JavaScriptCore/inspector/remote/RemoteConnectionToTarget.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2013, 2015 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +#include "InspectorFrontendChannel.h" +#include <wtf/Lock.h> +#include <wtf/ThreadSafeRefCounted.h> + +#if PLATFORM(COCOA) +#include <wtf/BlockPtr.h> +#include <wtf/RetainPtr.h> + +OBJC_CLASS NSString; +#endif + +namespace Inspector { + +class RemoteControllableTarget; + +#if PLATFORM(COCOA) +typedef Vector<BlockPtr<void ()>> RemoteTargetQueue; +#endif + +class RemoteConnectionToTarget final : public ThreadSafeRefCounted<RemoteConnectionToTarget>, public FrontendChannel { +public: +#if PLATFORM(COCOA) + RemoteConnectionToTarget(RemoteControllableTarget*, NSString* connectionIdentifier, NSString* destination); +#endif + virtual ~RemoteConnectionToTarget(); + + // Main API. + bool setup(bool isAutomaticInspection = false, bool automaticallyPause = false); +#if PLATFORM(COCOA) + void sendMessageToTarget(NSString *); +#else + void sendMessageToTarget(const String&); +#endif + void close(); + void targetClosed(); + + std::optional<unsigned> targetIdentifier() const; +#if PLATFORM(COCOA) + NSString *connectionIdentifier() const; + NSString *destination() const; + + Lock& queueMutex() { return m_queueMutex; } + const RemoteTargetQueue& queue() const { return m_queue; } + void clearQueue() { m_queue.clear(); } +#endif + + // FrontendChannel overrides. + ConnectionType connectionType() const override { return ConnectionType::Remote; } + void sendMessageToFrontend(const String&) override; + +private: +#if PLATFORM(COCOA) + void dispatchAsyncOnTarget(void (^block)()); + + void setupRunLoop(); + void teardownRunLoop(); + void queueTaskOnPrivateRunLoop(void (^block)()); +#endif + + // This connection from the RemoteInspector singleton to the InspectionTarget + // can be used on multiple threads. So any access to the target + // itself must take this mutex to ensure m_target is valid. + Lock m_targetMutex; + +#if PLATFORM(COCOA) + // If a target has a specific run loop it wants to evaluate on + // we setup our run loop sources on that specific run loop. + RetainPtr<CFRunLoopRef> m_runLoop; + RetainPtr<CFRunLoopSourceRef> m_runLoopSource; + RemoteTargetQueue m_queue; + Lock m_queueMutex; +#endif + + RemoteControllableTarget* m_target { nullptr }; + bool m_connected { false }; + +#if PLATFORM(COCOA) + RetainPtr<NSString> m_connectionIdentifier; + RetainPtr<NSString> m_destination; +#endif +}; + +} // namespace Inspector + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/JavaScriptCore/inspector/remote/RemoteControllableTarget.cpp b/Source/JavaScriptCore/inspector/remote/RemoteControllableTarget.cpp new file mode 100644 index 000000000..f52852b15 --- /dev/null +++ b/Source/JavaScriptCore/inspector/remote/RemoteControllableTarget.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "RemoteControllableTarget.h" + +#if ENABLE(REMOTE_INSPECTOR) + +#include "RemoteInspector.h" + +namespace Inspector { + +RemoteControllableTarget::~RemoteControllableTarget() +{ + RemoteInspector::singleton().unregisterTarget(this); +} + +void RemoteControllableTarget::init() +{ + RemoteInspector::singleton().registerTarget(this); +} + +void RemoteControllableTarget::update() +{ + RemoteInspector::singleton().updateTarget(this); +} + +} // namespace Inspector + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/JavaScriptCore/inspector/remote/RemoteControllableTarget.h b/Source/JavaScriptCore/inspector/remote/RemoteControllableTarget.h new file mode 100644 index 000000000..afae369ae --- /dev/null +++ b/Source/JavaScriptCore/inspector/remote/RemoteControllableTarget.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +#include <wtf/TypeCasts.h> +#include <wtf/text/WTFString.h> + +#if USE(CF) +#include <CoreFoundation/CFRunLoop.h> +#endif + +namespace Inspector { + +class FrontendChannel; + +class JS_EXPORT_PRIVATE RemoteControllableTarget { +public: + virtual ~RemoteControllableTarget(); + + void init(); + void update(); + + virtual void connect(FrontendChannel*, bool isAutomaticConnection = false) = 0; + virtual void disconnect(FrontendChannel*) = 0; + + unsigned targetIdentifier() const { return m_identifier; } + void setTargetIdentifier(unsigned identifier) { m_identifier = identifier; } + + enum class Type { JavaScript, Web, Automation }; + virtual Type type() const = 0; + virtual bool remoteControlAllowed() const = 0; + virtual void dispatchMessageFromRemote(const String& message) = 0; + +#if USE(CF) + // The dispatch block will be scheduled on a global run loop if null is returned. + virtual CFRunLoopRef targetRunLoop() { return nullptr; } +#endif +private: + unsigned m_identifier {0}; +}; + +} // namespace Inspector + +#define SPECIALIZE_TYPE_TRAITS_CONTROLLABLE_TARGET(ToClassName, ToClassType) \ +SPECIALIZE_TYPE_TRAITS_BEGIN(ToClassName) \ + static bool isType(const Inspector::RemoteControllableTarget& target) { return target.type() == Inspector::RemoteControllableTarget::Type::ToClassType; } \ +SPECIALIZE_TYPE_TRAITS_END() + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/JavaScriptCore/inspector/remote/RemoteInspectionTarget.cpp b/Source/JavaScriptCore/inspector/remote/RemoteInspectionTarget.cpp new file mode 100644 index 000000000..5d5f3ebc7 --- /dev/null +++ b/Source/JavaScriptCore/inspector/remote/RemoteInspectionTarget.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2013, 2015 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "RemoteInspectionTarget.h" + +#if ENABLE(REMOTE_INSPECTOR) + +#include "EventLoop.h" +#include "RemoteInspector.h" + +namespace Inspector { + +bool RemoteInspectionTarget::remoteControlAllowed() const +{ + return remoteDebuggingAllowed() || hasLocalDebugger(); +} + +void RemoteInspectionTarget::setRemoteDebuggingAllowed(bool allowed) +{ + if (m_allowed == allowed) + return; + + m_allowed = allowed; + + if (m_allowed && automaticInspectionAllowed()) + RemoteInspector::singleton().updateAutomaticInspectionCandidate(this); + else + RemoteInspector::singleton().updateTarget(this); +} + +void RemoteInspectionTarget::pauseWaitingForAutomaticInspection() +{ + ASSERT(targetIdentifier()); + ASSERT(m_allowed); + ASSERT(automaticInspectionAllowed()); + + EventLoop loop; + while (RemoteInspector::singleton().waitingForAutomaticInspection(targetIdentifier()) && !loop.ended()) + loop.cycle(); +} + +void RemoteInspectionTarget::unpauseForInitializedInspector() +{ + RemoteInspector::singleton().setupCompleted(targetIdentifier()); +} + +} // namespace Inspector + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/JavaScriptCore/inspector/remote/RemoteInspectionTarget.h b/Source/JavaScriptCore/inspector/remote/RemoteInspectionTarget.h new file mode 100644 index 000000000..45329f6d6 --- /dev/null +++ b/Source/JavaScriptCore/inspector/remote/RemoteInspectionTarget.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2013, 2015 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +#include "RemoteControllableTarget.h" +#include <wtf/RetainPtr.h> +#include <wtf/TypeCasts.h> +#include <wtf/text/WTFString.h> + +namespace Inspector { + +class FrontendChannel; + +class JS_EXPORT_PRIVATE RemoteInspectionTarget : public RemoteControllableTarget { +public: + bool remoteDebuggingAllowed() const { return m_allowed; } + void setRemoteDebuggingAllowed(bool); + +#if USE(CF) + CFRunLoopRef targetRunLoop() override { return m_runLoop.get(); } + void setTargetRunLoop(CFRunLoopRef runLoop) { m_runLoop = runLoop; } +#endif + + virtual String name() const { return String(); } // JavaScript and Web + virtual String url() const { return String(); } // Web + virtual bool hasLocalDebugger() const = 0; + + virtual void setIndicating(bool) { } // Default is to do nothing. + virtual void pause() { }; + + virtual bool automaticInspectionAllowed() const { return false; } + virtual void pauseWaitingForAutomaticInspection(); + virtual void unpauseForInitializedInspector(); + + // RemoteControllableTarget overrides. + bool remoteControlAllowed() const override; +private: + bool m_allowed {false}; +#if USE(CF) + RetainPtr<CFRunLoopRef> m_runLoop; +#endif +}; + +} // namespace Inspector + +SPECIALIZE_TYPE_TRAITS_BEGIN(Inspector::RemoteInspectionTarget) \ + static bool isType(const Inspector::RemoteControllableTarget& target) \ + { \ + return target.type() == Inspector::RemoteControllableTarget::Type::JavaScript \ + || target.type() == Inspector::RemoteControllableTarget::Type::Web; \ + } +SPECIALIZE_TYPE_TRAITS_END() + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/JavaScriptCore/inspector/remote/RemoteInspector.cpp b/Source/JavaScriptCore/inspector/remote/RemoteInspector.cpp new file mode 100644 index 000000000..af88dc13e --- /dev/null +++ b/Source/JavaScriptCore/inspector/remote/RemoteInspector.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2013-2016 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "RemoteInspector.h" + +#if ENABLE(REMOTE_INSPECTOR) + +#include "RemoteAutomationTarget.h" +#include "RemoteConnectionToTarget.h" +#include "RemoteInspectionTarget.h" +#include "RemoteInspectorConstants.h" +#include <wtf/MainThread.h> +#include <wtf/text/WTFString.h> + +namespace Inspector { + +bool RemoteInspector::startEnabled = true; + +void RemoteInspector::startDisabled() +{ + RemoteInspector::startEnabled = false; +} + +unsigned RemoteInspector::nextAvailableTargetIdentifier() +{ + unsigned nextValidTargetIdentifier; + do { + nextValidTargetIdentifier = m_nextAvailableTargetIdentifier++; + } while (!nextValidTargetIdentifier || nextValidTargetIdentifier == std::numeric_limits<unsigned>::max() || m_targetMap.contains(nextValidTargetIdentifier)); + return nextValidTargetIdentifier; +} + +void RemoteInspector::registerTarget(RemoteControllableTarget* target) +{ + ASSERT_ARG(target, target); + + std::lock_guard<Lock> lock(m_mutex); + + unsigned targetIdentifier = nextAvailableTargetIdentifier(); + target->setTargetIdentifier(targetIdentifier); + + { + auto result = m_targetMap.set(targetIdentifier, target); + ASSERT_UNUSED(result, result.isNewEntry); + } + + // If remote control is not allowed, a null listing is returned. + if (auto targetListing = listingForTarget(*target)) { + auto result = m_targetListingMap.set(targetIdentifier, targetListing); + ASSERT_UNUSED(result, result.isNewEntry); + } + + pushListingsSoon(); +} + +void RemoteInspector::unregisterTarget(RemoteControllableTarget* target) +{ + ASSERT_ARG(target, target); + + std::lock_guard<Lock> lock(m_mutex); + + unsigned targetIdentifier = target->targetIdentifier(); + if (!targetIdentifier) + return; + + bool wasRemoved = m_targetMap.remove(targetIdentifier); + ASSERT_UNUSED(wasRemoved, wasRemoved); + + // The listing may never have been added if remote control isn't allowed. + m_targetListingMap.remove(targetIdentifier); + + if (auto connectionToTarget = m_targetConnectionMap.take(targetIdentifier)) + connectionToTarget->targetClosed(); + + pushListingsSoon(); +} + +void RemoteInspector::updateTarget(RemoteControllableTarget* target) +{ + ASSERT_ARG(target, target); + + std::lock_guard<Lock> lock(m_mutex); + + unsigned targetIdentifier = target->targetIdentifier(); + if (!targetIdentifier) + return; + + { + auto result = m_targetMap.set(targetIdentifier, target); + ASSERT_UNUSED(result, !result.isNewEntry); + } + + // If the target has just allowed remote control, then the listing won't exist yet. + // If the target has no identifier remove the old listing. + if (auto targetListing = listingForTarget(*target)) + m_targetListingMap.set(targetIdentifier, targetListing); + else + m_targetListingMap.remove(targetIdentifier); + + pushListingsSoon(); +} + +void RemoteInspector::updateClientCapabilities() +{ + ASSERT(isMainThread()); + + std::lock_guard<Lock> lock(m_mutex); + + if (!m_client) + m_clientCapabilities = std::nullopt; + else { + RemoteInspector::Client::Capabilities updatedCapabilities = { + m_client->remoteAutomationAllowed() // remoteAutomationAllowed + }; + + m_clientCapabilities = updatedCapabilities; + } +} + +void RemoteInspector::setRemoteInspectorClient(RemoteInspector::Client* client) +{ + ASSERT_ARG(client, client); + ASSERT(!m_client); + + { + std::lock_guard<Lock> lock(m_mutex); + m_client = client; + } + + // Send an updated listing that includes whether the client allows remote automation. + updateClientCapabilities(); + pushListingsSoon(); +} + +void RemoteInspector::setupFailed(unsigned targetIdentifier) +{ + std::lock_guard<Lock> lock(m_mutex); + + m_targetConnectionMap.remove(targetIdentifier); + + if (targetIdentifier == m_automaticInspectionCandidateTargetIdentifier) + m_automaticInspectionPaused = false; + + updateHasActiveDebugSession(); + updateTargetListing(targetIdentifier); + pushListingsSoon(); +} + +void RemoteInspector::setupCompleted(unsigned targetIdentifier) +{ + std::lock_guard<Lock> lock(m_mutex); + + if (targetIdentifier == m_automaticInspectionCandidateTargetIdentifier) + m_automaticInspectionPaused = false; +} + +bool RemoteInspector::waitingForAutomaticInspection(unsigned) +{ + // We don't take the lock to check this because we assume it will be checked repeatedly. + return m_automaticInspectionPaused; +} + +void RemoteInspector::clientCapabilitiesDidChange() +{ + updateClientCapabilities(); + pushListingsSoon(); +} + +void RemoteInspector::stop() +{ + std::lock_guard<Lock> lock(m_mutex); + + stopInternal(StopSource::API); +} + +TargetListing RemoteInspector::listingForTarget(const RemoteControllableTarget& target) const +{ + if (is<RemoteInspectionTarget>(target)) + return listingForInspectionTarget(downcast<RemoteInspectionTarget>(target)); + if (is<RemoteAutomationTarget>(target)) + return listingForAutomationTarget(downcast<RemoteAutomationTarget>(target)); + + ASSERT_NOT_REACHED(); + return nullptr; +} + +void RemoteInspector::updateHasActiveDebugSession() +{ + bool hasActiveDebuggerSession = !m_targetConnectionMap.isEmpty(); + if (hasActiveDebuggerSession == m_hasActiveDebugSession) + return; + + m_hasActiveDebugSession = hasActiveDebuggerSession; + + // FIXME: Expose some way to access this state in an embedder. + // Legacy iOS WebKit 1 had a notification. This will need to be smarter with WebKit2. +} + +} // namespace Inspector + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/JavaScriptCore/inspector/remote/RemoteInspector.h b/Source/JavaScriptCore/inspector/remote/RemoteInspector.h new file mode 100644 index 000000000..b7ca1ea1e --- /dev/null +++ b/Source/JavaScriptCore/inspector/remote/RemoteInspector.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2013, 2015, 2016 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(REMOTE_INSPECTOR) + +#include <wtf/Forward.h> +#include <wtf/HashMap.h> +#include <wtf/Lock.h> + +#if PLATFORM(COCOA) +#include "RemoteInspectorXPCConnection.h" +#include <wtf/RetainPtr.h> + +OBJC_CLASS NSDictionary; +OBJC_CLASS NSString; +typedef RetainPtr<NSDictionary> TargetListing; +#endif + +namespace Inspector { + +class RemoteAutomationTarget; +class RemoteConnectionToTarget; +class RemoteControllableTarget; +class RemoteInspectionTarget; +class RemoteInspectorClient; + +class JS_EXPORT_PRIVATE RemoteInspector final +#if PLATFORM(COCOA) + : public RemoteInspectorXPCConnection::Client +#endif +{ +public: + class Client { + public: + struct Capabilities { + bool remoteAutomationAllowed : 1; + }; + + virtual ~Client() { } + virtual bool remoteAutomationAllowed() const = 0; + virtual void requestAutomationSession(const String& sessionIdentifier) = 0; + }; + + static void startDisabled(); + static RemoteInspector& singleton(); + friend class NeverDestroyed<RemoteInspector>; + + void registerTarget(RemoteControllableTarget*); + void unregisterTarget(RemoteControllableTarget*); + void updateTarget(RemoteControllableTarget*); + void sendMessageToRemote(unsigned targetIdentifier, const String& message); + + void setRemoteInspectorClient(RemoteInspector::Client*); + void clientCapabilitiesDidChange(); + + void setupFailed(unsigned targetIdentifier); + void setupCompleted(unsigned targetIdentifier); + bool waitingForAutomaticInspection(unsigned targetIdentifier); + void updateAutomaticInspectionCandidate(RemoteInspectionTarget*); + + bool enabled() const { return m_enabled; } + bool hasActiveDebugSession() const { return m_hasActiveDebugSession; } + + void start(); + void stop(); + +#if PLATFORM(COCOA) + bool hasParentProcessInformation() const { return m_parentProcessIdentifier != 0; } + pid_t parentProcessIdentifier() const { return m_parentProcessIdentifier; } + RetainPtr<CFDataRef> parentProcessAuditData() const { return m_parentProcessAuditData; } + void setParentProcessInformation(pid_t, RetainPtr<CFDataRef> auditData); + void setParentProcessInfomationIsDelayed(); +#endif + +private: + RemoteInspector(); + + unsigned nextAvailableTargetIdentifier(); + + enum class StopSource { API, XPCMessage }; + void stopInternal(StopSource); + +#if PLATFORM(COCOA) + void setupXPCConnectionIfNeeded(); +#endif + + TargetListing listingForTarget(const RemoteControllableTarget&) const; + TargetListing listingForInspectionTarget(const RemoteInspectionTarget&) const; + TargetListing listingForAutomationTarget(const RemoteAutomationTarget&) const; + + void pushListingsNow(); + void pushListingsSoon(); + + void updateTargetListing(unsigned targetIdentifier); + void updateTargetListing(const RemoteControllableTarget&); + + void updateHasActiveDebugSession(); + void updateClientCapabilities(); + + void sendAutomaticInspectionCandidateMessage(); + +#if PLATFORM(COCOA) + void xpcConnectionReceivedMessage(RemoteInspectorXPCConnection*, NSString *messageName, NSDictionary *userInfo) override; + void xpcConnectionFailed(RemoteInspectorXPCConnection*) override; + void xpcConnectionUnhandledMessage(RemoteInspectorXPCConnection*, xpc_object_t) override; + + void receivedSetupMessage(NSDictionary *userInfo); + void receivedDataMessage(NSDictionary *userInfo); + void receivedDidCloseMessage(NSDictionary *userInfo); + void receivedGetListingMessage(NSDictionary *userInfo); + void receivedIndicateMessage(NSDictionary *userInfo); + void receivedProxyApplicationSetupMessage(NSDictionary *userInfo); + void receivedConnectionDiedMessage(NSDictionary *userInfo); + void receivedAutomaticInspectionConfigurationMessage(NSDictionary *userInfo); + void receivedAutomaticInspectionRejectMessage(NSDictionary *userInfo); + void receivedAutomationSessionRequestMessage(NSDictionary *userInfo); +#endif + + static bool startEnabled; + + // Targets can be registered from any thread at any time. + // Any target can send messages over the XPC connection. + // So lock access to all maps and state as they can change + // from any thread. + Lock m_mutex; + + HashMap<unsigned, RemoteControllableTarget*> m_targetMap; + HashMap<unsigned, RefPtr<RemoteConnectionToTarget>> m_targetConnectionMap; + HashMap<unsigned, TargetListing> m_targetListingMap; + +#if PLATFORM(COCOA) + RefPtr<RemoteInspectorXPCConnection> m_relayConnection; +#endif + + RemoteInspector::Client* m_client { nullptr }; + std::optional<RemoteInspector::Client::Capabilities> m_clientCapabilities; + +#if PLATFORM(COCOA) + dispatch_queue_t m_xpcQueue; +#endif + unsigned m_nextAvailableTargetIdentifier { 1 }; + int m_notifyToken { 0 }; + bool m_enabled { false }; + bool m_hasActiveDebugSession { false }; + bool m_pushScheduled { false }; + + pid_t m_parentProcessIdentifier { 0 }; +#if PLATFORM(COCOA) + RetainPtr<CFDataRef> m_parentProcessAuditData; +#endif + bool m_shouldSendParentProcessInformation { false }; + bool m_automaticInspectionEnabled { false }; + bool m_automaticInspectionPaused { false }; + unsigned m_automaticInspectionCandidateTargetIdentifier { 0 }; +}; + +} // namespace Inspector + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/JavaScriptCore/inspector/remote/RemoteInspectorConstants.h b/Source/JavaScriptCore/inspector/remote/RemoteInspectorConstants.h new file mode 100644 index 000000000..700657be0 --- /dev/null +++ b/Source/JavaScriptCore/inspector/remote/RemoteInspectorConstants.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2011, 2016 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +// WIRConstants are "Web Inspector Relay" constants shared between +// the WebInspector framework on the OS X side, webinspectord, and +// iOS WebKit on the device side. + +#define WIRSimulatorTCPPortNumber 27753 +#define WIRXPCMachPortName "com.apple.webinspector" +#define WIRXPCDebuggerServiceName "com.apple.webinspector.debugger" +#define WIRServiceAvailableNotification "com.apple.webinspectord.available" +#define WIRServiceAvailabilityCheckNotification "com.apple.webinspectord.availability_check" +#define WIRServiceEnabledNotification "com.apple.webinspectord.enabled" +#define WIRServiceDisabledNotification "com.apple.webinspectord.disabled" +#define WIRAutomaticInspectionEnabledState "com.apple.webinspectord.automatic_inspection_enabled" + + +#define WIRApplicationIdentifierKey @"WIRApplicationIdentifierKey" +#define WIRApplicationBundleIdentifierKey @"WIRApplicationBundleIdentifierKey" +#define WIRApplicationNameKey @"WIRApplicationNameKey" +#define WIRIsApplicationProxyKey @"WIRIsApplicationProxyKey" +#define WIRIsApplicationActiveKey @"WIRIsApplicationActiveKey" +#define WIRHostApplicationIdentifierKey @"WIRHostApplicationIdentifierKey" +#define WIRHostApplicationNameKey @"WIRHostApplicationNameKey" +#define WIRConnectionIdentifierKey @"WIRConnectionIdentifierKey" +// COMPATABILITY(iOS 9): The key string is intentionally mismatched to support old relays. +#define WIRTargetIdentifierKey @"WIRPageIdentifierKey" +#define WIRHasLocalDebuggerKey @"WIRHasLocalDebuggerKey" +#define WIRTitleKey @"WIRTitleKey" +#define WIRURLKey @"WIRURLKey" +#define WIRUserInfoKey @"WIRUserInfoKey" +#define WIRApplicationDictionaryKey @"WIRApplicationDictionaryKey" +#define WIRMessageDataKey @"WIRMessageDataKey" +#define WIRApplicationGetListingMessage @"WIRApplicationGetListingMessage" +#define WIRIndicateMessage @"WIRIndicateMessage" +#define WIRIndicateEnabledKey @"WIRIndicateEnabledKey" +#define WIRSenderKey @"WIRSenderKey" +#define WIRSocketDataKey @"WIRSocketDataKey" +#define WIRSocketDataMessage @"WIRSocketDataMessage" +#define WIRSocketSetupMessage @"WIRSocketSetupMessage" +#define WIRWebPageCloseMessage @"WIRWebPageCloseMessage" +#define WIRRawDataMessage @"WIRRawDataMessage" +#define WIRRawDataKey @"WIRRawDataKey" +#define WIRListingMessage @"WIRListingMessage" +#define WIRListingKey @"WIRListingKey" +#define WIRRemoteAutomationEnabledKey @"WIRRemoteAutomationEnabledKey" +#define WIRDestinationKey @"WIRDestinationKey" +#define WIRConnectionDiedMessage @"WIRConnectionDiedMessage" +#define WIRTypeKey @"WIRTypeKey" +#define WIRTypeJavaScript @"WIRTypeJavaScript" +#define WIRTypeWeb @"WIRTypeWeb" +#define WIRTypeAutomation @"WIRTypeAutomation" +#define WIRAutomaticallyPause @"WIRAutomaticallyPause" + +#define WIRAutomaticInspectionEnabledKey @"WIRAutomaticInspectionEnabledKey" +#define WIRAutomaticInspectionSessionIdentifierKey @"WIRAutomaticInspectionSessionIdentifierKey" +#define WIRAutomaticInspectionConfigurationMessage @"WIRAutomaticInspectionConfigurationMessage" +#define WIRAutomaticInspectionRejectMessage @"WIRAutomaticInspectionRejectMessage" +#define WIRAutomaticInspectionCandidateMessage @"WIRAutomaticInspectionCandidateMessage" + +#define WIRAutomationTargetIsPairedKey @"WIRAutomationTargetIsPairedKey" +#define WIRSessionIdentifierKey @"WIRSessionIdentifierKey" +#define WIRAutomationSessionRequestMessage @"WIRAutomationSessionRequestMessage" + +// These definitions are shared with a Simulator webinspectord and +// OS X process communicating with it. + +#define WIRSimulatorBuildKey @"WIRSimulatorBuildKey" +#define WIRSimulatorProductVersionKey @"WIRSimulatorProductVersionKey" +#define WIRSimulatorNameKey @"WIRSimulatorNameKey" + +// These definitions are shared between webinspectord and WebKit. + +#define WIRPermissionDenied @"WIRPermissionDenied" +#define WIRProxyApplicationParentPIDKey @"WIRProxyApplicationParentPID" +#define WIRProxyApplicationParentAuditDataKey @"WIRProxyApplicationParentAuditData" +#define WIRProxyApplicationSetupMessage @"WIRProxyApplicationSetupMessage" +#define WIRProxyApplicationSetupResponseMessage @"WIRProxyApplicationSetupResponseMessage" |