https://bugs.webkit.org/show_bug.cgi?id=191494
<rdar://problem/
45469854>
Reviewed by Devin Rousso.
Source/JavaScriptCore:
* CMakeLists.txt:
* DerivedSources.make:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
New domain and resources.
* inspector/protocol/Target.json: Added.
New protocol domain, modeled after Worker.json, to allow for
multiplexing between different targets.
* inspector/InspectorTarget.h:
Each target will instantiate an InspectorTarget and must
provide an identifier, type, and means of connecting/disconnecting
to a frontend channel.
* inspector/agents/InspectorTargetAgent.cpp: Added.
(Inspector::InspectorTargetAgent::InspectorTargetAgent):
(Inspector::InspectorTargetAgent::didCreateFrontendAndBackend):
(Inspector::InspectorTargetAgent::willDestroyFrontendAndBackend):
(Inspector::InspectorTargetAgent::exists):
(Inspector::InspectorTargetAgent::initialized):
(Inspector::InspectorTargetAgent::sendMessageToTarget):
(Inspector::InspectorTargetAgent::sendMessageFromTargetToFrontend):
(Inspector::targetTypeToProtocolType):
(Inspector::buildTargetInfoObject):
(Inspector::InspectorTargetAgent::targetCreated):
(Inspector::InspectorTargetAgent::targetTerminated):
(Inspector::InspectorTargetAgent::connectToTargets):
(Inspector::InspectorTargetAgent::disconnectFromTargets):
* inspector/agents/InspectorTargetAgent.h: Added.
TargetAgent holds a list of targets, and connects/disconnects to each
of the targets when a frontend connects/disconnects.
* inspector/scripts/codegen/generator.py:
Better enum casing of ServiceWorker.
Source/WebCore:
* inspector/InspectorClient.h:
(WebCore::InspectorClient::allowRemoteInspectionToPageDirectly const):
Provide a hook so that a client may wish to allow direct remote inspection of the Page.
This is used by WebKitLegacy only.
* page/Page.cpp:
(Page::Page):
Only enable the PageDebuggable if the client wishes remote inspection of the Page directly.
This is used by WebKitLegacy only.
* inspector/InspectorController.cpp:
(WebCore::InspectorController::connectFrontend):
* inspector/InspectorController.h:
* page/PageDebuggable.cpp:
(WebCore::PageDebuggable::connect):
(WebCore::PageDebuggable::disconnect):
* page/PageDebuggable.h:
When a frontend connects, always enable the developer extras for the Page.
This is pretty much only for the remote path, which allows inspection if developer
extras were not already enabled (iOS). This simplifies the logic, and toggling
developer extras after it was already enabled is not really important.
Source/WebInspectorUI:
This starts introducing multi-target support into the Web Inspector frontend.
Specifically a backend connection that is persistent, but has the ability to
connect to and transition between Page targets received through that backend
connection.
This patch introduces the concept of a "Backend Target" which is the single
connection that the frontend contains to a backend. The old way of connecting
directly to a target is still supported. In that case the frontend constructs
a DirectBackendTarget for the debuggable type the frontend was spawns for.
However, if the frontend opens and has a TargetAgent, then it is likely
connected to a multi-target supporting backend and instead constructs a
MultiplexingBackendTarget, and will receive further information about
sub-targets to connect to. The only sub-target at the moment is a Page
sub-target.
As part of bringing up multi-target support this adds a few measures to
handle situations where the frontend is playing fast and loose with agents.
When the frontend does `FooAgent.method` it intends that to be performed
on the "main" target being debugged. Likewise when the frontend loops
over targets it expects them to be the debuggable targets. This patch
profiles a new implementation of `WI.mainTarget` and `WI.targets` to
match the assumptions being made by the frontend.
- In a direct-target world, there is a single target which
should be used for global agents and in WI.targets.
- In a multi-target world, the page target is the one that
should be used for global agents and WI.targets is the list
of sub-targets (excluding the MultiplexingBackendTarget).
In a multi-target world, there are now commonly two Targets. The
MultiplexingBackendTarget and a PageTarget sub-target. In the future
this may include more targets, such as ServiceWorkers, DedicatedWorkers,
and perhaps even frames.
In a multi-target world, the frontend is immediately told about targets
as soon as it opens (via Target.targetCreated). In order to support
this, frontend initialization happens without a main target being available.
So this makes a few small changes to frontend initialization to perform
a bit of work once we know what the main target is.
During a page transition the frontend is told to destroy existing targets
and is soon after told about any new page targets (via Target.targetDestroyed
and Target.targetCreated). The frontend special cases this page transition.
It expects only one Page target to be alive at any time, accessible through
WI.pageTarget. When a page transition happens the WI.pageTarget changes, and
the frontend performs a bit of work to prepare the UI to handle the transition:
`<Manager>.transitionPageTarget` / WI.Notification.TransitionPageTarget.
For the most part the UI behaves fine as long once there are main frame
change and main resource change events, but those other events allow
the frontend to respond to the specific page transition cases.
* UserInterface/Base/Main.js:
(WI.loaded):
(WI.initializeBackendTarget):
(WI.initializePageTarget):
(WI.transitionPageTarget):
(WI.terminatePageTarget):
(WI.resetMainExecutionContext):
(WI.redirectGlobalAgentsToConnection):
(WI.contentLoaded):
New global functions for target initialization
and page transitioning.
* UserInterface/Test/Test.js:
(WI.loaded):
(WI.initializeBackendTarget):
(WI.initializePageTarget):
(WI.transitionPageTarget):
(WI.terminatePageTarget):
(WI.resetMainExecutionContext):
(WI.redirectGlobalAgentsToConnection):
New global functions for target initialization.
Tests continue to be a direct connection to the Page.
* UserInterface/Protocol/TargetObserver.js:
(WI.TargetObserver.prototype.targetCreated):
(WI.TargetObserver.prototype.targetDestroyed):
(WI.TargetObserver.prototype.dispatchMessageFromTarget):
New observer goes to the manager.
* UserInterface/Controllers/TargetManager.js:
(WI.TargetManager):
(WI.TargetManager.prototype.get targets):
(WI.TargetManager.prototype.get allTargets):
(WI.TargetManager.prototype.targetForIdentifier):
(WI.TargetManager.prototype.targetCreated):
(WI.TargetManager.prototype.targetDestroyed):
(WI.TargetManager.prototype.dispatchMessageFromTarget):
(WI.TargetManager.prototype.createMultiplexingBackendTarget):
(WI.TargetManager.prototype.createDirectBackendTarget):
(WI.TargetManager.prototype._addTarget):
(WI.TargetManager.prototype._removeTarget):
(WI.TargetManager.prototype._createTarget):
(WI.TargetManager.prototype._checkAndHandlePageTargetTransition):
(WI.TargetManager.prototype._checkAndHandlePageTargetTermination):
(WI.TargetManager.prototype.addTarget): Deleted.
(WI.TargetManager.prototype.removeTarget): Deleted.
(WI.TargetManager.prototype.initializeMainTarget): Deleted.
TargetManager is where we handle creating and destroying targets
and their connections. In order to simplify things a bit we make
`WI.targets`, which goes through `get targets()` an array instead
of a Set. And this includes only the sub-targets.
* UserInterface/Controllers/WorkerManager.js:
(WI.WorkerManager.prototype.workerCreated):
(WI.WorkerManager.prototype.workerTerminated):
Workers are still special-target-like things that multiplex through
WorkerAgent instead of TargetAgent. We'd like to promote these to
be full targets in the future.
* UserInterface/Protocol/DirectBackendTarget.js: Renamed from Source/WebInspectorUI/UserInterface/Protocol/MainTarget.js.
(WI.DirectBackendTarget):
(WI.DirectBackendTarget.connectionInfoForDebuggable):
(WI.DirectBackendTarget.prototype.get mainResource):
(WI.DirectBackendTarget.prototype.set mainResource):
This is the only "MainTarget" class. It is the backend target for a direct connection.
* UserInterface/Protocol/MultiplexingBackendTarget.js:
(WI.MultiplexingBackendTarget):
(WI.MultiplexingBackendTarget.prototype.initialize):
(WI.MultiplexingBackendTarget.prototype.get name):
(WI.MultiplexingBackendTarget.prototype.get executionContext):
(WI.MultiplexingBackendTarget.prototype.get mainResource):
This is the new backend target for a multi-target connection.
We don't expect it to be treated like other targets, so we don't
expect anyone to ask it for resources/executionContext/name info.
* UserInterface/Controllers/RuntimeManager.js:
(WI.TargetManager.prototype.evaluateInInspectedWindow):
This can be triggered by watch expressions before any target, and
therefore execution context, is available. Just return null, when
an execution context is available those clients will try again.
* UserInterface/Debug/Bootstrap.js:
Provide an WI.isEngineeringBuild boolean that can be used for various
debugging features.
* UserInterface/Main.html:
* UserInterface/Test.html:
New resources.
* UserInterface/Protocol/InspectorBackend.js:
(InspectorBackendClass.prototype.dispatch):
(InspectorBackendClass.prototype.runAfterPendingDispatches):
(InspectorBackend.Agent):
`InspectorBackend.mainConnection` was renamed `InspectorBackend.backendConnection`.
* UserInterface/Protocol/Connection.js:
(InspectorBackend.Connection):
(InspectorBackend.Connection.prototype._dispatchResponse):
(InspectorBackend.Connection.prototype._sendCommandToBackendWithCallback):
(InspectorBackend.Connection.prototype._sendCommandToBackendExpectingPromise):
(InspectorBackend.BackendConnection):
(InspectorBackend.BackendConnection.prototype.sendMessageToBackend):
(InspectorBackend.WorkerConnection):
(InspectorBackend.TargetConnection):
(InspectorBackend.TargetConnection.sendMessageToBackend):
Use a global sequence id to make filtering a bit easier in protocol tracing.
TargetConnection is identical to WorkerConnection except it uses TargetAgent
instead of WorkerAgent to perform multiplexing.
* UserInterface/Protocol/JavaScriptContextTarget.js:
(WI.JavaScriptContextTarget):
* UserInterface/Protocol/PageTarget.js:
(WI.PageTarget):
(WI.PageTarget.prototype.get displayName):
Specialized target types.
* UserInterface/Views/DebuggerSidebarPanel.js:
(WI.DebuggerSidebarPanel):
(WI.DebuggerSidebarPanel.prototype._targetAdded):
(WI.DebuggerSidebarPanel.prototype._targetRemoved):
(WI.DebuggerSidebarPanel.prototype._updateCallStackTreeOutline):
* UserInterface/Views/SourceCodeTextEditor.js:
(WI.SourceCodeTextEditor.prototype._targetAdded):
(WI.SourceCodeTextEditor.prototype._targetRemoved):
(WI.SourceCodeTextEditor.prototype._callFramesDidChange):
(WI.SourceCodeTextEditor.prototype._updateThreadIndicatorWidget):
(WI.SourceCodeTextEditor.prototype._reinsertAllThreadIndicators):
* UserInterface/Views/QuickConsole.js:
(WI.QuickConsole.prototype.initializeMainExecutionContextPathComponent):
(WI.QuickConsole.prototype._targetAdded):
(WI.QuickConsole.prototype._targetRemoved):
We make target added get called with all targets, including the
MultiplexingBackendTarget and PageTargets, both of which would
not have happened before. Before it was only WorkerTargets. Make
these sites a little more robust for the type of target they expect
to be able to handle.
* UserInterface/Base/Object.js:
* UserInterface/Controllers/DOMManager.js:
(WI.DOMManager):
(WI.DOMManager.prototype.transitionPageTarget):
(WI.DOMManager.prototype.requestDocument):
(WI.DOMManager.prototype._setDocument):
* UserInterface/Controllers/NetworkManager.js:
(WI.NetworkManager):
(WI.NetworkManager.prototype.transitionPageTarget):
(WI.NetworkManager.prototype.executionContextCreated):
(WI.NetworkManager.prototype._processMainFrameResourceTreePayload):
* UserInterface/Models/DefaultDashboard.js:
(WI.DefaultDashboard):
(WI.DefaultDashboard.prototype._mainResourceDidChange):
(WI.DefaultDashboard.prototype._transitionPageTarget):
* UserInterface/Views/NetworkTableContentView.js:
(WI.NetworkTableContentView):
(WI.NetworkTableContentView.prototype._mainResourceDidChange):
(WI.NetworkTableContentView.prototype._transitionPageTarget):
Special case handling when performing a page transition.
* UserInterface/Views/SettingsTabContentView.js:
* UserInterface/Debug/UncaughtExceptionReporter.js:
Document reloads are not supported right now.
Source/WebKit:
To support process swapping a slim Web Inspector backend lives in the UIProcess.
The Web Inspector frontend connects to it and is told about sub-targets, namely
pages, that it can further connect to. When performing a process swap the backend
tells the frontend to destroy existing targets and create new targets.
In the UIProcess the WebPageProxy has a WebPageInspectorController, with a single
TargetAgent holding InspectorTargetProxies to targets it knows about. Inspector
protocol messages go through this inspector controller and are routed to the
WebPage and its WebCore::Page's InspectorController. The WebPageProxy decides
when to close and expose new page targets during process swap, or basically
any time it reconnects to a WebProcess. So this patch also makes Web Inspector
stay alive and reconnect to a page when the inspected page crashes!
In the WebContentProcess the WebPage has a WebPageInspectorTarget. It also
has a WebPageInspectorTargetController in anticipation of further sub-targets
within the page (workers, frames) but none exist at the moment. The WebPage
relies on the WebPageProxy to know when to expose this target as a debuggable.
* Sources.txt:
* WebKit.xcodeproj/project.pbxproj:
New files.
* Shared/WebPageCreationParameters.cpp:
(WebKit::WebPageCreationParameters::encode const):
(WebKit::WebPageCreationParameters::decode):
* Shared/WebPageCreationParameters.h:
Remote inspector state can now stay in the UIProcess and does not need to
be passed down to the WebContentProcess.
* UIProcess/WebPageDebuggable.cpp: Copied from Source/WebCore/page/PageDebuggable.cpp.
(WebKit::WebPageDebuggable::WebPageDebuggable):
(WebKit::WebPageDebuggable::name const):
(WebKit::WebPageDebuggable::url const):
(WebKit::WebPageDebuggable::hasLocalDebugger const):
(WebKit::WebPageDebuggable::connect):
(WebKit::WebPageDebuggable::disconnect):
(WebKit::WebPageDebuggable::dispatchMessageFromRemote):
(WebKit::WebPageDebuggable::setIndicating):
(WebKit::WebPageDebuggable::setNameOverride):
* UIProcess/WebPageDebuggable.h: Copied from Source/WebCore/page/PageDebuggable.h.
Remote debuggable entry point into the UIProcess for a page.
This is pretty much identical to the PageDebuggable in WebCore.
* Scripts/webkit/messages.py:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/WebPageProxy.cpp:
(WebKit::m_resetRecentCrashCountTimer):
(WebKit::WebPageProxy::finishAttachingToWebProcess):
(WebKit::WebPageProxy::close):
(WebKit::WebPageProxy::createInspectorTarget):
(WebKit::WebPageProxy::destroyInspectorTarget):
(WebKit::WebPageProxy::sendMessageToInspectorFrontend):
(WebKit::WebPageProxy::setIndicating):
(WebKit::WebPageProxy::allowsRemoteInspection const):
(WebKit::WebPageProxy::setAllowsRemoteInspection):
(WebKit::WebPageProxy::remoteInspectionNameOverride const):
(WebKit::WebPageProxy::setRemoteInspectionNameOverride):
(WebKit::WebPageProxy::remoteInspectorInformationDidChange):
(WebKit::WebPageProxy::clearInspectorTargets):
(WebKit::WebPageProxy::createInspectorTargets):
(WebKit::WebPageProxy::didCommitLoadForFrame):
(WebKit::WebPageProxy::didReceiveTitleForFrame):
(WebKit::WebPageProxy::creationParameters):
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::inspectorController):
(WebKit::WebPageProxy::allowsRemoteInspection const): Deleted.
(WebKit::WebPageProxy::remoteInspectionNameOverride const): Deleted.
Own more inspector state in the UIProcess including a debuggable and inspector controller.
* UIProcess/WebPageInspectorController.h: Added.
* UIProcess/WebPageInspectorController.cpp: Added.
(WebKit::WebPageInspectorController::WebPageInspectorController):
(WebKit::WebPageInspectorController::pageClosed):
(WebKit::WebPageInspectorController::hasLocalFrontend const):
(WebKit::WebPageInspectorController::hasRemoteFrontend const):
(WebKit::WebPageInspectorController::connectFrontend):
(WebKit::WebPageInspectorController::disconnectFrontend):
(WebKit::WebPageInspectorController::disconnectAllFrontends):
(WebKit::WebPageInspectorController::dispatchMessageFromFrontend):
(WebKit::WebPageInspectorController::setIndicating):
(WebKit::WebPageInspectorController::clearTargets):
(WebKit::WebPageInspectorController::createInspectorTarget):
(WebKit::WebPageInspectorController::destroyInspectorTarget):
(WebKit::WebPageInspectorController::sendMessageToInspectorFrontend):
InspectorController with a single TargetAgent in the UIProcess.
* UIProcess/WebPageInspectorTargetAgent.h:
* UIProcess/WebPageInspectorTargetAgent.cpp:
(WebKit::WebPageInspectorTargetAgent::WebPageInspectorTargetAgent):
(WebKit::WebPageInspectorTargetAgent::frontendChannel):
Target agent implementation.
* UIProcess/InspectorTargetProxy.cpp:
(WebKit::InspectorTargetProxy::create):
(WebKit::InspectorTargetProxy::InspectorTargetProxy):
(WebKit::InspectorTargetProxy::connect):
(WebKit::InspectorTargetProxy::disconnect):
(WebKit::InspectorTargetProxy::sendMessageToTargetBackend):
* UIProcess/InspectorTargetProxy.h:
UIProcess proxy for an InspectorTarget in the WebContentProcess.
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::processForNavigationInternal):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_shouldAttachDrawingAreaOnPageTransition):
(WebKit::WebPage::connectInspector):
(WebKit::WebPage::disconnectInspector):
(WebKit::WebPage::sendMessageToTargetBackend):
(WebKit::WebPage::setIndicating):
(WebKit::WebPage::setAllowsRemoteInspection): Deleted.
(WebKit::WebPage::setRemoteInspectionNameOverride): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/WebPageInspectorTarget.h:
* WebProcess/WebPage/WebPageInspectorTarget.cpp:
(WebKit::WebPageInspectorTarget::WebPageInspectorTarget):
(WebKit::WebPageInspectorTarget::identifier const):
(WebKit::WebPageInspectorTarget::connect):
(WebKit::WebPageInspectorTarget::disconnect):
(WebKit::WebPageInspectorTarget::sendMessageToTargetBackend):
InspectorTarget for this WebPage.
* WebProcess/WebPage/WebPageInspectorTargetController.cpp: Added.
(WebKit::WebPageInspectorTargetController::WebPageInspectorTargetController):
(WebKit::WebPageInspectorTargetController::~WebPageInspectorTargetController):
(WebKit::WebPageInspectorTargetController::addTarget):
(WebKit::WebPageInspectorTargetController::removeTarget):
(WebKit::WebPageInspectorTargetController::connectInspector):
(WebKit::WebPageInspectorTargetController::disconnectInspector):
(WebKit::WebPageInspectorTargetController::sendMessageToTargetBackend):
(WebKit::WebPageInspectorTargetController::sendMessageToTargetFrontend):
* WebProcess/WebPage/WebPageInspectorTargetController.h:
* WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.h:
* WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.cpp:
(WebKit::WebPageInspectorTargetFrontendChannel::create):
(WebKit::WebPageInspectorTargetFrontendChannel::WebPageInspectorTargetFrontendChannel):
(WebKit::WebPageInspectorTargetFrontendChannel::sendMessageToFrontend):
Preparation for more target managment in the WebContentProcess.
Source/WebKitLegacy/mac:
* WebCoreSupport/WebInspectorClient.h:
WebKitLegacy will still have remote inspection of the Page directly.
LayoutTests:
* inspector/unit-tests/target-manager.html:
WI.targets has switched to being an array instead of a set.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238192
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2018-11-14 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Keep Web Inspector window alive across process swaps (PSON) (Remote Inspector)
+ https://bugs.webkit.org/show_bug.cgi?id=191494
+ <rdar://problem/45469854>
+
+ Reviewed by Devin Rousso.
+
+ * inspector/unit-tests/target-manager.html:
+ WI.targets has switched to being an array instead of a set.
+
2018-11-14 Truitt Savell <tsavell@apple.com>
[ Sierra Release WK2 ] Layout Test fast/workers/worker-cloneport.html is flaky.
description: "We should always have the main target.",
async test() {
InspectorTest.assert(WI.targets === WI.targetManager.targets);
- InspectorTest.expectEqual(WI.targets.size, 1, "Targets list should always start out with the main target.");
+ InspectorTest.expectEqual(WI.targets.length, 1, "Targets list should always start out with the main target.");
InspectorTest.expectEqual([...WI.targets][0], WI.mainTarget, "Target list should always contain the main target.");
InspectorTest.expectNotNull(WI.mainTarget.executionContext, "Main target should have an ExecutionContext.");
InspectorTest.expectEqual(WI.mainTarget.RuntimeAgent, RuntimeAgent, "Main target should have the global RuntimeAgent.");
inspector/InspectorFrontendChannel.h
inspector/InspectorFrontendRouter.h
inspector/InspectorProtocolTypes.h
+ inspector/InspectorTarget.h
inspector/PerGlobalObjectWrapperWorld.h
inspector/ScriptArguments.h
inspector/ScriptBreakpoint.h
inspector/agents/InspectorHeapAgent.h
inspector/agents/InspectorRuntimeAgent.h
inspector/agents/InspectorScriptProfilerAgent.h
+ inspector/agents/InspectorTargetAgent.h
inspector/augmentable/AugmentableInspectorControllerClient.h
${JAVASCRIPTCORE_DIR}/inspector/protocol/Runtime.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/ScriptProfiler.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Security.json
+ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Target.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Timeline.json
${JAVASCRIPTCORE_DIR}/inspector/protocol/Worker.json
)
+2018-11-14 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Keep Web Inspector window alive across process swaps (PSON) (Remote Inspector)
+ https://bugs.webkit.org/show_bug.cgi?id=191494
+ <rdar://problem/45469854>
+
+ Reviewed by Devin Rousso.
+
+ * CMakeLists.txt:
+ * DerivedSources.make:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Sources.txt:
+ New domain and resources.
+
+ * inspector/protocol/Target.json: Added.
+ New protocol domain, modeled after Worker.json, to allow for
+ multiplexing between different targets.
+
+ * inspector/InspectorTarget.h:
+ Each target will instantiate an InspectorTarget and must
+ provide an identifier, type, and means of connecting/disconnecting
+ to a frontend channel.
+
+ * inspector/agents/InspectorTargetAgent.cpp: Added.
+ (Inspector::InspectorTargetAgent::InspectorTargetAgent):
+ (Inspector::InspectorTargetAgent::didCreateFrontendAndBackend):
+ (Inspector::InspectorTargetAgent::willDestroyFrontendAndBackend):
+ (Inspector::InspectorTargetAgent::exists):
+ (Inspector::InspectorTargetAgent::initialized):
+ (Inspector::InspectorTargetAgent::sendMessageToTarget):
+ (Inspector::InspectorTargetAgent::sendMessageFromTargetToFrontend):
+ (Inspector::targetTypeToProtocolType):
+ (Inspector::buildTargetInfoObject):
+ (Inspector::InspectorTargetAgent::targetCreated):
+ (Inspector::InspectorTargetAgent::targetTerminated):
+ (Inspector::InspectorTargetAgent::connectToTargets):
+ (Inspector::InspectorTargetAgent::disconnectFromTargets):
+ * inspector/agents/InspectorTargetAgent.h: Added.
+ TargetAgent holds a list of targets, and connects/disconnects to each
+ of the targets when a frontend connects/disconnects.
+
+ * inspector/scripts/codegen/generator.py:
+ Better enum casing of ServiceWorker.
+
2018-11-14 Yusuke Suzuki <yusukesuzuki@slowstart.org>
Unreviewed, rolling in CodeCache in r237254
$(JavaScriptCore)/inspector/protocol/Runtime.json \
$(JavaScriptCore)/inspector/protocol/ScriptProfiler.json \
$(JavaScriptCore)/inspector/protocol/Security.json \
+ $(JavaScriptCore)/inspector/protocol/Target.json \
$(JavaScriptCore)/inspector/protocol/Timeline.json \
$(JavaScriptCore)/inspector/protocol/Worker.json \
#
A513E5C7185F9446007E95AD /* InjectedScriptSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A513E5C6185F9436007E95AD /* InjectedScriptSource.h */; };
A513E5CB185F9624007E95AD /* InjectedScriptManager.h in Headers */ = {isa = PBXBuildFile; fileRef = A513E5C9185F9624007E95AD /* InjectedScriptManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
A514B2C3185A684400F3C7CB /* InjectedScriptBase.h in Headers */ = {isa = PBXBuildFile; fileRef = A514B2C1185A684400F3C7CB /* InjectedScriptBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ A52C95FF2159D432007D8AC0 /* InspectorTargetAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A555FF3D2159D41E00FCD826 /* InspectorTargetAgent.h */; settings = {ATTRIBUTES = (Private, ); }; };
A5311C361C77CEC500E6B1B6 /* HeapSnapshotBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = A5311C351C77CEAC00E6B1B6 /* HeapSnapshotBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; };
A532438818568335002ED692 /* InspectorBackendDispatchers.h in Headers */ = {isa = PBXBuildFile; fileRef = A532438218568317002ED692 /* InspectorBackendDispatchers.h */; settings = {ATTRIBUTES = (Private, ); }; };
A532438A18568335002ED692 /* InspectorFrontendDispatchers.h in Headers */ = {isa = PBXBuildFile; fileRef = A532438418568317002ED692 /* InspectorFrontendDispatchers.h */; settings = {ATTRIBUTES = (Private, ); }; };
A55165D31BDF0B9E003B75C1 /* InspectorScriptProfilerAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A55165D11BDEFDBD003B75C1 /* InspectorScriptProfilerAgent.h */; settings = {ATTRIBUTES = (Private, ); }; };
A55165D51BDF135A003B75C1 /* ScriptProfilingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = A55165D41BDF134D003B75C1 /* ScriptProfilingScope.h */; };
A552C3801ADDB8FE00139726 /* JSRemoteInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = A552C37E1ADDB8FE00139726 /* JSRemoteInspector.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ A555FF3B2159D2F500FCD826 /* InspectorTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = A555FF382159D2D600FCD826 /* InspectorTarget.h */; settings = {ATTRIBUTES = (Private, ); }; };
A55714BE1CD8049F0004D2C6 /* ConsoleObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A55714BD1CD8048E0004D2C6 /* ConsoleObject.h */; };
A55D93A6185012A800400DED /* ScriptFunctionCall.h in Headers */ = {isa = PBXBuildFile; fileRef = A55D93A4185012A800400DED /* ScriptFunctionCall.h */; settings = {ATTRIBUTES = (Private, ); }; };
A55D93AC18514F7900400DED /* InspectorProtocolTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = A55D93AB18514F7900400DED /* InspectorProtocolTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
A55165D41BDF134D003B75C1 /* ScriptProfilingScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptProfilingScope.h; sourceTree = "<group>"; };
A552C37D1ADDB8FE00139726 /* JSRemoteInspector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSRemoteInspector.cpp; sourceTree = "<group>"; };
A552C37E1ADDB8FE00139726 /* JSRemoteInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSRemoteInspector.h; sourceTree = "<group>"; };
+ A555FF382159D2D600FCD826 /* InspectorTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorTarget.h; sourceTree = "<group>"; };
+ A555FF3C2159D41E00FCD826 /* InspectorTargetAgent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorTargetAgent.cpp; sourceTree = "<group>"; };
+ A555FF3D2159D41E00FCD826 /* InspectorTargetAgent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InspectorTargetAgent.h; sourceTree = "<group>"; };
A55714BC1CD8048E0004D2C6 /* ConsoleObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConsoleObject.cpp; sourceTree = "<group>"; };
A55714BD1CD8048E0004D2C6 /* ConsoleObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConsoleObject.h; sourceTree = "<group>"; };
A55D93A3185012A800400DED /* ScriptFunctionCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptFunctionCall.cpp; sourceTree = "<group>"; };
A50E4B5E18809DD50068A46D /* InspectorRuntimeAgent.h */,
A55165D01BDEFDBD003B75C1 /* InspectorScriptProfilerAgent.cpp */,
A55165D11BDEFDBD003B75C1 /* InspectorScriptProfilerAgent.h */,
+ A555FF3C2159D41E00FCD826 /* InspectorTargetAgent.cpp */,
+ A555FF3D2159D41E00FCD826 /* InspectorTargetAgent.h */,
A57D23E71891B0770031C7FA /* JSGlobalObjectDebuggerAgent.cpp */,
A57D23E81891B0770031C7FA /* JSGlobalObjectDebuggerAgent.h */,
A50E4B5F18809DD50068A46D /* JSGlobalObjectRuntimeAgent.cpp */,
99F1A6FC1B8E6D9400463B26 /* InspectorFrontendRouter.cpp */,
99F1A7001B98FBEC00463B26 /* InspectorFrontendRouter.h */,
A55D93AB18514F7900400DED /* InspectorProtocolTypes.h */,
+ A555FF382159D2D600FCD826 /* InspectorTarget.h */,
A503FA13188E0FAF00110F14 /* JavaScriptCallFrame.cpp */,
A503FA14188E0FAF00110F14 /* JavaScriptCallFrame.h */,
A5C3A1A318C0490200C9593A /* JSGlobalObjectConsoleClient.cpp */,
A55D93AC18514F7900400DED /* InspectorProtocolTypes.h in Headers */,
A50E4B6218809DD50068A46D /* InspectorRuntimeAgent.h in Headers */,
A55165D31BDF0B9E003B75C1 /* InspectorScriptProfilerAgent.h in Headers */,
+ A555FF3B2159D2F500FCD826 /* InspectorTarget.h in Headers */,
+ A52C95FF2159D432007D8AC0 /* InspectorTargetAgent.h in Headers */,
0F49E9AA20AB4D00001CA0AA /* InstanceOfAccessCase.h in Headers */,
0FB399BF20AF6B3F0017E213 /* InstanceOfStatus.h in Headers */,
0FB399C020AF6B430017E213 /* InstanceOfVariant.h in Headers */,
inspector/agents/InspectorHeapAgent.cpp
inspector/agents/InspectorRuntimeAgent.cpp
inspector/agents/InspectorScriptProfilerAgent.cpp
+inspector/agents/InspectorTargetAgent.cpp
inspector/agents/JSGlobalObjectDebuggerAgent.cpp
inspector/agents/JSGlobalObjectRuntimeAgent.cpp
--- /dev/null
+/*
+ * Copyright (C) 2018 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
+
+#include "InspectorFrontendChannel.h"
+#include <wtf/text/WTFString.h>
+
+namespace Inspector {
+
+// FIXME: Add DedicatedWorker Inspector Targets
+// FIXME: Add ServiceWorker Inspector Targets
+enum class InspectorTargetType : uint8_t {
+ JavaScriptContext,
+ Page,
+ DedicatedWorker,
+ ServiceWorker,
+};
+
+class JS_EXPORT_PRIVATE InspectorTarget {
+public:
+ virtual ~InspectorTarget() = default;
+
+ // State.
+ virtual String identifier() const = 0;
+ virtual InspectorTargetType type() const = 0;
+
+ // Connection management.
+ virtual void connect(FrontendChannel&) = 0;
+ virtual void disconnect(FrontendChannel&) = 0;
+ virtual void sendMessageToTargetBackend(const String&) = 0;
+};
+
+} // namespace Inspector
+
+namespace WTF {
+
+template<> struct EnumTraits<Inspector::InspectorTargetType> {
+ using values = EnumValues<
+ Inspector::InspectorTargetType,
+ Inspector::InspectorTargetType::JavaScriptContext,
+ Inspector::InspectorTargetType::Page,
+ Inspector::InspectorTargetType::DedicatedWorker,
+ Inspector::InspectorTargetType::ServiceWorker
+ >;
+};
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2018 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 "InspectorTargetAgent.h"
+
+#include "InspectorTarget.h"
+
+namespace Inspector {
+
+InspectorTargetAgent::InspectorTargetAgent(FrontendRouter& frontendRouter, BackendDispatcher& backendDispatcher)
+ : InspectorAgentBase("Target"_s)
+ , m_frontendDispatcher(std::make_unique<TargetFrontendDispatcher>(frontendRouter))
+ , m_backendDispatcher(TargetBackendDispatcher::create(backendDispatcher, this))
+{
+}
+
+void InspectorTargetAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
+{
+ m_isConnected = true;
+
+ connectToTargets();
+}
+
+void InspectorTargetAgent::willDestroyFrontendAndBackend(DisconnectReason)
+{
+ disconnectFromTargets();
+
+ m_isConnected = false;
+}
+
+void InspectorTargetAgent::exists(ErrorString&)
+{
+ // Intentionally do nothing to return success.
+ // FIXME: Remove this when the local inspector has switched over to the modern path.
+}
+
+void InspectorTargetAgent::sendMessageToTarget(ErrorString& errorString, const String& targetId, const String& message)
+{
+ InspectorTarget* target = m_targets.get(targetId);
+ if (!target) {
+ errorString = "Target not found."_s;
+ return;
+ }
+
+ target->sendMessageToTargetBackend(message);
+}
+
+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.");
+
+ m_frontendDispatcher->dispatchMessageFromTarget(targetId, message);
+}
+
+static Protocol::Target::TargetInfo::Type targetTypeToProtocolType(InspectorTargetType type)
+{
+ switch (type) {
+ case InspectorTargetType::JavaScriptContext:
+ return Protocol::Target::TargetInfo::Type::JavaScript;
+ case InspectorTargetType::Page:
+ return Protocol::Target::TargetInfo::Type::Page;
+ case InspectorTargetType::DedicatedWorker:
+ return Protocol::Target::TargetInfo::Type::Worker;
+ case InspectorTargetType::ServiceWorker:
+ return Protocol::Target::TargetInfo::Type::ServiceWorker;
+ }
+
+ ASSERT_NOT_REACHED();
+ return Protocol::Target::TargetInfo::Type::JavaScript;
+}
+
+static Ref<Protocol::Target::TargetInfo> buildTargetInfoObject(const InspectorTarget& target)
+{
+ return Protocol::Target::TargetInfo::create()
+ .setTargetId(target.identifier())
+ .setType(targetTypeToProtocolType(target.type()))
+ .release();
+}
+
+void InspectorTargetAgent::targetCreated(InspectorTarget& target)
+{
+ auto addResult = m_targets.set(target.identifier(), &target);
+ ASSERT_UNUSED(addResult, addResult.isNewEntry);
+
+ if (!m_isConnected)
+ return;
+
+ target.connect(frontendChannel());
+
+ m_frontendDispatcher->targetCreated(buildTargetInfoObject(target));
+}
+
+void InspectorTargetAgent::targetDestroyed(InspectorTarget& target)
+{
+ m_targets.remove(target.identifier());
+
+ if (!m_isConnected)
+ return;
+
+ target.disconnect(frontendChannel());
+
+ m_frontendDispatcher->targetDestroyed(target.identifier());
+}
+
+void InspectorTargetAgent::connectToTargets()
+{
+ auto& channel = frontendChannel();
+
+ for (InspectorTarget* target : m_targets.values()) {
+ target->connect(channel);
+ m_frontendDispatcher->targetCreated(buildTargetInfoObject(*target));
+ }
+}
+
+void InspectorTargetAgent::disconnectFromTargets()
+{
+ auto& channel = frontendChannel();
+
+ for (InspectorTarget* target : m_targets.values())
+ target->disconnect(channel);
+}
+
+} // namespace Inspector
--- /dev/null
+/*
+ * Copyright (C) 2018 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
+
+#include "InspectorAgentBase.h"
+#include "InspectorBackendDispatchers.h"
+#include "InspectorFrontendDispatchers.h"
+#include <wtf/Forward.h>
+
+namespace Inspector {
+
+class InspectorTarget;
+
+typedef String ErrorString;
+
+class JS_EXPORT_PRIVATE InspectorTargetAgent : public InspectorAgentBase, public TargetBackendDispatcherHandler {
+ WTF_MAKE_NONCOPYABLE(InspectorTargetAgent);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InspectorTargetAgent(FrontendRouter&, BackendDispatcher&);
+ virtual ~InspectorTargetAgent() = default;
+
+ void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) final;
+ void willDestroyFrontendAndBackend(DisconnectReason) final;
+
+ virtual FrontendChannel& frontendChannel() = 0;
+
+ // TargetBackendDispatcherHandler
+ void exists(ErrorString&) final;
+ void sendMessageToTarget(ErrorString&, const String& targetId, const String& message) final;
+
+ // Target lifecycle.
+ void targetCreated(InspectorTarget&);
+ void targetDestroyed(InspectorTarget&);
+
+ // Target messages.
+ void sendMessageFromTargetToFrontend(const String& targetId, const String& message);
+
+private:
+ void connectToTargets();
+ void disconnectFromTargets();
+
+ std::unique_ptr<TargetFrontendDispatcher> m_frontendDispatcher;
+ Ref<TargetBackendDispatcher> m_backendDispatcher;
+ HashMap<String, InspectorTarget*> m_targets;
+ bool m_isConnected { false };
+};
+
+} // namespace Inspector
--- /dev/null
+{
+ "domain": "Target",
+ "availability": ["web"],
+ "types": [
+ {
+ "id": "TargetInfo",
+ "type": "object",
+ "description": "Description of a target.",
+ "properties": [
+ { "name": "targetId", "type": "string", "description": "Unique identifier for the target." },
+ { "name": "type", "type": "string", "enum": ["javascript", "page", "worker", "serviceworker"] }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "exists",
+ "description": "FIXME: Remove this when the local inspector has switched over to the modern path."
+ },
+ {
+ "name": "sendMessageToTarget",
+ "description": "Send an Inspector Protocol message to be dispatched to a Target's agents.",
+ "parameters": [
+ { "name": "targetId", "type": "string" },
+ { "name": "message", "type": "string", "description": "JSON Inspector Protocol message (command) to be dispatched on the backend." }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "targetCreated",
+ "parameters": [
+ { "name": "targetInfo", "$ref": "TargetInfo" }
+ ]
+ },
+ {
+ "name": "targetDestroyed",
+ "parameters": [
+ { "name": "targetId", "type": "string" }
+ ]
+ },
+ {
+ "name": "dispatchMessageFromTarget",
+ "parameters": [
+ { "name": "targetId", "type": "string" },
+ { "name": "message", "type": "string", "description": "JSON Inspector Protocol message (response or event) to be dispatched on the frontend." }
+ ]
+ }
+ ]
+}
def ucfirst(str):
return str[:1].upper() + str[1:]
-_ALWAYS_SPECIALCASED_ENUM_VALUE_SUBSTRINGS = set(['2D', 'API', 'CSS', 'DOM', 'HTML', 'JIT', 'XHR', 'XML', 'IOS', 'MacOS', 'JavaScript'])
+_ALWAYS_SPECIALCASED_ENUM_VALUE_SUBSTRINGS = set(['2D', 'API', 'CSS', 'DOM', 'HTML', 'JIT', 'XHR', 'XML', 'IOS', 'MacOS', 'JavaScript', 'ServiceWorker'])
_ALWAYS_SPECIALCASED_ENUM_VALUE_LOOKUP_TABLE = dict([(s.upper(), s) for s in _ALWAYS_SPECIALCASED_ENUM_VALUE_SUBSTRINGS])
_ENUM_IDENTIFIER_RENAME_MAP = {
+2018-11-14 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Keep Web Inspector window alive across process swaps (PSON) (Remote Inspector)
+ https://bugs.webkit.org/show_bug.cgi?id=191494
+ <rdar://problem/45469854>
+
+ Reviewed by Devin Rousso.
+
+ * inspector/InspectorClient.h:
+ (WebCore::InspectorClient::allowRemoteInspectionToPageDirectly const):
+ Provide a hook so that a client may wish to allow direct remote inspection of the Page.
+ This is used by WebKitLegacy only.
+
+ * page/Page.cpp:
+ (Page::Page):
+ Only enable the PageDebuggable if the client wishes remote inspection of the Page directly.
+ This is used by WebKitLegacy only.
+
+ * inspector/InspectorController.cpp:
+ (WebCore::InspectorController::connectFrontend):
+ * inspector/InspectorController.h:
+ * page/PageDebuggable.cpp:
+ (WebCore::PageDebuggable::connect):
+ (WebCore::PageDebuggable::disconnect):
+ * page/PageDebuggable.h:
+ When a frontend connects, always enable the developer extras for the Page.
+ This is pretty much only for the remote path, which allows inspection if developer
+ extras were not already enabled (iOS). This simplifies the logic, and toggling
+ developer extras after it was already enabled is not really important.
+
2018-11-14 Per Arne Vollan <pvollan@apple.com>
REGRESSION (WEBPROCESS_WINDOWSERVER_BLOCKING): requestAnimationFrame Stops Completing
virtual void didSetSearchingForNode(bool) { }
virtual void elementSelectionChanged(bool) { }
+#if ENABLE(REMOTE_INSPECTOR)
+ virtual bool allowRemoteInspectionToPageDirectly() const { return false; }
+#endif
+
WEBCORE_EXPORT static void doDispatchMessageOnFrontendPage(Page* frontendPage, const String& message);
};
ASSERT_ARG(frontendChannel, frontendChannel);
ASSERT(m_inspectorClient);
+ // If a frontend has connected enable the developer extras and keep them enabled.
+ m_page.settings().setDeveloperExtrasEnabled(true);
+
createLazyAgents();
bool connectedFirstFrontend = !m_frontendRouter->hasFrontends();
m_inspectorClient->frontendCountChanged(m_frontendRouter->frontendCount());
#if ENABLE(REMOTE_INSPECTOR)
- if (!m_frontendRouter->hasRemoteFrontend())
+ if (hasLocalFrontend())
m_page.remoteInspectorInformationDidChange();
#endif
}
m_inspectorClient->frontendCountChanged(m_frontendRouter->frontendCount());
#if ENABLE(REMOTE_INSPECTOR)
- if (!m_frontendRouter->hasFrontends())
+ if (disconnectedLastFrontend)
m_page.remoteInspectorInformationDidChange();
#endif
}
void InspectorController::show()
{
- ASSERT(!m_frontendRouter->hasRemoteFrontend());
+ ASSERT(!hasRemoteFrontend());
if (!enabled())
return;
void hideHighlight();
Node* highlightedNode() const;
- void setIndicating(bool);
+ WEBCORE_EXPORT void setIndicating(bool);
WEBCORE_EXPORT Ref<JSON::ArrayOf<Inspector::Protocol::OverlayTypes::NodeHighlightData>> buildObjectForHighlightedNodes() const;
#include "HTMLMediaElement.h"
#include "HistoryController.h"
#include "HistoryItem.h"
+#include "InspectorClient.h"
#include "InspectorController.h"
#include "InspectorInstrumentation.h"
#include "LibWebRTCProvider.h"
#endif
#if ENABLE(REMOTE_INSPECTOR)
- m_inspectorDebuggable->init();
+ if (m_inspectorController->inspectorClient() && m_inspectorController->inspectorClient()->allowRemoteInspectionToPageDirectly())
+ m_inspectorDebuggable->init();
#endif
#if PLATFORM(COCOA)
void PageDebuggable::connect(Inspector::FrontendChannel* channel, bool isAutomaticConnection, bool immediatelyPause)
{
- if (!m_page.settings().developerExtrasEnabled()) {
- m_forcedDeveloperExtrasEnabled = true;
- m_page.settings().setDeveloperExtrasEnabled(true);
- } else
- m_forcedDeveloperExtrasEnabled = false;
-
InspectorController& inspectorController = m_page.inspectorController();
inspectorController.connectFrontend(channel, isAutomaticConnection, immediatelyPause);
}
{
InspectorController& inspectorController = m_page.inspectorController();
inspectorController.disconnectFrontend(channel);
-
- if (m_forcedDeveloperExtrasEnabled) {
- m_forcedDeveloperExtrasEnabled = false;
- m_page.settings().setDeveloperExtrasEnabled(false);
- }
}
void PageDebuggable::dispatchMessageFromRemote(const String& message)
private:
Page& m_page;
String m_nameOverride;
- bool m_forcedDeveloperExtrasEnabled { false };
};
} // namespace WebCore
+2018-11-14 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Keep Web Inspector window alive across process swaps (PSON) (Remote Inspector)
+ https://bugs.webkit.org/show_bug.cgi?id=191494
+ <rdar://problem/45469854>
+
+ Reviewed by Devin Rousso.
+
+ This starts introducing multi-target support into the Web Inspector frontend.
+ Specifically a backend connection that is persistent, but has the ability to
+ connect to and transition between Page targets received through that backend
+ connection.
+
+ This patch introduces the concept of a "Backend Target" which is the single
+ connection that the frontend contains to a backend. The old way of connecting
+ directly to a target is still supported. In that case the frontend constructs
+ a DirectBackendTarget for the debuggable type the frontend was spawns for.
+ However, if the frontend opens and has a TargetAgent, then it is likely
+ connected to a multi-target supporting backend and instead constructs a
+ MultiplexingBackendTarget, and will receive further information about
+ sub-targets to connect to. The only sub-target at the moment is a Page
+ sub-target.
+
+ As part of bringing up multi-target support this adds a few measures to
+ handle situations where the frontend is playing fast and loose with agents.
+ When the frontend does `FooAgent.method` it intends that to be performed
+ on the "main" target being debugged. Likewise when the frontend loops
+ over targets it expects them to be the debuggable targets. This patch
+ profiles a new implementation of `WI.mainTarget` and `WI.targets` to
+ match the assumptions being made by the frontend.
+
+ - In a direct-target world, there is a single target which
+ should be used for global agents and in WI.targets.
+
+ - In a multi-target world, the page target is the one that
+ should be used for global agents and WI.targets is the list
+ of sub-targets (excluding the MultiplexingBackendTarget).
+
+ In a multi-target world, there are now commonly two Targets. The
+ MultiplexingBackendTarget and a PageTarget sub-target. In the future
+ this may include more targets, such as ServiceWorkers, DedicatedWorkers,
+ and perhaps even frames.
+
+ In a multi-target world, the frontend is immediately told about targets
+ as soon as it opens (via Target.targetCreated). In order to support
+ this, frontend initialization happens without a main target being available.
+ So this makes a few small changes to frontend initialization to perform
+ a bit of work once we know what the main target is.
+
+ During a page transition the frontend is told to destroy existing targets
+ and is soon after told about any new page targets (via Target.targetDestroyed
+ and Target.targetCreated). The frontend special cases this page transition.
+ It expects only one Page target to be alive at any time, accessible through
+ WI.pageTarget. When a page transition happens the WI.pageTarget changes, and
+ the frontend performs a bit of work to prepare the UI to handle the transition:
+ `<Manager>.transitionPageTarget` / WI.Notification.TransitionPageTarget.
+ For the most part the UI behaves fine as long once there are main frame
+ change and main resource change events, but those other events allow
+ the frontend to respond to the specific page transition cases.
+
+ * UserInterface/Base/Main.js:
+ (WI.loaded):
+ (WI.initializeBackendTarget):
+ (WI.initializePageTarget):
+ (WI.transitionPageTarget):
+ (WI.terminatePageTarget):
+ (WI.resetMainExecutionContext):
+ (WI.redirectGlobalAgentsToConnection):
+ (WI.contentLoaded):
+ New global functions for target initialization
+ and page transitioning.
+
+ * UserInterface/Test/Test.js:
+ (WI.loaded):
+ (WI.initializeBackendTarget):
+ (WI.initializePageTarget):
+ (WI.transitionPageTarget):
+ (WI.terminatePageTarget):
+ (WI.resetMainExecutionContext):
+ (WI.redirectGlobalAgentsToConnection):
+ New global functions for target initialization.
+ Tests continue to be a direct connection to the Page.
+
+ * UserInterface/Protocol/TargetObserver.js:
+ (WI.TargetObserver.prototype.targetCreated):
+ (WI.TargetObserver.prototype.targetDestroyed):
+ (WI.TargetObserver.prototype.dispatchMessageFromTarget):
+ New observer goes to the manager.
+
+ * UserInterface/Controllers/TargetManager.js:
+ (WI.TargetManager):
+ (WI.TargetManager.prototype.get targets):
+ (WI.TargetManager.prototype.get allTargets):
+ (WI.TargetManager.prototype.targetForIdentifier):
+ (WI.TargetManager.prototype.targetCreated):
+ (WI.TargetManager.prototype.targetDestroyed):
+ (WI.TargetManager.prototype.dispatchMessageFromTarget):
+ (WI.TargetManager.prototype.createMultiplexingBackendTarget):
+ (WI.TargetManager.prototype.createDirectBackendTarget):
+ (WI.TargetManager.prototype._addTarget):
+ (WI.TargetManager.prototype._removeTarget):
+ (WI.TargetManager.prototype._createTarget):
+ (WI.TargetManager.prototype._checkAndHandlePageTargetTransition):
+ (WI.TargetManager.prototype._checkAndHandlePageTargetTermination):
+ (WI.TargetManager.prototype.addTarget): Deleted.
+ (WI.TargetManager.prototype.removeTarget): Deleted.
+ (WI.TargetManager.prototype.initializeMainTarget): Deleted.
+ TargetManager is where we handle creating and destroying targets
+ and their connections. In order to simplify things a bit we make
+ `WI.targets`, which goes through `get targets()` an array instead
+ of a Set. And this includes only the sub-targets.
+
+ * UserInterface/Controllers/WorkerManager.js:
+ (WI.WorkerManager.prototype.workerCreated):
+ (WI.WorkerManager.prototype.workerTerminated):
+ Workers are still special-target-like things that multiplex through
+ WorkerAgent instead of TargetAgent. We'd like to promote these to
+ be full targets in the future.
+
+ * UserInterface/Protocol/DirectBackendTarget.js: Renamed from Source/WebInspectorUI/UserInterface/Protocol/MainTarget.js.
+ (WI.DirectBackendTarget):
+ (WI.DirectBackendTarget.connectionInfoForDebuggable):
+ (WI.DirectBackendTarget.prototype.get mainResource):
+ (WI.DirectBackendTarget.prototype.set mainResource):
+ This is the only "MainTarget" class. It is the backend target for a direct connection.
+
+ * UserInterface/Protocol/MultiplexingBackendTarget.js:
+ (WI.MultiplexingBackendTarget):
+ (WI.MultiplexingBackendTarget.prototype.initialize):
+ (WI.MultiplexingBackendTarget.prototype.get name):
+ (WI.MultiplexingBackendTarget.prototype.get executionContext):
+ (WI.MultiplexingBackendTarget.prototype.get mainResource):
+ This is the new backend target for a multi-target connection.
+ We don't expect it to be treated like other targets, so we don't
+ expect anyone to ask it for resources/executionContext/name info.
+
+ * UserInterface/Controllers/RuntimeManager.js:
+ (WI.TargetManager.prototype.evaluateInInspectedWindow):
+ This can be triggered by watch expressions before any target, and
+ therefore execution context, is available. Just return null, when
+ an execution context is available those clients will try again.
+
+ * UserInterface/Debug/Bootstrap.js:
+ Provide an WI.isEngineeringBuild boolean that can be used for various
+ debugging features.
+
+ * UserInterface/Main.html:
+ * UserInterface/Test.html:
+ New resources.
+
+ * UserInterface/Protocol/InspectorBackend.js:
+ (InspectorBackendClass.prototype.dispatch):
+ (InspectorBackendClass.prototype.runAfterPendingDispatches):
+ (InspectorBackend.Agent):
+ `InspectorBackend.mainConnection` was renamed `InspectorBackend.backendConnection`.
+
+ * UserInterface/Protocol/Connection.js:
+ (InspectorBackend.Connection):
+ (InspectorBackend.Connection.prototype._dispatchResponse):
+ (InspectorBackend.Connection.prototype._sendCommandToBackendWithCallback):
+ (InspectorBackend.Connection.prototype._sendCommandToBackendExpectingPromise):
+ (InspectorBackend.BackendConnection):
+ (InspectorBackend.BackendConnection.prototype.sendMessageToBackend):
+ (InspectorBackend.WorkerConnection):
+ (InspectorBackend.TargetConnection):
+ (InspectorBackend.TargetConnection.sendMessageToBackend):
+ Use a global sequence id to make filtering a bit easier in protocol tracing.
+ TargetConnection is identical to WorkerConnection except it uses TargetAgent
+ instead of WorkerAgent to perform multiplexing.
+
+ * UserInterface/Protocol/JavaScriptContextTarget.js:
+ (WI.JavaScriptContextTarget):
+ * UserInterface/Protocol/PageTarget.js:
+ (WI.PageTarget):
+ (WI.PageTarget.prototype.get displayName):
+ Specialized target types.
+
+ * UserInterface/Views/DebuggerSidebarPanel.js:
+ (WI.DebuggerSidebarPanel):
+ (WI.DebuggerSidebarPanel.prototype._targetAdded):
+ (WI.DebuggerSidebarPanel.prototype._targetRemoved):
+ (WI.DebuggerSidebarPanel.prototype._updateCallStackTreeOutline):
+ * UserInterface/Views/SourceCodeTextEditor.js:
+ (WI.SourceCodeTextEditor.prototype._targetAdded):
+ (WI.SourceCodeTextEditor.prototype._targetRemoved):
+ (WI.SourceCodeTextEditor.prototype._callFramesDidChange):
+ (WI.SourceCodeTextEditor.prototype._updateThreadIndicatorWidget):
+ (WI.SourceCodeTextEditor.prototype._reinsertAllThreadIndicators):
+ * UserInterface/Views/QuickConsole.js:
+ (WI.QuickConsole.prototype.initializeMainExecutionContextPathComponent):
+ (WI.QuickConsole.prototype._targetAdded):
+ (WI.QuickConsole.prototype._targetRemoved):
+ We make target added get called with all targets, including the
+ MultiplexingBackendTarget and PageTargets, both of which would
+ not have happened before. Before it was only WorkerTargets. Make
+ these sites a little more robust for the type of target they expect
+ to be able to handle.
+
+ * UserInterface/Base/Object.js:
+ * UserInterface/Controllers/DOMManager.js:
+ (WI.DOMManager):
+ (WI.DOMManager.prototype.transitionPageTarget):
+ (WI.DOMManager.prototype.requestDocument):
+ (WI.DOMManager.prototype._setDocument):
+ * UserInterface/Controllers/NetworkManager.js:
+ (WI.NetworkManager):
+ (WI.NetworkManager.prototype.transitionPageTarget):
+ (WI.NetworkManager.prototype.executionContextCreated):
+ (WI.NetworkManager.prototype._processMainFrameResourceTreePayload):
+ * UserInterface/Models/DefaultDashboard.js:
+ (WI.DefaultDashboard):
+ (WI.DefaultDashboard.prototype._mainResourceDidChange):
+ (WI.DefaultDashboard.prototype._transitionPageTarget):
+ * UserInterface/Views/NetworkTableContentView.js:
+ (WI.NetworkTableContentView):
+ (WI.NetworkTableContentView.prototype._mainResourceDidChange):
+ (WI.NetworkTableContentView.prototype._transitionPageTarget):
+ Special case handling when performing a page transition.
+
+ * UserInterface/Views/SettingsTabContentView.js:
+ * UserInterface/Debug/UncaughtExceptionReporter.js:
+ Document reloads are not supported right now.
+
2018-11-14 Devin Rousso <drousso@apple.com>
Web Inspector: Canvas: don't start with auto-capture enabled
localizedStrings["Lowest: %s"] = "Lowest: %s";
localizedStrings["MIME Type"] = "MIME Type";
localizedStrings["MIME Type:"] = "MIME Type:";
-localizedStrings["Main"] = "Main";
localizedStrings["Manifest URL"] = "Manifest URL";
localizedStrings["Mass"] = "Mass";
localizedStrings["Matching"] = "Matching";
localizedStrings["Whitespace characters"] = "Whitespace characters";
localizedStrings["Width"] = "Width";
localizedStrings["With Object Properties"] = "With Object Properties";
+localizedStrings["Worker"] = "Worker";
localizedStrings["Worker \u2014 %s"] = "Worker \u2014 %s";
localizedStrings["Working Copy"] = "Working Copy";
localizedStrings["Wrap lines to editor width"] = "Wrap lines to editor width";
WI.loaded = function()
{
// Register observers for events from the InspectorBackend.
+ if (InspectorBackend.registerTargetDispatcher)
+ InspectorBackend.registerTargetDispatcher(new WI.TargetObserver);
if (InspectorBackend.registerInspectorDispatcher)
InspectorBackend.registerInspectorDispatcher(new WI.InspectorObserver);
if (InspectorBackend.registerPageDispatcher)
this._windowKeydownListeners = [];
// Targets.
- WI.mainTarget = new WI.MainTarget;
- WI.mainTarget.initialize();
- WI.pageTarget = WI.sharedApp.debuggableType === WI.DebuggableType.Web ? WI.mainTarget : null;
+ WI.backendTarget = null;
+ WI.pageTarget = null;
- // Post-target initialization.
- WI.targetManager.initializeMainTarget();
- WI.runtimeManager.activeExecutionContext = WI.mainTarget.executionContext;
+ if (!window.TargetAgent)
+ WI.targetManager.createDirectBackendTarget();
+ else {
+ // FIXME: Eliminate `TargetAgent.exists` once the local inspector
+ // is configured to use the Multiplexing code path.
+ TargetAgent.exists((error) => {
+ if (error)
+ WI.targetManager.createDirectBackendTarget();
+ });
+ }
+};
+
+WI.initializeBackendTarget = function(target)
+{
+ console.assert(!WI.mainTarget);
+
+ WI.backendTarget = target;
+
+ WI.resetMainExecutionContext();
+};
+
+WI.initializePageTarget = function(target)
+{
+ console.assert(WI.sharedApp.debuggableType === WI.DebuggableType.Web);
+ console.assert(target.type === WI.Target.Type.Page || target instanceof WI.DirectBackendTarget);
+
+ WI.pageTarget = target;
+
+ WI.redirectGlobalAgentsToConnection(WI.pageTarget.connection);
+
+ WI.resetMainExecutionContext();
+};
+
+WI.transitionPageTarget = function(target)
+{
+ console.assert(!WI.pageTarget);
+ console.assert(WI.sharedApp.debuggableType === WI.DebuggableType.Web);
+ console.assert(target.type === WI.Target.Type.Page);
+
+ WI.pageTarget = target;
+
+ WI.redirectGlobalAgentsToConnection(WI.pageTarget.connection);
+
+ WI.resetMainExecutionContext();
+
+ // Actions to transition the page target.
+ this.notifications.dispatchEventToListeners(WI.Notification.TransitionPageTarget);
+ WI.domManager.transitionPageTarget();
+ WI.networkManager.transitionPageTarget();
+};
+
+WI.terminatePageTarget = function(target)
+{
+ console.assert(WI.pageTarget);
+ console.assert(WI.pageTarget === target);
+ console.assert(WI.sharedApp.debuggableType === WI.DebuggableType.Web);
+
+ WI.pageTarget = null;
+
+ WI.redirectGlobalAgentsToConnection(WI.backendConnection);
+};
+
+WI.resetMainExecutionContext = function()
+{
+ if (WI.mainTarget instanceof WI.MultiplexingBackendTarget)
+ return;
+
+ if (WI.mainTarget.executionContext) {
+ WI.runtimeManager.activeExecutionContext = WI.mainTarget.executionContext;
+ if (WI.quickConsole)
+ WI.quickConsole.initializeMainExecutionContextPathComponent();
+ }
+};
+
+WI.redirectGlobalAgentsToConnection = function(connection)
+{
+ // This makes global window.FooAgent dispatch to the active page target.
+ for (let [domain, agent] of Object.entries(InspectorBackend._agents)) {
+ if (domain !== "Target")
+ agent.connection = connection;
+ }
};
WI.contentLoaded = function()
// Store this on the window in case the WebInspector global gets corrupted.
window.__frontendCompletedLoad = true;
- if (this.runBootstrapOperations)
- this.runBootstrapOperations();
+ if (WI.runBootstrapOperations)
+ WI.runBootstrapOperations();
};
WI.performOneTimeFrontendInitializationsUsingTarget = function(target)
proposedContextMenu = WI.ContextMenu.createFromEvent(event);
proposedContextMenu.appendSeparator();
proposedContextMenu.appendItem(WI.unlocalizedString("Reload Web Inspector"), () => {
+ // FIXME: Reload Web Inspector does not work with MultiplexingBackendTarget.
window.location.reload();
});
if (WI.resolvedLayoutDirection() === WI.LayoutDirection.LTR && this._dockConfiguration === WI.DockConfiguration.Left)
this._dockRight();
+ // FIXME: Reload Web Inspector does not work with MultiplexingBackendTarget.
window.location.reload();
};
console.error(error);
};
+// Many places assume the "main" target has resources.
+// In the case where the main backend target is a MultiplexingBackendTarget
+// that target has essentially nothing. In that case defer to the page
+// target, since that is the real "main" target the frontend is assuming.
+Object.defineProperty(WI, "mainTarget",
+{
+ get() { return WI.pageTarget || WI.backendTarget; }
+});
+
+// This list of targets are non-Multiplexing targets.
+// So if there is a multiplexing target, and multiple sub-targets
+// this is just the list of sub-targets. Almost no code expects
+// to actually interact with the Multiplexing target.
Object.defineProperty(WI, "targets",
{
get() { return WI.targetManager.targets; }
return WI.mainTarget;
};
+WI.isEngineeringBuild = false;
+
// OpenResourceDialog delegate
WI.dialogWasDismissedWithRepresentedObject = function(dialog, representedObject)
ExtraDomainsActivated: "extra-domains-activated",
DebugUIEnabledDidChange: "debug-ui-enabled-did-change",
VisibilityStateDidChange: "visibility-state-did-change",
+ TransitionPageTarget: "transition-page-target",
};
// DebugUI
autoLogProtocolMessages: new WI.Setting("auto-collect-protocol-messages", false),
autoLogTimeStats: new WI.Setting("auto-collect-time-stats", false),
- enableUncaughtExceptionReporter: new WI.Setting("enable-uncaught-exception-reporter", true),
enableLayoutFlashing: new WI.Setting("enable-layout-flashing", false),
+ enableUncaughtExceptionReporter: new WI.Setting("enable-uncaught-exception-reporter", true),
+ filterMultiplexingBackendInspectorProtocolMessages: new WI.Setting("filter-multiplexing-backend-inspector-protocol-messages", true),
layoutDirection: new WI.Setting("layout-direction-override", "system"),
pauseForInternalScripts: new WI.Setting("pause-for-internal-scripts", false),
};
this._breakpointsForEventListeners = new Map;
+ this._hasRequestedDocument = false;
+ this._pendingDocumentRequestCallbacks = null;
+
WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
}
}
}
+ transitionPageTarget()
+ {
+ this._documentUpdated();
+ }
+
// Public
get eventListenerBreakpoints()
return;
}
- if (this._pendingDocumentRequestCallbacks) {
+ if (this._pendingDocumentRequestCallbacks)
this._pendingDocumentRequestCallbacks.push(callback);
+ else
+ this._pendingDocumentRequestCallbacks = [callback];
+
+ if (this._hasRequestedDocument)
+ return;
+
+ if (!WI.pageTarget)
return;
- }
- this._pendingDocumentRequestCallbacks = [callback];
+ if (!WI.pageTarget.DOMAgent)
+ return;
- if (window.DOMAgent) {
- DOMAgent.getDocument((error, root) => {
- if (!error)
- this._setDocument(root);
+ this._hasRequestedDocument = true;
- for (let callback of this._pendingDocumentRequestCallbacks)
- callback(this._document);
+ WI.pageTarget.DOMAgent.getDocument((error, root) => {
+ if (!error)
+ this._setDocument(root);
- this._pendingDocumentRequestCallbacks = null;
- });
- }
+ for (let callback of this._pendingDocumentRequestCallbacks)
+ callback(this._document);
+
+ this._pendingDocumentRequestCallbacks = null;
+ });
}
ensureDocument()
return;
this._document = newDocument;
+
+ if (!this._document)
+ this._hasRequestedDocument = false;
+
this.dispatchEventToListeners(WI.DOMManager.Event.DocumentUpdated, {document: this._document});
}
this._webSocketIdentifierToURL = new Map;
this._waitingForMainFrameResourceTreePayload = true;
+ this._transitioningPageTarget = false;
this._sourceMapURLMap = new Map;
this._downloadingSourceMaps = new Set;
this.adoptOrphanedResourcesForTarget(target);
}
+ transitionPageTarget()
+ {
+ this._transitioningPageTarget = true;
+ this._waitingForMainFrameResourceTreePayload = true;
+ }
+
// Public
get mainFrame()
{
// Called from WI.RuntimeObserver.
- var frame = this.frameForIdentifier(contextPayload.frameId);
+ let frame = this.frameForIdentifier(contextPayload.frameId);
console.assert(frame);
if (!frame)
return;
- var displayName = contextPayload.name || frame.mainResource.displayName;
- var executionContext = new WI.ExecutionContext(WI.mainTarget, contextPayload.id, displayName, contextPayload.isPageContext, frame);
+ let displayName = contextPayload.name || frame.mainResource.displayName;
+ let target = frame.mainResource.target;
+ let executionContext = new WI.ExecutionContext(target, contextPayload.id, displayName, contextPayload.isPageContext, frame);
frame.addExecutionContext(executionContext);
}
if (this._mainFrame !== oldMainFrame)
this._mainFrameDidChange(oldMainFrame);
+
+ // Emulate a main resource change within this page even though we are swapping out main frames.
+ // This is because many managers listen only for main resource change events to perform work,
+ // but they don't listen for main frame changes.
+ if (this._transitioningPageTarget) {
+ this._transitioningPageTarget = false;
+ this._mainFrame._dispatchMainResourceDidChangeEvent(oldMainFrame.mainResource);
+ }
}
_createFrame(payload)
evaluateInInspectedWindow(expression, options, callback)
{
+ if (!this._activeExecutionContext) {
+ callback(null, false);
+ return;
+ }
+
let {objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, saveResult, sourceURLAppender} = options;
includeCommandLineAPI = includeCommandLineAPI || false;
/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
{
super();
- this._targets = new Set;
+ this._targets = new Map;
+ this._cachedTargetsList = null;
+ this._seenPageTarget = false;
+ this._transitionTimeoutIdentifier = undefined;
}
// Public
get targets()
{
- return this._targets;
+ if (!this._cachedTargetsList)
+ this._cachedTargetsList = Array.from(this._targets.values()).filter((target) => !(target instanceof WI.MultiplexingBackendTarget));
+ return this._cachedTargetsList;
+ }
+
+ get allTargets()
+ {
+ return Array.from(this._targets.values());
}
targetForIdentifier(targetId)
if (!targetId)
return null;
- if (targetId === WI.mainTarget.identifier)
- return WI.mainTarget;
-
- for (let target of this._targets) {
+ for (let target of this._targets.values()) {
if (target.identifier === targetId)
return target;
}
return null;
}
+ targetCreated(targetInfo)
+ {
+ // Called from WI.TargetObserver.
+
+ // FIXME: Eliminate this once the local inspector is configured to use
+ // the Multiplexing code path. Then we can perform this immediately
+ // in `WI.loaded` if a TargetAgent exists.
+ if (this._targets.size === 0)
+ this.createMultiplexingBackendTarget(targetInfo);
+
+ let connection = new InspectorBackend.TargetConnection(targetInfo.targetId);
+ let target = this._createTarget(targetInfo, connection);
+ this._checkAndHandlePageTargetTransition(target);
+ target.initialize();
+
+ this.addTarget(target);
+ }
+
+ targetDestroyed(targetId)
+ {
+ // Called from WI.TargetObserver.
+
+ let target = this._targets.get(targetId);
+ this._checkAndHandlePageTargetTermination(target);
+ this.removeTarget(target);
+ }
+
+ dispatchMessageFromTarget(targetId, message)
+ {
+ // Called from WI.TargetObserver.
+
+ let target = this._targets.get(targetId);
+ console.assert(target);
+ if (!target)
+ return;
+
+ target.connection.dispatch(message);
+ }
+
addTarget(target)
{
- this._targets.add(target);
+ console.assert(target);
+ console.assert(!this._targets.has(target.identifier));
+
+ this._cachedTargetsList = null;
+ this._targets.set(target.identifier, target);
this.dispatchEventToListeners(WI.TargetManager.Event.TargetAdded, {target});
}
removeTarget(target)
{
- this._targets.delete(target);
+ console.assert(target);
+ console.assert(target !== WI.mainTarget);
+
+ this._cachedTargetsList = null;
+ this._targets.delete(target.identifier);
this.dispatchEventToListeners(WI.TargetManager.Event.TargetRemoved, {target});
}
- initializeMainTarget()
+ createMultiplexingBackendTarget(targetInfo)
+ {
+ let target = new WI.MultiplexingBackendTarget;
+ target.initialize();
+
+ WI.initializeBackendTarget(target);
+
+ // Add the target without dispatching an event.
+ this._targets.set(target.identifier, target);
+ }
+
+ createDirectBackendTarget()
+ {
+ let target = new WI.DirectBackendTarget;
+ target.initialize();
+
+ WI.initializeBackendTarget(target);
+
+ if (WI.sharedApp.debuggableType === WI.DebuggableType.Web)
+ WI.initializePageTarget(target);
+
+ this.addTarget(target);
+ }
+
+ // Private
+
+ _createTarget(targetInfo, connection)
+ {
+ let {targetId, type} = targetInfo;
+
+ switch (type) {
+ case TargetAgent.TargetInfoType.JavaScript:
+ return new WI.JavaScriptContextTarget(targetId, WI.UIString("JavaScript Context"), connection);
+ case TargetAgent.TargetInfoType.Page:
+ return new WI.PageTarget(targetId, WI.UIString("Page"), connection);
+ case TargetAgent.TargetInfoType.Worker:
+ return new WI.WorkerTarget(targetId, WI.UIString("Worker"), connection);
+ case TargetAgent.TargetInfoType.ServiceWorker:
+ return new WI.WorkerTarget(targetId, WI.UIString("ServiceWorker"), connection);
+ }
+
+ throw "Unknown Target type: " + type;
+ }
+
+ _checkAndHandlePageTargetTransition(target)
+ {
+ if (target.type !== WI.Target.Type.Page)
+ return;
+
+ // First page target.
+ if (!WI.pageTarget && !this._seenPageTarget) {
+ this._seenPageTarget = true;
+ WI.initializePageTarget(target);
+ return;
+ }
+
+ // Transitioning page target.
+ WI.transitionPageTarget(target);
+ }
+
+ _checkAndHandlePageTargetTermination(target)
{
- console.assert(WI.mainTarget);
- this._targets.add(WI.mainTarget);
+ if (target.type !== WI.Target.Type.Page)
+ return;
+
+ console.assert(target === WI.pageTarget);
+ console.assert(this._seenPageTarget);
+
+ // Terminating the page target.
+ WI.terminatePageTarget(target);
+
+ // Ensure we transition in a reasonable amount of time, otherwise close.
+ const timeToTransition = 2000;
+ clearTimeout(this._transitionTimeoutIdentifier);
+ this._transitionTimeoutIdentifier = setTimeout(() => {
+ this._transitionTimeoutIdentifier = undefined;
+ if (WI.pageTarget)
+ return;
+ if (WI.isEngineeringBuild)
+ throw new Error("Error: No new pageTarget some time after last page target was terminated. Failed transition?");
+ WI.close();
+ }, timeToTransition);
}
};
workerCreated(workerId, url)
{
+ // Called from WI.WorkerObserver.
+
let connection = new InspectorBackend.WorkerConnection(workerId);
let workerTarget = new WI.WorkerTarget(workerId, url, connection);
workerTarget.initialize();
workerTerminated(workerId)
{
+ // Called from WI.WorkerObserver.
+
let connection = this._connections.take(workerId);
WI.targetManager.removeTarget(connection.target);
dispatchMessageFromWorker(workerId, message)
{
+ // Called from WI.WorkerObserver.
+
let connection = this._connections.get(workerId);
console.assert(connection);
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-// This function is invoked after the inspector has loaded.
+WI.isEngineeringBuild = true;
+
+// This function is invoked after the inspector has loaded and has a backend target.
WI.runBootstrapOperations = function() {
WI.showDebugUISetting = new WI.Setting("show-debug-ui", false);
<dd><a class="bypass-event-blocking" id="dismiss-error-sheet">Click to close this view</a> and return
to the Web Inspector without reloading. However, some things might not work without reloading if the error corrupted the Inspector's internal state.</dd>`;
+ // FIXME: Reload Web Inspector does not work with MultiplexingBackendTarget.
let sheetElement = window.__sheetElement = document.createElement("div");
sheetElement.classList.add("sheet-container");
sheetElement.innerHTML = `<div class="uncaught-exception-sheet">
<script src="Protocol/RemoteObject.js"></script>
<script src="Protocol/Target.js"></script>
- <script src="Protocol/MainTarget.js"></script>
+ <script src="Protocol/DirectBackendTarget.js"></script>
+ <script src="Protocol/MultiplexingBackendTarget.js"></script>
+ <script src="Protocol/JavaScriptContextTarget.js"></script>
+ <script src="Protocol/PageTarget.js"></script>
<script src="Protocol/WorkerTarget.js"></script>
<script src="Protocol/ApplicationCacheObserver.js"></script>
<script src="Protocol/PageObserver.js"></script>
<script src="Protocol/RuntimeObserver.js"></script>
<script src="Protocol/ScriptProfilerObserver.js"></script>
+ <script src="Protocol/TargetObserver.js"></script>
<script src="Protocol/TimelineObserver.js"></script>
<script src="Protocol/WorkerObserver.js"></script>
WI.consoleManager.addEventListener(WI.ConsoleManager.Event.MessageAdded, this._consoleMessageAdded, this);
WI.consoleManager.addEventListener(WI.ConsoleManager.Event.PreviousMessageRepeatCountUpdated, this._consoleMessageWasRepeated, this);
+ // FIXME: This is working around the order of events. Normal page navigation
+ // triggers a MainResource change and then a MainFrame change. Page Transition
+ // triggers a MainFrame change then a MainResource change.
+ this._transitioningPageTarget = false;
+
+ WI.notifications.addEventListener(WI.Notification.TransitionPageTarget, this._transitionPageTarget, this);
+
this._resourcesCount = 0;
this._resourcesSize = 0;
this._time = 0;
if (!event.target.isMainFrame())
return;
- this._time = 0;
- this._resourcesCount = 1;
- this._resourcesSize = WI.networkManager.mainFrame.mainResource.size || 0;
+ if (!this._transitioningPageTarget) {
+ this._time = 0;
+ this._resourcesCount = 1;
+ this._resourcesSize = WI.networkManager.mainFrame.mainResource.size || 0;
+ }
// We should only track resource sizes on fresh loads.
if (this._waitingForFirstMainResourceToStartTrackingSize) {
}
this._dataDidChange();
- this._startUpdatingTime();
+
+ if (!this._transitioningPageTarget)
+ this._startUpdatingTime();
+
+ if (this._transitioningPageTarget)
+ this._transitioningPageTarget = false;
}
_capturingStopped(event)
this._errors = 0;
this._dataDidChange();
}
+
+ _transitionPageTarget()
+ {
+ this._transitioningPageTarget = true;
+
+ this._time = 0;
+ this._resourcesCount = 0;
+ this._resourcesSize = 0;
+
+ this._dataDidChange();
+ }
};
WI.DefaultDashboard.Event = {
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+InspectorBackend.globalSequenceId = 1;
+
InspectorBackend.Connection = class InspectorBackendConnection
{
constructor()
{
- this._lastSequenceId = 1;
this._pendingResponses = new Map;
this._agents = {};
this._deferredScripts = [];
}
let sequenceId = messageObject["id"];
- console.assert(this._pendingResponses.has(sequenceId), sequenceId, this._pendingResponses);
+ console.assert(this._pendingResponses.has(sequenceId), sequenceId, this._target ? this._target.identifier : "(unknown)", this._pendingResponses);
let responseData = this._pendingResponses.take(sequenceId) || {};
let {request, command, callback, promise} = responseData;
_sendCommandToBackendWithCallback(command, parameters, callback)
{
- let sequenceId = this._lastSequenceId++;
+ let sequenceId = InspectorBackend.globalSequenceId++;
let messageObject = {
"id": sequenceId,
_sendCommandToBackendExpectingPromise(command, parameters)
{
- let sequenceId = this._lastSequenceId++;
+ let sequenceId = InspectorBackend.globalSequenceId++;
let messageObject = {
"id": sequenceId,
}
};
-InspectorBackend.MainConnection = class InspectorBackendMainConnection extends InspectorBackend.Connection
+InspectorBackend.BackendConnection = class InspectorBackendBackendConnection extends InspectorBackend.Connection
{
constructor()
{
this._workerId = workerId;
- // Clone agents that will use this connection.
- for (let domain in InspectorBackend._agents) {
- let agent = InspectorBackend._agents[domain];
- let clone = Object.create(InspectorBackend._agents[domain]);
+ for (let [domain, agent] of Object.entries(InspectorBackend._agents)) {
+ let clone = Object.create(agent);
clone.connection = this;
if (agent.dispatcher)
clone.dispatcher = new agent.dispatcher.constructor;
}
};
-InspectorBackend.mainConnection = new InspectorBackend.MainConnection;
+InspectorBackend.TargetConnection = class InspectorBackendTargetConnection extends InspectorBackend.Connection
+{
+ constructor(targetId)
+ {
+ super();
+
+ this._targetId = targetId;
+
+ for (let [domain, agent] of Object.entries(InspectorBackend._agents)) {
+ let clone = Object.create(agent);
+ clone.connection = this;
+ if (agent.dispatcher)
+ clone.dispatcher = new agent.dispatcher.constructor;
+ this._agents[domain] = clone;
+ }
+ }
+
+ sendMessageToBackend(message)
+ {
+ TargetAgent.sendMessageToTarget(this._targetId, message);
+ }
+};
+
+InspectorBackend.backendConnection = new InspectorBackend.BackendConnection;
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-WI.MainTarget = class MainTarget extends WI.Target
+// This class is used when connecting directly to a single target.
+// The main connection is a direct connection to a target.
+
+WI.DirectBackendTarget = class DirectBackendTarget extends WI.Target
{
- constructor(connection)
+ constructor()
{
- let {type, displayName} = MainTarget.mainConnectionInfo();
+ let {type, displayName} = DirectBackendTarget.connectionInfoForDebuggable();
- super("main", displayName, type, InspectorBackend.mainConnection);
+ super("direct", displayName, type, InspectorBackend.backendConnection);
- this._executionContext = new WI.ExecutionContext(this, WI.RuntimeManager.TopLevelExecutionContextIdentifier, displayName, true, null);
+ this._executionContext = new WI.ExecutionContext(this, WI.RuntimeManager.TopLevelContextExecutionIdentifier, displayName, true, null);
this._mainResource = null;
}
// Static
- static mainConnectionInfo()
+ static connectionInfoForDebuggable()
{
switch (WI.sharedApp.debuggableType) {
case WI.DebuggableType.JavaScript:
default:
console.error("Unexpected debuggable type: ", WI.sharedApp.debuggableType);
return {
- type: WI.Target.Type.Page,
- displayName: WI.UIString("Main"),
+ type: WI.Target.Type.JSContext,
+ displayName: WI.UIString("JavaScript Context"),
};
}
}
dispatch(message)
{
- InspectorBackend.mainConnection.dispatch(message);
+ InspectorBackend.backendConnection.dispatch(message);
}
runAfterPendingDispatches(script)
{
// FIXME: Should this respect pending dispatches in all connections?
- InspectorBackend.mainConnection.runAfterPendingDispatches(script);
+ InspectorBackend.backendConnection.runAfterPendingDispatches(script);
}
activateDomain(domainName, activationDebuggableTypes)
this._domainName = domainName;
// Default connection is the main connection.
- this._connection = InspectorBackend.mainConnection;
+ this._connection = InspectorBackend.backendConnection;
this._dispatcher = null;
// Agents are always created, but are only useable after they are activated.
--- /dev/null
+/*
+ * Copyright (C) 2018 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.
+ */
+
+WI.JavaScriptContextTarget = class JavaScriptContextTarget extends WI.Target
+{
+ constructor(targetId, name, connection)
+ {
+ super(targetId, name, WI.Target.Type.JSContext, connection);
+
+ const isPageContext = false;
+ this._executionContext = new WI.ExecutionContext(this, WI.RuntimeManager.TopLevelContextExecutionIdentifier, this.displayName, isPageContext, null);
+ }
+};
--- /dev/null
+/*
+ * Copyright (C) 2018 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.
+ */
+
+// This class is used when connecting to a target which multiplexes to other targets.
+// The main connection is to a target that, currently, has only a Target agent.
+// All other Targets will have their messages be multiplexed through this
+// main connection's Target agent.
+
+WI.MultiplexingBackendTarget = class MultiplexingBackendTarget extends WI.Target
+{
+ constructor()
+ {
+ const type = WI.Target.Type.Page;
+ const displayName = WI.UIString("Page");
+
+ super("multi", displayName, type, InspectorBackend.backendConnection);
+
+ let agents = this._agents;
+ this._agents = {
+ Target: agents.Target,
+ };
+ }
+
+ // Target
+
+ initialize()
+ {
+ // Intentionally do nothing, including not calling super.
+ // No agents other than the TargetAgent, nothing to initialize.
+ }
+
+ // Protected (Target)
+
+ get name()
+ {
+ console.error("Called name on a MultiplexingBackendTarget");
+ return WI.UIString("Page");
+ }
+
+ get executionContext()
+ {
+ console.error("Called executionContext on a MultiplexingBackendTarget");
+ return null;
+ }
+
+ get mainResource()
+ {
+ console.error("Called mainResource on a MultiplexingBackendTarget");
+ return null;
+ }
+};
--- /dev/null
+/*
+ * Copyright (C) 2018 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.
+ */
+
+WI.PageTarget = class PageTarget extends WI.Target
+{
+ constructor(targetId, name, connection)
+ {
+ super(targetId, name, WI.Target.Type.Page, connection);
+
+ const isPageContext = true;
+ this._executionContext = new WI.ExecutionContext(this, WI.RuntimeManager.TopLevelContextExecutionIdentifier, this.displayName, isPageContext, null);
+ }
+};
--- /dev/null
+/*
+ * Copyright (C) 2018 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.
+ */
+
+WI.TargetObserver = class TargetObserver
+{
+ // Events defined by the "Target" domain.
+
+ targetCreated(targetInfo)
+ {
+ WI.targetManager.targetCreated(targetInfo);
+ }
+
+ targetDestroyed(targetId)
+ {
+ WI.targetManager.targetDestroyed(targetId);
+ }
+
+ dispatchMessageFromTarget(targetId, message)
+ {
+ WI.targetManager.dispatchMessageFromTarget(targetId, message);
+ }
+};
{
super(workerId, name, WI.Target.Type.Worker, connection);
- this._executionContext = new WI.ExecutionContext(this, WI.RuntimeManager.TopLevelContextExecutionIdentifier, this.displayName, false, null);
+ const isPageContext = false;
+ this._executionContext = new WI.ExecutionContext(this, WI.RuntimeManager.TopLevelContextExecutionIdentifier, this.displayName, isPageContext, null);
}
// Protected (Target)
<script src="Protocol/MessageDispatcher.js"></script>
<script src="Protocol/Target.js"></script>
- <script src="Protocol/MainTarget.js"></script>
+ <script src="Protocol/DirectBackendTarget.js"></script>
+ <script src="Protocol/MultiplexingBackendTarget.js"></script>
<script src="Protocol/WorkerTarget.js"></script>
<script src="Protocol/InspectorObserver.js"></script>
<script src="Protocol/RemoteObject.js"></script>
<script src="Protocol/RuntimeObserver.js"></script>
<script src="Protocol/ScriptProfilerObserver.js"></script>
+ <script src="Protocol/TargetObserver.js"></script>
<script src="Protocol/TimelineObserver.js"></script>
<script src="Protocol/WorkerObserver.js"></script>
{
// Register observers for events from the InspectorBackend.
// The initialization order should match the same in Main.js.
+ InspectorBackend.registerTargetDispatcher(new WI.TargetObserver);
InspectorBackend.registerInspectorDispatcher(new WI.InspectorObserver);
InspectorBackend.registerPageDispatcher(new WI.PageObserver);
InspectorBackend.registerConsoleDispatcher(new WI.ConsoleObserver);
WI.settings.showShadowDOM.value = true;
// Targets.
- WI.mainTarget = new WI.MainTarget;
- WI.mainTarget.initialize();
- WI.pageTarget = WI.sharedApp.debuggableType === WI.DebuggableType.Web ? WI.mainTarget : null;
+ WI.backendTarget = null;
+ WI.pageTarget = null;
+
+ // Tests directly connect to a page target.
+ WI.targetManager.createDirectBackendTarget();
+};
+
+WI.initializeBackendTarget = function(target)
+{
+ WI.backendTarget = target;
+
+ WI.resetMainExecutionContext();
+};
+
+WI.initializePageTarget = function(target)
+{
+ WI.pageTarget = target;
+
+ WI.redirectGlobalAgentsToConnection(WI.pageTarget.connection);
+
+ WI.resetMainExecutionContext();
+};
+
+WI.transitionPageTarget = function(target)
+{
+ console.error("WI.transitionPageTarget should not be reached in tests.");
+};
+
+WI.terminatePageTarget = function(target)
+{
+ console.error("WI.terminatePageTarget should not be reached in tests.");
+};
+
+WI.resetMainExecutionContext = function()
+{
+ console.assert(WI.mainTarget.executionContext);
- // Post-target initialization.
- WI.targetManager.initializeMainTarget();
WI.runtimeManager.activeExecutionContext = WI.mainTarget.executionContext;
};
+WI.redirectGlobalAgentsToConnection = function(connection)
+{
+ // This makes global window.FooAgent dispatch to the active page target.
+ for (let [domain, agent] of Object.entries(InspectorBackend._agents)) {
+ if (domain !== "Target")
+ agent.connection = connection;
+ }
+};
+
WI.contentLoaded = function()
{
// Signal that the frontend is now ready to receive messages.
}
};
+Object.defineProperty(WI, "mainTarget",
+{
+ get() { return WI.pageTarget || WI.backendTarget; }
+});
+
Object.defineProperty(WI, "targets",
{
get() { return WI.targetManager.targets; }
this._callStackTreeOutline = this.createContentTreeOutline(suppressFiltering);
this._callStackTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
- this._mainTargetTreeElement = new WI.ThreadTreeElement(WI.mainTarget);
- this._callStackTreeOutline.appendChild(this._mainTargetTreeElement);
-
- this._updateCallStackTreeOutline();
-
this._callStackRow = new WI.DetailsSectionRow;
this._callStackRow.element.appendChild(this._callStackTreeOutline.element);
this._callStackGroup = new WI.DetailsSectionGroup([this._callStackRow]);
this._callStackSection = new WI.DetailsSection("call-stack", WI.UIString("Call Stack"), [this._callStackGroup]);
+ this._mainTargetTreeElement = null;
this._activeCallFrameTreeElement = null;
this._pauseReasonTreeOutline = null;
if (InspectorBackend.domains.Debugger.setPauseOnAssertions && WI.settings.showAssertionFailuresBreakpoint.value)
WI.debuggerManager.addBreakpoint(WI.debuggerManager.assertionFailuresBreakpoint);
+ for (let target of WI.targets)
+ this._addTarget(target);
+ this._updateCallStackTreeOutline();
+
if (WI.networkManager.mainFrame)
this._addResourcesRecursivelyForFrame(WI.networkManager.mainFrame);
- for (var script of WI.debuggerManager.knownNonResourceScripts)
+ for (let script of WI.debuggerManager.knownNonResourceScripts)
this._addScript(script);
if (WI.domDebuggerManager.supported) {
_targetAdded(event)
{
- let target = event.data.target;
+ this._addTarget(event.data.target);
+ }
+
+ _addTarget(target)
+ {
let treeElement = new WI.ThreadTreeElement(target);
this._callStackTreeOutline.appendChild(treeElement);
+ // FIXME: When WI.mainTarget changes?
+ if (target === WI.mainTarget)
+ this._mainTargetTreeElement = treeElement;
+
this._updateCallStackTreeOutline();
}
_updateCallStackTreeOutline()
{
- let singleThreadShowing = WI.targets.size === 1;
+ let singleThreadShowing = WI.targets.length <= 1;
this._callStackTreeOutline.element.classList.toggle("single-thread", singleThreadShowing);
- this._mainTargetTreeElement.selectable = !singleThreadShowing;
+ if (this._mainTargetTreeElement)
+ this._mainTargetTreeElement.selectable = !singleThreadShowing;
}
_handleDebuggerObjectDisplayLocationDidChange(event)
WI.networkManager.addEventListener(WI.NetworkManager.Event.MainFrameDidChange, this._mainFrameDidChange, this);
this._needsInitialPopulate = true;
+
+ // FIXME: This is working around the order of events. Normal page navigation
+ // triggers a MainResource change and then a MainFrame change. Page Transition
+ // triggers a MainFrame change then a MainResource change.
+ this._transitioningPageTarget = false;
+
+ WI.notifications.addEventListener(WI.Notification.TransitionPageTarget, this._transitionPageTarget, this);
}
// Static
this.reset();
+ if (this._transitioningPageTarget) {
+ this._transitioningPageTarget = false;
+ this._needsInitialPopulate = true;
+ this._populateWithInitialResourcesIfNeeded();
+ return;
+ }
+
this._insertResourceAndReloadTable(frame.mainResource);
}
{
this._table.reloadVisibleColumnCells(this._waterfallColumn);
}
+
+ _transitionPageTarget(event)
+ {
+ this._transitioningPageTarget = true;
+ }
};
this._toggleOrFocusKeyboardShortcut = new WI.KeyboardShortcut(null, WI.KeyboardShortcut.Key.Escape, this._toggleOrFocus.bind(this));
this._toggleOrFocusKeyboardShortcut.implicitlyPreventsDefault = false;
- this._mainExecutionContextPathComponent = this._createExecutionContextPathComponent(WI.mainTarget.executionContext);
+ this._mainExecutionContextPathComponent = null;
+ this.initializeMainExecutionContextPathComponent();
this._otherExecutionContextPathComponents = [];
this._frameToPathComponent = new Map;
super.closed();
}
+ initializeMainExecutionContextPathComponent()
+ {
+ if (!WI.mainTarget || !WI.mainTarget.executionContext)
+ return;
+
+ this._mainExecutionContextPathComponent = this._createExecutionContextPathComponent(WI.mainTarget.executionContext);
+ }
+
// Protected
layout()
_targetAdded(event)
{
let target = event.data.target;
+ if (target.type !== WI.Target.Type.Worker)
+ return;
+
console.assert(target.type === WI.Target.Type.Worker);
let preferredName = WI.UIString("Worker \u2014 %s").format(target.displayName);
let executionContextPathComponent = this._createExecutionContextPathComponent(target.executionContext, preferredName);
_targetRemoved(event)
{
let target = event.data.target;
+ if (target.type !== WI.Target.Type.Worker)
+ return;
+
let executionContextPathComponent = this._targetToPathComponent.take(target);
this._removeOtherExecutionContextPathComponent(executionContextPathComponent);
experimentalSettingsView.addSetting(WI.UIString("User Interface:"), WI.settings.experimentalEnableNewTabBar, WI.UIString("Enable New Tab Bar"));
experimentalSettingsView.addSeparator();
+ // FIXME: Reload Web Inspector does not work with MultiplexingBackendTarget.
let reloadInspectorButton = document.createElement("button");
reloadInspectorButton.textContent = WI.UIString("Reload Web Inspector");
reloadInspectorButton.addEventListener("click", () => { window.location.reload(); });
_targetAdded(event)
{
- if (WI.targets.size === 2)
+ if (WI.targets.length === 2)
this._reinsertAllThreadIndicators();
}
_targetRemoved(event)
{
- if (WI.targets.size === 1) {
+ if (WI.targets.length === 1) {
// Back to one thread, remove thread indicators.
this._reinsertAllThreadIndicators();
return;
_callFramesDidChange(event)
{
- if (WI.targets.size === 1)
+ if (WI.targets.length === 1)
return;
let target = event.data.target;
if (!widget)
return;
- console.assert(WI.targets.size > 1);
+ console.assert(WI.targets.length > 1);
let widgetElement = widget.widgetElement;
widgetElement.removeChildren();
// Clear other maps.
this._threadTargetMap.clear();
- if (WI.targets.size > 1) {
- for (let target of WI.targets)
+ let debuggableTargets = WI.targets;
+ if (debuggableTargets.length > 1) {
+ for (let target of debuggableTargets)
this._addThreadIndicatorForTarget(target);
}
}
+2018-11-14 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Keep Web Inspector window alive across process swaps (PSON) (Remote Inspector)
+ https://bugs.webkit.org/show_bug.cgi?id=191494
+ <rdar://problem/45469854>
+
+ Reviewed by Devin Rousso.
+
+ To support process swapping a slim Web Inspector backend lives in the UIProcess.
+ The Web Inspector frontend connects to it and is told about sub-targets, namely
+ pages, that it can further connect to. When performing a process swap the backend
+ tells the frontend to destroy existing targets and create new targets.
+
+ In the UIProcess the WebPageProxy has a WebPageInspectorController, with a single
+ TargetAgent holding InspectorTargetProxies to targets it knows about. Inspector
+ protocol messages go through this inspector controller and are routed to the
+ WebPage and its WebCore::Page's InspectorController. The WebPageProxy decides
+ when to close and expose new page targets during process swap, or basically
+ any time it reconnects to a WebProcess. So this patch also makes Web Inspector
+ stay alive and reconnect to a page when the inspected page crashes!
+
+ In the WebContentProcess the WebPage has a WebPageInspectorTarget. It also
+ has a WebPageInspectorTargetController in anticipation of further sub-targets
+ within the page (workers, frames) but none exist at the moment. The WebPage
+ relies on the WebPageProxy to know when to expose this target as a debuggable.
+
+ * Sources.txt:
+ * WebKit.xcodeproj/project.pbxproj:
+ New files.
+
+ * Shared/WebPageCreationParameters.cpp:
+ (WebKit::WebPageCreationParameters::encode const):
+ (WebKit::WebPageCreationParameters::decode):
+ * Shared/WebPageCreationParameters.h:
+ Remote inspector state can now stay in the UIProcess and does not need to
+ be passed down to the WebContentProcess.
+
+ * UIProcess/WebPageDebuggable.cpp: Copied from Source/WebCore/page/PageDebuggable.cpp.
+ (WebKit::WebPageDebuggable::WebPageDebuggable):
+ (WebKit::WebPageDebuggable::name const):
+ (WebKit::WebPageDebuggable::url const):
+ (WebKit::WebPageDebuggable::hasLocalDebugger const):
+ (WebKit::WebPageDebuggable::connect):
+ (WebKit::WebPageDebuggable::disconnect):
+ (WebKit::WebPageDebuggable::dispatchMessageFromRemote):
+ (WebKit::WebPageDebuggable::setIndicating):
+ (WebKit::WebPageDebuggable::setNameOverride):
+ * UIProcess/WebPageDebuggable.h: Copied from Source/WebCore/page/PageDebuggable.h.
+ Remote debuggable entry point into the UIProcess for a page.
+ This is pretty much identical to the PageDebuggable in WebCore.
+
+ * Scripts/webkit/messages.py:
+ * UIProcess/WebPageProxy.messages.in:
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::m_resetRecentCrashCountTimer):
+ (WebKit::WebPageProxy::finishAttachingToWebProcess):
+ (WebKit::WebPageProxy::close):
+ (WebKit::WebPageProxy::createInspectorTarget):
+ (WebKit::WebPageProxy::destroyInspectorTarget):
+ (WebKit::WebPageProxy::sendMessageToInspectorFrontend):
+ (WebKit::WebPageProxy::setIndicating):
+ (WebKit::WebPageProxy::allowsRemoteInspection const):
+ (WebKit::WebPageProxy::setAllowsRemoteInspection):
+ (WebKit::WebPageProxy::remoteInspectionNameOverride const):
+ (WebKit::WebPageProxy::setRemoteInspectionNameOverride):
+ (WebKit::WebPageProxy::remoteInspectorInformationDidChange):
+ (WebKit::WebPageProxy::clearInspectorTargets):
+ (WebKit::WebPageProxy::createInspectorTargets):
+ (WebKit::WebPageProxy::didCommitLoadForFrame):
+ (WebKit::WebPageProxy::didReceiveTitleForFrame):
+ (WebKit::WebPageProxy::creationParameters):
+ * UIProcess/WebPageProxy.h:
+ (WebKit::WebPageProxy::inspectorController):
+ (WebKit::WebPageProxy::allowsRemoteInspection const): Deleted.
+ (WebKit::WebPageProxy::remoteInspectionNameOverride const): Deleted.
+ Own more inspector state in the UIProcess including a debuggable and inspector controller.
+
+ * UIProcess/WebPageInspectorController.h: Added.
+ * UIProcess/WebPageInspectorController.cpp: Added.
+ (WebKit::WebPageInspectorController::WebPageInspectorController):
+ (WebKit::WebPageInspectorController::pageClosed):
+ (WebKit::WebPageInspectorController::hasLocalFrontend const):
+ (WebKit::WebPageInspectorController::hasRemoteFrontend const):
+ (WebKit::WebPageInspectorController::connectFrontend):
+ (WebKit::WebPageInspectorController::disconnectFrontend):
+ (WebKit::WebPageInspectorController::disconnectAllFrontends):
+ (WebKit::WebPageInspectorController::dispatchMessageFromFrontend):
+ (WebKit::WebPageInspectorController::setIndicating):
+ (WebKit::WebPageInspectorController::clearTargets):
+ (WebKit::WebPageInspectorController::createInspectorTarget):
+ (WebKit::WebPageInspectorController::destroyInspectorTarget):
+ (WebKit::WebPageInspectorController::sendMessageToInspectorFrontend):
+ InspectorController with a single TargetAgent in the UIProcess.
+
+ * UIProcess/WebPageInspectorTargetAgent.h:
+ * UIProcess/WebPageInspectorTargetAgent.cpp:
+ (WebKit::WebPageInspectorTargetAgent::WebPageInspectorTargetAgent):
+ (WebKit::WebPageInspectorTargetAgent::frontendChannel):
+ Target agent implementation.
+
+ * UIProcess/InspectorTargetProxy.cpp:
+ (WebKit::InspectorTargetProxy::create):
+ (WebKit::InspectorTargetProxy::InspectorTargetProxy):
+ (WebKit::InspectorTargetProxy::connect):
+ (WebKit::InspectorTargetProxy::disconnect):
+ (WebKit::InspectorTargetProxy::sendMessageToTargetBackend):
+ * UIProcess/InspectorTargetProxy.h:
+ UIProcess proxy for an InspectorTarget in the WebContentProcess.
+
+ * UIProcess/WebProcessPool.cpp:
+ (WebKit::WebProcessPool::processForNavigationInternal):
+
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::m_shouldAttachDrawingAreaOnPageTransition):
+ (WebKit::WebPage::connectInspector):
+ (WebKit::WebPage::disconnectInspector):
+ (WebKit::WebPage::sendMessageToTargetBackend):
+ (WebKit::WebPage::setIndicating):
+ (WebKit::WebPage::setAllowsRemoteInspection): Deleted.
+ (WebKit::WebPage::setRemoteInspectionNameOverride): Deleted.
+ * WebProcess/WebPage/WebPage.h:
+ * WebProcess/WebPage/WebPage.messages.in:
+
+ * WebProcess/WebPage/WebPageInspectorTarget.h:
+ * WebProcess/WebPage/WebPageInspectorTarget.cpp:
+ (WebKit::WebPageInspectorTarget::WebPageInspectorTarget):
+ (WebKit::WebPageInspectorTarget::identifier const):
+ (WebKit::WebPageInspectorTarget::connect):
+ (WebKit::WebPageInspectorTarget::disconnect):
+ (WebKit::WebPageInspectorTarget::sendMessageToTargetBackend):
+ InspectorTarget for this WebPage.
+
+ * WebProcess/WebPage/WebPageInspectorTargetController.cpp: Added.
+ (WebKit::WebPageInspectorTargetController::WebPageInspectorTargetController):
+ (WebKit::WebPageInspectorTargetController::~WebPageInspectorTargetController):
+ (WebKit::WebPageInspectorTargetController::addTarget):
+ (WebKit::WebPageInspectorTargetController::removeTarget):
+ (WebKit::WebPageInspectorTargetController::connectInspector):
+ (WebKit::WebPageInspectorTargetController::disconnectInspector):
+ (WebKit::WebPageInspectorTargetController::sendMessageToTargetBackend):
+ (WebKit::WebPageInspectorTargetController::sendMessageToTargetFrontend):
+ * WebProcess/WebPage/WebPageInspectorTargetController.h:
+ * WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.h:
+ * WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.cpp:
+ (WebKit::WebPageInspectorTargetFrontendChannel::create):
+ (WebKit::WebPageInspectorTargetFrontendChannel::WebPageInspectorTargetFrontendChannel):
+ (WebKit::WebPageInspectorTargetFrontendChannel::sendMessageToFrontend):
+ Preparation for more target managment in the WebContentProcess.
+
2018-11-14 Alex Christensen <achristensen@webkit.org>
Add SPI to show a safe browsing warning
'MachSendRight': ['<wtf/MachSendRight.h>'],
'JSC::MessageLevel': ['<JavaScriptCore/ConsoleTypes.h>'],
'JSC::MessageSource': ['<JavaScriptCore/ConsoleTypes.h>'],
+ 'Inspector::InspectorTargetType': ['<JavaScriptCore/InspectorTarget.h>'],
'MonotonicTime': ['<wtf/MonotonicTime.h>'],
'Seconds': ['<wtf/Seconds.h>'],
'WallTime': ['<wtf/WallTime.h>'],
encoder << mimeTypesWithCustomContentProviders;
encoder << controlledByAutomation;
-#if ENABLE(REMOTE_INSPECTOR)
- encoder << allowsRemoteInspection;
- encoder << remoteInspectionNameOverride;
-#endif
#if PLATFORM(MAC)
encoder << colorSpace;
encoder << useSystemAppearance;
if (!decoder.decode(parameters.controlledByAutomation))
return std::nullopt;
-#if ENABLE(REMOTE_INSPECTOR)
- if (!decoder.decode(parameters.allowsRemoteInspection))
- return std::nullopt;
- if (!decoder.decode(parameters.remoteInspectionNameOverride))
- return std::nullopt;
-#endif
-
#if PLATFORM(MAC)
if (!decoder.decode(parameters.colorSpace))
return std::nullopt;
bool controlledByAutomation;
-#if ENABLE(REMOTE_INSPECTOR)
- bool allowsRemoteInspection;
- String remoteInspectionNameOverride;
-#endif
-
#if PLATFORM(MAC)
ColorSpaceData colorSpace;
bool useSystemAppearance;
UIProcess/FrameLoadState.cpp
UIProcess/GeolocationPermissionRequestManagerProxy.cpp
UIProcess/GeolocationPermissionRequestProxy.cpp
+UIProcess/InspectorTargetProxy.cpp
UIProcess/PageLoadState.cpp
UIProcess/DeviceIdHashSaltStorage.cpp
UIProcess/ProcessAssertion.cpp
UIProcess/WebInspectorUtilities.cpp
UIProcess/WebNavigationState.cpp
UIProcess/WebOpenPanelResultListenerProxy.cpp
+UIProcess/WebPageDebuggable.cpp
UIProcess/WebPageDiagnosticLoggingClient.cpp
UIProcess/WebPageGroup.cpp
UIProcess/WebPageInjectedBundleClient.cpp
+UIProcess/WebPageInspectorController.cpp
+UIProcess/WebPageInspectorTargetAgent.cpp
UIProcess/WebPageProxy.cpp
UIProcess/WebPasteboardProxy.cpp
UIProcess/WebPreferences.cpp
WebProcess/WebPage/WebOpenPanelResultListener.cpp
WebProcess/WebPage/WebPage.cpp @no-unify
WebProcess/WebPage/WebPageGroupProxy.cpp
+WebProcess/WebPage/WebPageInspectorTarget.cpp
+WebProcess/WebPage/WebPageInspectorTargetController.cpp
+WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.cpp
WebProcess/WebPage/WebPageOverlay.cpp
WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp
WebProcess/WebPage/WebURLSchemeTaskProxy.cpp
--- /dev/null
+/*
+ * Copyright (C) 2018 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 "InspectorTargetProxy.h"
+
+#include "WebFrameProxy.h"
+#include "WebPageMessages.h"
+#include "WebPageProxy.h"
+
+namespace WebKit {
+
+using namespace Inspector;
+
+Ref<InspectorTargetProxy> InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type)
+{
+ return adoptRef(*new InspectorTargetProxy(page, targetId, type));
+}
+
+InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type)
+ : m_page(page)
+ , m_identifier(targetId)
+ , m_type(type)
+{
+}
+
+void InspectorTargetProxy::connect(Inspector::FrontendChannel&)
+{
+ if (m_page.isValid())
+ m_page.process().send(Messages::WebPage::ConnectInspector(identifier()), m_page.pageID());
+}
+
+void InspectorTargetProxy::disconnect(Inspector::FrontendChannel&)
+{
+ if (m_page.isValid())
+ m_page.process().send(Messages::WebPage::DisconnectInspector(identifier()), m_page.pageID());
+}
+
+void InspectorTargetProxy::sendMessageToTargetBackend(const String& message)
+{
+ if (m_page.isValid())
+ m_page.process().send(Messages::WebPage::SendMessageToTargetBackend(identifier(), message), m_page.pageID());
+}
+
+} // namespace WebKit
--- /dev/null
+/*
+ * Copyright (C) 2018 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
+
+#include <JavaScriptCore/InspectorTarget.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebKit {
+
+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, public RefCounted<InspectorTargetProxy> {
+ WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_NONCOPYABLE(InspectorTargetProxy);
+public:
+ static Ref<InspectorTargetProxy> create(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
+ InspectorTargetProxy(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
+ ~InspectorTargetProxy() = default;
+
+ Inspector::InspectorTargetType type() const final { return m_type; }
+ String identifier() const final { return m_identifier; }
+
+ void connect(Inspector::FrontendChannel&);
+ void disconnect(Inspector::FrontendChannel&);
+ void sendMessageToTargetBackend(const String&);
+
+private:
+ WebPageProxy& m_page;
+ String m_identifier;
+ Inspector::InspectorTargetType m_type;
+};
+
+} // namespace WebKit
--- /dev/null
+/*
+ * Copyright (C) 2018 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 "WebPageDebuggable.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "WebFrameProxy.h"
+#include "WebPageInspectorController.h"
+#include "WebPageProxy.h"
+
+namespace WebKit {
+
+using namespace Inspector;
+
+WebPageDebuggable::WebPageDebuggable(WebPageProxy& page)
+ : m_page(page)
+{
+}
+
+String WebPageDebuggable::name() const
+{
+ if (!m_nameOverride.isNull())
+ return m_nameOverride;
+
+ if (!m_page.mainFrame())
+ return String();
+
+ return m_page.mainFrame()->title();
+}
+
+String WebPageDebuggable::url() const
+{
+ if (!m_page.mainFrame())
+ return String();
+
+ String url = m_page.mainFrame()->url().string();
+ return url.isEmpty() ? "about:blank"_s : url;
+}
+
+bool WebPageDebuggable::hasLocalDebugger() const
+{
+ return m_page.inspectorController().hasLocalFrontend();
+}
+
+void WebPageDebuggable::connect(Inspector::FrontendChannel* channel, bool isAutomaticConnection, bool immediatelyPause)
+{
+ m_page.inspectorController().connectFrontend(channel, isAutomaticConnection, immediatelyPause);
+}
+
+void WebPageDebuggable::disconnect(Inspector::FrontendChannel* channel)
+{
+ m_page.inspectorController().disconnectFrontend(channel);
+}
+
+void WebPageDebuggable::dispatchMessageFromRemote(const String& message)
+{
+ m_page.inspectorController().dispatchMessageFromFrontend(message);
+}
+
+void WebPageDebuggable::setIndicating(bool indicating)
+{
+ m_page.inspectorController().setIndicating(indicating);
+}
+
+void WebPageDebuggable::setNameOverride(const String& name)
+{
+ m_nameOverride = name;
+ update();
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(REMOTE_INSPECTOR)
--- /dev/null
+/*
+ * Copyright (C) 2018 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 <JavaScriptCore/RemoteInspectionTarget.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class WebPageDebuggable final : public Inspector::RemoteInspectionTarget {
+ WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_NONCOPYABLE(WebPageDebuggable);
+public:
+ WebPageDebuggable(WebPageProxy&);
+ ~WebPageDebuggable() = default;
+
+ Inspector::RemoteControllableTarget::Type type() const final { return Inspector::RemoteControllableTarget::Type::Web; }
+
+ String name() const final;
+ String url() const final;
+ bool hasLocalDebugger() const final;
+
+ void connect(Inspector::FrontendChannel*, bool isAutomaticConnection = false, bool immediatelyPause = false) final;
+ void disconnect(Inspector::FrontendChannel*) final;
+ void dispatchMessageFromRemote(const String& message) final;
+ void setIndicating(bool) final;
+
+ const String& nameOverride() const { return m_nameOverride; }
+ void setNameOverride(const String&);
+
+private:
+ WebPageProxy& m_page;
+ String m_nameOverride;
+};
+
+} // namespace WebKit
+
+SPECIALIZE_TYPE_TRAITS_CONTROLLABLE_TARGET(WebKit::WebPageDebuggable, Web);
+
+#endif // ENABLE(REMOTE_INSPECTOR)
--- /dev/null
+/*
+ * Copyright (C) 2018 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 "WebPageInspectorController.h"
+
+#include "WebFrameProxy.h"
+#include "WebPageInspectorTargetAgent.h"
+#include "WebPageProxy.h"
+#include <JavaScriptCore/InspectorAgentBase.h>
+#include <JavaScriptCore/InspectorBackendDispatcher.h>
+#include <JavaScriptCore/InspectorBackendDispatchers.h>
+#include <JavaScriptCore/InspectorFrontendRouter.h>
+
+namespace WebKit {
+
+using namespace Inspector;
+
+WebPageInspectorController::WebPageInspectorController(WebPageProxy& page)
+ : m_page(page)
+ , m_frontendRouter(FrontendRouter::create())
+ , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
+{
+ auto targetAgent = std::make_unique<WebPageInspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
+
+ m_targetAgent = targetAgent.get();
+
+ m_agents.append(WTFMove(targetAgent));
+}
+
+void WebPageInspectorController::pageClosed()
+{
+ disconnectAllFrontends();
+
+ m_agents.discardValues();
+}
+
+bool WebPageInspectorController::hasLocalFrontend() const
+{
+ return m_frontendRouter->hasLocalFrontend();
+}
+
+void WebPageInspectorController::connectFrontend(Inspector::FrontendChannel* frontendChannel, bool, bool)
+{
+ ASSERT_ARG(frontendChannel, frontendChannel);
+
+ bool connectingFirstFrontend = !m_frontendRouter->hasFrontends();
+
+ m_frontendRouter->connectFrontend(frontendChannel);
+
+ if (connectingFirstFrontend)
+ m_agents.didCreateFrontendAndBackend(&m_frontendRouter.get(), &m_backendDispatcher.get());
+
+ m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
+
+#if ENABLE(REMOTE_INSPECTOR)
+ if (hasLocalFrontend())
+ m_page.remoteInspectorInformationDidChange();
+#endif
+}
+
+void WebPageInspectorController::disconnectFrontend(FrontendChannel* frontendChannel)
+{
+ m_frontendRouter->disconnectFrontend(frontendChannel);
+
+ bool disconnectingLastFrontend = !m_frontendRouter->hasFrontends();
+ if (disconnectingLastFrontend)
+ m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectorDestroyed);
+
+ m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
+
+#if ENABLE(REMOTE_INSPECTOR)
+ if (disconnectingLastFrontend)
+ m_page.remoteInspectorInformationDidChange();
+#endif
+}
+
+void WebPageInspectorController::disconnectAllFrontends()
+{
+ // FIXME: Handle a local inspector client.
+
+ if (!m_frontendRouter->hasFrontends())
+ return;
+
+ // Notify agents first, since they may need to use InspectorClient.
+ m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectedTargetDestroyed);
+
+ // Disconnect any remaining remote frontends.
+ m_frontendRouter->disconnectAllFrontends();
+
+ m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
+
+#if ENABLE(REMOTE_INSPECTOR)
+ m_page.remoteInspectorInformationDidChange();
+#endif
+}
+
+void WebPageInspectorController::dispatchMessageFromFrontend(const String& message)
+{
+ m_backendDispatcher->dispatch(message);
+}
+
+#if ENABLE(REMOTE_INSPECTOR)
+void WebPageInspectorController::setIndicating(bool indicating)
+{
+#if !PLATFORM(IOS_FAMILY)
+ m_page.setIndicating(indicating);
+#else
+ if (indicating)
+ m_page.showInspectorIndication();
+ else
+ m_page.hideInspectorIndication();
+#endif
+}
+#endif
+
+void WebPageInspectorController::clearTargets()
+{
+ for (auto& target : m_targets)
+ m_targetAgent->targetDestroyed(*target.get());
+
+ m_targets.clear();
+}
+
+void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
+{
+ auto target = InspectorTargetProxy::create(m_page, targetId, type);
+ m_targets.append(target.copyRef());
+
+ m_targetAgent->targetCreated(target.get());
+}
+
+void WebPageInspectorController::destroyInspectorTarget(const String& targetId)
+{
+ auto position = m_targets.findMatching([&](const auto& item) { return item->identifier() == targetId; });
+ if (position == notFound)
+ return;
+
+ auto& target = m_targets[position];
+ m_targetAgent->targetDestroyed(*target.get());
+
+ m_targets.remove(position);
+}
+
+void WebPageInspectorController::sendMessageToInspectorFrontend(const String& targetId, const String& message)
+{
+ m_targetAgent->sendMessageFromTargetToFrontend(targetId, message);
+}
+
+} // namespace WebKit
--- /dev/null
+/*
+ * Copyright (C) 2018 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
+
+#include "InspectorTargetProxy.h"
+#include <JavaScriptCore/InspectorAgentRegistry.h>
+#include <JavaScriptCore/InspectorTargetAgent.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/text/WTFString.h>
+
+namespace Inspector {
+class BackendDispatcher;
+class FrontendChannel;
+class FrontendRouter;
+}
+
+namespace WebKit {
+
+class WebPageInspectorController {
+ WTF_MAKE_NONCOPYABLE(WebPageInspectorController);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ WebPageInspectorController(WebPageProxy&);
+
+ void pageClosed();
+
+ bool hasLocalFrontend() const;
+
+ void connectFrontend(Inspector::FrontendChannel*, bool isAutomaticInspection = false, bool immediatelyPause = false);
+ void disconnectFrontend(Inspector::FrontendChannel*);
+ void disconnectAllFrontends();
+
+ void dispatchMessageFromFrontend(const String& message);
+
+#if ENABLE(REMOTE_INSPECTOR)
+ void setIndicating(bool);
+#endif
+
+ void clearTargets();
+ void createInspectorTarget(const String& targetId, Inspector::InspectorTargetType);
+ void destroyInspectorTarget(const String& targetId);
+ void sendMessageToInspectorFrontend(const String& targetId, const String& message);
+
+private:
+ WebPageProxy& m_page;
+ Ref<Inspector::FrontendRouter> m_frontendRouter;
+ Ref<Inspector::BackendDispatcher> m_backendDispatcher;
+ Inspector::AgentRegistry m_agents;
+ Inspector::InspectorTargetAgent* m_targetAgent;
+ Vector<RefPtr<InspectorTargetProxy>> m_targets;
+};
+
+} // namespace WebKit
--- /dev/null
+/*
+ * Copyright (C) 2018 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 "WebPageInspectorTargetAgent.h"
+
+namespace WebKit {
+
+class StubFrontendChannel final : public Inspector::FrontendChannel {
+ ConnectionType connectionType() const final { return Inspector::FrontendChannel::ConnectionType::Remote; }
+ void sendMessageToFrontend(const String&) final { }
+};
+
+WebPageInspectorTargetAgent::WebPageInspectorTargetAgent(Inspector::FrontendRouter& frontendRouter, Inspector::BackendDispatcher& backendDispatcher)
+ : Inspector::InspectorTargetAgent(frontendRouter, backendDispatcher)
+{
+}
+
+Inspector::FrontendChannel& WebPageInspectorTargetAgent::frontendChannel()
+{
+ if (!m_frontendChannel)
+ m_frontendChannel = std::make_unique<StubFrontendChannel>();
+ return *m_frontendChannel.get();
+}
+
+} // namespace WebKit
--- /dev/null
+/*
+ * Copyright (C) 2018 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
+
+#include <JavaScriptCore/InspectorTargetAgent.h>
+
+namespace WebKit {
+
+class WebPageInspectorTargetAgent final : public Inspector::InspectorTargetAgent {
+public:
+ WebPageInspectorTargetAgent(Inspector::FrontendRouter&, Inspector::BackendDispatcher&);
+ virtual ~WebPageInspectorTargetAgent() = default;
+
+private:
+ Inspector::FrontendChannel& frontendChannel() final;
+
+ std::unique_ptr<Inspector::FrontendChannel> m_frontendChannel;
+};
+
+} // namespace WebKit
#include "WebNotificationManagerProxy.h"
#include "WebOpenPanelResultListenerProxy.h"
#include "WebPageCreationParameters.h"
+#include "WebPageDebuggable.h"
#include "WebPageGroup.h"
#include "WebPageGroupData.h"
+#include "WebPageInspectorController.h"
#include "WebPageMessages.h"
#include "WebPageProxyMessages.h"
#include "WebPaymentCoordinatorProxy.h"
#include "WebResourceLoadStatisticsStore.h"
#endif
+#if ENABLE(REMOTE_INSPECTOR)
+#include <JavaScriptCore/RemoteInspector.h>
+#endif
+
#if HAVE(SEC_KEY_PROXY)
#include "SecKeyProxyStore.h"
#endif
#endif
, m_pageLoadState(*this)
, m_configurationPreferenceValues(m_configuration->preferenceValues())
+ , m_inspectorController(std::make_unique<WebPageInspectorController>(*this))
+#if ENABLE(REMOTE_INSPECTOR)
+ , m_inspectorDebuggable(std::make_unique<WebPageDebuggable>(*this))
+#endif
, m_resetRecentCrashCountTimer(RunLoop::main(), this, &WebPageProxy::resetRecentCrashCount)
{
m_webProcessLifetimeTracker.addObserver(m_visitedLinkStore);
this->dispatchActivityStateChange();
});
#endif
+
+#if ENABLE(REMOTE_INSPECTOR)
+ m_inspectorDebuggable->setRemoteDebuggingAllowed(true);
+ m_inspectorDebuggable->init();
+#endif
+
+ createInspectorTargets();
}
WebPageProxy::~WebPageProxy()
initializeWebPage(shouldDelayAttachingDrawingArea);
+#if ENABLE(REMOTE_INSPECTOR)
+ remoteInspectorInformationDidChange();
+#endif
+
+ clearInspectorTargets();
+ createInspectorTargets();
+
pageClient().didRelaunchProcess();
m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
}
#endif
m_backForwardList->pageClosed();
+ m_inspectorController->pageClosed();
pageClient().pageClosed();
m_process->disconnectFramesFromPage(this);
m_process->processPool().sendToNetworkingProcess(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation));
}
+void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
+{
+ m_inspectorController->createInspectorTarget(targetId, type);
+}
+
+void WebPageProxy::destroyInspectorTarget(const String& targetId)
+{
+ m_inspectorController->destroyInspectorTarget(targetId);
+}
+
+void WebPageProxy::sendMessageToInspectorFrontend(const String& targetId, const String& message)
+{
+ m_inspectorController->sendMessageToInspectorFrontend(targetId, message);
+}
+
#if ENABLE(REMOTE_INSPECTOR)
-void WebPageProxy::setAllowsRemoteInspection(bool allow)
+void WebPageProxy::setIndicating(bool indicating)
{
- if (m_allowsRemoteInspection == allow)
+ if (!isValid())
return;
- m_allowsRemoteInspection = allow;
+ m_process->send(Messages::WebPage::SetIndicating(indicating), m_pageID);
+}
- if (isValid())
- m_process->send(Messages::WebPage::SetAllowsRemoteInspection(allow), m_pageID);
+bool WebPageProxy::allowsRemoteInspection() const
+{
+ return m_inspectorDebuggable->remoteDebuggingAllowed();
}
-void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
+void WebPageProxy::setAllowsRemoteInspection(bool allow)
{
- if (m_remoteInspectionNameOverride == name)
- return;
+ m_inspectorDebuggable->setRemoteDebuggingAllowed(allow);
+}
- m_remoteInspectionNameOverride = name;
+String WebPageProxy::remoteInspectionNameOverride() const
+{
+ return m_inspectorDebuggable->nameOverride();
+}
- if (isValid())
- m_process->send(Messages::WebPage::SetRemoteInspectionNameOverride(m_remoteInspectionNameOverride), m_pageID);
+void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
+{
+ m_inspectorDebuggable->setNameOverride(name);
}
+void WebPageProxy::remoteInspectorInformationDidChange()
+{
+ m_inspectorDebuggable->update();
+}
#endif
+void WebPageProxy::clearInspectorTargets()
+{
+ m_inspectorController->clearTargets();
+}
+
+void WebPageProxy::createInspectorTargets()
+{
+ String pageTargetId = makeString("page-", String::number(m_pageID));
+ m_inspectorController->createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
+}
+
void WebPageProxy::setDrawsBackground(bool drawsBackground)
{
if (m_drawsBackground == drawsBackground)
if (frame->isMainFrame())
invalidateAllAttachments();
#endif
+
+#if ENABLE(REMOTE_INSPECTOR)
+ if (frame->isMainFrame())
+ remoteInspectorInformationDidChange();
+#endif
}
void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
frame->didChangeTitle(title);
m_pageLoadState.commitChanges();
+
+#if ENABLE(REMOTE_INSPECTOR)
+ if (frame->isMainFrame())
+ remoteInspectorInformationDidChange();
+#endif
}
void WebPageProxy::didFirstLayoutForFrame(uint64_t, const UserData& userData)
parameters.backgroundExtendsBeyondPage = m_backgroundExtendsBeyondPage;
parameters.layerHostingMode = m_layerHostingMode;
parameters.controlledByAutomation = m_controlledByAutomation;
-#if ENABLE(REMOTE_INSPECTOR)
- parameters.allowsRemoteInspection = m_allowsRemoteInspection;
- parameters.remoteInspectionNameOverride = m_remoteInspectionNameOverride;
-#endif
#if PLATFORM(MAC)
parameters.colorSpace = pageClient().colorSpace();
parameters.useSystemAppearance = m_useSystemAppearance;
class WebURLSchemeHandler;
class WebMouseEvent;
class WebOpenPanelResultListenerProxy;
+class WebPageDebuggable;
class WebPageGroup;
+class WebPageInspectorController;
class WebProcessProxy;
class WebUserContentControllerProxy;
class WebWheelEvent;
bool isControlledByAutomation() const { return m_controlledByAutomation; }
void setControlledByAutomation(bool);
+ WebPageInspectorController& inspectorController() { return *m_inspectorController; }
+
+#if PLATFORM(IOS_FAMILY)
+ void showInspectorIndication();
+ void hideInspectorIndication();
+#endif
+
+ void createInspectorTarget(const String& targetId, Inspector::InspectorTargetType);
+ void destroyInspectorTarget(const String& targetId);
+ void sendMessageToInspectorFrontend(const String& targetId, const String& message);
+
#if ENABLE(REMOTE_INSPECTOR)
- bool allowsRemoteInspection() const { return m_allowsRemoteInspection; }
+ void setIndicating(bool);
+ bool allowsRemoteInspection() const;
void setAllowsRemoteInspection(bool);
- String remoteInspectionNameOverride() const { return m_remoteInspectionNameOverride; }
+ String remoteInspectionNameOverride() const;
void setRemoteInspectionNameOverride(const String&);
+ void remoteInspectorInformationDidChange();
#endif
#if ENABLE(FULLSCREEN_API)
void showInspectorHighlight(const WebCore::Highlight&);
void hideInspectorHighlight();
- void showInspectorIndication();
- void hideInspectorIndication();
-
void enableInspectorNodeSearch();
void disableInspectorNodeSearch();
void assistedNodeInformationCallback(const AssistedNodeInformation&, CallbackID);
void stopAllURLSchemeTasks();
+ void clearInspectorTargets();
+ void createInspectorTargets();
+
#if ENABLE(ATTACHMENT_ELEMENT)
void registerAttachmentIdentifierFromData(const String&, const String& contentType, const String& preferredFileName, const IPC::DataReference&);
void registerAttachmentIdentifierFromFilePath(const String&, const String& contentType, const String& filePath);
bool m_controlledByAutomation { false };
-#if ENABLE(REMOTE_INSPECTOR)
- bool m_allowsRemoteInspection { true };
- String m_remoteInspectionNameOverride;
-#endif
unsigned m_inspectorFrontendCount { 0 };
#if PLATFORM(COCOA)
#if ENABLE(ATTACHMENT_ELEMENT)
HashMap<String, Ref<API::Attachment>> m_attachmentIdentifierToAttachmentMap;
#endif
-
+
+ const std::unique_ptr<WebPageInspectorController> m_inspectorController;
+#if ENABLE(REMOTE_INSPECTOR)
+ const std::unique_ptr<WebPageDebuggable> m_inspectorDebuggable;
+#endif
+
std::optional<SpellDocumentTag> m_spellDocumentTag;
std::optional<MonotonicTime> m_pageLoadStart;
DidChangeInspectorFrontendCount(uint64_t count)
+ CreateInspectorTarget(String targetId, enum:uint8_t Inspector::InspectorTargetType type)
+ DestroyInspectorTarget(String targetId)
+ SendMessageToInspectorFrontend(String targetId, String message)
+
# Search popup menus
SaveRecentSearches(String name, Vector<WebCore::RecentSearch> searchItems)
LoadRecentSearches(String name) -> (Vector<WebCore::RecentSearch> result) LegacySync
return page.process();
}
- if (page.inspectorFrontendCount() > 0) {
- reason = "A Web Inspector frontend is connected"_s;
- return page.process();
- }
-
if (m_automationSession) {
reason = "An automation session is active"_s;
return page.process();
A1EA02401DAC31DB0096021F /* WebContextMenuListenerProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = A1EA023E1DAC31DB0096021F /* WebContextMenuListenerProxy.h */; };
A1FB68241F6E518200C43F9F /* WKCrashReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = A1FB68221F6E518200C43F9F /* WKCrashReporter.h */; settings = {ATTRIBUTES = (Private, ); }; };
A1FB68271F6E51C100C43F9F /* CrashReporterClientSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = A1FB68261F6E51C100C43F9F /* CrashReporterClientSPI.h */; };
+ A513F5402154A5D700662841 /* WebPageInspectorController.h in Headers */ = {isa = PBXBuildFile; fileRef = A513F53E2154A5CC00662841 /* WebPageInspectorController.h */; };
A518B5D21FE1D55B00F9FA28 /* WKInspectorWKWebView.h in Headers */ = {isa = PBXBuildFile; fileRef = A518B5D01FE1D55B00F9FA28 /* WKInspectorWKWebView.h */; };
A54293A4195A43DA002782C7 /* WKInspectorNodeSearchGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = A54293A2195A43C6002782C7 /* WKInspectorNodeSearchGestureRecognizer.h */; };
+ A543E307215AD13700279CD9 /* WebPageInspectorTargetFrontendChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = A543E305215AD12D00279CD9 /* WebPageInspectorTargetFrontendChannel.h */; };
+ A543E30C215C8A8D00279CD9 /* WebPageInspectorTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = A543E308215C8A8300279CD9 /* WebPageInspectorTarget.h */; };
+ A543E30D215C8A9000279CD9 /* WebPageInspectorTargetController.h in Headers */ = {isa = PBXBuildFile; fileRef = A543E30B215C8A8400279CD9 /* WebPageInspectorTargetController.h */; };
+ A543E310215D8CE600279CD9 /* WebPageInspectorTargetAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A543E30E215D8CE200279CD9 /* WebPageInspectorTargetAgent.h */; };
A55BA8101BA1317E007CD33D /* _WKRemoteWebInspectorViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = A55BA80C1BA12BE1007CD33D /* _WKRemoteWebInspectorViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
A55BA8171BA23E12007CD33D /* RemoteWebInspectorUI.h in Headers */ = {isa = PBXBuildFile; fileRef = A55BA8131BA23E05007CD33D /* RemoteWebInspectorUI.h */; };
A55BA81F1BA25B27007CD33D /* RemoteWebInspectorProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = A55BA8191BA25B1E007CD33D /* RemoteWebInspectorProxy.h */; };
A58B6F0818FCA733008CBA53 /* WKFileUploadPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = A58B6F0618FCA733008CBA53 /* WKFileUploadPanel.h */; };
A5C0F0A72000654D00536536 /* _WKNSWindowExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = A5C0F0A62000654400536536 /* _WKNSWindowExtras.h */; settings = {ATTRIBUTES = (Private, ); }; };
A5C0F0AB2000658200536536 /* WKInspectorWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = A5C0F0AA2000656E00536536 /* WKInspectorWindow.h */; };
+ A5E391FD2183C1F800C8FB31 /* InspectorTargetProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = A5E391FC2183C1E900C8FB31 /* InspectorTargetProxy.h */; };
+ A5EC6AD42151BD7B00677D17 /* WebPageDebuggable.h in Headers */ = {isa = PBXBuildFile; fileRef = A5EC6AD32151BD6900677D17 /* WebPageDebuggable.h */; };
A5EFD38C16B0E88C00B2F0E8 /* WKPageVisibilityTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = A5EFD38B16B0E88C00B2F0E8 /* WKPageVisibilityTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
A78CCDDB193AC9F8005ECC25 /* com.apple.WebKit.Networking.sb in CopyFiles */ = {isa = PBXBuildFile; fileRef = A78CCDD8193AC9E3005ECC25 /* com.apple.WebKit.Networking.sb */; };
A78CCDDC193AC9FB005ECC25 /* com.apple.WebKit.WebContent.sb in CopyFiles */ = {isa = PBXBuildFile; fileRef = A78CCDD9193AC9E3005ECC25 /* com.apple.WebKit.WebContent.sb */; };
A1FB68221F6E518200C43F9F /* WKCrashReporter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKCrashReporter.h; sourceTree = "<group>"; };
A1FB68231F6E518200C43F9F /* WKCrashReporter.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WKCrashReporter.mm; sourceTree = "<group>"; };
A1FB68261F6E51C100C43F9F /* CrashReporterClientSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CrashReporterClientSPI.h; sourceTree = "<group>"; };
+ A513F53E2154A5CC00662841 /* WebPageInspectorController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorController.h; sourceTree = "<group>"; };
+ A513F53F2154A5CD00662841 /* WebPageInspectorController.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageInspectorController.cpp; sourceTree = "<group>"; };
A518B5D01FE1D55B00F9FA28 /* WKInspectorWKWebView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKInspectorWKWebView.h; sourceTree = "<group>"; };
A518B5D11FE1D55B00F9FA28 /* WKInspectorWKWebView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WKInspectorWKWebView.mm; sourceTree = "<group>"; };
A54293A2195A43C6002782C7 /* WKInspectorNodeSearchGestureRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKInspectorNodeSearchGestureRecognizer.h; path = ios/WKInspectorNodeSearchGestureRecognizer.h; sourceTree = "<group>"; };
A54293A3195A43C6002782C7 /* WKInspectorNodeSearchGestureRecognizer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKInspectorNodeSearchGestureRecognizer.mm; path = ios/WKInspectorNodeSearchGestureRecognizer.mm; sourceTree = "<group>"; };
+ A543E305215AD12D00279CD9 /* WebPageInspectorTargetFrontendChannel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorTargetFrontendChannel.h; sourceTree = "<group>"; };
+ A543E306215AD12E00279CD9 /* WebPageInspectorTargetFrontendChannel.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageInspectorTargetFrontendChannel.cpp; sourceTree = "<group>"; };
+ A543E308215C8A8300279CD9 /* WebPageInspectorTarget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorTarget.h; sourceTree = "<group>"; };
+ A543E309215C8A8300279CD9 /* WebPageInspectorTargetController.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageInspectorTargetController.cpp; sourceTree = "<group>"; };
+ A543E30A215C8A8400279CD9 /* WebPageInspectorTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageInspectorTarget.cpp; sourceTree = "<group>"; };
+ A543E30B215C8A8400279CD9 /* WebPageInspectorTargetController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorTargetController.h; sourceTree = "<group>"; };
+ A543E30E215D8CE200279CD9 /* WebPageInspectorTargetAgent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorTargetAgent.h; sourceTree = "<group>"; };
+ A543E30F215D8CE200279CD9 /* WebPageInspectorTargetAgent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageInspectorTargetAgent.cpp; sourceTree = "<group>"; };
A55BA80C1BA12BE1007CD33D /* _WKRemoteWebInspectorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKRemoteWebInspectorViewController.h; sourceTree = "<group>"; };
A55BA80D1BA12BE1007CD33D /* _WKRemoteWebInspectorViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKRemoteWebInspectorViewController.mm; sourceTree = "<group>"; };
A55BA8121BA23E05007CD33D /* RemoteWebInspectorUI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteWebInspectorUI.cpp; sourceTree = "<group>"; };
A5C0F0A92000656E00536536 /* WKInspectorWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKInspectorWindow.mm; sourceTree = "<group>"; };
A5C0F0AA2000656E00536536 /* WKInspectorWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKInspectorWindow.h; sourceTree = "<group>"; };
A5D3504D1D78F0D2005124A9 /* RemoteWebInspectorProxyMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RemoteWebInspectorProxyMac.mm; sourceTree = "<group>"; };
+ A5E391FB2183C1E900C8FB31 /* InspectorTargetProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorTargetProxy.cpp; sourceTree = "<group>"; };
+ A5E391FC2183C1E900C8FB31 /* InspectorTargetProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorTargetProxy.h; sourceTree = "<group>"; };
+ A5EC6AD22151BD6900677D17 /* WebPageDebuggable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageDebuggable.cpp; sourceTree = "<group>"; };
+ A5EC6AD32151BD6900677D17 /* WebPageDebuggable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebPageDebuggable.h; sourceTree = "<group>"; };
A5EFD38B16B0E88C00B2F0E8 /* WKPageVisibilityTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKPageVisibilityTypes.h; sourceTree = "<group>"; };
A72D5D7F1236CBA800A88B15 /* APISerializedScriptValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APISerializedScriptValue.h; sourceTree = "<group>"; };
A78CCDD7193AC9E3005ECC25 /* com.apple.WebKit.Storage.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.WebKit.Storage.sb; sourceTree = "<group>"; };
C0CE72581247E4DA00BC0EC4 /* WebPage.messages.in */,
BC7B621412A4219A00D174A4 /* WebPageGroupProxy.cpp */,
BC7B621312A4219A00D174A4 /* WebPageGroupProxy.h */,
+ A543E30A215C8A8400279CD9 /* WebPageInspectorTarget.cpp */,
+ A543E308215C8A8300279CD9 /* WebPageInspectorTarget.h */,
+ A543E309215C8A8300279CD9 /* WebPageInspectorTargetController.cpp */,
+ A543E30B215C8A8400279CD9 /* WebPageInspectorTargetController.h */,
+ A543E306215AD12E00279CD9 /* WebPageInspectorTargetFrontendChannel.cpp */,
+ A543E305215AD12D00279CD9 /* WebPageInspectorTargetFrontendChannel.h */,
2D5C9D0319C81D8F00B3C5C1 /* WebPageOverlay.cpp */,
2D5C9D0419C81D8F00B3C5C1 /* WebPageOverlay.h */,
BCA0EF7E12331E78007D3CFB /* WebUndoStep.cpp */,
2DD5A72A1EBF09A7009BA597 /* HiddenPageThrottlingAutoIncreasesCounter.h */,
839A2F2F1E2067390039057E /* HighPerformanceGraphicsUsageSampler.cpp */,
839A2F301E2067390039057E /* HighPerformanceGraphicsUsageSampler.h */,
+ A5E391FB2183C1E900C8FB31 /* InspectorTargetProxy.cpp */,
+ A5E391FC2183C1E900C8FB31 /* InspectorTargetProxy.h */,
31607F3819627002009B87DA /* LegacySessionStateCoding.h */,
BC6EDAA5111271C600E7678B /* PageClient.h */,
1AC75379183A9FDA0072CB15 /* PageLoadState.cpp */,
7CCCC8F91A5F50FD008FB0DA /* WebNavigationState.h */,
BC1DFEA312B31F87005DF730 /* WebOpenPanelResultListenerProxy.cpp */,
BC1DFEA212B31F87005DF730 /* WebOpenPanelResultListenerProxy.h */,
+ A5EC6AD22151BD6900677D17 /* WebPageDebuggable.cpp */,
+ A5EC6AD32151BD6900677D17 /* WebPageDebuggable.h */,
8372DB261A67562800C697C5 /* WebPageDiagnosticLoggingClient.cpp */,
8372DB271A67562800C697C5 /* WebPageDiagnosticLoggingClient.h */,
BC7B6205129A0A6700D174A4 /* WebPageGroup.cpp */,
BC7B6204129A0A6700D174A4 /* WebPageGroup.h */,
2D9EA3101A96D9EB002D2807 /* WebPageInjectedBundleClient.cpp */,
2D9EA30E1A96CBFF002D2807 /* WebPageInjectedBundleClient.h */,
+ A513F53F2154A5CD00662841 /* WebPageInspectorController.cpp */,
+ A513F53E2154A5CC00662841 /* WebPageInspectorController.h */,
+ A543E30F215D8CE200279CD9 /* WebPageInspectorTargetAgent.cpp */,
+ A543E30E215D8CE200279CD9 /* WebPageInspectorTargetAgent.h */,
BC111B0B112F5E4F00337BAB /* WebPageProxy.cpp */,
BC032DCB10F4389F0058C15A /* WebPageProxy.h */,
BCBD38FA125BAB9A00D2C29F /* WebPageProxy.messages.in */,
BC33E0D112408E8600360F3F /* InjectedBundleRangeHandle.h in Headers */,
BC14DF77120B5B7900826C0C /* InjectedBundleScriptWorld.h in Headers */,
2DD45ADE1E5F8972006C355F /* InputViewUpdateDeferrer.h in Headers */,
+ A5E391FD2183C1F800C8FB31 /* InspectorTargetProxy.h in Headers */,
C5BCE5DF1C50766A00CDE3FA /* InteractionInformationAtPosition.h in Headers */,
2D4D2C811DF60BF3002EB10C /* InteractionInformationRequest.h in Headers */,
1AE49A4911FFA8CE0048B464 /* JSNPMethod.h in Headers */,
BC857F8512B82D0B00EDEB2E /* WebOpenPanelResultListener.h in Headers */,
BC1DFEA412B31F87005DF730 /* WebOpenPanelResultListenerProxy.h in Headers */,
BC032D8F10F437A00058C15A /* WebPage.h in Headers */,
+ A5EC6AD42151BD7B00677D17 /* WebPageDebuggable.h in Headers */,
8372DB291A67562800C697C5 /* WebPageDiagnosticLoggingClient.h in Headers */,
BC7B6206129A0A6700D174A4 /* WebPageGroup.h in Headers */,
BC7B625212A43C9600D174A4 /* WebPageGroupData.h in Headers */,
BC7B621512A4219A00D174A4 /* WebPageGroupProxy.h in Headers */,
2D9EA30F1A96CBFF002D2807 /* WebPageInjectedBundleClient.h in Headers */,
+ A513F5402154A5D700662841 /* WebPageInspectorController.h in Headers */,
+ A543E30C215C8A8D00279CD9 /* WebPageInspectorTarget.h in Headers */,
+ A543E310215D8CE600279CD9 /* WebPageInspectorTargetAgent.h in Headers */,
+ A543E30D215C8A9000279CD9 /* WebPageInspectorTargetController.h in Headers */,
+ A543E307215AD13700279CD9 /* WebPageInspectorTargetFrontendChannel.h in Headers */,
C0CE72A11247E71D00BC0EC4 /* WebPageMessages.h in Headers */,
2D5C9D0619C81D8F00B3C5C1 /* WebPageOverlay.h in Headers */,
BCBD3915125BB1A800D2C29F /* WebPageProxyMessages.h in Headers */,
#include "WebOpenPanelResultListener.h"
#include "WebPageCreationParameters.h"
#include "WebPageGroupProxy.h"
+#include "WebPageInspectorTargetController.h"
#include "WebPageMessages.h"
#include "WebPageOverlay.h"
#include "WebPageProxyMessages.h"
, m_resourceLoadClient(std::make_unique<API::InjectedBundle::ResourceLoadClient>())
, m_uiClient(std::make_unique<API::InjectedBundle::PageUIClient>())
, m_findController(makeUniqueRef<FindController>(this))
+ , m_inspectorTargetController(std::make_unique<WebPageInspectorTargetController>(*this))
, m_userContentController(WebUserContentController::getOrCreate(parameters.userContentControllerID))
#if ENABLE(GEOLOCATION)
, m_geolocationPermissionRequestManager(makeUniqueRef<GeolocationPermissionRequestManager>(*this))
m_page->setControlledByAutomation(parameters.controlledByAutomation);
-#if ENABLE(REMOTE_INSPECTOR)
- m_page->setRemoteInspectionAllowed(parameters.allowsRemoteInspection);
- m_page->setRemoteInspectionNameOverride(parameters.remoteInspectionNameOverride);
-#endif
-
m_page->setCanStartMedia(false);
m_mayStartMediaWhenInWindow = parameters.mayStartMediaWhenInWindow;
m_page->setControlledByAutomation(controlled);
}
+void WebPage::connectInspector(const String& targetId)
+{
+ m_inspectorTargetController->connectInspector(targetId);
+}
+
+void WebPage::disconnectInspector(const String& targetId)
+{
+ m_inspectorTargetController->disconnectInspector(targetId);
+}
+
+void WebPage::sendMessageToTargetBackend(const String& targetId, const String& message)
+{
+ m_inspectorTargetController->sendMessageToTargetBackend(targetId, message);
+}
+
void WebPage::insertNewlineInQuotedContent()
{
Frame& frame = m_page->focusController().focusedOrMainFrame();
}
#if ENABLE(REMOTE_INSPECTOR)
-void WebPage::setAllowsRemoteInspection(bool allow)
-{
- m_page->setRemoteInspectionAllowed(allow);
-}
-
-void WebPage::setRemoteInspectionNameOverride(const String& name)
+void WebPage::setIndicating(bool indicating)
{
- m_page->setRemoteInspectionNameOverride(name);
+ m_page->inspectorController().setIndicating(indicating);
}
#endif
class WebDataListSuggestionPicker;
class WebDocumentLoader;
class WebEvent;
+class PlaybackSessionManager;
+class VideoFullscreenManager;
class WebFrame;
class WebFullScreenManager;
+class WebGestureEvent;
class WebImage;
class WebInspector;
class WebInspectorClient;
class WebInspectorUI;
-class WebGestureEvent;
class WebKeyboardEvent;
-class WebURLSchemeHandlerProxy;
class WebMouseEvent;
class WebNotificationClient;
class WebOpenPanelResultListener;
class WebPageGroupProxy;
+class WebPageInspectorTargetController;
class WebPageOverlay;
-class PlaybackSessionManager;
class WebPopupMenu;
+class WebTouchEvent;
+class WebURLSchemeHandlerProxy;
class WebUndoStep;
class WebUserContentController;
-class VideoFullscreenManager;
class WebWheelEvent;
-class WebTouchEvent;
class RemoteLayerTreeTransaction;
enum class DeviceAccessState : uint8_t;
bool isControlledByAutomation() const;
void setControlledByAutomation(bool);
+ void connectInspector(const String& targetId);
+ void disconnectInspector(const String& targetId);
+ void sendMessageToTargetBackend(const String& targetId, const String& message);
+
void insertNewlineInQuotedContent();
#if USE(OS_STATE)
void requestFontAttributesAtSelectionStart(CallbackID);
#if ENABLE(REMOTE_INSPECTOR)
- void setAllowsRemoteInspection(bool);
- void setRemoteInspectionNameOverride(const String&);
+ void setIndicating(bool);
#endif
void setDrawsBackground(bool);
RefPtr<WebInspector> m_inspector;
RefPtr<WebInspectorUI> m_inspectorUI;
RefPtr<RemoteWebInspectorUI> m_remoteInspectorUI;
+ std::unique_ptr<WebPageInspectorTargetController> m_inspectorTargetController;
#if (PLATFORM(IOS_FAMILY) && HAVE(AVKIT)) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
RefPtr<PlaybackSessionManager> m_playbackSessionManager;
SetControlledByAutomation(bool controlled)
+ ConnectInspector(String targetId)
+ DisconnectInspector(String targetId)
+ SendMessageToTargetBackend(String targetId, String message)
+
#if ENABLE(REMOTE_INSPECTOR)
- SetAllowsRemoteInspection(bool allow)
- SetRemoteInspectionNameOverride(String name)
+ SetIndicating(bool indicating);
#endif
#if ENABLE(IOS_TOUCH_EVENTS)
--- /dev/null
+/*
+ * Copyright (C) 2018 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 "WebPageInspectorTarget.h"
+
+#include "WebPage.h"
+#include <WebCore/InspectorController.h>
+#include <WebCore/Page.h>
+
+namespace WebKit {
+
+using namespace Inspector;
+
+WebPageInspectorTarget::WebPageInspectorTarget(WebPage& page)
+ : m_page(page)
+{
+}
+
+String WebPageInspectorTarget::identifier() const
+{
+ return makeString("page-", String::number(m_page.pageID()));
+}
+
+void WebPageInspectorTarget::connect(Inspector::FrontendChannel& channel)
+{
+ if (m_page.corePage())
+ m_page.corePage()->inspectorController().connectFrontend(&channel);
+}
+
+void WebPageInspectorTarget::disconnect(Inspector::FrontendChannel& channel)
+{
+ if (m_page.corePage())
+ m_page.corePage()->inspectorController().disconnectFrontend(&channel);
+}
+
+void WebPageInspectorTarget::sendMessageToTargetBackend(const String& message)
+{
+ if (m_page.corePage())
+ m_page.corePage()->inspectorController().dispatchMessageFromFrontend(message);
+}
+
+} // namespace WebKit
--- /dev/null
+/*
+ * Copyright (C) 2018 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
+
+#include <JavaScriptCore/InspectorTarget.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebKit {
+
+class WebPage;
+
+class WebPageInspectorTarget final : public Inspector::InspectorTarget {
+ WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_NONCOPYABLE(WebPageInspectorTarget);
+public:
+ WebPageInspectorTarget(WebPage&);
+ ~WebPageInspectorTarget() = default;
+
+ Inspector::InspectorTargetType type() const final { return Inspector::InspectorTargetType::Page; }
+
+ String identifier() const final;
+
+ void connect(Inspector::FrontendChannel&);
+ void disconnect(Inspector::FrontendChannel&);
+ void sendMessageToTargetBackend(const String&);
+
+private:
+ WebPage& m_page;
+};
+
+} // namespace WebKit
--- /dev/null
+/*
+ * Copyright (C) 2018 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 "WebPageInspectorTargetController.h"
+
+#include "WebPage.h"
+#include "WebPageProxyMessages.h"
+
+namespace WebKit {
+
+WebPageInspectorTargetController::WebPageInspectorTargetController(WebPage& page)
+ : m_page(page)
+ , m_pageTarget(page)
+{
+ // Do not send the page target to the UIProcess, the WebPageProxy will manager this for us.
+ m_targets.set(m_pageTarget.identifier(), &m_pageTarget);
+}
+
+WebPageInspectorTargetController::~WebPageInspectorTargetController()
+{
+}
+
+void WebPageInspectorTargetController::addTarget(Inspector::InspectorTarget& target)
+{
+ auto addResult = m_targets.set(target.identifier(), &target);
+ ASSERT_UNUSED(addResult, addResult.isNewEntry);
+
+ m_page.send(Messages::WebPageProxy::CreateInspectorTarget(target.identifier(), target.type()));
+}
+
+void WebPageInspectorTargetController::removeTarget(Inspector::InspectorTarget& target)
+{
+ ASSERT_WITH_MESSAGE(target.identifier() != m_pageTarget.identifier(), "Should never remove the main target.");
+
+ m_page.send(Messages::WebPageProxy::DestroyInspectorTarget(target.identifier()));
+
+ m_targets.remove(target.identifier());
+ m_targetFrontendChannels.remove(target.identifier());
+}
+
+void WebPageInspectorTargetController::connectInspector(const String& targetId)
+{
+ InspectorTarget* target = m_targets.get(targetId);
+ if (!target)
+ return;
+
+ RefPtr<WebPageInspectorTargetFrontendChannel> channel = m_targetFrontendChannels.get(targetId);
+ if (!channel) {
+ channel = WebPageInspectorTargetFrontendChannel::create(*this, targetId);
+ m_targetFrontendChannels.set(target->identifier(), channel);
+ }
+
+ target->connect(*channel.get());
+}
+
+void WebPageInspectorTargetController::disconnectInspector(const String& targetId)
+{
+ InspectorTarget* target = m_targets.get(targetId);
+ if (!target)
+ return;
+
+ RefPtr<WebPageInspectorTargetFrontendChannel> channel = m_targetFrontendChannels.take(targetId);
+ if (!channel)
+ return;
+
+ target->disconnect(*channel.get());
+}
+
+void WebPageInspectorTargetController::sendMessageToTargetBackend(const String& targetId, const String& message)
+{
+ InspectorTarget* target = m_targets.get(targetId);
+ if (!target)
+ return;
+
+ target->sendMessageToTargetBackend(message);
+}
+
+void WebPageInspectorTargetController::sendMessageToTargetFrontend(const String& targetId, const String& message)
+{
+ m_page.send(Messages::WebPageProxy::SendMessageToInspectorFrontend(targetId, message));
+}
+
+} // namespace WebKit
--- /dev/null
+/*
+ * Copyright (C) 2018 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
+
+#include "WebPageInspectorTarget.h"
+#include "WebPageInspectorTargetFrontendChannel.h"
+#include <wtf/text/WTFString.h>
+
+namespace Inspector {
+class InspectorTarget;
+}
+
+namespace WebKit {
+
+class WebPage;
+
+class WebPageInspectorTargetController {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ WebPageInspectorTargetController(WebPage&);
+ ~WebPageInspectorTargetController();
+
+ void addTarget(Inspector::InspectorTarget&);
+ void removeTarget(Inspector::InspectorTarget&);
+
+ void connectInspector(const String& targetId);
+ void disconnectInspector(const String& targetId);
+ void sendMessageToTargetBackend(const String& targetId, const String& message);
+ void sendMessageToTargetFrontend(const String& targetId, const String& message);
+
+private:
+ WebPage& m_page;
+ WebPageInspectorTarget m_pageTarget;
+ HashMap<String, Inspector::InspectorTarget*> m_targets;
+ HashMap<String, RefPtr<WebPageInspectorTargetFrontendChannel>> m_targetFrontendChannels;
+};
+
+} // namespace WebKit
--- /dev/null
+/*
+ * Copyright (C) 2018 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 "WebPageInspectorTargetFrontendChannel.h"
+
+#include "WebPageInspectorTargetController.h"
+
+namespace WebKit {
+
+using namespace WebCore;
+
+Ref<WebPageInspectorTargetFrontendChannel> WebPageInspectorTargetFrontendChannel::create(WebPageInspectorTargetController& targetController, const String& targetId)
+{
+ return adoptRef(*new WebPageInspectorTargetFrontendChannel(targetController, targetId));
+}
+
+WebPageInspectorTargetFrontendChannel::WebPageInspectorTargetFrontendChannel(WebPageInspectorTargetController& targetController, const String& targetId)
+ : m_targetController(targetController)
+ , m_targetId(targetId)
+{
+}
+
+void WebPageInspectorTargetFrontendChannel::sendMessageToFrontend(const String& message)
+{
+ m_targetController.sendMessageToTargetFrontend(m_targetId, message);
+}
+
+} // namespace WebKit
--- /dev/null
+/*
+ * Copyright (C) 2018 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
+
+#include <JavaScriptCore/InspectorFrontendChannel.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+class WebPageInspectorTargetController;
+
+class WebPageInspectorTargetFrontendChannel final : public RefCounted<WebPageInspectorTargetFrontendChannel>, public Inspector::FrontendChannel {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ static Ref<WebPageInspectorTargetFrontendChannel> create(WebPageInspectorTargetController&, const String& targetId);
+ virtual ~WebPageInspectorTargetFrontendChannel() = default;
+
+private:
+ WebPageInspectorTargetFrontendChannel(WebPageInspectorTargetController&, const String& targetId);
+
+ ConnectionType connectionType() const override { return ConnectionType::Remote; }
+ void sendMessageToFrontend(const String& message) override;
+
+private:
+ WebPageInspectorTargetController& m_targetController;
+ String m_targetId;
+};
+
+} // namespace WebKit
+2018-11-14 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Keep Web Inspector window alive across process swaps (PSON) (Remote Inspector)
+ https://bugs.webkit.org/show_bug.cgi?id=191494
+ <rdar://problem/45469854>
+
+ Reviewed by Devin Rousso.
+
+ * WebCoreSupport/WebInspectorClient.h:
+ WebKitLegacy will still have remote inspection of the Page directly.
+
2018-11-12 Simon Fraser <simon.fraser@apple.com>
Make compositing updates incremental
class WebInspectorFrontendClient;
-class WebInspectorClient : public WebCore::InspectorClient, public Inspector::FrontendChannel {
+class WebInspectorClient final : public WebCore::InspectorClient, public Inspector::FrontendChannel {
public:
explicit WebInspectorClient(WebView *inspectedWebView);
void highlight() override;
void hideHighlight() override;
+#if ENABLE(REMOTE_INSPECTOR)
+ bool allowRemoteInspectionToPageDirectly() const override { return true; }
+#endif
+
#if PLATFORM(IOS_FAMILY)
void showInspectorIndication() override;
void hideInspectorIndication() override;