Title: [189375] trunk
Revision
189375
Author
[email protected]
Date
2015-09-04 13:00:22 -0700 (Fri, 04 Sep 2015)

Log Message

Web Inspector: InspectorController should support multiple frontend channels
https://bugs.webkit.org/show_bug.cgi?id=148538

Reviewed by Joseph Pecoraro.

Source/_javascript_Core:

Instead of a singleton, it should be possible to have multiple channels open
at the same time and to individually close channels as frontends come and go.

The FrontendRouter class keeps a list of open FrontendChannels and sends messages
to the appropriate frontends based on whether the message is a response or event.
Each InspectorController owns a single FrontendRouter and BackendDispatcher instance.
Inspector backend code that sends messages to the frontend should switch over to
using the router rather than directly using a FrontendChannel.

* CMakeLists.txt:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj:
* _javascript_Core.xcodeproj/project.pbxproj:
* inspector/InspectorBackendDispatcher.cpp: Move constructors/destructors out of the header
to avoid including InspectorFrontendRouter everywhere. Use the router instead of a
specific frontend channel. Remove guards that are no longer necessary since the router
is guaranteed to outlive the backend dispatcher.

(Inspector::SupplementalBackendDispatcher::SupplementalBackendDispatcher):
(Inspector::SupplementalBackendDispatcher::~SupplementalBackendDispatcher):
(Inspector::BackendDispatcher::BackendDispatcher):
(Inspector::BackendDispatcher::create):
(Inspector::BackendDispatcher::isActive):
(Inspector::BackendDispatcher::registerDispatcherForDomain):
(Inspector::BackendDispatcher::sendResponse):
(Inspector::BackendDispatcher::sendPendingErrors):
* inspector/InspectorBackendDispatcher.h:
(Inspector::SupplementalBackendDispatcher::SupplementalBackendDispatcher): Deleted.
(Inspector::SupplementalBackendDispatcher::~SupplementalBackendDispatcher): Deleted.
(Inspector::BackendDispatcher::clearFrontend): Deleted, no longer necessary.
(Inspector::BackendDispatcher::isActive): Moved to implementation file.
(Inspector::BackendDispatcher::BackendDispatcher): Moved to implementation file.
* inspector/InspectorFrontendRouter.cpp: Added.
(Inspector::FrontendRouter::create):
(Inspector::FrontendRouter::connectFrontend):
(Inspector::FrontendRouter::disconnectFrontend):
(Inspector::FrontendRouter::disconnectAllFrontends):
(Inspector::FrontendRouter::leakChannel):
(Inspector::FrontendRouter::hasLocalFrontend):
(Inspector::FrontendRouter::hasRemoteFrontend):
(Inspector::FrontendRouter::sendEvent):
(Inspector::FrontendRouter::sendResponse):
* inspector/InspectorFrontendRouter.h: Added.
* inspector/JSGlobalObjectInspectorController.cpp: Remove guards that are no longer necessary.
The frontend router and backend dispatcher now have the same lifetime as the controller.
Explicitly connect/disconnect the frontend channel.

(Inspector::JSGlobalObjectInspectorController::JSGlobalObjectInspectorController):
(Inspector::JSGlobalObjectInspectorController::globalObjectDestroyed):
(Inspector::JSGlobalObjectInspectorController::connectFrontend):
(Inspector::JSGlobalObjectInspectorController::disconnectFrontend):
(Inspector::JSGlobalObjectInspectorController::disconnectAllFrontends):
(Inspector::JSGlobalObjectInspectorController::dispatchMessageFromFrontend):
(Inspector::JSGlobalObjectInspectorController::appendExtraAgent):
(Inspector::JSGlobalObjectInspectorController::pause): Deleted.
* inspector/JSGlobalObjectInspectorController.h:
* inspector/agents/InspectorAgent.cpp:
* inspector/agents/InspectorConsoleAgent.cpp:
* inspector/agents/InspectorDebuggerAgent.cpp:
* inspector/agents/InspectorRuntimeAgent.cpp:
* inspector/augmentable/AugmentableInspectorController.h:
(Inspector::AugmentableInspectorController::connected):
* inspector/remote/RemoteInspectorDebuggable.h:
* inspector/remote/RemoteInspectorDebuggableConnection.mm:
(Inspector::RemoteInspectorDebuggableConnection::close):
* inspector/scripts/codegen/generate_cpp_alternate_backend_dispatcher_header.py:
(CppAlternateBackendDispatcherHeaderGenerator.generate_output):
* inspector/scripts/codegen/generate_objc_frontend_dispatcher_implementation.py:
(ObjCFrontendDispatcherImplementationGenerator._generate_event): Use the router.
* runtime/JSGlobalObjectDebuggable.cpp:
(JSC::JSGlobalObjectDebuggable::disconnect):
* runtime/JSGlobalObjectDebuggable.h:

Source/WebCore:

No new tests, no behavior change from this patch. Teardown scenarios are
covered by existing protocol and inspector tests running under DRT and WKTR.

* ForwardingHeaders/inspector/InspectorFrontendRouter.h: Added.
* WebCore.vcxproj/WebCore.vcxproj:
* inspector/InspectorClient.h: Stop using forwarded types.
* inspector/InspectorController.cpp:
(WebCore::InspectorController::InspectorController):
(WebCore::InspectorController::inspectedPageDestroyed):
(WebCore::InspectorController::hasLocalFrontend):
(WebCore::InspectorController::hasRemoteFrontend):
(WebCore::InspectorController::connectFrontend):
(WebCore::InspectorController::disconnectFrontend):
(WebCore::InspectorController::disconnectAllFrontends): Added. Disconnects all
frontends and signals DisconnectReason::InspectedTargetDestroyed.

(WebCore::InspectorController::show):
(WebCore::InspectorController::close):
(WebCore::InspectorController::dispatchMessageFromFrontend):
* inspector/InspectorController.h: Add default value for isAutomaticInspection.
* inspector/InspectorDatabaseAgent.cpp:
* inspector/InspectorIndexedDBAgent.cpp:
* inspector/InspectorResourceAgent.cpp:
* inspector/WorkerInspectorController.cpp: Use a router with a singleton channel
that forwards messages over to the main page.

(WebCore::WorkerInspectorController::WorkerInspectorController):
(WebCore::WorkerInspectorController::connectFrontend):
(WebCore::WorkerInspectorController::disconnectFrontend):
(WebCore::WorkerInspectorController::dispatchMessageFromFrontend):
* inspector/WorkerInspectorController.h:
* page/PageDebuggable.cpp:
(WebCore::PageDebuggable::disconnect):
* page/PageDebuggable.h:
* testing/Internals.cpp: Clear the frontend client before disconnecting frontend channel.
(WebCore::Internals::openDummyInspectorFrontend):
(WebCore::Internals::closeDummyInspectorFrontend):

Source/WebKit/mac:

Remove the notifyInspectorController flag from closeWindow. Since InspectorClients
must now manually disconnect their FrontendChannel(s), we should always
perform the teardown that was guarded by this flag.

* WebCoreSupport/WebInspectorClient.h:
* WebCoreSupport/WebInspectorClient.mm:
(WebInspectorClient::bringFrontendToFront): Add a missing assertion.
(WebInspectorFrontendClient::closeWindow):
(WebInspectorFrontendClient::disconnectFromBackend):
(-[WebInspectorWindowController windowShouldClose:]):
(-[WebInspectorWindowController destroyInspectorView]): Always clear the frontend client.
(-[WebInspectorWindowController destroyInspectorView:]): Renamed to above.

Source/WebKit/win:

Remove the notifyInspectorController flag from closeWindow. Since InspectorClients
must now manually disconnect their FrontendChannel(s), we should always
perform the teardown that was guarded by this flag.

* WebCoreSupport/WebInspectorClient.cpp:
(WebInspectorClient::closeInspectorFrontend):
(WebInspectorFrontendClient::~WebInspectorFrontendClient):
(WebInspectorFrontendClient::closeWindow):
(WebInspectorFrontendClient::destroyInspectorView):
* WebCoreSupport/WebInspectorClient.h:

Source/WebKit2:

Explicitly disconnect the frontend channel when closing the frontend.

Rename createInspectorPage/closeFrontend to the symmetric and unambiguous
{open,close}FrontendConnection in the WebInspector class.

* WebProcess/WebCoreSupport/WebInspectorClient.cpp:
(WebKit::WebInspectorClient::openInspectorFrontend):
(WebKit::WebInspectorClient::closeInspectorFrontend):
* WebProcess/WebCoreSupport/WebInspectorClient.h: Stop using a forwarded type.
* WebProcess/WebPage/WebInspector.cpp:
(WebKit::WebInspector::openFrontendConnection):
(WebKit::WebInspector::closeFrontendConnection):
(WebKit::WebInspector::remoteFrontendConnected):
(WebKit::WebInspector::remoteFrontendDisconnected):
(WebKit::WebInspector::createInspectorPage): Deleted.
(WebKit::WebInspector::closeFrontend): Deleted.
* WebProcess/WebPage/WebInspector.h:

Tools:

InspectorClients must explicitly disconnect their frontend channel(s) from the
inspected page's InspectorController.

To make this possible, DumpRenderTree should not destroy non-primary views until
it has tried to close any abandoned Web Inspector instances. Performing teardown
in the reverse order prevents disconnection of the frontend channel because that
prematurely destroys the inspector frontend client.

* DumpRenderTree/mac/DumpRenderTree.mm:
(runTest):
* DumpRenderTree/win/DumpRenderTree.cpp:
(runTest):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (189374 => 189375)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2015-09-04 20:00:22 UTC (rev 189375)
@@ -324,6 +324,7 @@
     inspector/InjectedScriptManager.cpp
     inspector/InjectedScriptModule.cpp
     inspector/InspectorAgentRegistry.cpp
+    inspector/InspectorFrontendRouter.cpp
     inspector/InspectorBackendDispatcher.cpp
     inspector/InspectorValues.cpp
     inspector/JSGlobalObjectConsoleClient.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (189374 => 189375)


