blob: 5232b94edd2edf078f7c45071ed2cc3df3cad569 [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(
136 'recordCoverageWithPerformanceTracing', 'Record coverage while performance tracing');
137 Root.Runtime.experiments.register('samplingHeapProfilerTimeline', 'Sampling heap profiler timeline', true);
138 Root.Runtime.experiments.register('sourceDiff', 'Source diff');
Tim van der Lippe99e59b82019-09-30 20:00:59139 Root.Runtime.experiments.register('spotlight', 'Spotlight', true);
Blink Reformat4c46d092018-04-07 15:32:37140
141 // Timeline
Tim van der Lippe99e59b82019-09-30 20:00:59142 Root.Runtime.experiments.register('timelineEventInitiators', 'Timeline: event initiators');
143 Root.Runtime.experiments.register('timelineFlowEvents', 'Timeline: flow events', true);
144 Root.Runtime.experiments.register('timelineInvalidationTracking', 'Timeline: invalidation tracking', true);
145 Root.Runtime.experiments.register('timelineShowAllEvents', 'Timeline: show all events', true);
146 Root.Runtime.experiments.register(
147 'timelineV8RuntimeCallStats', 'Timeline: V8 Runtime Call Stats on Timeline', true);
148 Root.Runtime.experiments.register('timelineWebGL', 'Timeline: WebGL-based flamechart');
Blink Reformat4c46d092018-04-07 15:32:37149
Tim van der Lippe99e59b82019-09-30 20:00:59150 Root.Runtime.experiments.cleanUpStaleExperiments();
151 const enabledExperiments = Root.Runtime.queryParam('enabledExperiments');
Tim van der Lippe1d6e57a2019-09-30 11:55:34152 if (enabledExperiments) {
Tim van der Lippe99e59b82019-09-30 20:00:59153 Root.Runtime.experiments.setServerEnabledExperiments(enabledExperiments.split(';'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34154 }
Tim van der Lippe99e59b82019-09-30 20:00:59155 Root.Runtime.experiments.setDefaultExperiments([
Rayan Kanso93bacf72019-08-28 12:33:23156 'backgroundServices',
157 'backgroundServicesNotifications',
158 'backgroundServicesPushMessaging',
159 'backgroundServicesPaymentHandler',
160 ]);
Alexei Filippovfdfefe02019-03-09 00:33:24161
Tim van der Lippe99e59b82019-09-30 20:00:59162 if (Host.isUnderTest() && Root.Runtime.queryParam('test').includes('live-line-level-heap-profile.js')) {
163 Root.Runtime.experiments.enableForTest('liveHeapProfile');
Tim van der Lippe1d6e57a2019-09-30 11:55:34164 }
Blink Reformat4c46d092018-04-07 15:32:37165 }
166
167 /**
168 * @suppressGlobalPropertiesCheck
169 */
170 async _createAppUI() {
Paul Lewisc1d99fa2019-12-10 16:26:28171 MainImpl.time('Main._createAppUI');
Blink Reformat4c46d092018-04-07 15:32:37172
173 UI.viewManager = new UI.ViewManager();
174
175 // Request filesystems early, we won't create connections until callback is fired. Things will happen in parallel.
176 Persistence.isolatedFileSystemManager = new Persistence.IsolatedFileSystemManager();
177
Erik Luo9adba992019-06-26 01:17:52178 const themeSetting = Common.settings.createSetting('uiTheme', 'systemPreferred');
Blink Reformat4c46d092018-04-07 15:32:37179 UI.initializeUIUtils(document, themeSetting);
180 themeSetting.addChangeListener(Components.reload.bind(Components));
181
182 UI.installComponentRootStyles(/** @type {!Element} */ (document.body));
183
184 this._addMainEventListeners(document);
185
Tim van der Lippe99e59b82019-09-30 20:00:59186 const canDock = !!Root.Runtime.queryParam('can_dock');
Tim van der Lippe50cfa9b2019-10-01 10:40:58187 UI.zoomManager = new UI.ZoomManager(window, Host.InspectorFrontendHost);
Blink Reformat4c46d092018-04-07 15:32:37188 UI.inspectorView = UI.InspectorView.instance();
189 UI.ContextMenu.initialize();
190 UI.ContextMenu.installHandler(document);
191 UI.Tooltip.installHandler(document);
192 Components.dockController = new Components.DockController(canDock);
193 SDK.consoleModel = new SDK.ConsoleModel();
194 SDK.multitargetNetworkManager = new SDK.MultitargetNetworkManager();
195 SDK.domDebuggerManager = new SDK.DOMDebuggerManager();
196 SDK.targetManager.addEventListener(
197 SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged.bind(this));
198
199 UI.shortcutsScreen = new UI.ShortcutsScreen();
200 // set order of some sections explicitly
201 UI.shortcutsScreen.section(Common.UIString('Elements Panel'));
202 UI.shortcutsScreen.section(Common.UIString('Styles Pane'));
203 UI.shortcutsScreen.section(Common.UIString('Debugger'));
204 UI.shortcutsScreen.section(Common.UIString('Console'));
205
206 Workspace.fileManager = new Workspace.FileManager();
207 Workspace.workspace = new Workspace.Workspace();
208
209 Bindings.networkProjectManager = new Bindings.NetworkProjectManager();
210 Bindings.resourceMapping = new Bindings.ResourceMapping(SDK.targetManager, Workspace.workspace);
211 new Bindings.PresentationConsoleMessageManager();
212 Bindings.cssWorkspaceBinding = new Bindings.CSSWorkspaceBinding(SDK.targetManager, Workspace.workspace);
213 Bindings.debuggerWorkspaceBinding = new Bindings.DebuggerWorkspaceBinding(SDK.targetManager, Workspace.workspace);
214 Bindings.breakpointManager =
215 new Bindings.BreakpointManager(Workspace.workspace, SDK.targetManager, Bindings.debuggerWorkspaceBinding);
216 Extensions.extensionServer = new Extensions.ExtensionServer();
217
218 new Persistence.FileSystemWorkspaceBinding(Persistence.isolatedFileSystemManager, Workspace.workspace);
219 Persistence.persistence = new Persistence.Persistence(Workspace.workspace, Bindings.breakpointManager);
220 Persistence.networkPersistenceManager = new Persistence.NetworkPersistenceManager(Workspace.workspace);
221
222 new Main.ExecutionContextSelector(SDK.targetManager, UI.context);
223 Bindings.blackboxManager = new Bindings.BlackboxManager(Bindings.debuggerWorkspaceBinding);
224
Paul Lewisc1d99fa2019-12-10 16:26:28225 new PauseListener();
Blink Reformat4c46d092018-04-07 15:32:37226
227 UI.actionRegistry = new UI.ActionRegistry();
228 UI.shortcutRegistry = new UI.ShortcutRegistry(UI.actionRegistry, document);
229 UI.ShortcutsScreen.registerShortcuts();
230 this._registerForwardedShortcuts();
231 this._registerMessageSinkListener();
232
Paul Lewisc1d99fa2019-12-10 16:26:28233 MainImpl.timeEnd('Main._createAppUI');
Blink Reformat4c46d092018-04-07 15:32:37234 this._showAppUI(await self.runtime.extension(Common.AppProvider).instance());
235 }
236
237 /**
238 * @param {!Object} appProvider
239 * @suppressGlobalPropertiesCheck
240 */
241 _showAppUI(appProvider) {
Paul Lewisc1d99fa2019-12-10 16:26:28242 MainImpl.time('Main._showAppUI');
Blink Reformat4c46d092018-04-07 15:32:37243 const app = /** @type {!Common.AppProvider} */ (appProvider).createApp();
244 // It is important to kick controller lifetime after apps are instantiated.
245 Components.dockController.initialize();
246 app.presentUI(document);
247
248 const toggleSearchNodeAction = UI.actionRegistry.action('elements.toggle-element-search');
249 // TODO: we should not access actions from other modules.
250 if (toggleSearchNodeAction) {
Tim van der Lippe50cfa9b2019-10-01 10:40:58251 Host.InspectorFrontendHost.events.addEventListener(
Tim van der Lippe7b190162019-09-27 15:10:44252 Host.InspectorFrontendHostAPI.Events.EnterInspectElementMode,
Blink Reformat4c46d092018-04-07 15:32:37253 toggleSearchNodeAction.execute.bind(toggleSearchNodeAction), this);
254 }
Tim van der Lippe50cfa9b2019-10-01 10:40:58255 Host.InspectorFrontendHost.events.addEventListener(
Tim van der Lippe7b190162019-09-27 15:10:44256 Host.InspectorFrontendHostAPI.Events.RevealSourceLine, this._revealSourceLine, this);
Blink Reformat4c46d092018-04-07 15:32:37257
258 UI.inspectorView.createToolbars();
Tim van der Lippe50cfa9b2019-10-01 10:40:58259 Host.InspectorFrontendHost.loadCompleted();
Blink Reformat4c46d092018-04-07 15:32:37260
261 const extensions = self.runtime.extensions(Common.QueryParamHandler);
262 for (const extension of extensions) {
Tim van der Lippe99e59b82019-09-30 20:00:59263 const value = Root.Runtime.queryParam(extension.descriptor()['name']);
Tim van der Lippe1d6e57a2019-09-30 11:55:34264 if (value !== null) {
Blink Reformat4c46d092018-04-07 15:32:37265 extension.instance().then(handleQueryParam.bind(null, value));
Tim van der Lippe1d6e57a2019-09-30 11:55:34266 }
Blink Reformat4c46d092018-04-07 15:32:37267 }
268
269 /**
270 * @param {string} value
271 * @param {!Common.QueryParamHandler} handler
272 */
273 function handleQueryParam(value, handler) {
274 handler.handleQueryParam(value);
275 }
276
277 // Allow UI cycles to repaint prior to creating connection.
278 setTimeout(this._initializeTarget.bind(this), 0);
Paul Lewisc1d99fa2019-12-10 16:26:28279 MainImpl.timeEnd('Main._showAppUI');
Blink Reformat4c46d092018-04-07 15:32:37280 }
281
282 async _initializeTarget() {
Paul Lewisc1d99fa2019-12-10 16:26:28283 MainImpl.time('Main._initializeTarget');
Blink Reformat4c46d092018-04-07 15:32:37284 const instances =
285 await Promise.all(self.runtime.extensions('early-initialization').map(extension => extension.instance()));
Tim van der Lippe1d6e57a2019-09-30 11:55:34286 for (const instance of instances) {
Pavel Feldman07ef9722018-12-13 23:52:22287 await /** @type {!Common.Runnable} */ (instance).run();
Tim van der Lippe1d6e57a2019-09-30 11:55:34288 }
Blink Reformat4c46d092018-04-07 15:32:37289 // Used for browser tests.
Tim van der Lippe50cfa9b2019-10-01 10:40:58290 Host.InspectorFrontendHost.readyForTest();
Blink Reformat4c46d092018-04-07 15:32:37291 // Asynchronously run the extensions.
292 setTimeout(this._lateInitialization.bind(this), 100);
Paul Lewisc1d99fa2019-12-10 16:26:28293 MainImpl.timeEnd('Main._initializeTarget');
Blink Reformat4c46d092018-04-07 15:32:37294 }
295
296 _lateInitialization() {
Paul Lewisc1d99fa2019-12-10 16:26:28297 MainImpl.time('Main._lateInitialization');
Blink Reformat4c46d092018-04-07 15:32:37298 this._registerShortcuts();
299 Extensions.extensionServer.initializeExtensions();
Alexei Filippov19be5102019-04-16 20:40:24300 const extensions = self.runtime.extensions('late-initialization');
301 const promises = [];
302 for (const extension of extensions) {
303 const setting = extension.descriptor()['setting'];
304 if (!setting || Common.settings.moduleSetting(setting).get()) {
305 promises.push(extension.instance().then(instance => (/** @type {!Common.Runnable} */ (instance)).run()));
306 continue;
307 }
308 /**
309 * @param {!Common.Event} event
310 */
311 async function changeListener(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34312 if (!event.data) {
Alexei Filippov19be5102019-04-16 20:40:24313 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34314 }
Alexei Filippov19be5102019-04-16 20:40:24315 Common.settings.moduleSetting(setting).removeChangeListener(changeListener);
316 (/** @type {!Common.Runnable} */ (await extension.instance())).run();
317 }
318 Common.settings.moduleSetting(setting).addChangeListener(changeListener);
319 }
320 this._lateInitDonePromise = Promise.all(promises);
Paul Lewisc1d99fa2019-12-10 16:26:28321 MainImpl.timeEnd('Main._lateInitialization');
Blink Reformat4c46d092018-04-07 15:32:37322 }
323
Alexei Filippov19be5102019-04-16 20:40:24324 /**
325 * @return {!Promise}
326 */
327 lateInitDonePromiseForTest() {
328 return this._lateInitDonePromise;
329 }
330
Blink Reformat4c46d092018-04-07 15:32:37331 _registerForwardedShortcuts() {
332 /** @const */ const forwardedActions = [
333 'main.toggle-dock', 'debugger.toggle-breakpoints-active', 'debugger.toggle-pause', 'commandMenu.show',
334 'console.show'
335 ];
336 const actionKeys =
337 UI.shortcutRegistry.keysForActions(forwardedActions).map(UI.KeyboardShortcut.keyCodeAndModifiersFromKey);
Tim van der Lippe50cfa9b2019-10-01 10:40:58338 Host.InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
Blink Reformat4c46d092018-04-07 15:32:37339 }
340
341 _registerMessageSinkListener() {
342 Common.console.addEventListener(Common.Console.Events.MessageAdded, messageAdded);
343
344 /**
345 * @param {!Common.Event} event
346 */
347 function messageAdded(event) {
348 const message = /** @type {!Common.Console.Message} */ (event.data);
Tim van der Lippe1d6e57a2019-09-30 11:55:34349 if (message.show) {
Blink Reformat4c46d092018-04-07 15:32:37350 Common.console.show();
Tim van der Lippe1d6e57a2019-09-30 11:55:34351 }
Blink Reformat4c46d092018-04-07 15:32:37352 }
353 }
354
355 /**
356 * @param {!Common.Event} event
357 */
358 _revealSourceLine(event) {
359 const url = /** @type {string} */ (event.data['url']);
360 const lineNumber = /** @type {number} */ (event.data['lineNumber']);
361 const columnNumber = /** @type {number} */ (event.data['columnNumber']);
362
363 const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
364 if (uiSourceCode) {
365 Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
366 return;
367 }
368
369 /**
370 * @param {!Common.Event} event
371 */
372 function listener(event) {
373 const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
374 if (uiSourceCode.url() === url) {
375 Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
376 Workspace.workspace.removeEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
377 }
378 }
379
380 Workspace.workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
381 }
382
383 _registerShortcuts() {
384 const shortcut = UI.KeyboardShortcut;
385 const section = UI.shortcutsScreen.section(Common.UIString('All Panels'));
386 let keys = [
387 shortcut.makeDescriptor('[', shortcut.Modifiers.CtrlOrMeta),
388 shortcut.makeDescriptor(']', shortcut.Modifiers.CtrlOrMeta)
389 ];
390 section.addRelatedKeys(keys, Common.UIString('Go to the panel to the left/right'));
391
392 const toggleConsoleLabel = Common.UIString('Show console');
393 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Tilde, shortcut.Modifiers.Ctrl), toggleConsoleLabel);
394 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Esc), Common.UIString('Toggle drawer'));
395 if (Components.dockController.canDock()) {
396 section.addKey(
397 shortcut.makeDescriptor('M', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
398 Common.UIString('Toggle device mode'));
399 section.addKey(
400 shortcut.makeDescriptor('D', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
401 Common.UIString('Toggle dock side'));
402 }
403 section.addKey(shortcut.makeDescriptor('f', shortcut.Modifiers.CtrlOrMeta), Common.UIString('Search'));
404
405 const advancedSearchShortcutModifier = Host.isMac() ?
406 UI.KeyboardShortcut.Modifiers.Meta | UI.KeyboardShortcut.Modifiers.Alt :
407 UI.KeyboardShortcut.Modifiers.Ctrl | UI.KeyboardShortcut.Modifiers.Shift;
408 const advancedSearchShortcut = shortcut.makeDescriptor('f', advancedSearchShortcutModifier);
409 section.addKey(advancedSearchShortcut, Common.UIString('Search across all sources'));
410
411 const inspectElementModeShortcuts =
412 UI.shortcutRegistry.shortcutDescriptorsForAction('elements.toggle-element-search');
Tim van der Lippe1d6e57a2019-09-30 11:55:34413 if (inspectElementModeShortcuts.length) {
Blink Reformat4c46d092018-04-07 15:32:37414 section.addKey(inspectElementModeShortcuts[0], Common.UIString('Select node to inspect'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34415 }
Blink Reformat4c46d092018-04-07 15:32:37416
417 const openResourceShortcut = UI.KeyboardShortcut.makeDescriptor('p', UI.KeyboardShortcut.Modifiers.CtrlOrMeta);
418 section.addKey(openResourceShortcut, Common.UIString('Go to source'));
419
420 if (Host.isMac()) {
421 keys = [
422 shortcut.makeDescriptor('g', shortcut.Modifiers.Meta),
423 shortcut.makeDescriptor('g', shortcut.Modifiers.Meta | shortcut.Modifiers.Shift)
424 ];
425 section.addRelatedKeys(keys, Common.UIString('Find next/previous'));
426 }
427 }
428
429 _postDocumentKeyDown(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34430 if (!event.handled) {
Joel Einbindera66e5bf2018-05-31 01:26:37431 UI.shortcutRegistry.handleShortcut(event);
Tim van der Lippe1d6e57a2019-09-30 11:55:34432 }
Blink Reformat4c46d092018-04-07 15:32:37433 }
434
435 /**
436 * @param {!Event} event
437 */
438 _redispatchClipboardEvent(event) {
439 const eventCopy = new CustomEvent('clipboard-' + event.type, {bubbles: true});
440 eventCopy['original'] = event;
441 const document = event.target && event.target.ownerDocument;
442 const target = document ? document.deepActiveElement() : null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34443 if (target) {
Blink Reformat4c46d092018-04-07 15:32:37444 target.dispatchEvent(eventCopy);
Tim van der Lippe1d6e57a2019-09-30 11:55:34445 }
446 if (eventCopy.handled) {
Blink Reformat4c46d092018-04-07 15:32:37447 event.preventDefault();
Tim van der Lippe1d6e57a2019-09-30 11:55:34448 }
Blink Reformat4c46d092018-04-07 15:32:37449 }
450
451 _contextMenuEventFired(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34452 if (event.handled || event.target.classList.contains('popup-glasspane')) {
Blink Reformat4c46d092018-04-07 15:32:37453 event.preventDefault();
Tim van der Lippe1d6e57a2019-09-30 11:55:34454 }
Blink Reformat4c46d092018-04-07 15:32:37455 }
456
457 /**
458 * @param {!Document} document
459 */
460 _addMainEventListeners(document) {
461 document.addEventListener('keydown', this._postDocumentKeyDown.bind(this), false);
462 document.addEventListener('beforecopy', this._redispatchClipboardEvent.bind(this), true);
463 document.addEventListener('copy', this._redispatchClipboardEvent.bind(this), false);
464 document.addEventListener('cut', this._redispatchClipboardEvent.bind(this), false);
465 document.addEventListener('paste', this._redispatchClipboardEvent.bind(this), false);
466 document.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), true);
467 }
468
469 _onSuspendStateChanged() {
470 const suspended = SDK.targetManager.allTargetsSuspended();
471 UI.inspectorView.onSuspendStateChanged(suspended);
472 }
Paul Lewisc1d99fa2019-12-10 16:26:28473}
Blink Reformat4c46d092018-04-07 15:32:37474
475/**
476 * @implements {UI.ActionDelegate}
477 * @unrestricted
478 */
Paul Lewisc1d99fa2019-12-10 16:26:28479export class ZoomActionDelegate {
Blink Reformat4c46d092018-04-07 15:32:37480 /**
481 * @override
482 * @param {!UI.Context} context
483 * @param {string} actionId
484 * @return {boolean}
485 */
486 handleAction(context, actionId) {
Tim van der Lippe50cfa9b2019-10-01 10:40:58487 if (Host.InspectorFrontendHost.isHostedMode()) {
Blink Reformat4c46d092018-04-07 15:32:37488 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34489 }
Blink Reformat4c46d092018-04-07 15:32:37490
491 switch (actionId) {
492 case 'main.zoom-in':
Tim van der Lippe50cfa9b2019-10-01 10:40:58493 Host.InspectorFrontendHost.zoomIn();
Blink Reformat4c46d092018-04-07 15:32:37494 return true;
495 case 'main.zoom-out':
Tim van der Lippe50cfa9b2019-10-01 10:40:58496 Host.InspectorFrontendHost.zoomOut();
Blink Reformat4c46d092018-04-07 15:32:37497 return true;
498 case 'main.zoom-reset':
Tim van der Lippe50cfa9b2019-10-01 10:40:58499 Host.InspectorFrontendHost.resetZoom();
Blink Reformat4c46d092018-04-07 15:32:37500 return true;
501 }
502 return false;
503 }
Paul Lewisc1d99fa2019-12-10 16:26:28504}
Blink Reformat4c46d092018-04-07 15:32:37505
506/**
507 * @implements {UI.ActionDelegate}
508 * @unrestricted
509 */
Paul Lewisc1d99fa2019-12-10 16:26:28510export class SearchActionDelegate {
Blink Reformat4c46d092018-04-07 15:32:37511 /**
512 * @override
513 * @param {!UI.Context} context
514 * @param {string} actionId
515 * @return {boolean}
516 * @suppressGlobalPropertiesCheck
517 */
518 handleAction(context, actionId) {
519 const searchableView = UI.SearchableView.fromElement(document.deepActiveElement()) ||
520 UI.inspectorView.currentPanelDeprecated().searchableView();
Tim van der Lippe1d6e57a2019-09-30 11:55:34521 if (!searchableView) {
Blink Reformat4c46d092018-04-07 15:32:37522 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34523 }
Blink Reformat4c46d092018-04-07 15:32:37524 switch (actionId) {
525 case 'main.search-in-panel.find':
526 return searchableView.handleFindShortcut();
527 case 'main.search-in-panel.cancel':
528 return searchableView.handleCancelSearchShortcut();
529 case 'main.search-in-panel.find-next':
530 return searchableView.handleFindNextShortcut();
531 case 'main.search-in-panel.find-previous':
532 return searchableView.handleFindPreviousShortcut();
533 }
534 return false;
535 }
Paul Lewisc1d99fa2019-12-10 16:26:28536}
Blink Reformat4c46d092018-04-07 15:32:37537
538/**
539 * @implements {UI.ToolbarItem.Provider}
540 */
Paul Lewisc1d99fa2019-12-10 16:26:28541export class MainMenuItem {
Blink Reformat4c46d092018-04-07 15:32:37542 constructor() {
543 this._item = new UI.ToolbarMenuButton(this._handleContextMenu.bind(this), true);
544 this._item.setTitle(Common.UIString('Customize and control DevTools'));
545 }
546
547 /**
548 * @override
549 * @return {?UI.ToolbarItem}
550 */
551 item() {
552 return this._item;
553 }
554
555 /**
556 * @param {!UI.ContextMenu} contextMenu
557 */
558 _handleContextMenu(contextMenu) {
559 if (Components.dockController.canDock()) {
560 const dockItemElement = createElementWithClass('div', 'flex-centered flex-auto');
Joel Einbinder57b9fad2019-02-08 23:31:35561 dockItemElement.tabIndex = -1;
Blink Reformat4c46d092018-04-07 15:32:37562 const titleElement = dockItemElement.createChild('span', 'flex-auto');
563 titleElement.textContent = Common.UIString('Dock side');
564 const toggleDockSideShorcuts = UI.shortcutRegistry.shortcutDescriptorsForAction('main.toggle-dock');
565 titleElement.title = Common.UIString(
566 'Placement of DevTools relative to the page. (%s to restore last position)', toggleDockSideShorcuts[0].name);
567 dockItemElement.appendChild(titleElement);
568 const dockItemToolbar = new UI.Toolbar('', dockItemElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34569 if (Host.isMac() && !UI.themeSupport.hasTheme()) {
Joel Einbinder9a6bead2018-08-06 18:02:35570 dockItemToolbar.makeBlueOnHover();
Tim van der Lippe1d6e57a2019-09-30 11:55:34571 }
Blink Reformat4c46d092018-04-07 15:32:37572 const undock = new UI.ToolbarToggle(Common.UIString('Undock into separate window'), 'largeicon-undock');
573 const bottom = new UI.ToolbarToggle(Common.UIString('Dock to bottom'), 'largeicon-dock-to-bottom');
574 const right = new UI.ToolbarToggle(Common.UIString('Dock to right'), 'largeicon-dock-to-right');
575 const left = new UI.ToolbarToggle(Common.UIString('Dock to left'), 'largeicon-dock-to-left');
576 undock.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
577 bottom.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
578 right.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
579 left.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
580 undock.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35581 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.Undocked));
Blink Reformat4c46d092018-04-07 15:32:37582 bottom.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35583 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToBottom));
Blink Reformat4c46d092018-04-07 15:32:37584 right.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35585 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToRight));
Blink Reformat4c46d092018-04-07 15:32:37586 left.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35587 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToLeft));
Blink Reformat4c46d092018-04-07 15:32:37588 undock.setToggled(Components.dockController.dockSide() === Components.DockController.State.Undocked);
589 bottom.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToBottom);
590 right.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToRight);
591 left.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToLeft);
592 dockItemToolbar.appendToolbarItem(undock);
593 dockItemToolbar.appendToolbarItem(left);
594 dockItemToolbar.appendToolbarItem(bottom);
595 dockItemToolbar.appendToolbarItem(right);
Joel Einbinder57b9fad2019-02-08 23:31:35596 dockItemElement.addEventListener('keydown', event => {
597 let dir = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:34598 if (event.key === 'ArrowLeft') {
Joel Einbinder57b9fad2019-02-08 23:31:35599 dir = -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:34600 } else if (event.key === 'ArrowRight') {
Joel Einbinder57b9fad2019-02-08 23:31:35601 dir = 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:34602 } else {
Joel Einbinder57b9fad2019-02-08 23:31:35603 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34604 }
Joel Einbinder57b9fad2019-02-08 23:31:35605
606 const buttons = [undock, left, bottom, right];
607 let index = buttons.findIndex(button => button.element.hasFocus());
608 index = Number.constrain(index + dir, 0, buttons.length - 1);
609
610 buttons[index].element.focus();
611 event.consume(true);
612 });
Blink Reformat4c46d092018-04-07 15:32:37613 contextMenu.headerSection().appendCustomItem(dockItemElement);
614 }
615
Jan Scheffler53de0572019-10-16 12:31:18616
617 const button = this._item.element;
618
Blink Reformat4c46d092018-04-07 15:32:37619 /**
620 * @param {string} side
Jan Scheffler53de0572019-10-16 12:31:18621 * @suppressGlobalPropertiesCheck
Blink Reformat4c46d092018-04-07 15:32:37622 */
623 function setDockSide(side) {
Jan Scheffler53de0572019-10-16 12:31:18624 const hadKeyboardFocus = document.deepActiveElement().hasAttribute('data-keyboard-focus');
625 Components.dockController.once(Components.DockController.Events.AfterDockSideChanged).then(() => {
626 button.focus();
627 if (hadKeyboardFocus) {
628 UI.markAsFocusedByKeyboard(button);
629 }
630 });
Blink Reformat4c46d092018-04-07 15:32:37631 Components.dockController.setDockSide(side);
632 contextMenu.discard();
633 }
634
635 if (Components.dockController.dockSide() === Components.DockController.State.Undocked &&
Tim van der Lippe1d6e57a2019-09-30 11:55:34636 SDK.targetManager.mainTarget() && SDK.targetManager.mainTarget().type() === SDK.Target.Type.Frame) {
Blink Reformat4c46d092018-04-07 15:32:37637 contextMenu.defaultSection().appendAction('inspector_main.focus-debuggee', Common.UIString('Focus debuggee'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34638 }
Blink Reformat4c46d092018-04-07 15:32:37639
640 contextMenu.defaultSection().appendAction(
641 'main.toggle-drawer',
642 UI.inspectorView.drawerVisible() ? Common.UIString('Hide console drawer') :
643 Common.UIString('Show console drawer'));
644 contextMenu.appendItemsAtLocation('mainMenu');
645 const moreTools = contextMenu.defaultSection().appendSubMenuItem(Common.UIString('More tools'));
646 const extensions = self.runtime.extensions('view', undefined, true);
647 for (const extension of extensions) {
648 const descriptor = extension.descriptor();
Tim van der Lippe1d6e57a2019-09-30 11:55:34649 if (descriptor['persistence'] !== 'closeable') {
Blink Reformat4c46d092018-04-07 15:32:37650 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34651 }
652 if (descriptor['location'] !== 'drawer-view' && descriptor['location'] !== 'panel') {
Blink Reformat4c46d092018-04-07 15:32:37653 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34654 }
Blink Reformat4c46d092018-04-07 15:32:37655 moreTools.defaultSection().appendItem(
656 extension.title(), UI.viewManager.showView.bind(UI.viewManager, descriptor['id']));
657 }
658
659 const helpSubMenu = contextMenu.footerSection().appendSubMenuItem(Common.UIString('Help'));
660 helpSubMenu.appendItemsAtLocation('mainMenuHelp');
661 }
Paul Lewisc1d99fa2019-12-10 16:26:28662}
Blink Reformat4c46d092018-04-07 15:32:37663
664/**
665 * @unrestricted
666 */
Paul Lewisc1d99fa2019-12-10 16:26:28667export class PauseListener {
Blink Reformat4c46d092018-04-07 15:32:37668 constructor() {
669 SDK.targetManager.addModelListener(
670 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
671 }
672
673 /**
674 * @param {!Common.Event} event
675 */
676 _debuggerPaused(event) {
677 SDK.targetManager.removeModelListener(
678 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
679 const debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.data);
680 const debuggerPausedDetails = debuggerModel.debuggerPausedDetails();
681 UI.context.setFlavor(SDK.Target, debuggerModel.target());
682 Common.Revealer.reveal(debuggerPausedDetails);
683 }
Paul Lewisc1d99fa2019-12-10 16:26:28684}
Blink Reformat4c46d092018-04-07 15:32:37685
Tim van der Lippe4221a1a2019-11-05 12:54:17686/**
687 * @param {string} method
688 * @param {?Object} params
689 * @return {!Promise}
690 */
Paul Lewisc1d99fa2019-12-10 16:26:28691export function sendOverProtocol(method, params) {
Tim van der Lippe4221a1a2019-11-05 12:54:17692 return new Promise((resolve, reject) => {
693 Protocol.test.sendRawMessage(method, params, (err, ...results) => {
694 if (err) {
695 return reject(err);
696 }
697 return resolve(results);
698 });
699 });
Paul Lewisc1d99fa2019-12-10 16:26:28700}
Tim van der Lippe4221a1a2019-11-05 12:54:17701
702/**
703 * @implements {UI.ActionDelegate}
704 * @unrestricted
705 */
Paul Lewisc1d99fa2019-12-10 16:26:28706export class ReloadActionDelegate {
Tim van der Lippe4221a1a2019-11-05 12:54:17707 /**
708 * @override
709 * @param {!UI.Context} context
710 * @param {string} actionId
711 * @return {boolean}
712 */
713 handleAction(context, actionId) {
714 switch (actionId) {
715 case 'main.debug-reload':
716 Components.reload();
717 return true;
718 }
719 return false;
720 }
Paul Lewisc1d99fa2019-12-10 16:26:28721}
Tim van der Lippe4221a1a2019-11-05 12:54:17722
Paul Lewisc1d99fa2019-12-10 16:26:28723new MainImpl();
724
725/* Legacy exported object */
726self.Main = self.Main || {};
727
728/* Legacy exported object */
729Main = Main || {};
730
731/**
732 * @constructor
733 */
734Main.Main = MainImpl;
735
736/**
737 * @constructor
738 */
739Main.Main.ZoomActionDelegate = ZoomActionDelegate;
740
741/**
742 * @constructor
743 */
744Main.Main.SearchActionDelegate = SearchActionDelegate;
745
746/**
747 * @constructor
748 */
749Main.Main.MainMenuItem = MainMenuItem;
750
751/**
752 * @constructor
753 */
754Main.Main.PauseListener = PauseListener;
755
756/**
757 * @constructor
758 */
759Main.ReloadActionDelegate = ReloadActionDelegate;
760Main.sendOverProtocol = sendOverProtocol;