2
* Copyright (C) 2010, 2014-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. AND ITS CONTRIBUTORS ``AS IS''
14
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
* THE POSSIBILITY OF SUCH DAMAGE.
27
#include "WebInspector.h"
30
#include "WebInspectorMessages.h"
31
#include "WebInspectorProxyMessages.h"
32
#include "WebInspectorUIMessages.h"
34
#include "WebProcess.h"
35
#include <WebCore/Chrome.h>
36
#include <WebCore/Document.h>
37
#include <WebCore/Frame.h>
38
#include <WebCore/FrameLoadRequest.h>
39
#include <WebCore/FrameLoader.h>
40
#include <WebCore/FrameView.h>
41
#include <WebCore/InspectorController.h>
42
#include <WebCore/InspectorFrontendClient.h>
43
#include <WebCore/InspectorPageAgent.h>
44
#include <WebCore/NavigationAction.h>
45
#include <WebCore/NotImplemented.h>
46
#include <WebCore/Page.h>
47
#include <WebCore/ScriptController.h>
48
#include <WebCore/WindowFeatures.h>
50
static const float minimumAttachedHeight = 250;
51
static const float maximumAttachedHeightRatio = 0.75;
52
static const float minimumAttachedWidth = 500;
55
using namespace WebCore;
57
Ref<WebInspector> WebInspector::create(WebPage* page)
59
return adoptRef(*new WebInspector(page));
62
WebInspector::WebInspector(WebPage* page)
67
WebInspector::~WebInspector()
69
if (m_frontendConnection)
70
m_frontendConnection->invalidate();
73
void WebInspector::openLocalInspectorFrontend(bool underTest)
75
WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::OpenLocalInspectorFrontend(canAttachWindow(), underTest), m_page->identifier());
78
void WebInspector::setFrontendConnection(IPC::Attachment encodedConnectionIdentifier)
80
// We might receive multiple updates if this web process got swapped into a WebPageProxy
81
// shortly after another process established the connection.
82
if (m_frontendConnection) {
83
m_frontendConnection->invalidate();
84
m_frontendConnection = nullptr;
87
#if USE(UNIX_DOMAIN_SOCKETS)
88
IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.releaseFileDescriptor());
90
IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
92
IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.handle());
98
if (!IPC::Connection::identifierIsValid(connectionIdentifier))
101
m_frontendConnection = IPC::Connection::createClientConnection(connectionIdentifier, *this);
102
m_frontendConnection->open();
104
for (auto& callback : m_frontendConnectionActions)
106
m_frontendConnectionActions.clear();
109
void WebInspector::closeFrontendConnection()
111
WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::DidClose(), m_page->identifier());
113
// If we tried to close the frontend before it was created, then no connection exists yet.
114
if (m_frontendConnection) {
115
m_frontendConnection->invalidate();
116
m_frontendConnection = nullptr;
119
m_frontendConnectionActions.clear();
122
m_previousCanAttach = false;
125
void WebInspector::bringToFront()
127
WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::BringToFront(), m_page->identifier());
130
void WebInspector::whenFrontendConnectionEstablished(Function<void()>&& callback)
132
if (m_frontendConnection) {
137
m_frontendConnectionActions.append(WTFMove(callback));
140
// Called by WebInspector messages
141
void WebInspector::show()
143
if (!m_page->corePage())
146
m_page->corePage()->inspectorController().show();
149
void WebInspector::close()
151
if (!m_page->corePage())
154
// Close could be called multiple times during teardown.
155
if (!m_frontendConnection)
158
closeFrontendConnection();
161
void WebInspector::openInNewTab(const String& urlString)
163
UserGestureIndicator indicator { ProcessingUserGesture };
165
Page* inspectedPage = m_page->corePage();
169
Frame& inspectedMainFrame = inspectedPage->mainFrame();
170
FrameLoadRequest frameLoadRequest { *inspectedMainFrame.document(), inspectedMainFrame.document()->securityOrigin(), ResourceRequest { urlString }, "_blank"_s, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown };
172
NavigationAction action { *inspectedMainFrame.document(), frameLoadRequest.resourceRequest(), frameLoadRequest.initiatedByMainFrame(), NavigationType::LinkClicked };
173
Page* newPage = inspectedPage->chrome().createWindow(inspectedMainFrame, frameLoadRequest, { }, action);
177
newPage->mainFrame().loader().load(WTFMove(frameLoadRequest));
180
void WebInspector::evaluateScriptForTest(const String& script)
182
if (!m_page->corePage())
185
m_page->corePage()->inspectorController().evaluateForTestInFrontend(script);
188
void WebInspector::showConsole()
190
if (!m_page->corePage())
193
m_page->corePage()->inspectorController().show();
195
whenFrontendConnectionEstablished([=] {
196
m_frontendConnection->send(Messages::WebInspectorUI::ShowConsole(), 0);
200
void WebInspector::showResources()
202
if (!m_page->corePage())
205
m_page->corePage()->inspectorController().show();
207
whenFrontendConnectionEstablished([=] {
208
m_frontendConnection->send(Messages::WebInspectorUI::ShowResources(), 0);
212
void WebInspector::showMainResourceForFrame(WebCore::FrameIdentifier frameIdentifier)
214
WebFrame* frame = WebProcess::singleton().webFrame(frameIdentifier);
218
if (!m_page->corePage())
221
m_page->corePage()->inspectorController().show();
223
String inspectorFrameIdentifier = m_page->corePage()->inspectorController().ensurePageAgent().frameId(frame->coreFrame());
225
whenFrontendConnectionEstablished([=] {
226
m_frontendConnection->send(Messages::WebInspectorUI::ShowMainResourceForFrame(inspectorFrameIdentifier), 0);
230
void WebInspector::startPageProfiling()
232
if (!m_page->corePage())
235
m_page->corePage()->inspectorController().show();
237
whenFrontendConnectionEstablished([=] {
238
m_frontendConnection->send(Messages::WebInspectorUI::StartPageProfiling(), 0);
242
void WebInspector::stopPageProfiling()
244
if (!m_page->corePage())
247
m_page->corePage()->inspectorController().show();
249
whenFrontendConnectionEstablished([=] {
250
m_frontendConnection->send(Messages::WebInspectorUI::StopPageProfiling(), 0);
254
void WebInspector::startElementSelection()
256
if (!m_page->corePage())
259
whenFrontendConnectionEstablished([=] {
260
m_frontendConnection->send(Messages::WebInspectorUI::StartElementSelection(), 0);
264
void WebInspector::stopElementSelection()
266
if (!m_page->corePage())
269
whenFrontendConnectionEstablished([=] {
270
m_frontendConnection->send(Messages::WebInspectorUI::StopElementSelection(), 0);
274
void WebInspector::elementSelectionChanged(bool active)
276
WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::ElementSelectionChanged(active), m_page->identifier());
279
void WebInspector::timelineRecordingChanged(bool active)
281
WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::TimelineRecordingChanged(active), m_page->identifier());
284
void WebInspector::setMockCaptureDevicesEnabledOverride(Optional<bool> enabled)
286
WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SetMockCaptureDevicesEnabledOverride(enabled), m_page->identifier());
289
bool WebInspector::canAttachWindow()
291
if (!m_page->corePage())
294
// Don't allow attaching to another inspector -- two inspectors in one window is too much!
295
if (m_page->isInspectorPage())
298
// If we are already attached, allow attaching again to allow switching sides.
302
// Don't allow the attach if the window would be too small to accommodate the minimum inspector size.
303
unsigned inspectedPageHeight = m_page->corePage()->mainFrame().view()->visibleHeight();
304
unsigned inspectedPageWidth = m_page->corePage()->mainFrame().view()->visibleWidth();
305
unsigned maximumAttachedHeight = inspectedPageHeight * maximumAttachedHeightRatio;
306
return minimumAttachedHeight <= maximumAttachedHeight && minimumAttachedWidth <= inspectedPageWidth;
309
void WebInspector::updateDockingAvailability()
314
bool canAttachWindow = this->canAttachWindow();
315
if (m_previousCanAttach == canAttachWindow)
318
m_previousCanAttach = canAttachWindow;
320
WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::AttachAvailabilityChanged(canAttachWindow), m_page->identifier());
323
} // namespace WebKit