1/*
2 * Copyright (C) 2013, 2015, 2016 Apple Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#if ENABLE(REMOTE_INSPECTOR)
29
30#include "RemoteControllableTarget.h"
31
32#include <utility>
33#include <wtf/Forward.h>
34#include <wtf/HashMap.h>
35#include <wtf/Lock.h>
36#include <wtf/ProcessID.h>
37#include <wtf/text/WTFString.h>
38
39#if PLATFORM(COCOA)
40#include "RemoteInspectorXPCConnection.h"
41#include <wtf/RetainPtr.h>
42
43OBJC_CLASS NSDictionary;
44OBJC_CLASS NSString;
45typedef RetainPtr<NSDictionary> TargetListing;
46#endif
47
48#if USE(GLIB)
49#include <wtf/glib/GRefPtr.h>
50typedef GRefPtr<GVariant> TargetListing;
51typedef struct _GCancellable GCancellable;
52typedef struct _GDBusConnection GDBusConnection;
53typedef struct _GDBusInterfaceVTable GDBusInterfaceVTable;
54#endif
55
56#if USE(INSPECTOR_SOCKET_SERVER)
57#include "RemoteConnectionToTarget.h"
58#include "RemoteInspectorConnectionClient.h"
59#include "RemoteInspectorSocketEndpoint.h"
60#include <wtf/JSONValues.h>
61#include <wtf/RefCounted.h>
62#include <wtf/RefPtr.h>
63
64namespace Inspector {
65using TargetListing = RefPtr<JSON::Object>;
66}
67#endif
68
69namespace Inspector {
70
71class RemoteAutomationTarget;
72class RemoteConnectionToTarget;
73class RemoteControllableTarget;
74class RemoteInspectionTarget;
75class RemoteInspectorClient;
76
77class JS_EXPORT_PRIVATE RemoteInspector final
78#if PLATFORM(COCOA)
79 : public RemoteInspectorXPCConnection::Client
80#elif USE(INSPECTOR_SOCKET_SERVER)
81 : public RemoteInspectorConnectionClient
82#endif
83{
84public:
85 class Client {
86 public:
87 struct Capabilities {
88 bool remoteAutomationAllowed : 1;
89 String browserName;
90 String browserVersion;
91 };
92
93 struct SessionCapabilities {
94 bool acceptInsecureCertificates { false };
95#if USE(GLIB)
96 Vector<std::pair<String, String>> certificates;
97#endif
98#if PLATFORM(COCOA)
99 Optional<bool> allowInsecureMediaCapture;
100 Optional<bool> suppressICECandidateFiltering;
101#endif
102 };
103
104 virtual ~Client();
105 virtual bool remoteAutomationAllowed() const = 0;
106 virtual String browserName() const { return { }; }
107 virtual String browserVersion() const { return { }; }
108 virtual void requestAutomationSession(const String& sessionIdentifier, const SessionCapabilities&) = 0;
109 };
110
111 static void startDisabled();
112 static RemoteInspector& singleton();
113 friend class NeverDestroyed<RemoteInspector>;
114
115 void registerTarget(RemoteControllableTarget*);
116 void unregisterTarget(RemoteControllableTarget*);
117 void updateTarget(RemoteControllableTarget*);
118 void sendMessageToRemote(TargetID, const String& message);
119
120 RemoteInspector::Client* client() const { return m_client; }
121 void setClient(RemoteInspector::Client*);
122 void clientCapabilitiesDidChange();
123 Optional<RemoteInspector::Client::Capabilities> clientCapabilities() const { return m_clientCapabilities; }
124
125 void setupFailed(TargetID);
126 void setupCompleted(TargetID);
127 bool waitingForAutomaticInspection(TargetID);
128 void updateAutomaticInspectionCandidate(RemoteInspectionTarget*);
129
130 bool enabled() const { return m_enabled; }
131 bool hasActiveDebugSession() const { return m_hasActiveDebugSession; }
132
133 void start();
134 void stop();
135
136#if PLATFORM(COCOA)
137 bool hasParentProcessInformation() const { return m_parentProcessIdentifier != 0; }
138 ProcessID parentProcessIdentifier() const { return m_parentProcessIdentifier; }
139 RetainPtr<CFDataRef> parentProcessAuditData() const { return m_parentProcessAuditData; }
140 void setParentProcessInformation(ProcessID, RetainPtr<CFDataRef> auditData);
141 void setParentProcessInfomationIsDelayed();
142#endif
143
144 void updateTargetListing(TargetID);
145
146#if USE(GLIB)
147 void requestAutomationSession(const char* sessionID, const Client::SessionCapabilities&);
148#endif
149#if USE(GLIB) || USE(INSPECTOR_SOCKET_SERVER)
150 void setup(TargetID);
151 void sendMessageToTarget(TargetID, const char* message);
152#endif
153#if USE(INSPECTOR_SOCKET_SERVER)
154 static void setConnectionIdentifier(PlatformSocketType);
155 static void setServerPort(uint16_t);
156#endif
157
158private:
159 RemoteInspector();
160
161 TargetID nextAvailableTargetIdentifier();
162
163 enum class StopSource { API, XPCMessage };
164 void stopInternal(StopSource);
165
166#if PLATFORM(COCOA)
167 void setupXPCConnectionIfNeeded();
168#endif
169#if USE(GLIB)
170 void setupConnection(GRefPtr<GDBusConnection>&&);
171 static const GDBusInterfaceVTable s_interfaceVTable;
172
173 void receivedGetTargetListMessage();
174 void receivedSetupMessage(TargetID);
175 void receivedDataMessage(TargetID, const char* message);
176 void receivedCloseMessage(TargetID);
177 void receivedAutomationSessionRequestMessage(const char* sessionID);
178#endif
179
180 TargetListing listingForTarget(const RemoteControllableTarget&) const;
181 TargetListing listingForInspectionTarget(const RemoteInspectionTarget&) const;
182 TargetListing listingForAutomationTarget(const RemoteAutomationTarget&) const;
183
184 bool updateTargetMap(RemoteControllableTarget*);
185
186 void pushListingsNow();
187 void pushListingsSoon();
188
189 void updateTargetListing(const RemoteControllableTarget&);
190
191 void updateHasActiveDebugSession();
192 void updateClientCapabilities();
193
194 void sendAutomaticInspectionCandidateMessage();
195
196#if PLATFORM(COCOA)
197 void xpcConnectionReceivedMessage(RemoteInspectorXPCConnection*, NSString *messageName, NSDictionary *userInfo) override;
198 void xpcConnectionFailed(RemoteInspectorXPCConnection*) override;
199 void xpcConnectionUnhandledMessage(RemoteInspectorXPCConnection*, xpc_object_t) override;
200
201 void receivedSetupMessage(NSDictionary *userInfo);
202 void receivedDataMessage(NSDictionary *userInfo);
203 void receivedDidCloseMessage(NSDictionary *userInfo);
204 void receivedGetListingMessage(NSDictionary *userInfo);
205 void receivedIndicateMessage(NSDictionary *userInfo);
206 void receivedProxyApplicationSetupMessage(NSDictionary *userInfo);
207 void receivedConnectionDiedMessage(NSDictionary *userInfo);
208 void receivedAutomaticInspectionConfigurationMessage(NSDictionary *userInfo);
209 void receivedAutomaticInspectionRejectMessage(NSDictionary *userInfo);
210 void receivedAutomationSessionRequestMessage(NSDictionary *userInfo);
211#endif
212#if USE(INSPECTOR_SOCKET_SERVER)
213 HashMap<String, CallHandler>& dispatchMap() override;
214 void didClose(ConnectionID) override;
215
216 void sendWebInspectorEvent(const String&);
217
218 void receivedGetTargetListMessage(const Event&);
219 void receivedSetupMessage(const Event&);
220 void receivedDataMessage(const Event&);
221 void receivedCloseMessage(const Event&);
222#endif
223 static bool startEnabled;
224
225 // Targets can be registered from any thread at any time.
226 // Any target can send messages over the XPC connection.
227 // So lock access to all maps and state as they can change
228 // from any thread.
229 Lock m_mutex;
230
231 HashMap<TargetID, RemoteControllableTarget*> m_targetMap;
232 HashMap<TargetID, RefPtr<RemoteConnectionToTarget>> m_targetConnectionMap;
233 HashMap<TargetID, TargetListing> m_targetListingMap;
234
235#if PLATFORM(COCOA)
236 RefPtr<RemoteInspectorXPCConnection> m_relayConnection;
237#endif
238#if USE(GLIB)
239 GRefPtr<GDBusConnection> m_dbusConnection;
240 GRefPtr<GCancellable> m_cancellable;
241#endif
242
243#if USE(INSPECTOR_SOCKET_SERVER)
244 std::unique_ptr<RemoteInspectorSocketEndpoint> m_socketConnection;
245 static PlatformSocketType s_connectionIdentifier;
246 static uint16_t s_serverPort;
247 Optional<ConnectionID> m_clientID;
248#endif
249
250 RemoteInspector::Client* m_client { nullptr };
251 Optional<RemoteInspector::Client::Capabilities> m_clientCapabilities;
252
253#if PLATFORM(COCOA)
254 dispatch_queue_t m_xpcQueue;
255#endif
256 TargetID m_nextAvailableTargetIdentifier { 1 };
257 int m_notifyToken { 0 };
258 bool m_enabled { false };
259 bool m_hasActiveDebugSession { false };
260 bool m_pushScheduled { false };
261
262 ProcessID m_parentProcessIdentifier { 0 };
263#if PLATFORM(COCOA)
264 RetainPtr<CFDataRef> m_parentProcessAuditData;
265#endif
266 bool m_shouldSendParentProcessInformation { false };
267 bool m_automaticInspectionEnabled { false };
268 bool m_automaticInspectionPaused { false };
269 TargetID m_automaticInspectionCandidateTargetIdentifier { 0 };
270};
271
272} // namespace Inspector
273
274#endif // ENABLE(REMOTE_INSPECTOR)
275