2
* Copyright (C) 2018 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
13
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
#include "WebPageInspectorController.h"
29
#include "ProvisionalPageProxy.h"
30
#include "WebFrameProxy.h"
31
#include "WebPageInspectorTarget.h"
32
#include "WebPageProxy.h"
33
#include <JavaScriptCore/InspectorAgentBase.h>
34
#include <JavaScriptCore/InspectorBackendDispatcher.h>
35
#include <JavaScriptCore/InspectorBackendDispatchers.h>
36
#include <JavaScriptCore/InspectorFrontendRouter.h>
37
#include <JavaScriptCore/InspectorTargetAgent.h>
38
#include <wtf/HashMap.h>
42
using namespace Inspector;
44
static String getTargetID(const ProvisionalPageProxy& provisionalPage)
46
return WebPageInspectorTarget::toTargetID(provisionalPage.webPageID());
49
WebPageInspectorController::WebPageInspectorController(WebPageProxy& page)
51
, m_frontendRouter(FrontendRouter::create())
52
, m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
54
auto targetAgent = makeUnique<InspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
56
m_targetAgent = targetAgent.get();
58
m_agents.append(WTFMove(targetAgent));
61
void WebPageInspectorController::init()
63
String pageTargetId = WebPageInspectorTarget::toTargetID(m_page.webPageID());
64
createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
67
void WebPageInspectorController::pageClosed()
69
disconnectAllFrontends();
71
m_agents.discardValues();
74
bool WebPageInspectorController::hasLocalFrontend() const
76
return m_frontendRouter->hasLocalFrontend();
79
void WebPageInspectorController::connectFrontend(Inspector::FrontendChannel& frontendChannel, bool, bool)
81
bool connectingFirstFrontend = !m_frontendRouter->hasFrontends();
83
m_frontendRouter->connectFrontend(frontendChannel);
85
if (connectingFirstFrontend)
86
m_agents.didCreateFrontendAndBackend(&m_frontendRouter.get(), &m_backendDispatcher.get());
88
m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
90
#if ENABLE(REMOTE_INSPECTOR)
91
if (hasLocalFrontend())
92
m_page.remoteInspectorInformationDidChange();
96
void WebPageInspectorController::disconnectFrontend(FrontendChannel& frontendChannel)
98
m_frontendRouter->disconnectFrontend(frontendChannel);
100
bool disconnectingLastFrontend = !m_frontendRouter->hasFrontends();
101
if (disconnectingLastFrontend)
102
m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectorDestroyed);
104
m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
106
#if ENABLE(REMOTE_INSPECTOR)
107
if (disconnectingLastFrontend)
108
m_page.remoteInspectorInformationDidChange();
112
void WebPageInspectorController::disconnectAllFrontends()
114
// FIXME: Handle a local inspector client.
116
if (!m_frontendRouter->hasFrontends())
119
// Notify agents first, since they may need to use InspectorClient.
120
m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectedTargetDestroyed);
122
// Disconnect any remaining remote frontends.
123
m_frontendRouter->disconnectAllFrontends();
125
m_page.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount());
127
#if ENABLE(REMOTE_INSPECTOR)
128
m_page.remoteInspectorInformationDidChange();
132
void WebPageInspectorController::dispatchMessageFromFrontend(const String& message)
134
m_backendDispatcher->dispatch(message);
137
#if ENABLE(REMOTE_INSPECTOR)
138
void WebPageInspectorController::setIndicating(bool indicating)
140
#if !PLATFORM(IOS_FAMILY)
141
m_page.setIndicating(indicating);
144
m_page.showInspectorIndication();
146
m_page.hideInspectorIndication();
151
void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
153
addTarget(InspectorTargetProxy::create(m_page, targetId, type));
156
void WebPageInspectorController::destroyInspectorTarget(const String& targetId)
158
auto it = m_targets.find(targetId);
159
if (it == m_targets.end())
161
m_targetAgent->targetDestroyed(*it->value);
162
m_targets.remove(it);
165
void WebPageInspectorController::sendMessageToInspectorFrontend(const String& targetId, const String& message)
167
m_targetAgent->sendMessageFromTargetToFrontend(targetId, message);
170
bool WebPageInspectorController::shouldPauseLoading(const ProvisionalPageProxy& provisionalPage) const
172
if (!m_frontendRouter->hasFrontends())
175
auto* target = m_targets.get(getTargetID(provisionalPage));
177
return target->isPaused();
180
void WebPageInspectorController::setContinueLoadingCallback(const ProvisionalPageProxy& provisionalPage, WTF::Function<void()>&& callback)
182
auto* target = m_targets.get(getTargetID(provisionalPage));
184
target->setResumeCallback(WTFMove(callback));
187
void WebPageInspectorController::didCreateProvisionalPage(ProvisionalPageProxy& provisionalPage)
189
addTarget(InspectorTargetProxy::create(provisionalPage, getTargetID(provisionalPage), Inspector::InspectorTargetType::Page));
192
void WebPageInspectorController::willDestroyProvisionalPage(const ProvisionalPageProxy& provisionalPage)
194
destroyInspectorTarget(getTargetID(provisionalPage));
197
void WebPageInspectorController::didCommitProvisionalPage(WebCore::PageIdentifier oldWebPageID, WebCore::PageIdentifier newWebPageID)
199
String oldID = WebPageInspectorTarget::toTargetID(oldWebPageID);
200
String newID = WebPageInspectorTarget::toTargetID(newWebPageID);
201
auto newTarget = m_targets.take(newID);
203
newTarget->didCommitProvisionalTarget();
204
m_targetAgent->didCommitProvisionalTarget(oldID, newID);
206
// We've disconnected from the old page and will not receive any message from it, so
207
// we destroy everything but the new target here.
208
// FIXME: <https://webkit.org/b/202937> do not destroy targets that belong to the committed page.
209
for (auto& target : m_targets.values())
210
m_targetAgent->targetDestroyed(*target);
212
m_targets.set(newTarget->identifier(), WTFMove(newTarget));
215
void WebPageInspectorController::addTarget(std::unique_ptr<InspectorTargetProxy>&& target)
217
m_targetAgent->targetCreated(*target);
218
m_targets.set(target->identifier(), WTFMove(target));
221
} // namespace WebKit