--- trunk/Source/_javascript_Core/ChangeLog	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-09-04 20:00:22 UTC (rev 189375)
@@ -1,3 +1,82 @@
+2015-09-04  Brian Burg  <[email protected]>
+
+        Web Inspector: InspectorController should support multiple frontend channels
+        https://bugs.webkit.org/show_bug.cgi?id=148538
+
+        Reviewed by Joseph Pecoraro.
+
+        Instead of a singleton, it should be possible to have multiple channels open
+        at the same time and to individually close channels as frontends come and go.
+
+        The FrontendRouter class keeps a list of open FrontendChannels and sends messages
+        to the appropriate frontends based on whether the message is a response or event.
+        Each InspectorController owns a single FrontendRouter and BackendDispatcher instance.
+        Inspector backend code that sends messages to the frontend should switch over to
+        using the router rather than directly using a FrontendChannel.
+
+        * CMakeLists.txt:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * inspector/InspectorBackendDispatcher.cpp: Move constructors/destructors out of the header
+        to avoid including InspectorFrontendRouter everywhere. Use the router instead of a
+        specific frontend channel. Remove guards that are no longer necessary since the router
+        is guaranteed to outlive the backend dispatcher.
+
+        (Inspector::SupplementalBackendDispatcher::SupplementalBackendDispatcher):
+        (Inspector::SupplementalBackendDispatcher::~SupplementalBackendDispatcher):
+        (Inspector::BackendDispatcher::BackendDispatcher):
+        (Inspector::BackendDispatcher::create):
+        (Inspector::BackendDispatcher::isActive):
+        (Inspector::BackendDispatcher::registerDispatcherForDomain):
+        (Inspector::BackendDispatcher::sendResponse):
+        (Inspector::BackendDispatcher::sendPendingErrors):
+        * inspector/InspectorBackendDispatcher.h:
+        (Inspector::SupplementalBackendDispatcher::SupplementalBackendDispatcher): Deleted.
+        (Inspector::SupplementalBackendDispatcher::~SupplementalBackendDispatcher): Deleted.
+        (Inspector::BackendDispatcher::clearFrontend): Deleted, no longer necessary.
+        (Inspector::BackendDispatcher::isActive): Moved to implementation file.
+        (Inspector::BackendDispatcher::BackendDispatcher): Moved to implementation file.
+        * inspector/InspectorFrontendRouter.cpp: Added.
+        (Inspector::FrontendRouter::create):
+        (Inspector::FrontendRouter::connectFrontend):
+        (Inspector::FrontendRouter::disconnectFrontend):
+        (Inspector::FrontendRouter::disconnectAllFrontends):
+        (Inspector::FrontendRouter::leakChannel):
+        (Inspector::FrontendRouter::hasLocalFrontend):
+        (Inspector::FrontendRouter::hasRemoteFrontend):
+        (Inspector::FrontendRouter::sendEvent):
+        (Inspector::FrontendRouter::sendResponse):
+        * inspector/InspectorFrontendRouter.h: Added.
+        * inspector/JSGlobalObjectInspectorController.cpp: Remove guards that are no longer necessary.
+        The frontend router and backend dispatcher now have the same lifetime as the controller.
+        Explicitly connect/disconnect the frontend channel.
+
+        (Inspector::JSGlobalObjectInspectorController::JSGlobalObjectInspectorController):
+        (Inspector::JSGlobalObjectInspectorController::globalObjectDestroyed):
+        (Inspector::JSGlobalObjectInspectorController::connectFrontend):
+        (Inspector::JSGlobalObjectInspectorController::disconnectFrontend):
+        (Inspector::JSGlobalObjectInspectorController::disconnectAllFrontends):
+        (Inspector::JSGlobalObjectInspectorController::dispatchMessageFromFrontend):
+        (Inspector::JSGlobalObjectInspectorController::appendExtraAgent):
+        (Inspector::JSGlobalObjectInspectorController::pause): Deleted.
+        * inspector/JSGlobalObjectInspectorController.h:
+        * inspector/agents/InspectorAgent.cpp:
+        * inspector/agents/InspectorConsoleAgent.cpp:
+        * inspector/agents/InspectorDebuggerAgent.cpp:
+        * inspector/agents/InspectorRuntimeAgent.cpp:
+        * inspector/augmentable/AugmentableInspectorController.h:
+        (Inspector::AugmentableInspectorController::connected):
+        * inspector/remote/RemoteInspectorDebuggable.h:
+        * inspector/remote/RemoteInspectorDebuggableConnection.mm:
+        (Inspector::RemoteInspectorDebuggableConnection::close):
+        * inspector/scripts/codegen/generate_cpp_alternate_backend_dispatcher_header.py:
+        (CppAlternateBackendDispatcherHeaderGenerator.generate_output):
+        * inspector/scripts/codegen/generate_objc_frontend_dispatcher_implementation.py:
+        (ObjCFrontendDispatcherImplementationGenerator._generate_event): Use the router.
+        * runtime/JSGlobalObjectDebuggable.cpp:
+        (JSC::JSGlobalObjectDebuggable::disconnect):
+        * runtime/JSGlobalObjectDebuggable.h:
+
 2015-09-04  Joseph Pecoraro  <[email protected]>
 
         Web Inspector: Expand Console domain test coverage

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (189374 => 189375)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2015-09-04 20:00:22 UTC (rev 189375)
@@ -595,6 +595,7 @@
     <ClCompile Include="..\inspector\InjectedScriptModule.cpp" />
     <ClCompile Include="..\inspector\InspectorAgentRegistry.cpp" />
     <ClCompile Include="..\inspector\InspectorBackendDispatcher.cpp" />
+    <ClCompile Include="..\inspector\InspectorFrontendRouter.cpp" />
     <ClCompile Include="..\inspector\InspectorValues.cpp" />
     <ClCompile Include="..\inspector\JSInjectedScriptHost.cpp" />
     <ClCompile Include="..\inspector\JSInjectedScriptHostPrototype.cpp" />
@@ -1384,6 +1385,7 @@
     <ClInclude Include="..\inspector\InspectorBackendDispatcher.h" />
     <ClInclude Include="..\inspector\InspectorEnvironment.h" />
     <ClInclude Include="..\inspector\InspectorFrontendChannel.h" />
+    <ClInclude Include="..\inspector\InspectorFrontendRouter.h" />
     <ClInclude Include="..\inspector\InspectorValues.h" />
     <ClInclude Include="..\inspector\JSInjectedScriptHost.h" />
     <ClInclude Include="..\inspector\JSInjectedScriptHostPrototype.h" />

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (189374 => 189375)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-09-04 20:00:22 UTC (rev 189375)
@@ -1195,6 +1195,8 @@
 		99E45A2618A1B2590026D88F /* EncodedValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 99E45A2118A1B2590026D88F /* EncodedValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		99E45A2718A1B2590026D88F /* InputCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 99E45A2218A1B2590026D88F /* InputCursor.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		99E45A2818A1B2590026D88F /* NondeterministicInput.h in Headers */ = {isa = PBXBuildFile; fileRef = 99E45A2318A1B2590026D88F /* NondeterministicInput.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		99F1A6FE1B8E6D9400463B26 /* InspectorFrontendRouter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99F1A6FC1B8E6D9400463B26 /* InspectorFrontendRouter.cpp */; };
+		99F1A7011B98FBEC00463B26 /* InspectorFrontendRouter.h in Headers */ = {isa = PBXBuildFile; fileRef = 99F1A7001B98FBEC00463B26 /* InspectorFrontendRouter.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		9E729407190F01A5001A91B5 /* InitializeThreading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */; };
 		9E729408190F021E001A91B5 /* InitializeLLVMPOSIX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAC51805E75500472CE4 /* InitializeLLVMPOSIX.cpp */; };
 		9E72940B190F0514001A91B5 /* BundlePath.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E72940A190F0514001A91B5 /* BundlePath.h */; };
