~mmach/netext73/webkit2gtk

« back to all changes in this revision

Viewing changes to Source/WebKit/WebProcess/Inspector/WebInspector.cpp

  • Committer: mmach
  • Date: 2023-06-16 17:21:37 UTC
  • Revision ID: netbit73@gmail.com-20230616172137-2rqx6yr96ga9g3kp
1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010, 2014-2018 Apple Inc. All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions
 
6
 * are met:
 
7
 * 1. Redistributions of source code must retain the above copyright
 
8
 *    notice, this list of conditions and the following disclaimer.
 
9
 * 2. Redistributions in binary form must reproduce the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer in the
 
11
 *    documentation and/or other materials provided with the distribution.
 
12
 *
 
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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.
 
24
 */
 
25
 
 
26
#include "config.h"
 
27
#include "WebInspector.h"
 
28
 
 
29
#include "WebFrame.h"
 
30
#include "WebInspectorMessages.h"
 
31
#include "WebInspectorProxyMessages.h"
 
32
#include "WebInspectorUIMessages.h"
 
33
#include "WebPage.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>
 
49
 
 
50
static const float minimumAttachedHeight = 250;
 
51
static const float maximumAttachedHeightRatio = 0.75;
 
52
static const float minimumAttachedWidth = 500;
 
53
 
 
54
namespace WebKit {
 
55
using namespace WebCore;
 
56
 
 
57
Ref<WebInspector> WebInspector::create(WebPage* page)
 
58
{
 
59
    return adoptRef(*new WebInspector(page));
 
60
}
 
61
 
 
62
WebInspector::WebInspector(WebPage* page)
 
63
    : m_page(page)
 
64
{
 
65
}
 
66
 
 
67
WebInspector::~WebInspector()
 
68
{
 
69
    if (m_frontendConnection)
 
70
        m_frontendConnection->invalidate();
 
71
}
 
72
 
 
73
void WebInspector::openLocalInspectorFrontend(bool underTest)
 
74
{
 
75
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::OpenLocalInspectorFrontend(canAttachWindow(), underTest), m_page->identifier());
 
76
}
 
77
 
 
78
void WebInspector::setFrontendConnection(IPC::Attachment encodedConnectionIdentifier)
 
79
{
 
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;
 
85
    }
 
86
 
 
87
#if USE(UNIX_DOMAIN_SOCKETS)
 
88
    IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.releaseFileDescriptor());
 
89
#elif OS(DARWIN)
 
90
    IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
 
91
#elif OS(WINDOWS)
 
92
    IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.handle());
 
93
#else
 
94
    notImplemented();
 
95
    return;
 
96
#endif
 
97
 
 
98
    if (!IPC::Connection::identifierIsValid(connectionIdentifier))
 
99
        return;
 
100
 
 
101
    m_frontendConnection = IPC::Connection::createClientConnection(connectionIdentifier, *this);
 
102
    m_frontendConnection->open();
 
103
 
 
104
    for (auto& callback : m_frontendConnectionActions)
 
105
        callback();
 
106
    m_frontendConnectionActions.clear();
 
107
}
 
108
 
 
109
void WebInspector::closeFrontendConnection()
 
110
{
 
111
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::DidClose(), m_page->identifier());
 
112
 
 
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;
 
117
    }
 
118
 
 
119
    m_frontendConnectionActions.clear();
 
120
 
 
121
    m_attached = false;
 
122
    m_previousCanAttach = false;
 
123
}
 
124
 
 
125
void WebInspector::bringToFront()
 
126
{
 
127
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::BringToFront(), m_page->identifier());
 
128
}
 
129
 
 
130
void WebInspector::whenFrontendConnectionEstablished(Function<void()>&& callback)
 
131
{
 
132
    if (m_frontendConnection) {
 
133
        callback();
 
134
        return;
 
135
    }
 
136
 
 
137
    m_frontendConnectionActions.append(WTFMove(callback));
 
138
}
 
139
 
 
140
// Called by WebInspector messages
 
141
void WebInspector::show()
 
142
{
 
143
    if (!m_page->corePage())
 
144
        return;
 
145
 
 
146
    m_page->corePage()->inspectorController().show();
 
147
}
 
148
 
 
149
void WebInspector::close()
 
150
{
 
151
    if (!m_page->corePage())
 
152
        return;
 
153
 
 
154
    // Close could be called multiple times during teardown.
 
155
    if (!m_frontendConnection)
 
156
        return;
 
157
 
 
158
    closeFrontendConnection();
 
159
}
 
160
 
 
161
void WebInspector::openInNewTab(const String& urlString)
 
162
{
 
163
    UserGestureIndicator indicator { ProcessingUserGesture };
 
164
 
 
165
    Page* inspectedPage = m_page->corePage();
 
166
    if (!inspectedPage)
 
167
        return;
 
168
 
 
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 };
 
171
 
 
172
    NavigationAction action { *inspectedMainFrame.document(), frameLoadRequest.resourceRequest(), frameLoadRequest.initiatedByMainFrame(), NavigationType::LinkClicked };
 
173
    Page* newPage = inspectedPage->chrome().createWindow(inspectedMainFrame, frameLoadRequest, { }, action);
 
174
    if (!newPage)
 
175
        return;
 
