blob: 6289c5eab18f2847ca1da34df203749b7b4e35d7 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371/*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Matt Lilek ([email protected]).
4 * Copyright (C) 2009 Joseph Pecoraro
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/**
32 * @unrestricted
33 */
Paul Lewisc1d99fa2019-12-10 16:26:2834export class MainImpl {
Blink Reformat4c46d092018-04-07 15:32:3735 /**
36 * @suppressGlobalPropertiesCheck
37 */
38 constructor() {
Paul Lewisc1d99fa2019-12-10 16:26:2839 MainImpl._instanceForTest = this;
Blink Reformat4c46d092018-04-07 15:32:3740 runOnWindowLoad(this._loaded.bind(this));
41 }
42
43 /**
44 * @param {string} label
45 */
46 static time(label) {
Tim van der Lippe1d6e57a2019-09-30 11:55:3447 if (Host.isUnderTest()) {
Blink Reformat4c46d092018-04-07 15:32:3748 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:3449 }
Blink Reformat4c46d092018-04-07 15:32:3750 console.time(label);
51 }
52
53 /**
54 * @param {string} label
55 */
56 static timeEnd(label) {
Tim van der Lippe1d6e57a2019-09-30 11:55:3457 if (Host.isUnderTest()) {
Blink Reformat4c46d092018-04-07 15:32:3758 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:3459 }
Blink Reformat4c46d092018-04-07 15:32:3760 console.timeEnd(label);
61 }
62
63 async _loaded() {
64 console.timeStamp('Main._loaded');
Tim van der Lippe99e59b82019-09-30 20:00:5965 await Root.Runtime.appStarted();
66 Root.Runtime.setPlatform(Host.platform());
67 Root.Runtime.setL10nCallback(ls);
Tim van der Lippe50cfa9b2019-10-01 10:40:5868 Host.InspectorFrontendHost.getPreferences(this._gotPreferences.bind(this));
Blink Reformat4c46d092018-04-07 15:32:3769 }
70
71 /**
72 * @param {!Object<string, string>} prefs
73 */
74 _gotPreferences(prefs) {
75 console.timeStamp('Main._gotPreferences');
Tim van der Lippe1d6e57a2019-09-30 11:55:3476 if (Host.isUnderTest(prefs)) {
Blink Reformat4c46d092018-04-07 15:32:3777 self.runtime.useTestBase();
Tim van der Lippe1d6e57a2019-09-30 11:55:3478 }
Blink Reformat4c46d092018-04-07 15:32:3779 this._createSettings(prefs);
80 this._createAppUI();
81 }
82
83 /**
84 * @param {!Object<string, string>} prefs
85 * Note: this function is called from testSettings in Tests.js.
86 */
87 _createSettings(prefs) {
88 this._initializeExperiments();
89 let storagePrefix = '';
Tim van der Lippe1d6e57a2019-09-30 11:55:3490 if (Host.isCustomDevtoolsFrontend()) {
Blink Reformat4c46d092018-04-07 15:32:3791 storagePrefix = '__custom__';
Tim van der Lippe99e59b82019-09-30 20:00:5992 } else if (
93 !Root.Runtime.queryParam('can_dock') && !!Root.Runtime.queryParam('debugFrontend') && !Host.isUnderTest()) {
Blink Reformat4c46d092018-04-07 15:32:3794 storagePrefix = '__bundled__';
Tim van der Lippe1d6e57a2019-09-30 11:55:3495 }
Blink Reformat4c46d092018-04-07 15:32:3796
97 let localStorage;
98 if (!Host.isUnderTest() && window.localStorage) {
99 localStorage = new Common.SettingsStorage(
100 window.localStorage, undefined, undefined, () => window.localStorage.clear(), storagePrefix);
101 } else {
102 localStorage = new Common.SettingsStorage({}, undefined, undefined, undefined, storagePrefix);
103 }
104 const globalStorage = new Common.SettingsStorage(
Tim van der Lippe50cfa9b2019-10-01 10:40:58105 prefs, Host.InspectorFrontendHost.setPreference, Host.InspectorFrontendHost.removePreference,
106 Host.InspectorFrontendHost.clearPreferences, storagePrefix);
Blink Reformat4c46d092018-04-07 15:32:37107 Common.settings = new Common.Settings(globalStorage, localStorage);
Tim van der Lippe1d6e57a2019-09-30 11:55:34108 if (!Host.isUnderTest()) {
Blink Reformat4c46d092018-04-07 15:32:37109 new Common.VersionController().updateVersion();
Tim van der Lippe1d6e57a2019-09-30 11:55:34110 }
Blink Reformat4c46d092018-04-07 15:32:37111 }
112
113 _initializeExperiments() {
114 // Keep this sorted alphabetically: both keys and values.
Tim van der Lippe99e59b82019-09-30 20:00:59115 Root.Runtime.experiments.register('applyCustomStylesheet', 'Allow custom UI themes');
116 Root.Runtime.experiments.register('captureNodeCreationStacks', 'Capture node creation stacks');
117 Root.Runtime.experiments.register('sourcesPrettyPrint', 'Automatically pretty print in the Sources Panel');
118 Root.Runtime.experiments.register('backgroundServices', 'Background web platform feature events', true);
119 Root.Runtime.experiments.register(
120 'backgroundServicesNotifications', 'Background services section for Notifications');
121 Root.Runtime.experiments.register(
122 'backgroundServicesPaymentHandler', 'Background services section for Payment Handler');
123 Root.Runtime.experiments.register(
124 'backgroundServicesPushMessaging', 'Background services section for Push Messaging');
125 Root.Runtime.experiments.register(
Rayan Kanso54809672019-07-24 18:40:28126 'backgroundServicesPeriodicBackgroundSync', 'Background services section for Periodic Background Sync');
Tim van der Lippe99e59b82019-09-30 20:00:59127 Root.Runtime.experiments.register('blackboxJSFramesOnTimeline', 'Blackbox JavaScript frames on Timeline', true);
128 Root.Runtime.experiments.register('cssOverview', 'CSS Overview');
129 Root.Runtime.experiments.register('emptySourceMapAutoStepping', 'Empty sourcemap auto-stepping');
130 Root.Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true);
131 Root.Runtime.experiments.register('liveHeapProfile', 'Live heap profile', true);
Ted Meyer79b022f2019-10-08 18:24:30132 Root.Runtime.experiments.register('mediaInspector', 'Media Element Inspection');
Tim van der Lippe99e59b82019-09-30 20:00:59133 Root.Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true);
134 Root.Runtime.experiments.register('protocolMonitor', 'Protocol Monitor');
135 Root.Runtime.experiments.register(
Sigurd Schneider4c5f0c62019-12-11 12:24:09136 'reportInternalNetErrorOnSourceMapLoadFail', 'Report internal net error code when a SourceMap fails to load');
137 Root.Runtime.experiments.register(
Tim van der Lippe99e59b82019-09-30 20:00:59138 'recordCoverageWithPerformanceTracing', 'Record coverage while performance tracing');
139 Root.Runtime.experiments.register('samplingHeapProfilerTimeline', 'Sampling heap profiler timeline', true);
140 Root.Runtime.experiments.register('sourceDiff', 'Source diff');
Tim van der Lippe99e59b82019-09-30 20:00:59141 Root.Runtime.experiments.register('spotlight', 'Spotlight', true);
Blink Reformat4c46d092018-04-07 15:32:37142
143 // Timeline
Tim van der Lippe99e59b82019-09-30 20:00:59144 Root.Runtime.experiments.register('timelineEventInitiators', 'Timeline: event initiators');
145 Root.Runtime.experiments.register('timelineFlowEvents', 'Timeline: flow events', true);
146 Root.Runtime.experiments.register('timelineInvalidationTracking', 'Timeline: invalidation tracking', true);
147 Root.Runtime.experiments.register('timelineShowAllEvents', 'Timeline: show all events', true);
148 Root.Runtime.experiments.register(
149 'timelineV8RuntimeCallStats', 'Timeline: V8 Runtime Call Stats on Timeline', true);
150 Root.Runtime.experiments.register('timelineWebGL', 'Timeline: WebGL-based flamechart');
Ella Ge78047ef2019-12-13 14:19:51151 Root.Runtime.experiments.register('timelineReplayEvent', 'Timeline: Replay input events');
Blink Reformat4c46d092018-04-07 15:32:37152
Tim van der Lippe99e59b82019-09-30 20:00:59153 Root.Runtime.experiments.cleanUpStaleExperiments();
154 const enabledExperiments = Root.Runtime.queryParam('enabledExperiments');
Tim van der Lippe1d6e57a2019-09-30 11:55:34155 if (enabledExperiments) {
Tim van der Lippe99e59b82019-09-30 20:00:59156 Root.Runtime.experiments.setServerEnabledExperiments(enabledExperiments.split(';'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34157 }
Tim van der Lippe99e59b82019-09-30 20:00:59158 Root.Runtime.experiments.setDefaultExperiments([
Rayan Kanso93bacf72019-08-28 12:33:23159 'backgroundServices',
160 'backgroundServicesNotifications',
161 'backgroundServicesPushMessaging',
162 'backgroundServicesPaymentHandler',
163 ]);
Alexei Filippovfdfefe02019-03-09 00:33:24164
Tim van der Lippe99e59b82019-09-30 20:00:59165 if (Host.isUnderTest() && Root.Runtime.queryParam('test').includes('live-line-level-heap-profile.js')) {
166 Root.Runtime.experiments.enableForTest('liveHeapProfile');
Tim van der Lippe1d6e57a2019-09-30 11:55:34167 }
Blink Reformat4c46d092018-04-07 15:32:37168 }
169
170 /**
171 * @suppressGlobalPropertiesCheck
172 */
173 async _createAppUI() {
Paul Lewisc1d99fa2019-12-10 16:26:28174 MainImpl.time('Main._createAppUI');
Blink Reformat4c46d092018-04-07 15:32:37175
176 UI.viewManager = new UI.ViewManager();
177
178 // Request filesystems early, we won't create connections until callback is fired. Things will happen in parallel.
179 Persistence.isolatedFileSystemManager = new Persistence.IsolatedFileSystemManager();
180
Erik Luo9adba992019-06-26 01:17:52181 const themeSetting = Common.settings.createSetting('uiTheme', 'systemPreferred');
Blink Reformat4c46d092018-04-07 15:32:37182 UI.initializeUIUtils(document, themeSetting);
183 themeSetting.addChangeListener(Components.reload.bind(Components));
184
185 UI.installComponentRootStyles(/** @type {!Element} */ (document.body));
186
187 this._addMainEventListeners(document);
188
Tim van der Lippe99e59b82019-09-30 20:00:59189 const canDock = !!Root.Runtime.queryParam('can_dock');
Tim van der Lippe50cfa9b2019-10-01 10:40:58190 UI.zoomManager = new UI.ZoomManager(window, Host.InspectorFrontendHost);
Blink Reformat4c46d092018-04-07 15:32:37191 UI.inspectorView = UI.InspectorView.instance();
192 UI.ContextMenu.initialize();
193 UI.ContextMenu.installHandler(document);
194 UI.Tooltip.installHandler(document);
195 Components.dockController = new Components.DockController(canDock);
196 SDK.consoleModel = new SDK.ConsoleModel();
197 SDK.multitargetNetworkManager = new SDK.MultitargetNetworkManager();
198 SDK.domDebuggerManager = new SDK.DOMDebuggerManager();
199 SDK.targetManager.addEventListener(
200 SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged.bind(this));
201
202 UI.shortcutsScreen = new UI.ShortcutsScreen();
203 // set order of some sections explicitly
204 UI.shortcutsScreen.section(Common.UIString('Elements Panel'));
205 UI.shortcutsScreen.section(Common.UIString('Styles Pane'));
206 UI.shortcutsScreen.section(Common.UIString('Debugger'));
207 UI.shortcutsScreen.section(Common.UIString('Console'));
208
209 Workspace.fileManager = new Workspace.FileManager();
210 Workspace.workspace = new Workspace.Workspace();
211
212 Bindings.networkProjectManager = new Bindings.NetworkProjectManager();
213 Bindings.resourceMapping = new Bindings.ResourceMapping(SDK.targetManager, Workspace.workspace);
214 new Bindings.PresentationConsoleMessageManager();
215 Bindings.cssWorkspaceBinding = new Bindings.CSSWorkspaceBinding(SDK.targetManager, Workspace.workspace);
216 Bindings.debuggerWorkspaceBinding = new Bindings.DebuggerWorkspaceBinding(SDK.targetManager, Workspace.workspace);
217 Bindings.breakpointManager =
218 new Bindings.BreakpointManager(Workspace.workspace, SDK.targetManager, Bindings.debuggerWorkspaceBinding);
219 Extensions.extensionServer = new Extensions.ExtensionServer();
220
221 new Persistence.FileSystemWorkspaceBinding(Persistence.isolatedFileSystemManager, Workspace.workspace);
222 Persistence.persistence = new Persistence.Persistence(Workspace.workspace, Bindings.breakpointManager);
223 Persistence.networkPersistenceManager = new Persistence.NetworkPersistenceManager(Workspace.workspace);
224
225 new Main.ExecutionContextSelector(SDK.targetManager, UI.context);
226 Bindings.blackboxManager = new Bindings.BlackboxManager(Bindings.debuggerWorkspaceBinding);
227
Paul Lewisc1d99fa2019-12-10 16:26:28228 new PauseListener();
Blink Reformat4c46d092018-04-07 15:32:37229
230 UI.actionRegistry = new UI.ActionRegistry();
231 UI.shortcutRegistry = new UI.ShortcutRegistry(UI.actionRegistry, document);
232 UI.ShortcutsScreen.registerShortcuts();
233 this._registerForwardedShortcuts();
234 this._registerMessageSinkListener();
235
Paul Lewisc1d99fa2019-12-10 16:26:28236 MainImpl.timeEnd('Main._createAppUI');
Blink Reformat4c46d092018-04-07 15:32:37237 this._showAppUI(await self.runtime.extension(Common.AppProvider).instance());
238 }
239
240 /**
241 * @param {!Object} appProvider
242 * @suppressGlobalPropertiesCheck
243 */
244 _showAppUI(appProvider) {
Paul Lewisc1d99fa2019-12-10 16:26:28245 MainImpl.time('Main._showAppUI');
Blink Reformat4c46d092018-04-07 15:32:37246 const app = /** @type {!Common.AppProvider} */ (appProvider).createApp();
247 // It is important to kick controller lifetime after apps are instantiated.
248 Components.dockController.initialize();
249 app.presentUI(document);
250
251 const toggleSearchNodeAction = UI.actionRegistry.action('elements.toggle-element-search');
252 // TODO: we should not access actions from other modules.
253 if (toggleSearchNodeAction) {
Tim van der Lippe50cfa9b2019-10-01 10:40:58254 Host.InspectorFrontendHost.events.addEventListener(
Tim van der Lippe7b190162019-09-27 15:10:44255 Host.InspectorFrontendHostAPI.Events.EnterInspectElementMode,
Blink Reformat4c46d092018-04-07 15:32:37256 toggleSearchNodeAction.execute.bind(toggleSearchNodeAction), this);
257 }
Tim van der Lippe50cfa9b2019-10-01 10:40:58258 Host.InspectorFrontendHost.events.addEventListener(
Tim van der Lippe7b190162019-09-27 15:10:44259 Host.InspectorFrontendHostAPI.Events.RevealSourceLine, this._revealSourceLine, this);
Blink Reformat4c46d092018-04-07 15:32:37260
261 UI.inspectorView.createToolbars();
Tim van der Lippe50cfa9b2019-10-01 10:40:58262 Host.InspectorFrontendHost.loadCompleted();
Blink Reformat4c46d092018-04-07 15:32:37263
264 const extensions = self.runtime.extensions(Common.QueryParamHandler);
265 for (const extension of extensions) {
Tim van der Lippe99e59b82019-09-30 20:00:59266 const value = Root.Runtime.queryParam(extension.descriptor()['name']);
Tim van der Lippe1d6e57a2019-09-30 11:55:34267 if (value !== null) {
Blink Reformat4c46d092018-04-07 15:32:37268 extension.instance().then(handleQueryParam.bind(null, value));
Tim van der Lippe1d6e57a2019-09-30 11:55:34269 }
Blink Reformat4c46d092018-04-07 15:32:37270 }
271
272 /**
273 * @param {string} value
274 * @param {!Common.QueryParamHandler} handler
275 */
276 function handleQueryParam(value, handler) {
277 handler.handleQueryParam(value);
278 }
279
280 // Allow UI cycles to repaint prior to creating connection.
281 setTimeout(this._initializeTarget.bind(this), 0);
Paul Lewisc1d99fa2019-12-10 16:26:28282 MainImpl.timeEnd('Main._showAppUI');
Blink Reformat4c46d092018-04-07 15:32:37283 }
284
285 async _initializeTarget() {
Paul Lewisc1d99fa2019-12-10 16:26:28286 MainImpl.time('Main._initializeTarget');
Blink Reformat4c46d092018-04-07 15:32:37287 const instances =
288 await Promise.all(self.runtime.extensions('early-initialization').map(extension => extension.instance()));
Tim van der Lippe1d6e57a2019-09-30 11:55:34289 for (const instance of instances) {
Pavel Feldman07ef9722018-12-13 23:52:22290 await /** @type {!Common.Runnable} */ (instance).run();
Tim van der Lippe1d6e57a2019-09-30 11:55:34291 }
Blink Reformat4c46d092018-04-07 15:32:37292 // Used for browser tests.
Tim van der Lippe50cfa9b2019-10-01 10:40:58293 Host.InspectorFrontendHost.readyForTest();
Blink Reformat4c46d092018-04-07 15:32:37294 // Asynchronously run the extensions.
295 setTimeout(this._lateInitialization.bind(this), 100);
Paul Lewisc1d99fa2019-12-10 16:26:28296 MainImpl.timeEnd('Main._initializeTarget');
Blink Reformat4c46d092018-04-07 15:32:37297 }
298
299 _lateInitialization() {
Paul Lewisc1d99fa2019-12-10 16:26:28300 MainImpl.time('Main._lateInitialization');
Blink Reformat4c46d092018-04-07 15:32:37301 this._registerShortcuts();
302 Extensions.extensionServer.initializeExtensions();
Alexei Filippov19be5102019-04-16 20:40:24303 const extensions = self.runtime.extensions('late-initialization');
304 const promises = [];
305 for (const extension of extensions) {
306 const setting = extension.descriptor()['setting'];
307 if (!setting || Common.settings.moduleSetting(setting).get()) {
308 promises.push(extension.instance().then(instance => (/** @type {!Common.Runnable} */ (instance)).run()));
309 continue;
310 }
311 /**
312 * @param {!Common.Event} event
313 */
314 async function changeListener(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34315 if (!event.data) {
Alexei Filippov19be5102019-04-16 20:40:24316 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34317 }
Alexei Filippov19be5102019-04-16 20:40:24318 Common.settings.moduleSetting(setting).removeChangeListener(changeListener);
319 (/** @type {!Common.Runnable} */ (await extension.instance())).run();
320 }
321 Common.settings.moduleSetting(setting).addChangeListener(changeListener);
322 }
323 this._lateInitDonePromise = Promise.all(promises);
Paul Lewisc1d99fa2019-12-10 16:26:28324 MainImpl.timeEnd('Main._lateInitialization');
Blink Reformat4c46d092018-04-07 15:32:37325 }
326
Alexei Filippov19be5102019-04-16 20:40:24327 /**
328 * @return {!Promise}
329 */
330 lateInitDonePromiseForTest() {
331 return this._lateInitDonePromise;
332 }
333
Blink Reformat4c46d092018-04-07 15:32:37334 _registerForwardedShortcuts() {
335 /** @const */ const forwardedActions = [
336 'main.toggle-dock', 'debugger.toggle-breakpoints-active', 'debugger.toggle-pause', 'commandMenu.show',
337 'console.show'
338 ];
339 const actionKeys =
340 UI.shortcutRegistry.keysForActions(forwardedActions).map(UI.KeyboardShortcut.keyCodeAndModifiersFromKey);
Tim van der Lippe50cfa9b2019-10-01 10:40:58341 Host.InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
Blink Reformat4c46d092018-04-07 15:32:37342 }
343
344 _registerMessageSinkListener() {
345 Common.console.addEventListener(Common.Console.Events.MessageAdded, messageAdded);
346
347 /**
348 * @param {!Common.Event} event
349 */
350 function messageAdded(event) {
351 const message = /** @type {!Common.Console.Message} */ (event.data);
Tim van der Lippe1d6e57a2019-09-30 11:55:34352 if (message.show) {
Blink Reformat4c46d092018-04-07 15:32:37353 Common.console.show();
Tim van der Lippe1d6e57a2019-09-30 11:55:34354 }
Blink Reformat4c46d092018-04-07 15:32:37355 }
356 }
357
358 /**
359 * @param {!Common.Event} event
360 */
361 _revealSourceLine(event) {
362 const url = /** @type {string} */ (event.data['url']);
363 const lineNumber = /** @type {number} */ (event.data['lineNumber']);
364 const columnNumber = /** @type {number} */ (event.data['columnNumber']);
365
366 const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
367 if (uiSourceCode) {
368 Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
369 return;
370 }
371
372 /**
373 * @param {!Common.Event} event
374 */
375 function listener(event) {
376 const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
377 if (uiSourceCode.url() === url) {
378 Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
379 Workspace.workspace.removeEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
380 }
381 }
382
383 Workspace.workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
384 }
385
386 _registerShortcuts() {
387 const shortcut = UI.KeyboardShortcut;
388 const section = UI.shortcutsScreen.section(Common.UIString('All Panels'));
389 let keys = [
390 shortcut.makeDescriptor('[', shortcut.Modifiers.CtrlOrMeta),
391 shortcut.makeDescriptor(']', shortcut.Modifiers.CtrlOrMeta)
392 ];
393 section.addRelatedKeys(keys, Common.UIString('Go to the panel to the left/right'));
394
395 const toggleConsoleLabel = Common.UIString('Show console');
396 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Tilde, shortcut.Modifiers.Ctrl), toggleConsoleLabel);
397 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Esc), Common.UIString('Toggle drawer'));
398 if (Components.dockController.canDock()) {
399 section.addKey(
400 shortcut.makeDescriptor('M', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
401 Common.UIString('Toggle device mode'));
402 section.addKey(
403 shortcut.makeDescriptor('D', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
404 Common.UIString('Toggle dock side'));
405 }
406 section.addKey(shortcut.makeDescriptor('f', shortcut.Modifiers.CtrlOrMeta), Common.UIString('Search'));
407
408 const advancedSearchShortcutModifier = Host.isMac() ?
409 UI.KeyboardShortcut.Modifiers.Meta | UI.KeyboardShortcut.Modifiers.Alt :
410 UI.KeyboardShortcut.Modifiers.Ctrl | UI.KeyboardShortcut.Modifiers.Shift;
411 const advancedSearchShortcut = shortcut.makeDescriptor('f', advancedSearchShortcutModifier);
412 section.addKey(advancedSearchShortcut, Common.UIString('Search across all sources'));
413
414 const inspectElementModeShortcuts =
415 UI.shortcutRegistry.shortcutDescriptorsForAction('elements.toggle-element-search');
Tim van der Lippe1d6e57a2019-09-30 11:55:34416 if (inspectElementModeShortcuts.length) {
Blink Reformat4c46d092018-04-07 15:32:37417 section.addKey(inspectElementModeShortcuts[0], Common.UIString('Select node to inspect'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34418 }
Blink Reformat4c46d092018-04-07 15:32:37419
420 const openResourceShortcut = UI.KeyboardShortcut.makeDescriptor('p', UI.KeyboardShortcut.Modifiers.CtrlOrMeta);
421 section.addKey(openResourceShortcut, Common.UIString('Go to source'));
422
423 if (Host.isMac()) {
424 keys = [
425 shortcut.makeDescriptor('g', shortcut.Modifiers.Meta),
426 shortcut.makeDescriptor('g', shortcut.Modifiers.Meta | shortcut.Modifiers.Shift)
427 ];
428 section.addRelatedKeys(keys, Common.UIString('Find next/previous'));
429 }
430 }
431
432 _postDocumentKeyDown(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34433 if (!event.handled) {
Joel Einbindera66e5bf2018-05-31 01:26:37434 UI.shortcutRegistry.handleShortcut(event);
Tim van der Lippe1d6e57a2019-09-30 11:55:34435 }
Blink Reformat4c46d092018-04-07 15:32:37436 }
437
438 /**
439 * @param {!Event} event
440 */
441 _redispatchClipboardEvent(event) {
442 const eventCopy = new CustomEvent('clipboard-' + event.type, {bubbles: true});
443 eventCopy['original'] = event;
444 const document = event.target && event.target.ownerDocument;
445 const target = document ? document.deepActiveElement() : null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34446 if (target) {
Blink Reformat4c46d092018-04-07 15:32:37447 target.dispatchEvent(eventCopy);
Tim van der Lippe1d6e57a2019-09-30 11:55:34448 }
449 if (eventCopy.handled) {
Blink Reformat4c46d092018-04-07 15:32:37450 event.preventDefault();
Tim van der Lippe1d6e57a2019-09-30 11:55:34451 }
Blink Reformat4c46d092018-04-07 15:32:37452 }
453
454 _contextMenuEventFired(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34455 if (event.handled || event.target.classList.contains('popup-glasspane')) {
Blink Reformat4c46d092018-04-07 15:32:37456 event.preventDefault();
Tim van der Lippe1d6e57a2019-09-30 11:55:34457 }
Blink Reformat4c46d092018-04-07 15:32:37458 }
459
460 /**
461 * @param {!Document} document
462 */
463 _addMainEventListeners(document) {
464 document.addEventListener('keydown', this._postDocumentKeyDown.bind(this), false);
465 document.addEventListener('beforecopy', this._redispatchClipboardEvent.bind(this), true);
466 document.addEventListener('copy', this._redispatchClipboardEvent.bind(this), false);
467 document.addEventListener('cut', this._redispatchClipboardEvent.bind(this), false);
468 document.addEventListener('paste', this._redispatchClipboardEvent.bind(this), false);
469 document.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), true);
470 }
471
472 _onSuspendStateChanged() {
473 const suspended = SDK.targetManager.allTargetsSuspended();
474 UI.inspectorView.onSuspendStateChanged(suspended);
475 }
Paul Lewisc1d99fa2019-12-10 16:26:28476}
Blink Reformat4c46d092018-04-07 15:32:37477
478/**
479 * @implements {UI.ActionDelegate}
480 * @unrestricted
481 */
Paul Lewisc1d99fa2019-12-10 16:26:28482export class ZoomActionDelegate {
Blink Reformat4c46d092018-04-07 15:32:37483 /**
484 * @override
485 * @param {!UI.Context} context
486 * @param {string} actionId
487 * @return {boolean}
488 */
489 handleAction(context, actionId) {
Tim van der Lippe50cfa9b2019-10-01 10:40:58490 if (Host.InspectorFrontendHost.isHostedMode()) {
Blink Reformat4c46d092018-04-07 15:32:37491 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34492 }
Blink Reformat4c46d092018-04-07 15:32:37493
494 switch (actionId) {
495 case 'main.zoom-in':
Tim van der Lippe50cfa9b2019-10-01 10:40:58496 Host.InspectorFrontendHost.zoomIn();
Blink Reformat4c46d092018-04-07 15:32:37497 return true;
498 case 'main.zoom-out':
Tim van der Lippe50cfa9b2019-10-01 10:40:58499 Host.InspectorFrontendHost.zoomOut();
Blink Reformat4c46d092018-04-07 15:32:37500 return true;
501 case 'main.zoom-reset':
Tim van der Lippe50cfa9b2019-10-01 10:40:58502 Host.InspectorFrontendHost.resetZoom();
Blink Reformat4c46d092018-04-07 15:32:37503 return true;
504 }
505 return false;
506 }
Paul Lewisc1d99fa2019-12-10 16:26:28507}
Blink Reformat4c46d092018-04-07 15:32:37508
509/**
510 * @implements {UI.ActionDelegate}
511 * @unrestricted
512 */
Paul Lewisc1d99fa2019-12-10 16:26:28513export class SearchActionDelegate {
Blink Reformat4c46d092018-04-07 15:32:37514 /**
515 * @override
516 * @param {!UI.Context} context
517 * @param {string} actionId
518 * @return {boolean}
519 * @suppressGlobalPropertiesCheck
520 */
521 handleAction(context, actionId) {
Mandy Chenc1c5bec2019-12-10 19:11:31522 let searchableView = UI.SearchableView.fromElement(document.deepActiveElement());
Tim van der Lippe1d6e57a2019-09-30 11:55:34523 if (!searchableView) {
Mandy Chenc1c5bec2019-12-10 19:11:31524 const currentPanel = UI.inspectorView.currentPanelDeprecated();
525 if (currentPanel) {
526 searchableView = currentPanel.searchableView();
527 }
528 if (!searchableView) {
529 return false;
530 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34531 }
Blink Reformat4c46d092018-04-07 15:32:37532 switch (actionId) {
533 case 'main.search-in-panel.find':
534 return searchableView.handleFindShortcut();
535 case 'main.search-in-panel.cancel':
536 return searchableView.handleCancelSearchShortcut();
537 case 'main.search-in-panel.find-next':
538 return searchableView.handleFindNextShortcut();
539 case 'main.search-in-panel.find-previous':
540 return searchableView.handleFindPreviousShortcut();
541 }
542 return false;
543 }
Paul Lewisc1d99fa2019-12-10 16:26:28544}
Blink Reformat4c46d092018-04-07 15:32:37545
546/**
547 * @implements {UI.ToolbarItem.Provider}
548 */
Paul Lewisc1d99fa2019-12-10 16:26:28549export class MainMenuItem {
Blink Reformat4c46d092018-04-07 15:32:37550 constructor() {
551 this._item = new UI.ToolbarMenuButton(this._handleContextMenu.bind(this), true);
552 this._item.setTitle(Common.UIString('Customize and control DevTools'));
553 }
554
555 /**
556 * @override
557 * @return {?UI.ToolbarItem}
558 */
559 item() {
560 return this._item;
561 }
562
563 /**
564 * @param {!UI.ContextMenu} contextMenu
565 */
566 _handleContextMenu(contextMenu) {
567 if (Components.dockController.canDock()) {
568 const dockItemElement = createElementWithClass('div', 'flex-centered flex-auto');
Joel Einbinder57b9fad2019-02-08 23:31:35569 dockItemElement.tabIndex = -1;
Blink Reformat4c46d092018-04-07 15:32:37570 const titleElement = dockItemElement.createChild('span', 'flex-auto');
571 titleElement.textContent = Common.UIString('Dock side');
572 const toggleDockSideShorcuts = UI.shortcutRegistry.shortcutDescriptorsForAction('main.toggle-dock');
573 titleElement.title = Common.UIString(
574 'Placement of DevTools relative to the page. (%s to restore last position)', toggleDockSideShorcuts[0].name);
575 dockItemElement.appendChild(titleElement);
576 const dockItemToolbar = new UI.Toolbar('', dockItemElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34577 if (Host.isMac() && !UI.themeSupport.hasTheme()) {
Joel Einbinder9a6bead2018-08-06 18:02:35578 dockItemToolbar.makeBlueOnHover();
Tim van der Lippe1d6e57a2019-09-30 11:55:34579 }
Blink Reformat4c46d092018-04-07 15:32:37580 const undock = new UI.ToolbarToggle(Common.UIString('Undock into separate window'), 'largeicon-undock');
581 const bottom = new UI.ToolbarToggle(Common.UIString('Dock to bottom'), 'largeicon-dock-to-bottom');
582 const right = new UI.ToolbarToggle(Common.UIString('Dock to right'), 'largeicon-dock-to-right');
583 const left = new UI.ToolbarToggle(Common.UIString('Dock to left'), 'largeicon-dock-to-left');
584 undock.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
585 bottom.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
586 right.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
587 left.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
588 undock.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35589 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.Undocked));
Blink Reformat4c46d092018-04-07 15:32:37590 bottom.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35591 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToBottom));
Blink Reformat4c46d092018-04-07 15:32:37592 right.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35593 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToRight));
Blink Reformat4c46d092018-04-07 15:32:37594 left.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35595 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToLeft));
Blink Reformat4c46d092018-04-07 15:32:37596 undock.setToggled(Components.dockController.dockSide() === Components.DockController.State.Undocked);
597 bottom.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToBottom);
598 right.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToRight);
599 left.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToLeft);
600 dockItemToolbar.appendToolbarItem(undock);
601 dockItemToolbar.appendToolbarItem(left);
602 dockItemToolbar.appendToolbarItem(bottom);
603 dockItemToolbar.appendToolbarItem(right);
Joel Einbinder57b9fad2019-02-08 23:31:35604 dockItemElement.addEventListener('keydown', event => {
605 let dir = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:34606 if (event.key === 'ArrowLeft') {
Joel Einbinder57b9fad2019-02-08 23:31:35607 dir = -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:34608 } else if (event.key === 'ArrowRight') {
Joel Einbinder57b9fad2019-02-08 23:31:35609 dir = 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:34610 } else {
Joel Einbinder57b9fad2019-02-08 23:31:35611 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34612 }
Joel Einbinder57b9fad2019-02-08 23:31:35613
614 const buttons = [undock, left, bottom, right];
615 let index = buttons.findIndex(button => button.element.hasFocus());
616 index = Number.constrain(index + dir, 0, buttons.length - 1);
617
618 buttons[index].element.focus();
619 event.consume(true);
620 });
Blink Reformat4c46d092018-04-07 15:32:37621 contextMenu.headerSection().appendCustomItem(dockItemElement);
622 }
623
Jan Scheffler53de0572019-10-16 12:31:18624
625 const button = this._item.element;
626
Blink Reformat4c46d092018-04-07 15:32:37627 /**
628 * @param {string} side
Jan Scheffler53de0572019-10-16 12:31:18629 * @suppressGlobalPropertiesCheck
Blink Reformat4c46d092018-04-07 15:32:37630 */
631 function setDockSide(side) {
Jan Scheffler53de0572019-10-16 12:31:18632 const hadKeyboardFocus = document.deepActiveElement().hasAttribute('data-keyboard-focus');
633 Components.dockController.once(Components.DockController.Events.AfterDockSideChanged).then(() => {
634 button.focus();
635 if (hadKeyboardFocus) {
636 UI.markAsFocusedByKeyboard(button);
637 }
638 });
Blink Reformat4c46d092018-04-07 15:32:37639 Components.dockController.setDockSide(side);
640 contextMenu.discard();
641 }
642
643 if (Components.dockController.dockSide() === Components.DockController.State.Undocked &&
Tim van der Lippe1d6e57a2019-09-30 11:55:34644 SDK.targetManager.mainTarget() && SDK.targetManager.mainTarget().type() === SDK.Target.Type.Frame) {
Blink Reformat4c46d092018-04-07 15:32:37645 contextMenu.defaultSection().appendAction('inspector_main.focus-debuggee', Common.UIString('Focus debuggee'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34646 }
Blink Reformat4c46d092018-04-07 15:32:37647
648 contextMenu.defaultSection().appendAction(
649 'main.toggle-drawer',
650 UI.inspectorView.drawerVisible() ? Common.UIString('Hide console drawer') :
651 Common.UIString('Show console drawer'));
652 contextMenu.appendItemsAtLocation('mainMenu');
653 const moreTools = contextMenu.defaultSection().appendSubMenuItem(Common.UIString('More tools'));
654 const extensions = self.runtime.extensions('view', undefined, true);
655 for (const extension of extensions) {
656 const descriptor = extension.descriptor();
Tim van der Lippe1d6e57a2019-09-30 11:55:34657 if (descriptor['persistence'] !== 'closeable') {
Blink Reformat4c46d092018-04-07 15:32:37658 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34659 }
660 if (descriptor['location'] !== 'drawer-view' && descriptor['location'] !== 'panel') {
Blink Reformat4c46d092018-04-07 15:32:37661 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34662 }
Blink Reformat4c46d092018-04-07 15:32:37663 moreTools.defaultSection().appendItem(
664 extension.title(), UI.viewManager.showView.bind(UI.viewManager, descriptor['id']));
665 }
666
667 const helpSubMenu = contextMenu.footerSection().appendSubMenuItem(Common.UIString('Help'));
668 helpSubMenu.appendItemsAtLocation('mainMenuHelp');
669 }
Paul Lewisc1d99fa2019-12-10 16:26:28670}
Blink Reformat4c46d092018-04-07 15:32:37671
672/**
673 * @unrestricted
674 */
Paul Lewisc1d99fa2019-12-10 16:26:28675export class PauseListener {
Blink Reformat4c46d092018-04-07 15:32:37676 constructor() {
677 SDK.targetManager.addModelListener(
678 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
679 }
680
681 /**
682 * @param {!Common.Event} event
683 */
684 _debuggerPaused(event) {
685 SDK.targetManager.removeModelListener(
686 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
687 const debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.data);
688 const debuggerPausedDetails = debuggerModel.debuggerPausedDetails();
689 UI.context.setFlavor(SDK.Target, debuggerModel.target());
690 Common.Revealer.reveal(debuggerPausedDetails);
691 }
Paul Lewisc1d99fa2019-12-10 16:26:28692}
Blink Reformat4c46d092018-04-07 15:32:37693
Tim van der Lippe4221a1a2019-11-05 12:54:17694/**
695 * @param {string} method
696 * @param {?Object} params
697 * @return {!Promise}
698 */
Paul Lewisc1d99fa2019-12-10 16:26:28699export function sendOverProtocol(method, params) {
Tim van der Lippe4221a1a2019-11-05 12:54:17700 return new Promise((resolve, reject) => {
701 Protocol.test.sendRawMessage(method, params, (err, ...results) => {
702 if (err) {
703 return reject(err);
704 }
705 return resolve(results);
706 });
707 });
Paul Lewisc1d99fa2019-12-10 16:26:28708}
Tim van der Lippe4221a1a2019-11-05 12:54:17709
710/**
711 * @implements {UI.ActionDelegate}
712 * @unrestricted
713 */
Paul Lewisc1d99fa2019-12-10 16:26:28714export class ReloadActionDelegate {
Tim van der Lippe4221a1a2019-11-05 12:54:17715 /**
716 * @override
717 * @param {!UI.Context} context
718 * @param {string} actionId
719 * @return {boolean}
720 */
721 handleAction(context, actionId) {
722 switch (actionId) {
723 case 'main.debug-reload':
724 Components.reload();
725 return true;
726 }
727 return false;
728 }
Paul Lewisc1d99fa2019-12-10 16:26:28729}
Tim van der Lippe4221a1a2019-11-05 12:54:17730
Paul Lewisc1d99fa2019-12-10 16:26:28731new MainImpl();
732
733/* Legacy exported object */
734self.Main = self.Main || {};
735
736/* Legacy exported object */
737Main = Main || {};
738
739/**
740 * @constructor
741 */
742Main.Main = MainImpl;
743
744/**
745 * @constructor
746 */
747Main.Main.ZoomActionDelegate = ZoomActionDelegate;
748
749/**
750 * @constructor
751 */
752Main.Main.SearchActionDelegate = SearchActionDelegate;
753
754/**
755 * @constructor
756 */
757Main.Main.MainMenuItem = MainMenuItem;
758
759/**
760 * @constructor
761 */
762Main.Main.PauseListener = PauseListener;
763
764/**
765 * @constructor
766 */
767Main.ReloadActionDelegate = ReloadActionDelegate;
768Main.sendOverProtocol = sendOverProtocol;