@@ -3063,6 +3065,8 @@
 		99E45A2118A1B2590026D88F /* EncodedValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncodedValue.h; sourceTree = "<group>"; };
 		99E45A2218A1B2590026D88F /* InputCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputCursor.h; sourceTree = "<group>"; };
 		99E45A2318A1B2590026D88F /* NondeterministicInput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NondeterministicInput.h; sourceTree = "<group>"; };
+		99F1A6FC1B8E6D9400463B26 /* InspectorFrontendRouter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorFrontendRouter.cpp; sourceTree = "<group>"; };
+		99F1A7001B98FBEC00463B26 /* InspectorFrontendRouter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorFrontendRouter.h; sourceTree = "<group>"; };
 		9B4954E81A6640DB002815A6 /* ParserFunctionInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ParserFunctionInfo.h; sourceTree = "<group>"; };
 		9E729409190F0306001A91B5 /* BundlePath.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BundlePath.mm; sourceTree = "<group>"; };
 		9E72940A190F0514001A91B5 /* BundlePath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BundlePath.h; sourceTree = "<group>"; };
@@ -5713,6 +5717,7 @@
 		A5BA15DF1823409200A82E69 /* inspector */ = {
 			isa = PBXGroup;
 			children = (
+				99F1A7001B98FBEC00463B26 /* InspectorFrontendRouter.h */,
 				A513E5CC185FB992007E95AD /* agents */,
 				A5EA70E319F5B0E20098F5EC /* augmentable */,
 				A532438D185696CA002ED692 /* protocol */,
@@ -5744,6 +5749,7 @@
 				A593CF7B1840360300BFCE27 /* InspectorBackendDispatcher.h */,
 				A5D0A1BA1862301B00C7B496 /* InspectorEnvironment.h */,
 				A5945594182479EB00CC3843 /* InspectorFrontendChannel.h */,
+				99F1A6FC1B8E6D9400463B26 /* InspectorFrontendRouter.cpp */,
 				A55D93AB18514F7900400DED /* InspectorProtocolTypes.h */,
 				A593CF801840377100BFCE27 /* InspectorValues.cpp */,
 				A593CF811840377100BFCE27 /* InspectorValues.h */,
@@ -5907,6 +5913,7 @@
 				A1A009C11831A26E00CF8711 /* ARM64Assembler.h in Headers */,
 				0F898F321B27689F0083A33C /* DFGIntegerRangeOptimizationPhase.h in Headers */,
 				86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
+				99F1A7011B98FBEC00463B26 /* InspectorFrontendRouter.h in Headers */,
 				7964656A1B952FF0003059EE /* GetPutInfo.h in Headers */,
 				797E07AA1B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h in Headers */,
 				0FE050281AA9095600D33B33 /* ScopedArguments.h in Headers */,
@@ -7941,6 +7948,7 @@
 				C225494315F7DBAA0065E898 /* SlotVisitor.cpp in Sources */,
 				9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */,
 				E3EF88741B66DF23003F26CB /* JSPropertyNameIterator.cpp in Sources */,
+				99F1A6FE1B8E6D9400463B26 /* InspectorFrontendRouter.cpp in Sources */,
 				0F8F2B9E17306C8D007DBDA5 /* SourceCode.cpp in Sources */,
 				0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */,
 				E33E8D1C1B9013C300346B52 /* JSNativeStdFunction.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/inspector/InspectorBackendDispatcher.cpp (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/InspectorBackendDispatcher.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/InspectorBackendDispatcher.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -28,6 +28,7 @@
 #include "InspectorBackendDispatcher.h"
 
 #include "InspectorFrontendChannel.h"
+#include "InspectorFrontendRouter.h"
 #include "InspectorValues.h"
 #include <wtf/TemporaryChange.h>
 #include <wtf/text/CString.h>
@@ -35,6 +36,15 @@
 
 namespace Inspector {
 
+SupplementalBackendDispatcher::SupplementalBackendDispatcher(BackendDispatcher& backendDispatcher)
+    : m_backendDispatcher(backendDispatcher)
+{
+}
+
+SupplementalBackendDispatcher::~SupplementalBackendDispatcher()
+{
+}
+
 BackendDispatcher::CallbackBase::CallbackBase(Ref<BackendDispatcher>&& backendDispatcher, long requestId)
     : m_backendDispatcher(WTF::move(backendDispatcher))
     , m_requestId(requestId)
@@ -69,15 +79,28 @@
     m_backendDispatcher->sendResponse(m_requestId, WTF::move(partialMessage));
 }
 
-Ref<BackendDispatcher> BackendDispatcher::create(FrontendChannel* frontendChannel)
+BackendDispatcher::BackendDispatcher(Ref<FrontendRouter>&& router)
+    : m_frontendRouter(WTF::move(router))
 {
-    return adoptRef(*new BackendDispatcher(frontendChannel));
 }
 
+Ref<BackendDispatcher> BackendDispatcher::create(Ref<FrontendRouter>&& router)
+{
+    return adoptRef(*new BackendDispatcher(WTF::move(router)));
+}
+
+bool BackendDispatcher::isActive() const
+{
+    return m_frontendRouter->hasFrontends();
+}
+
 void BackendDispatcher::registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher* dispatcher)
 {
-    auto result = m_dispatchers.add(domain, dispatcher);
-    ASSERT_UNUSED(result, result.isNewEntry);
+    ASSERT_ARG(dispatcher, dispatcher);
+
+    // FIXME: <https://webkit.org/b/148492> Agents should only register with the backend once,
+    // and we should re-add the assertion that only one dispatcher is registered per domain.
+    m_dispatchers.set(domain, dispatcher);
 }
 
 void BackendDispatcher::dispatch(const String& message)
@@ -165,9 +188,6 @@
 
 void BackendDispatcher::sendResponse(long requestId, RefPtr<InspectorObject>&& result)
 {
-    if (!m_frontendChannel)
-        return;
-
     ASSERT(!m_protocolErrors.size());
 
     // The JSON-RPC 2.0 specification requires that the "error" member have the value 'null'
@@ -175,7 +195,7 @@
     Ref<InspectorObject> responseMessage = InspectorObject::create();
     responseMessage->setObject(ASCIILiteral("result"), result);
     responseMessage->setInteger(ASCIILiteral("id"), requestId);
-    m_frontendChannel->sendMessageToFrontend(responseMessage->toJSONString());
+    m_frontendRouter->sendResponse(responseMessage->toJSONString());
 }
 
 void BackendDispatcher::sendPendingErrors()
@@ -190,9 +210,6 @@
         -32000, // ServerError
     };
 
-    if (!m_frontendChannel)
-        return;
-    
     // To construct the error object, only use the last error's code and message.
     // Per JSON-RPC 2.0, Section 5.1, the 'data' member may contain nested errors,
     // but only one top-level Error object should be sent per request.
@@ -227,7 +244,7 @@
         message->setValue(ASCIILiteral("id"), InspectorValue::null());
     }
 
-    m_frontendChannel->sendMessageToFrontend(message->toJSONString());
+    m_frontendRouter->sendResponse(message->toJSONString());
 
     m_protocolErrors.clear();
     m_currentRequestId = Nullopt;

Modified: trunk/Source/_javascript_Core/inspector/InspectorBackendDispatcher.h (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/InspectorBackendDispatcher.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/InspectorBackendDispatcher.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -35,15 +35,14 @@
 namespace Inspector {
 
 class BackendDispatcher;
-class FrontendChannel;
+class FrontendRouter;
 
 typedef String ErrorString;
 
 class SupplementalBackendDispatcher : public RefCounted<SupplementalBackendDispatcher> {
 public:
-    SupplementalBackendDispatcher(BackendDispatcher& backendDispatcher)
-        : m_backendDispatcher(backendDispatcher) { }
-    virtual ~SupplementalBackendDispatcher() { }
+    SupplementalBackendDispatcher(BackendDispatcher&);
+    virtual ~SupplementalBackendDispatcher();
     virtual void dispatch(long requestId, const String& method, Ref<InspectorObject>&& message) = 0;
 protected:
     Ref<BackendDispatcher> m_backendDispatcher;
@@ -51,7 +50,7 @@
 
 class BackendDispatcher : public RefCounted<BackendDispatcher> {
 public:
-    JS_EXPORT_PRIVATE static Ref<BackendDispatcher> create(FrontendChannel*);
+    JS_EXPORT_PRIVATE static Ref<BackendDispatcher> create(Ref<FrontendRouter>&&);
 
     class JS_EXPORT_PRIVATE CallbackBase : public RefCounted<CallbackBase> {
     public:
@@ -69,8 +68,7 @@
         bool m_alreadySent { false };
     };
 
-    void clearFrontend() { m_frontendChannel = nullptr; }
-    bool isActive() const { return !!m_frontendChannel; }
+    bool isActive() const;
 
     bool hasProtocolErrors() const { return m_protocolErrors.size() > 0; }
 
@@ -104,12 +102,9 @@
     RefPtr<InspectorArray> getArray(InspectorObject*, const String& name, bool* valueFound);
 
 private:
-    BackendDispatcher(FrontendChannel* channel)
-        : m_frontendChannel(channel)
-    {
-    }
+    BackendDispatcher(Ref<FrontendRouter>&&);
 
-    FrontendChannel* m_frontendChannel;
+    Ref<FrontendRouter> m_frontendRouter;
     HashMap<String, SupplementalBackendDispatcher*> m_dispatchers;
 
     // Protocol errors reported for the top-level request being processed.

Added: trunk/Source/_javascript_Core/inspector/InspectorFrontendRouter.cpp (0 => 189375)


--- trunk/Source/_javascript_Core/inspector/InspectorFrontendRouter.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/inspector/InspectorFrontendRouter.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorFrontendRouter.h"
+
+#include "InspectorFrontendChannel.h"
+#include <wtf/Assertions.h>
+
+namespace Inspector {
+
+Ref<FrontendRouter> FrontendRouter::create()
+{
+    return adoptRef(*new FrontendRouter);
+}
+
+void FrontendRouter::connectFrontend(FrontendChannel* connection)
+{
+    ASSERT_ARG(connection, connection);
+
+    if (m_connections.contains(connection)) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    m_connections.append(connection);
+}
+
+void FrontendRouter::disconnectFrontend(FrontendChannel* connection)
+{
+    ASSERT_ARG(connection, connection);
+
+    if (!m_connections.contains(connection)) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    m_connections.removeFirst(connection);
+}
+
+void FrontendRouter::disconnectAllFrontends()
+{
+    m_connections.clear();
+}
+
+// FIXME: <https://webkit.org/b/148492> remove this method once agents move to using FrontendRouter directly.
+FrontendChannel* FrontendRouter::leakChannel() const
+{
+    if (m_connections.size())
+        return m_connections.at(0);
+
+    return nullptr;
+}
+
+bool FrontendRouter::hasLocalFrontend() const
+{
+    for (auto* connection : m_connections) {
+        if (connection->connectionType() == FrontendChannel::ConnectionType::Local)
+            return true;
+    }
+
+    return false;
+}
+
+bool FrontendRouter::hasRemoteFrontend() const
+{
+    for (auto* connection : m_connections) {
+        if (connection->connectionType() == FrontendChannel::ConnectionType::Remote)
+            return true;
+    }
+
+    return false;
+}
+
+void FrontendRouter::sendEvent(const String& message) const
+{
+    for (auto* connection : m_connections)
+        connection->sendMessageToFrontend(message);
+}
+
+void FrontendRouter::sendResponse(const String& message) const
+{
+    // FIXME: send responses to the appropriate frontend.
+    for (auto* connection : m_connections)
+        connection->sendMessageToFrontend(message);
+}
+
+} // namespace Inspector

Added: trunk/Source/_javascript_Core/inspector/InspectorFrontendRouter.h (0 => 189375)


--- trunk/Source/_javascript_Core/inspector/InspectorFrontendRouter.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/inspector/InspectorFrontendRouter.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef InspectorFrontendRouter_h
+#define InspectorFrontendRouter_h
+
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace Inspector {
+
+class FrontendChannel;
+
+class JS_EXPORT_PRIVATE FrontendRouter : public RefCounted<FrontendRouter> {
+public:
+    static Ref<FrontendRouter> create();
+
+    bool hasFrontends() const { return !m_connections.isEmpty(); }
+    bool hasLocalFrontend() const;
+    bool hasRemoteFrontend() const;
+
+    void connectFrontend(FrontendChannel*);
+    void disconnectFrontend(FrontendChannel*);
+    void disconnectAllFrontends();
+
+    // FIXME: <https://webkit.org/b/148492> remove this method once agents move to using FrontendRouter directly.
+    FrontendChannel* leakChannel() const;
+
+    void sendEvent(const String& message) const;
+    void sendResponse(const String& message) const;
+
+private:
+    Vector<FrontendChannel*, 2> m_connections;
+};
+
+} // namespace Inspector
+
+#endif // !defined(InspectorFrontendRouter_h)

Modified: trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.cpp (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -35,6 +35,7 @@
 #include "InspectorAgent.h"
 #include "InspectorBackendDispatcher.h"
 #include "InspectorFrontendChannel.h"
+#include "InspectorFrontendRouter.h"
 #include "JSGlobalObject.h"
 #include "JSGlobalObjectConsoleAgent.h"
 #include "JSGlobalObjectConsoleClient.h"
@@ -63,7 +64,8 @@
 JSGlobalObjectInspectorController::JSGlobalObjectInspectorController(JSGlobalObject& globalObject)
     : m_globalObject(globalObject)
     , m_injectedScriptManager(std::make_unique<InjectedScriptManager>(*this, InjectedScriptHost::create()))
-    , m_frontendChannel(nullptr)
+    , m_frontendRouter(FrontendRouter::create())
+    , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
     , m_executionStopwatch(Stopwatch::create())
     , m_includeNativeCallStackWithExceptions(true)
     , m_isAutomaticInspection(false)
@@ -98,23 +100,25 @@
 
 void JSGlobalObjectInspectorController::globalObjectDestroyed()
 {
-    disconnectFrontend(DisconnectReason::InspectedTargetDestroyed);
+    disconnectAllFrontends();
 
     m_injectedScriptManager->disconnect();
 }
 
 void JSGlobalObjectInspectorController::connectFrontend(FrontendChannel* frontendChannel, bool isAutomaticInspection)
 {
-    ASSERT(!m_frontendChannel);
-    ASSERT(!m_backendDispatcher);
+    ASSERT_ARG(frontendChannel, frontendChannel);
 
     m_isAutomaticInspection = isAutomaticInspection;
 
-    m_frontendChannel = frontendChannel;
-    m_backendDispatcher = BackendDispatcher::create(frontendChannel);
+    bool connectedFirstFrontend = !m_frontendRouter->hasFrontends();
+    m_frontendRouter->connectFrontend(frontendChannel);
 
-    m_agents.didCreateFrontendAndBackend(frontendChannel, m_backendDispatcher.get());
+    if (!connectedFirstFrontend)
+        return;
 
+    m_agents.didCreateFrontendAndBackend(frontendChannel, &m_backendDispatcher.get());
+
 #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
     m_inspectorAgent->activateExtraDomains(m_agents.extraDomains());
 
@@ -123,17 +127,32 @@
 #endif
 }
 
-void JSGlobalObjectInspectorController::disconnectFrontend(DisconnectReason reason)
+void JSGlobalObjectInspectorController::disconnectFrontend(FrontendChannel* frontendChannel)
 {
-    if (!m_frontendChannel)
+    ASSERT_ARG(frontendChannel, frontendChannel);
+
+    m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectorDestroyed);
+
+    m_frontendRouter->disconnectFrontend(frontendChannel);
+
+    m_isAutomaticInspection = false;
+
+    bool disconnectedLastFrontend = !m_frontendRouter->hasFrontends();
+    if (!disconnectedLastFrontend)
         return;
 
-    m_agents.willDestroyFrontendAndBackend(reason);
+#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
+    if (m_augmentingClient)
+        m_augmentingClient->inspectorDisconnected();
+#endif
+}
 
-    m_backendDispatcher->clearFrontend();
-    m_backendDispatcher = nullptr;
-    m_frontendChannel = nullptr;
+void JSGlobalObjectInspectorController::disconnectAllFrontends()
+{
+    m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectedTargetDestroyed);
 
+    m_frontendRouter->disconnectAllFrontends();
+
     m_isAutomaticInspection = false;
 
 #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
@@ -144,15 +163,11 @@
 
 void JSGlobalObjectInspectorController::dispatchMessageFromFrontend(const String& message)
 {
-    if (m_backendDispatcher)
-        m_backendDispatcher->dispatch(message);
+    m_backendDispatcher->dispatch(message);
 }
 
 void JSGlobalObjectInspectorController::pause()
 {
-    if (!m_frontendChannel)
-        return;
-
     ErrorString dummyError;
     m_debuggerAgent->enable(dummyError);
     m_debuggerAgent->pause(dummyError);
@@ -262,13 +277,11 @@
 {
     String domainName = agent->domainName();
 
-    if (m_frontendChannel)
-        agent->didCreateFrontendAndBackend(m_frontendChannel, m_backendDispatcher.get());
+    agent->didCreateFrontendAndBackend(m_frontendRouter->leakChannel(), &m_backendDispatcher.get());
 
     m_agents.appendExtraAgent(WTF::move(agent));
 
-    if (m_frontendChannel)
-        m_inspectorAgent->activateExtraDomain(domainName);
+    m_inspectorAgent->activateExtraDomain(domainName);
 }
 #endif
 

Modified: trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.h (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -53,6 +53,7 @@
 
 class BackendDispatcher;
 class FrontendChannel;
+class FrontendRouter;
 class InjectedScriptManager;
 class InspectorAgent;
 class InspectorConsoleAgent;
@@ -73,7 +74,9 @@
     ~JSGlobalObjectInspectorController();
 
     void connectFrontend(FrontendChannel*, bool isAutomaticInspection);
-    void disconnectFrontend(DisconnectReason);
+    void disconnectFrontend(FrontendChannel*);
+    void disconnectAllFrontends();
+
     void dispatchMessageFromFrontend(const String&);
 
     void globalObjectDestroyed();
@@ -99,7 +102,7 @@
     virtual AugmentableInspectorControllerClient* augmentableInspectorControllerClient() const override { return m_augmentingClient; } 
     virtual void setAugmentableInspectorControllerClient(AugmentableInspectorControllerClient* client) override { m_augmentingClient = client; }
 
-    virtual FrontendChannel* frontendChannel() const override { return m_frontendChannel; }
+    virtual const FrontendRouter& frontendRouter() const override { return m_frontendRouter.get(); }
     virtual void appendExtraAgent(std::unique_ptr<InspectorAgentBase>) override;
 #endif
 
@@ -113,8 +116,8 @@
     InspectorConsoleAgent* m_consoleAgent;
     InspectorDebuggerAgent* m_debuggerAgent;
     AgentRegistry m_agents;
-    FrontendChannel* m_frontendChannel;
-    RefPtr<BackendDispatcher> m_backendDispatcher;
+    Ref<FrontendRouter> m_frontendRouter;
+    Ref<BackendDispatcher> m_backendDispatcher;
     Ref<WTF::Stopwatch> m_executionStopwatch;
     bool m_includeNativeCallStackWithExceptions;
     bool m_isAutomaticInspection;

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorAgent.cpp (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorAgent.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorAgent.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -32,6 +32,7 @@
 #include "InspectorAgent.h"
 
 #include "InspectorEnvironment.h"
+#include "InspectorFrontendRouter.h"
 #include "InspectorValues.h"
 #include "ScriptValue.h"
 

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorConsoleAgent.cpp (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorConsoleAgent.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorConsoleAgent.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -28,6 +28,7 @@
 
 #include "ConsoleMessage.h"
 #include "InjectedScriptManager.h"
+#include "InspectorFrontendRouter.h"
 #include "ScriptArguments.h"
 #include "ScriptCallFrame.h"
 #include "ScriptCallStack.h"

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -33,6 +33,7 @@
 #include "ContentSearchUtilities.h"
 #include "InjectedScript.h"
 #include "InjectedScriptManager.h"
+#include "InspectorFrontendRouter.h"
 #include "InspectorValues.h"
 #include "RegularExpression.h"
 #include "ScriptDebugServer.h"

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorRuntimeAgent.cpp (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorRuntimeAgent.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorRuntimeAgent.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -37,6 +37,7 @@
 #include "HeapIterationScope.h"
 #include "InjectedScript.h"
 #include "InjectedScriptManager.h"
+#include "InspectorFrontendRouter.h"
 #include "InspectorValues.h"
 #include "JSLock.h"
 #include "ParserError.h"

Modified: trunk/Source/_javascript_Core/inspector/augmentable/AugmentableInspectorController.h (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/augmentable/AugmentableInspectorController.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/augmentable/AugmentableInspectorController.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -29,7 +29,7 @@
 #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
 
 #include <_javascript_Core/AugmentableInspectorControllerClient.h>
-#include <_javascript_Core/InspectorFrontendChannel.h>
+#include <_javascript_Core/InspectorFrontendRouter.h>
 
 namespace Inspector {
 
@@ -42,10 +42,10 @@
     virtual AugmentableInspectorControllerClient* augmentableInspectorControllerClient() const = 0;
     virtual void setAugmentableInspectorControllerClient(AugmentableInspectorControllerClient*) = 0;
 
-    virtual FrontendChannel* frontendChannel() const = 0;
+    virtual const FrontendRouter& frontendRouter() const = 0;
     virtual void appendExtraAgent(std::unique_ptr<InspectorAgentBase>) = 0;
 
-    bool connected() const { return !!frontendChannel(); }
+    bool connected() const { return frontendRouter().hasFrontends(); }
 };
 
 } // namespace Inspector

Modified: trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorDebuggable.h (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorDebuggable.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorDebuggable.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -64,7 +64,7 @@
     virtual bool hasLocalDebugger() const = 0;
 
     virtual void connect(FrontendChannel*, bool isAutomaticInspection) = 0;
-    virtual void disconnect() = 0;
+    virtual void disconnect(FrontendChannel*) = 0;
     virtual void dispatchMessageFromRemoteFrontend(const String& message) = 0;
     virtual void setIndicating(bool) { } // Default is to do nothing.
     virtual void pause() { };

Modified: trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorDebuggableConnection.mm (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorDebuggableConnection.mm	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorDebuggableConnection.mm	2015-09-04 20:00:22 UTC (rev 189375)
@@ -191,7 +191,7 @@
 
             if (m_debuggable) {
                 if (m_connected)
-                    m_debuggable->disconnect();
+                    m_debuggable->disconnect(this);
 
                 m_debuggable = nullptr;
             }

Modified: trunk/Source/_javascript_Core/inspector/scripts/codegen/generate_cpp_alternate_backend_dispatcher_header.py (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/scripts/codegen/generate_cpp_alternate_backend_dispatcher_header.py	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/scripts/codegen/generate_cpp_alternate_backend_dispatcher_header.py	2015-09-04 20:00:22 UTC (rev 189375)
@@ -47,6 +47,7 @@
     def generate_output(self):
         headers = [
             '"InspectorProtocolTypes.h"',
+            '<inspector/InspectorFrontendRouter.h>',
             '<_javascript_Core/InspectorBackendDispatcher.h>',
         ]
 

Modified: trunk/Source/_javascript_Core/inspector/scripts/codegen/generate_cpp_backend_dispatcher_implementation.py (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/scripts/codegen/generate_cpp_backend_dispatcher_implementation.py	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/scripts/codegen/generate_cpp_backend_dispatcher_implementation.py	2015-09-04 20:00:22 UTC (rev 189375)
@@ -50,6 +50,7 @@
     def generate_output(self):
         secondary_headers = [
             '<inspector/InspectorFrontendChannel.h>',
+            '<inspector/InspectorFrontendRouter.h>',
             '<inspector/InspectorValues.h>',
             '<wtf/NeverDestroyed.h>',
             '<wtf/text/CString.h>']

Modified: trunk/Source/_javascript_Core/inspector/scripts/codegen/generate_objc_frontend_dispatcher_implementation.py (189374 => 189375)


--- trunk/Source/_javascript_Core/inspector/scripts/codegen/generate_objc_frontend_dispatcher_implementation.py	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/inspector/scripts/codegen/generate_objc_frontend_dispatcher_implementation.py	2015-09-04 20:00:22 UTC (rev 189375)
@@ -98,9 +98,7 @@
         lines = []
         lines.append(self._generate_event_signature(domain, event))
         lines.append('{')
-        lines.append('    FrontendChannel* frontendChannel = _controller->frontendChannel();')
-        lines.append('    if (!frontendChannel)')
-        lines.append('        return;')
+        lines.append('    const FrontendRouter& router = _controller->frontendRouter();')
         lines.append('')
 
         required_pointer_parameters = filter(lambda parameter: not parameter.is_optional and ObjCGenerator.is_type_objc_pointer_type(parameter.type), event.event_parameters)
@@ -126,7 +124,7 @@
         lines.append('    jsonMessage->setString(ASCIILiteral("method"), ASCIILiteral("%s.%s"));' % (domain.domain_name, event.event_name))
         if event.event_parameters:
             lines.extend(self._generate_event_out_parameters(domain, event))
-        lines.append('    frontendChannel->sendMessageToFrontend(jsonMessage->toJSONString());')
+        lines.append('    router.sendEvent(jsonMessage->toJSONString());')
         lines.append('}')
         return '\n'.join(lines)
 

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectDebuggable.cpp (189374 => 189375)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectDebuggable.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectDebuggable.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -56,11 +56,11 @@
     m_globalObject.inspectorController().connectFrontend(frontendChannel, automaticInspection);
 }
 
-void JSGlobalObjectDebuggable::disconnect()
+void JSGlobalObjectDebuggable::disconnect(FrontendChannel* frontendChannel)
 {
     JSLockHolder locker(&m_globalObject.vm());
 
-    m_globalObject.inspectorController().disconnectFrontend(DisconnectReason::InspectorDestroyed);
+    m_globalObject.inspectorController().disconnectFrontend(frontendChannel);
 }
 
 void JSGlobalObjectDebuggable::pause()

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectDebuggable.h (189374 => 189375)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectDebuggable.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectDebuggable.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -54,7 +54,7 @@
     virtual bool hasLocalDebugger() const override { return false; }
 
     virtual void connect(Inspector::FrontendChannel*, bool automaticInspection) override;
-    virtual void disconnect() override;
+    virtual void disconnect(Inspector::FrontendChannel*) override;
     virtual void dispatchMessageFromRemoteFrontend(const String& message) override;
     virtual void pause() override;
 

Modified: trunk/Source/WebCore/ChangeLog (189374 => 189375)


--- trunk/Source/WebCore/ChangeLog	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/ChangeLog	2015-09-04 20:00:22 UTC (rev 189375)
@@ -1,3 +1,48 @@
+2015-09-04  Brian Burg  <[email protected]>
+
+        Web Inspector: InspectorController should support multiple frontend channels
+        https://bugs.webkit.org/show_bug.cgi?id=148538
+
+        Reviewed by Joseph Pecoraro.
+
+        No new tests, no behavior change from this patch. Teardown scenarios are
+        covered by existing protocol and inspector tests running under DRT and WKTR.
+
+        * ForwardingHeaders/inspector/InspectorFrontendRouter.h: Added.
+        * WebCore.vcxproj/WebCore.vcxproj:
+        * inspector/InspectorClient.h: Stop using forwarded types.
+        * inspector/InspectorController.cpp:
+        (WebCore::InspectorController::InspectorController):
+        (WebCore::InspectorController::inspectedPageDestroyed):
+        (WebCore::InspectorController::hasLocalFrontend):
+        (WebCore::InspectorController::hasRemoteFrontend):
+        (WebCore::InspectorController::connectFrontend):
+        (WebCore::InspectorController::disconnectFrontend):
+        (WebCore::InspectorController::disconnectAllFrontends): Added. Disconnects all
+        frontends and signals DisconnectReason::InspectedTargetDestroyed.
+
+        (WebCore::InspectorController::show):
+        (WebCore::InspectorController::close):
+        (WebCore::InspectorController::dispatchMessageFromFrontend):
+        * inspector/InspectorController.h: Add default value for isAutomaticInspection.
+        * inspector/InspectorDatabaseAgent.cpp:
+        * inspector/InspectorIndexedDBAgent.cpp:
+        * inspector/InspectorResourceAgent.cpp:
+        * inspector/WorkerInspectorController.cpp: Use a router with a singleton channel
+        that forwards messages over to the main page.
+
+        (WebCore::WorkerInspectorController::WorkerInspectorController):
+        (WebCore::WorkerInspectorController::connectFrontend):
+        (WebCore::WorkerInspectorController::disconnectFrontend):
+        (WebCore::WorkerInspectorController::dispatchMessageFromFrontend):
+        * inspector/WorkerInspectorController.h:
+        * page/PageDebuggable.cpp:
+        (WebCore::PageDebuggable::disconnect):
+        * page/PageDebuggable.h:
+        * testing/Internals.cpp: Clear the frontend client before disconnecting frontend channel.
+        (WebCore::Internals::openDummyInspectorFrontend):
+        (WebCore::Internals::closeDummyInspectorFrontend):
+
 2015-09-04  Jer Noble  <[email protected]>
 
         [iOS] Enable media layout tests to run simultaneously by ignoring system-level interruptions

Added: trunk/Source/WebCore/ForwardingHeaders/inspector/InspectorFrontendRouter.h (0 => 189375)


--- trunk/Source/WebCore/ForwardingHeaders/inspector/InspectorFrontendRouter.h	                        (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/inspector/InspectorFrontendRouter.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -0,0 +1,4 @@
+#ifndef WebCore_FWD_InspectorFrontendRouter_h
+#define WebCore_FWD_InspectorFrontendRouter_h
+#include <_javascript_Core/InspectorFrontendRouter.h>
+#endif

Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (189374 => 189375)


--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj	2015-09-04 20:00:22 UTC (rev 189375)
@@ -20336,6 +20336,7 @@
     <ClInclude Include="..\ForwardingHeaders\inspector\InspectorBackendDispatcher.h" />
     <ClInclude Include="..\ForwardingHeaders\inspector\InspectorEnvironment.h" />
     <ClInclude Include="..\ForwardingHeaders\inspector\InspectorFrontendChannel.h" />
+    <ClInclude Include="..\ForwardingHeaders\inspector\InspectorFrontendRouter.h" />
     <ClInclude Include="..\ForwardingHeaders\inspector\InspectorBackendDispatchers.h" />
     <ClInclude Include="..\ForwardingHeaders\inspector\InspectorFrontendDispatchers.h" />
     <ClInclude Include="..\ForwardingHeaders\inspector\InspectorProtocolObjects.h" />

Modified: trunk/Source/WebCore/inspector/InspectorClient.h (189374 => 189375)


--- trunk/Source/WebCore/inspector/InspectorClient.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/inspector/InspectorClient.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -27,11 +27,14 @@
 #ifndef InspectorClient_h
 #define InspectorClient_h
 
-#include "InspectorForwarding.h"
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 
+namespace Inspector {
+class FrontendChannel;
+}
+
 namespace WebCore {
 
 class FloatRect;
@@ -45,7 +48,7 @@
 
     virtual void inspectorDestroyed() = 0;
 
-    virtual InspectorFrontendChannel* openInspectorFrontend(InspectorController*) = 0;
+    virtual Inspector::FrontendChannel* openInspectorFrontend(InspectorController*) = 0;
     virtual void closeInspectorFrontend() = 0;
     virtual void bringFrontendToFront() = 0;
     virtual void didResizeMainFrame(Frame*) { }

Modified: trunk/Source/WebCore/inspector/InspectorController.cpp (189374 => 189375)


--- trunk/Source/WebCore/inspector/InspectorController.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/inspector/InspectorController.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -68,6 +68,7 @@
 #include <inspector/InspectorBackendDispatcher.h>
 #include <inspector/InspectorBackendDispatchers.h>
 #include <inspector/InspectorFrontendDispatchers.h>
+#include <inspector/InspectorFrontendRouter.h>
 #include <inspector/agents/InspectorAgent.h>
 #include <profiler/LegacyProfiler.h>
 #include <runtime/JSLock.h>
@@ -85,6 +86,8 @@
 InspectorController::InspectorController(Page& page, InspectorClient* inspectorClient)
     : m_instrumentingAgents(InstrumentingAgents::create(*this))
     , m_injectedScriptManager(std::make_unique<WebInjectedScriptManager>(*this, WebInjectedScriptHost::create()))
+    , m_frontendRouter(FrontendRouter::create())
+    , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
     , m_overlay(std::make_unique<InspectorOverlay>(page, inspectorClient))
     , m_executionStopwatch(Stopwatch::create())
     , m_page(page)
@@ -177,7 +180,8 @@
 
 void InspectorController::inspectedPageDestroyed()
 {
-    disconnectFrontend(DisconnectReason::InspectedTargetDestroyed);
+    disconnectAllFrontends();
+
     m_injectedScriptManager->disconnect();
     m_inspectorClient->inspectorDestroyed();
     m_inspectorClient = nullptr;
@@ -190,12 +194,12 @@
 
 bool InspectorController::hasLocalFrontend() const
 {
-    return m_frontendChannel && m_frontendChannel->connectionType() == FrontendChannel::ConnectionType::Local;
+    return m_frontendRouter->hasLocalFrontend();
 }
 
 bool InspectorController::hasRemoteFrontend() const
 {
-    return m_frontendChannel && m_frontendChannel->connectionType() == FrontendChannel::ConnectionType::Remote;
+    return m_frontendRouter->hasRemoteFrontend();
 }
 
 bool InspectorController::hasInspectorFrontendClient() const
@@ -219,74 +223,96 @@
 
 void InspectorController::connectFrontend(Inspector::FrontendChannel* frontendChannel, bool isAutomaticInspection)
 {
-    ASSERT(frontendChannel);
+    ASSERT_ARG(frontendChannel, frontendChannel);
     ASSERT(m_inspectorClient);
-    ASSERT(!m_frontendChannel);
-    ASSERT(!m_backendDispatcher);
 
+    bool connectedFirstFrontend = !m_frontendRouter->hasFrontends();
     m_isAutomaticInspection = isAutomaticInspection;
 
-    m_frontendChannel = frontendChannel;
-    m_backendDispatcher = BackendDispatcher::create(frontendChannel);
+    m_frontendRouter->connectFrontend(frontendChannel);
 
-    m_agents.didCreateFrontendAndBackend(frontendChannel, m_backendDispatcher.get());
-
-    InspectorInstrumentation::registerInstrumentingAgents(m_instrumentingAgents.get());
     InspectorInstrumentation::frontendCreated();
 
+    if (connectedFirstFrontend) {
+        InspectorInstrumentation::registerInstrumentingAgents(m_instrumentingAgents.get());
+        m_agents.didCreateFrontendAndBackend(frontendChannel, &m_backendDispatcher.get());
+    }
+
 #if ENABLE(REMOTE_INSPECTOR)
-    if (!hasRemoteFrontend())
+    if (!m_frontendRouter->hasRemoteFrontend())
         m_page.remoteInspectorInformationDidChange();
 #endif
 }
 
-void InspectorController::disconnectFrontend(DisconnectReason reason)
+void InspectorController::disconnectFrontend(FrontendChannel* frontendChannel)
 {
-    if (!m_frontendChannel)
-        return;
+    // The local frontend client should be disconnected first so it stops sending messages.
+    ASSERT(!m_frontendRouter->hasLocalFrontend() || !m_inspectorFrontendClient);
 
+    m_frontendRouter->disconnectFrontend(frontendChannel);
+    m_isAutomaticInspection = false;
+
+    InspectorInstrumentation::frontendDeleted();
+
+    bool disconnectedLastFrontend = !m_frontendRouter->hasFrontends();
+    if (disconnectedLastFrontend) {
+        // Release overlay page resources.
+        m_overlay->freePage();
+        m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectorDestroyed);
+        InspectorInstrumentation::unregisterInstrumentingAgents(m_instrumentingAgents.get());
+    }
+
 #if ENABLE(REMOTE_INSPECTOR)
-    if (!hasRemoteFrontend())
+    if (!m_frontendRouter->hasFrontends())
         m_page.remoteInspectorInformationDidChange();
 #endif
+}
 
-    m_agents.willDestroyFrontendAndBackend(reason);
+void InspectorController::disconnectAllFrontends()
+{
+    // The local frontend client should be disconnected first so it stops sending messages.
+    ASSERT(!m_frontendRouter->hasLocalFrontend() || !m_inspectorFrontendClient);
 
-    m_backendDispatcher->clearFrontend();
-    m_backendDispatcher = nullptr;
-    m_frontendChannel = nullptr;
+    m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectedTargetDestroyed);
 
+    m_frontendRouter->disconnectAllFrontends();
     m_isAutomaticInspection = false;
 
     // Release overlay page resources.
     m_overlay->freePage();
-    InspectorInstrumentation::frontendDeleted();
+
+    while (InspectorInstrumentation::hasFrontends())
+        InspectorInstrumentation::frontendDeleted();
+
     InspectorInstrumentation::unregisterInstrumentingAgents(m_instrumentingAgents.get());
+    
+#if ENABLE(REMOTE_INSPECTOR)
+    m_page.remoteInspectorInformationDidChange();
+#endif
 }
 
 void InspectorController::show()
 {
-    ASSERT(!hasRemoteFrontend());
+    ASSERT(!m_frontendRouter->hasRemoteFrontend());
 
+    // The local frontend client should be disconnected if there's no local frontend.
+    ASSERT(m_frontendRouter->hasLocalFrontend() || !m_inspectorFrontendClient);
+
     if (!enabled())
         return;
 
-    if (m_frontendChannel)
+    if (m_frontendRouter->hasLocalFrontend())
         m_inspectorClient->bringFrontendToFront();
-    else {
-        if (Inspector::FrontendChannel* frontendChannel = m_inspectorClient->openInspectorFrontend(this)) {
-            bool isAutomaticInspection = false;
-            connectFrontend(frontendChannel, isAutomaticInspection);
-        }
-    }
+    else if (Inspector::FrontendChannel* frontendChannel = m_inspectorClient->openInspectorFrontend(this))
+        connectFrontend(frontendChannel);
 }
 
 void InspectorController::close()
 {
-    if (!m_frontendChannel)
-        return;
-    disconnectFrontend(DisconnectReason::InspectorDestroyed);
-    m_inspectorClient->closeInspectorFrontend();
+    if (m_frontendRouter->hasLocalFrontend())
+        m_inspectorClient->closeInspectorFrontend();
+
+    ASSERT(!m_frontendRouter->hasLocalFrontend());
 }
 
 void InspectorController::setProcessId(long processId)
@@ -337,8 +363,7 @@
 
 void InspectorController::dispatchMessageFromFrontend(const String& message)
 {
-    if (m_backendDispatcher)
-        m_backendDispatcher->dispatch(message);
+    m_backendDispatcher->dispatch(message);
 }
 
 void InspectorController::hideHighlight()

Modified: trunk/Source/WebCore/inspector/InspectorController.h (189374 => 189375)


--- trunk/Source/WebCore/inspector/InspectorController.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/inspector/InspectorController.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -45,6 +45,7 @@
 namespace Inspector {
 class BackendDispatcher;
 class FrontendChannel;
+class FrontendRouter;
 class InspectorAgent;
 class InspectorObject;
 
@@ -98,8 +99,9 @@
     bool hasLocalFrontend() const;
     bool hasRemoteFrontend() const;
 
-    WEBCORE_EXPORT void connectFrontend(Inspector::FrontendChannel*, bool isAutomaticInspection);
-    WEBCORE_EXPORT void disconnectFrontend(Inspector::DisconnectReason);
+    WEBCORE_EXPORT void connectFrontend(Inspector::FrontendChannel*, bool isAutomaticInspection = false);
+    WEBCORE_EXPORT void disconnectFrontend(Inspector::FrontendChannel*);
+    WEBCORE_EXPORT void disconnectAllFrontends();
     void setProcessId(long);
 
     void inspect(Node*);
@@ -140,8 +142,8 @@
 
     Ref<InstrumentingAgents> m_instrumentingAgents;
     std::unique_ptr<WebInjectedScriptManager> m_injectedScriptManager;
-    RefPtr<Inspector::BackendDispatcher> m_backendDispatcher;
-    Inspector::FrontendChannel* m_frontendChannel { nullptr };
+    Ref<Inspector::FrontendRouter> m_frontendRouter;
+    Ref<Inspector::BackendDispatcher> m_backendDispatcher;
     std::unique_ptr<InspectorOverlay> m_overlay;
     Ref<WTF::Stopwatch> m_executionStopwatch;
     Inspector::AgentRegistry m_agents;

Modified: trunk/Source/WebCore/inspector/InspectorDatabaseAgent.cpp (189374 => 189375)


--- trunk/Source/WebCore/inspector/InspectorDatabaseAgent.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/inspector/InspectorDatabaseAgent.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -44,6 +44,7 @@
 #include "SQLTransactionErrorCallback.h"
 #include "SQLValue.h"
 #include "VoidCallback.h"
+#include <inspector/InspectorFrontendRouter.h>
 #include <inspector/InspectorValues.h>
 #include <wtf/Vector.h>
 

Modified: trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp (189374 => 189375)


--- trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -64,6 +64,7 @@
 #include <inspector/InjectedScript.h>
 #include <inspector/InjectedScriptManager.h>
 #include <inspector/InspectorFrontendDispatchers.h>
+#include <inspector/InspectorFrontendRouter.h>
 #include <inspector/InspectorValues.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/Vector.h>

Modified: trunk/Source/WebCore/inspector/InspectorResourceAgent.cpp (189374 => 189375)


--- trunk/Source/WebCore/inspector/InspectorResourceAgent.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/inspector/InspectorResourceAgent.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -62,6 +62,7 @@
 #include "URL.h"
 #include "WebSocketFrame.h"
 #include <inspector/IdentifiersFactory.h>
+#include <inspector/InspectorFrontendRouter.h>
 #include <inspector/InspectorValues.h>
 #include <inspector/ScriptCallStack.h>
 #include <inspector/ScriptCallStackFactory.h>

Modified: trunk/Source/WebCore/inspector/WorkerInspectorController.cpp (189374 => 189375)


--- trunk/Source/WebCore/inspector/WorkerInspectorController.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/inspector/WorkerInspectorController.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -48,6 +48,7 @@
 #include "WorkerThread.h"
 #include <inspector/InspectorBackendDispatcher.h>
 #include <inspector/InspectorFrontendDispatchers.h>
+#include <inspector/InspectorFrontendRouter.h>
 #include <wtf/Stopwatch.h>
 
 using namespace Inspector;
@@ -80,6 +81,8 @@
     , m_instrumentingAgents(InstrumentingAgents::create(*this))
     , m_injectedScriptManager(std::make_unique<WebInjectedScriptManager>(*this, WebInjectedScriptHost::create()))
     , m_executionStopwatch(Stopwatch::create())
+    , m_frontendRouter(FrontendRouter::create())
+    , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
 {
     auto runtimeAgent = std::make_unique<WorkerRuntimeAgent>(*m_injectedScriptManager, &workerGlobalScope);
     m_runtimeAgent = runtimeAgent.get();
@@ -108,33 +111,36 @@
  
 WorkerInspectorController::~WorkerInspectorController()
 {
+    ASSERT(!m_frontendRouter->hasFrontends());
+    ASSERT(!m_forwardingChannel);
+
     m_instrumentingAgents->reset();
-    disconnectFrontend(Inspector::DisconnectReason::InspectedTargetDestroyed);
+    m_agents.discardAgents();
 }
 
 void WorkerInspectorController::connectFrontend()
 {
-    ASSERT(!m_frontendChannel);
-    m_frontendChannel = std::make_unique<PageInspectorProxy>(m_workerGlobalScope);
-    m_backendDispatcher = BackendDispatcher::create(m_frontendChannel.get());
-    m_agents.didCreateFrontendAndBackend(m_frontendChannel.get(), m_backendDispatcher.get());
+    ASSERT(!m_frontendRouter->hasFrontends());
+    ASSERT(!m_forwardingChannel);
+
+    m_forwardingChannel = std::make_unique<PageInspectorProxy>(m_workerGlobalScope);
+    m_frontendRouter->connectFrontend(m_forwardingChannel.get());
+    m_agents.didCreateFrontendAndBackend(m_forwardingChannel.get(), &m_backendDispatcher.get());
 }
 
 void WorkerInspectorController::disconnectFrontend(Inspector::DisconnectReason reason)
 {
-    if (!m_frontendChannel)
-        return;
+    ASSERT(m_frontendRouter->hasFrontends());
+    ASSERT(m_forwardingChannel);
 
     m_agents.willDestroyFrontendAndBackend(reason);
-    m_backendDispatcher->clearFrontend();
-    m_backendDispatcher = nullptr;
-    m_frontendChannel = nullptr;
+    m_frontendRouter->disconnectFrontend(m_forwardingChannel.get());
+    m_forwardingChannel = nullptr;
 }
 
 void WorkerInspectorController::dispatchMessageFromFrontend(const String& message)
 {
-    if (m_backendDispatcher)
-        m_backendDispatcher->dispatch(message);
+    m_backendDispatcher->dispatch(message);
 }
 
 void WorkerInspectorController::resume()

Modified: trunk/Source/WebCore/inspector/WorkerInspectorController.h (189374 => 189375)


--- trunk/Source/WebCore/inspector/WorkerInspectorController.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/inspector/WorkerInspectorController.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -41,6 +41,10 @@
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
 
+namespace Inspector {
+class FrontendRouter;
+};
+
 namespace WebCore {
 
 class InspectorInstrumentation;
@@ -78,9 +82,10 @@
     std::unique_ptr<WebInjectedScriptManager> m_injectedScriptManager;
     WorkerRuntimeAgent* m_runtimeAgent { nullptr };
     Inspector::AgentRegistry m_agents;
-    std::unique_ptr<Inspector::FrontendChannel> m_frontendChannel;
+    std::unique_ptr<Inspector::FrontendChannel> m_forwardingChannel;
     Ref<WTF::Stopwatch> m_executionStopwatch;
-    RefPtr<Inspector::BackendDispatcher> m_backendDispatcher;
+    Ref<Inspector::FrontendRouter> m_frontendRouter;
+    Ref<Inspector::BackendDispatcher> m_backendDispatcher;
     Vector<InspectorInstrumentationCookie, 2> m_injectedScriptInstrumentationCookies;
 };
 

Modified: trunk/Source/WebCore/page/PageDebuggable.cpp (189374 => 189375)


--- trunk/Source/WebCore/page/PageDebuggable.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/page/PageDebuggable.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -80,10 +80,10 @@
     inspectorController.connectFrontend(channel, isAutomaticInspection);
 }
 
-void PageDebuggable::disconnect()
+void PageDebuggable::disconnect(Inspector::FrontendChannel* channel)
 {
     InspectorController& inspectorController = m_page.inspectorController();
-    inspectorController.disconnectFrontend(Inspector::DisconnectReason::InspectorDestroyed);
+    inspectorController.disconnectFrontend(channel);
 
     if (m_forcedDeveloperExtrasEnabled) {
         m_forcedDeveloperExtrasEnabled = false;

Modified: trunk/Source/WebCore/page/PageDebuggable.h (189374 => 189375)


--- trunk/Source/WebCore/page/PageDebuggable.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/page/PageDebuggable.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -49,7 +49,7 @@
     virtual bool hasLocalDebugger() const override;
 
     virtual void connect(Inspector::FrontendChannel*, bool isAutomaticInspection) override;
-    virtual void disconnect() override;
+    virtual void disconnect(Inspector::FrontendChannel*) override;
     virtual void dispatchMessageFromRemoteFrontend(const String& message) override;
     virtual void setIndicating(bool) override;
 

Modified: trunk/Source/WebCore/testing/Internals.cpp (189374 => 189375)


--- trunk/Source/WebCore/testing/Internals.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebCore/testing/Internals.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -1735,9 +1735,8 @@
     m_frontendClient = std::make_unique<InspectorFrontendClientDummy>(&page->inspectorController(), frontendPage);
     frontendPage->inspectorController().setInspectorFrontendClient(m_frontendClient.get());
 
-    bool isAutomaticInspection = false;
     m_frontendChannel = std::make_unique<InspectorFrontendChannelDummy>(frontendPage);
-    page->inspectorController().connectFrontend(m_frontendChannel.get(), isAutomaticInspection);
+    page->inspectorController().connectFrontend(m_frontendChannel.get());
 
     return m_frontendWindow;
 }
@@ -1748,9 +1747,13 @@
     ASSERT(page);
     ASSERT(m_frontendWindow);
 
-    page->inspectorController().disconnectFrontend(Inspector::DisconnectReason::InspectorDestroyed);
+    Page* frontendPage = m_frontendWindow->document()->page();
+    ASSERT(frontendPage);
 
+    frontendPage->inspectorController().setInspectorFrontendClient(nullptr);
     m_frontendClient = nullptr;
+
+    page->inspectorController().disconnectFrontend(m_frontendChannel.get());
     m_frontendChannel = nullptr;
 
     m_frontendWindow->close(m_frontendWindow->scriptExecutionContext());

Modified: trunk/Source/WebKit/mac/ChangeLog (189374 => 189375)


--- trunk/Source/WebKit/mac/ChangeLog	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit/mac/ChangeLog	2015-09-04 20:00:22 UTC (rev 189375)
@@ -1,3 +1,23 @@
+2015-09-04  Brian Burg  <[email protected]>
+
+        Web Inspector: InspectorController should support multiple frontend channels
+        https://bugs.webkit.org/show_bug.cgi?id=148538
+
+        Reviewed by Joseph Pecoraro.
+
+        Remove the notifyInspectorController flag from closeWindow. Since InspectorClients
+        must now manually disconnect their FrontendChannel(s), we should always
+        perform the teardown that was guarded by this flag.
+
+        * WebCoreSupport/WebInspectorClient.h:
+        * WebCoreSupport/WebInspectorClient.mm:
+        (WebInspectorClient::bringFrontendToFront): Add a missing assertion.
+        (WebInspectorFrontendClient::closeWindow):
+        (WebInspectorFrontendClient::disconnectFromBackend):
+        (-[WebInspectorWindowController windowShouldClose:]):
+        (-[WebInspectorWindowController destroyInspectorView]): Always clear the frontend client.
+        (-[WebInspectorWindowController destroyInspectorView:]): Renamed to above.
+
 2015-09-03  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r189338.

Modified: trunk/Source/WebKit/mac/WebCoreSupport/WebInspectorClient.h (189374 => 189375)


--- trunk/Source/WebKit/mac/WebCoreSupport/WebInspectorClient.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit/mac/WebCoreSupport/WebInspectorClient.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -124,7 +124,7 @@
 
     virtual void bringToFront() override;
     virtual void closeWindow() override;
-    virtual void disconnectFromBackend();
+    void disconnectFromBackend();
 
     virtual void attachWindow(DockSide) override;
     virtual void detachWindow() override;

Modified: trunk/Source/WebKit/mac/WebCoreSupport/WebInspectorClient.mm (189374 => 189375)


--- trunk/Source/WebKit/mac/WebCoreSupport/WebInspectorClient.mm	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit/mac/WebCoreSupport/WebInspectorClient.mm	2015-09-04 20:00:22 UTC (rev 189375)
@@ -87,7 +87,7 @@
 - (WebInspectorClient*)inspectorClient;
 - (void)setAttachedWindowHeight:(unsigned)height;
 - (void)setDockingUnavailable:(BOOL)unavailable;
-- (void)destroyInspectorView:(bool)notifyInspectorController;
+- (void)destroyInspectorView;
 @end
 
 
@@ -130,6 +130,7 @@
 
 void WebInspectorClient::bringFrontendToFront()
 {
+    ASSERT(m_frontendClient);
     m_frontendClient->bringToFront();
 }
 
@@ -252,12 +253,12 @@
 
 void WebInspectorFrontendClient::closeWindow()
 {
-    [m_windowController.get() destroyInspectorView:true];
+    [m_windowController.get() destroyInspectorView];
 }
 
 void WebInspectorFrontendClient::disconnectFromBackend()
 {
-    [m_windowController.get() destroyInspectorView:false];
+    [m_windowController.get() destroyInspectorView];
 }
 
 void WebInspectorFrontendClient::attachWindow(DockSide)
@@ -522,7 +523,7 @@
 
 - (BOOL)windowShouldClose:(id)sender
 {
-    [self destroyInspectorView:true];
+    [self destroyInspectorView];
 
     return YES;
 }
@@ -676,7 +677,7 @@
     // Do nothing.
 }
 
-- (void)destroyInspectorView:(bool)notifyInspectorController
+- (void)destroyInspectorView
 {
     RetainPtr<WebInspectorWindowController> protect(self);
 
@@ -692,9 +693,9 @@
 
     _visible = NO;
 
-    if (notifyInspectorController) {
-        if (Page* inspectedPage = [_inspectedWebView.get() page])
-            inspectedPage->inspectorController().disconnectFrontend(Inspector::DisconnectReason::InspectorDestroyed);
+    if (Page* inspectedPage = [_inspectedWebView.get() page]) {
+        inspectedPage->inspectorController().setInspectorFrontendClient(nullptr);
+        inspectedPage->inspectorController().disconnectFrontend(_inspectorClient);
     }
 
     [_webView close];

Modified: trunk/Source/WebKit/win/ChangeLog (189374 => 189375)


--- trunk/Source/WebKit/win/ChangeLog	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit/win/ChangeLog	2015-09-04 20:00:22 UTC (rev 189375)
@@ -1,3 +1,21 @@
+2015-09-04  Brian Burg  <[email protected]>
+
+        Web Inspector: InspectorController should support multiple frontend channels
+        https://bugs.webkit.org/show_bug.cgi?id=148538
+
+        Reviewed by Joseph Pecoraro.
+
+        Remove the notifyInspectorController flag from closeWindow. Since InspectorClients
+        must now manually disconnect their FrontendChannel(s), we should always
+        perform the teardown that was guarded by this flag.
+
+        * WebCoreSupport/WebInspectorClient.cpp:
+        (WebInspectorClient::closeInspectorFrontend):
+        (WebInspectorFrontendClient::~WebInspectorFrontendClient):
+        (WebInspectorFrontendClient::closeWindow):
+        (WebInspectorFrontendClient::destroyInspectorView):
+        * WebCoreSupport/WebInspectorClient.h:
+
 2015-09-03  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r189338.

Modified: trunk/Source/WebKit/win/WebCoreSupport/WebInspectorClient.cpp (189374 => 189375)


--- trunk/Source/WebKit/win/WebCoreSupport/WebInspectorClient.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit/win/WebCoreSupport/WebInspectorClient.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -174,7 +174,7 @@
 void WebInspectorClient::closeInspectorFrontend()
 {
     if (m_frontendClient)
-        m_frontendClient->destroyInspectorView(false);
+        m_frontendClient->destroyInspectorView();
 }
 
 void WebInspectorClient::bringFrontendToFront()
@@ -237,7 +237,7 @@
 
 WebInspectorFrontendClient::~WebInspectorFrontendClient()
 {
-    destroyInspectorView(true);
+    destroyInspectorView();
 }
 
 void WebInspectorFrontendClient::frontendLoaded()
@@ -269,7 +269,7 @@
 
 void WebInspectorFrontendClient::closeWindow()
 {
-    destroyInspectorView(true);
+    destroyInspectorView();
 }
 
 void WebInspectorFrontendClient::attachWindow(DockSide)
@@ -421,7 +421,7 @@
     m_inspectorClient->updateHighlight();
 }
 
-void WebInspectorFrontendClient::destroyInspectorView(bool notifyInspectorController)
+void WebInspectorFrontendClient::destroyInspectorView()
 {
     m_inspectorClient->releaseFrontend();
 
@@ -431,10 +431,10 @@
 
     closeWindowWithoutNotifications();
 
-    if (notifyInspectorController) {
-        m_inspectedWebView->page()->inspectorController().disconnectFrontend(Inspector::DisconnectReason::InspectorDestroyed);
-        m_inspectorClient->updateHighlight();
-    }
+    m_inspectedWebView->page()->inspectorController().setInspectorFrontendClient(nullptr);
+    m_inspectedWebView->page()->inspectorController().disconnectFrontend(m_inspectorClient);
+    m_inspectorClient->updateHighlight();
+
     ::DestroyWindow(m_frontendHwnd);
 }
 

Modified: trunk/Source/WebKit/win/WebCoreSupport/WebInspectorClient.h (189374 => 189375)


--- trunk/Source/WebKit/win/WebCoreSupport/WebInspectorClient.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit/win/WebCoreSupport/WebInspectorClient.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -113,7 +113,7 @@
 
     virtual void inspectedURLChanged(const WTF::String& newURL);
 
-    void destroyInspectorView(bool notifyInspectorController);
+    void destroyInspectorView();
 
 private:
     void closeWindowWithoutNotifications();

Modified: trunk/Source/WebKit2/ChangeLog (189374 => 189375)


--- trunk/Source/WebKit2/ChangeLog	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit2/ChangeLog	2015-09-04 20:00:22 UTC (rev 189375)
@@ -1,3 +1,28 @@
+2015-09-04  Brian Burg  <[email protected]>
+
+        Web Inspector: InspectorController should support multiple frontend channels
+        https://bugs.webkit.org/show_bug.cgi?id=148538
+
+        Reviewed by Joseph Pecoraro.
+
+        Explicitly disconnect the frontend channel when closing the frontend.
+
+        Rename createInspectorPage/closeFrontend to the symmetric and unambiguous
+        {open,close}FrontendConnection in the WebInspector class.
+
+        * WebProcess/WebCoreSupport/WebInspectorClient.cpp:
+        (WebKit::WebInspectorClient::openInspectorFrontend):
+        (WebKit::WebInspectorClient::closeInspectorFrontend):
+        * WebProcess/WebCoreSupport/WebInspectorClient.h: Stop using a forwarded type.
+        * WebProcess/WebPage/WebInspector.cpp:
+        (WebKit::WebInspector::openFrontendConnection):
+        (WebKit::WebInspector::closeFrontendConnection):
+        (WebKit::WebInspector::remoteFrontendConnected):
+        (WebKit::WebInspector::remoteFrontendDisconnected):
+        (WebKit::WebInspector::createInspectorPage): Deleted.
+        (WebKit::WebInspector::closeFrontend): Deleted.
+        * WebProcess/WebPage/WebInspector.h:
+
 2015-09-04  Dan Bernstein  <[email protected]>
 
         [iOS] Disable backspace key navigation by default

Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebInspectorClient.cpp (189374 => 189375)


--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebInspectorClient.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebInspectorClient.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -82,17 +82,19 @@
     delete this;
 }
 
-WebCore::InspectorFrontendChannel* WebInspectorClient::openInspectorFrontend(InspectorController* controller)
+Inspector::FrontendChannel* WebInspectorClient::openInspectorFrontend(InspectorController* controller)
 {
-    m_page->inspector()->createInspectorPage(controller->isUnderTest());
+    m_page->inspector()->openFrontendConnection(controller->isUnderTest());
 
     return m_page->inspector();
 }
 
 void WebInspectorClient::closeInspectorFrontend()
 {
-    if (m_page->inspector())
-        m_page->inspector()->closeFrontend();
+    if (m_page->inspector()) {
+        m_page->corePage()->inspectorController().disconnectFrontend(m_page->inspector());
+        m_page->inspector()->closeFrontendConnection();
+    }
 }
 
 void WebInspectorClient::bringFrontendToFront()

Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebInspectorClient.h (189374 => 189375)


--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebInspectorClient.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebInspectorClient.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -27,7 +27,6 @@
 #define WebInspectorClient_h
 
 #include <WebCore/InspectorClient.h>
-#include <WebCore/InspectorForwarding.h>
 #include <WebCore/PageOverlay.h>
 #include <wtf/HashSet.h>
 
@@ -53,7 +52,7 @@
     // WebCore::InspectorClient
     void inspectorDestroyed() override;
 
-    WebCore::InspectorFrontendChannel* openInspectorFrontend(WebCore::InspectorController*) override;
+    Inspector::FrontendChannel* openInspectorFrontend(WebCore::InspectorController*) override;
     void closeInspectorFrontend() override;
     void bringFrontendToFront() override;
     void didResizeMainFrame(WebCore::Frame*) override;

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebInspector.cpp (189374 => 189375)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebInspector.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebInspector.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -70,7 +70,7 @@
 }
 
 // Called from WebInspectorClient
-void WebInspector::createInspectorPage(bool underTest)
+void WebInspector::openFrontendConnection(bool underTest)
 {
 #if OS(DARWIN)
     mach_port_t listeningPort;
@@ -93,7 +93,7 @@
     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::CreateInspectorPage(connectionClientPort, canAttachWindow(), underTest), m_page->pageID());
 }
 
-void WebInspector::closeFrontend()
+void WebInspector::closeFrontendConnection()
 {
     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::DidClose(), m_page->pageID());
 
@@ -262,8 +262,7 @@
 {
     if (m_page->corePage()) {
         m_remoteFrontendConnected = true;
-        bool isAutomaticInspection = false;
-        m_page->corePage()->inspectorController().connectFrontend(this, isAutomaticInspection);
+        m_page->corePage()->inspectorController().connectFrontend(this);
     }
 }
 
@@ -272,7 +271,7 @@
     m_remoteFrontendConnected = false;
 
     if (m_page->corePage())
-        m_page->corePage()->inspectorController().disconnectFrontend(Inspector::DisconnectReason::InspectorDestroyed);
+        m_page->corePage()->inspectorController().disconnectFrontend(this);
 }
 #endif
 

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebInspector.h (189374 => 189375)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebInspector.h	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebInspector.h	2015-09-04 20:00:22 UTC (rev 189375)
@@ -97,9 +97,9 @@
     bool canAttachWindow();
 
     // Called from WebInspectorClient
-    void createInspectorPage(bool underTest);
+    void openFrontendConnection(bool underTest);
+    void closeFrontendConnection();
 
-    void closeFrontend();
     void bringToFront();
 
     WebPage* m_page;

Modified: trunk/Tools/ChangeLog (189374 => 189375)


--- trunk/Tools/ChangeLog	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Tools/ChangeLog	2015-09-04 20:00:22 UTC (rev 189375)
@@ -1,3 +1,23 @@
+2015-09-04  Brian Burg  <[email protected]>
+
+        Web Inspector: InspectorController should support multiple frontend channels
+        https://bugs.webkit.org/show_bug.cgi?id=148538
+
+        Reviewed by Joseph Pecoraro.
+
+        InspectorClients must explicitly disconnect their frontend channel(s) from the
+        inspected page's InspectorController.
+
+        To make this possible, DumpRenderTree should not destroy non-primary views until
+        it has tried to close any abandoned Web Inspector instances. Performing teardown
+        in the reverse order prevents disconnection of the frontend channel because that
+        prematurely destroys the inspector frontend client.
+
+        * DumpRenderTree/mac/DumpRenderTree.mm:
+        (runTest):
+        * DumpRenderTree/win/DumpRenderTree.cpp:
+        (runTest):
+
 2015-09-04  Beth Dakin  <[email protected]>
 
         Need to be able to test default behaviors on force click

Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm (189374 => 189375)


--- trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm	2015-09-04 20:00:22 UTC (rev 189375)
@@ -2039,6 +2039,13 @@
 
     workQueue.clear();
 
+    // If the test page could have possibly opened the Web Inspector frontend,
+    // then try to close it in case it was accidentally left open.
+    if (shouldEnableDeveloperExtras(pathOrURL.c_str())) {
+        gTestRunner->closeWebInspector();
+        gTestRunner->setDeveloperExtrasEnabled(false);
+    }
+
     if (gTestRunner->closeRemainingWindowsWhenComplete()) {
         NSArray* array = [DumpRenderTreeWindow openWindows];
 
@@ -2062,12 +2069,6 @@
         }
     }
 
-    // If developer extras enabled Web Inspector may have been open by the test.
-    if (shouldEnableDeveloperExtras(pathOrURL.c_str())) {
-        gTestRunner->closeWebInspector();
-        gTestRunner->setDeveloperExtrasEnabled(false);
-    }
-
     resetWebViewToConsistentStateBeforeTesting();
 
     // Loading an empty request synchronously replaces the document with a blank one, which is necessary

Modified: trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp (189374 => 189375)


--- trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp	2015-09-04 19:57:17 UTC (rev 189374)
+++ trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp	2015-09-04 20:00:22 UTC (rev 189375)
@@ -1147,6 +1147,13 @@
     // EventSendingController clearSavedEvents
     workQueue.clear();
 
+    // If the test page could have possibly opened the Web Inspector frontend,
+    // then try to close it in case it was accidentally left open.
+    if (shouldEnableDeveloperExtras(pathOrURL.c_str())) {
+        ::gTestRunner->closeWebInspector();
+        ::gTestRunner->setDeveloperExtrasEnabled(false);
+    }
+
     if (::gTestRunner->closeRemainingWindowsWhenComplete()) {
         Vector<HWND> windows = openWindows();
         unsigned size = windows.size();
@@ -1161,11 +1168,6 @@
         }
     }
 
-    if (shouldEnableDeveloperExtras(pathOrURL.c_str())) {
-        ::gTestRunner->closeWebInspector();
-        ::gTestRunner->setDeveloperExtrasEnabled(false);
-    }
-
     resetWebViewToConsistentStateBeforeTesting();
 
     // Loading an empty request synchronously replaces the document with a blank one, which is necessary
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to