176
 
 
177
    newPage->mainFrame().loader().load(WTFMove(frameLoadRequest));
 
178
}
 
179
 
 
180
void WebInspector::evaluateScriptForTest(const String& script)
 
181
{
 
182
    if (!m_page->corePage())
 
183
        return;
 
184
 
 
185
    m_page->corePage()->inspectorController().evaluateForTestInFrontend(script);
 
186
}
 
187
 
 
188
void WebInspector::showConsole()
 
189
{
 
190
    if (!m_page->corePage())
 
191
        return;
 
192
 
 
193
    m_page->corePage()->inspectorController().show();
 
194
 
 
195
    whenFrontendConnectionEstablished([=] {
 
196
        m_frontendConnection->send(Messages::WebInspectorUI::ShowConsole(), 0);
 
197
    });
 
198
}
 
199
 
 
200
void WebInspector::showResources()
 
201
{
 
202
    if (!m_page->corePage())
 
203
        return;
 
204
 
 
205
    m_page->corePage()->inspectorController().show();
 
206
 
 
207
    whenFrontendConnectionEstablished([=] {
 
208
        m_frontendConnection->send(Messages::WebInspectorUI::ShowResources(), 0);
 
209
    });
 
210
}
 
211
 
 
212
void WebInspector::showMainResourceForFrame(WebCore::FrameIdentifier frameIdentifier)
 
213
{
 
214
    WebFrame* frame = WebProcess::singleton().webFrame(frameIdentifier);
 
215
    if (!frame)
 
216
        return;
 
217
 
 
218
    if (!m_page->corePage())
 
219
        return;
 
220
 
 
221
    m_page->corePage()->inspectorController().show();
 
222
 
 
223
    String inspectorFrameIdentifier = m_page->corePage()->inspectorController().ensurePageAgent().frameId(frame->coreFrame());
 
224
 
 
225
    whenFrontendConnectionEstablished([=] {
 
226
        m_frontendConnection->send(Messages::WebInspectorUI::ShowMainResourceForFrame(inspectorFrameIdentifier), 0);
 
227
    });
 
228
}
 
229
 
 
230
void WebInspector::startPageProfiling()
 
231
{
 
232
    if (!m_page->corePage())
 
233
        return;
 
234
 
 
235
    m_page->corePage()->inspectorController().show();
 
236
 
 
237
    whenFrontendConnectionEstablished([=] {
 
238
        m_frontendConnection->send(Messages::WebInspectorUI::StartPageProfiling(), 0);
 
239
    });
 
240
}
 
241
 
 
242
void WebInspector::stopPageProfiling()
 
243
{
 
244
    if (!m_page->corePage())
 
245
        return;
 
246
 
 
247
    m_page->corePage()->inspectorController().show();
 
248
 
 
249
    whenFrontendConnectionEstablished([=] {
 
250
        m_frontendConnection->send(Messages::WebInspectorUI::StopPageProfiling(), 0);
 
251
    });
 
252
}
 
253
 
 
254
void WebInspector::startElementSelection()
 
255
{
 
256
    if (!m_page->corePage())
 
257
        return;
 
258
 
 
259
    whenFrontendConnectionEstablished([=] {
 
260
        m_frontendConnection->send(Messages::WebInspectorUI::StartElementSelection(), 0);
 
261
    });
 
262
}
 
263
 
 
264
void WebInspector::stopElementSelection()
 
265
{
 
266
    if (!m_page->corePage())
 
267
        return;
 
268
 
 
269
    whenFrontendConnectionEstablished([=] {
 
270
        m_frontendConnection->send(Messages::WebInspectorUI::StopElementSelection(), 0);
 
271
    });
 
272
}
 
273
 
 
274
void WebInspector::elementSelectionChanged(bool active)
 
275
{
 
276
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::ElementSelectionChanged(active), m_page->identifier());
 
277
}
 
278
 
 
279
void WebInspector::timelineRecordingChanged(bool active)
 
280
{
 
281
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::TimelineRecordingChanged(active), m_page->identifier());
 
282
}
 
283
 
 
284
void WebInspector::setMockCaptureDevicesEnabledOverride(Optional<bool> enabled)
 
285
{
 
286
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SetMockCaptureDevicesEnabledOverride(enabled), m_page->identifier());
 
287
}
 
288
 
 
289
bool WebInspector::canAttachWindow()
 
290
{
 
291
    if (!m_page->corePage())
 
292
        return false;
 
293
 
 
294
    // Don't allow attaching to another inspector -- two inspectors in one window is too much!
 
295
    if (m_page->isInspectorPage())
 
296
        return false;
 
297
 
 
298
    // If we are already attached, allow attaching again to allow switching sides.
 
299
    if (m_attached)
 
300
        return true;
 
301
 
 
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;
 
307
}
 
308
 
 
309
void WebInspector::updateDockingAvailability()
 
310
{
 
311
    if (m_attached)
 
312
        return;
 
313
 
 
314
    bool canAttachWindow = this->canAttachWindow();
 
315
    if (m_previousCanAttach == canAttachWindow)
 
316
        return;
 
317
 
 
318
    m_previousCanAttach = canAttachWindow;
 
319
 
 
320
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::AttachAvailabilityChanged(canAttachWindow), m_page->identifier());
 
321
}
 
322
 
 
323
} // namespace WebKit