blob: ab633c6a0f3c26f38c552e71f0f6d1577f7e273c [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) {
Mandy Chenc1c5bec2019-12-10 19:11:31519 let searchableView = UI.SearchableView.fromElement(document.deepActiveElement());
Tim van der Lippe1d6e57a2019-09-30 11:55:34520 if (!searchableView) {
Mandy Chenc1c5bec2019-12-10 19:11:31521 const currentPanel = UI.inspectorView.currentPanelDeprecated();
522 if (currentPanel) {
523 searchableView = currentPanel.searchableView();
524 }
525 if (!searchableView) {
526 return false;
527 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34528 }
Blink Reformat4c46d092018-04-07 15:32:37529 switch (actionId) {
530 case 'main.search-in-panel.find':
531 return searchableView.handleFindShortcut();
532 case 'main.search-in-panel.cancel':
533 return searchableView.handleCancelSearchShortcut();
534 case 'main.search-in-panel.find-next':
535 return searchableView.handleFindNextShortcut();
536 case 'main.search-in-panel.find-previous':
537 return searchableView.handleFindPreviousShortcut();
538 }
539 return false;
540 }
Paul Lewisc1d99fa2019-12-10 16:26:28541}
Blink Reformat4c46d092018-04-07 15:32:37542
543/**
544 * @implements {UI.ToolbarItem.Provider}
545 */
Paul Lewisc1d99fa2019-12-10 16:26:28546export class MainMenuItem {
Blink Reformat4c46d092018-04-07 15:32:37547 constructor() {
548 this._item = new UI.ToolbarMenuButton(this._handleContextMenu.bind(this), true);
549 this._item.setTitle(Common.UIString('Customize and control DevTools'));
550 }
551
552 /**
553 * @override
554 * @return {?UI.ToolbarItem}
555 */
556 item() {
557 return this._item;
558 }
559
560 /**
561 * @param {!UI.ContextMenu} contextMenu
562 */
563 _handleContextMenu(contextMenu) {
564 if (Components.dockController.canDock()) {
565 const dockItemElement = createElementWithClass('div', 'flex-centered flex-auto');
Joel Einbinder57b9fad2019-02-08 23:31:35566 dockItemElement.tabIndex = -1;
Blink Reformat4c46d092018-04-07 15:32:37567 const titleElement = dockItemElement.createChild('span', 'flex-auto');
568 titleElement.textContent = Common.UIString('Dock side');
569 const toggleDockSideShorcuts = UI.shortcutRegistry.shortcutDescriptorsForAction('main.toggle-dock');
570 titleElement.title = Common.UIString(
571 'Placement of DevTools relative to the page. (%s to restore last position)', toggleDockSideShorcuts[0].name);
572 dockItemElement.appendChild(titleElement);
573 const dockItemToolbar = new UI.Toolbar('', dockItemElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34574 if (Host.isMac() && !UI.themeSupport.hasTheme()) {
Joel Einbinder9a6bead2018-08-06 18:02:35575 dockItemToolbar.makeBlueOnHover();
Tim van der Lippe1d6e57a2019-09-30 11:55:34576 }
Blink Reformat4c46d092018-04-07 15:32:37577 const undock = new UI.ToolbarToggle(Common.UIString('Undock into separate window'), 'largeicon-undock');
578 const bottom = new UI.ToolbarToggle(Common.UIString('Dock to bottom'), 'largeicon-dock-to-bottom');
579 const right = new UI.ToolbarToggle(Common.UIString('Dock to right'), 'largeicon-dock-to-right');
580 const left = new UI.ToolbarToggle(Common.UIString('Dock to left'), 'largeicon-dock-to-left');
581 undock.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
582 bottom.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
583 right.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
584 left.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
585 undock.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35586 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.Undocked));
Blink Reformat4c46d092018-04-07 15:32:37587 bottom.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35588 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToBottom));
Blink Reformat4c46d092018-04-07 15:32:37589 right.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35590 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToRight));
Blink Reformat4c46d092018-04-07 15:32:37591 left.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35592 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToLeft));
Blink Reformat4c46d092018-04-07 15:32:37593 undock.setToggled(Components.dockController.dockSide() === Components.DockController.State.Undocked);
594 bottom.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToBottom);
595 right.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToRight);
596 left.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToLeft);
597 dockItemToolbar.appendToolbarItem(undock);
598 dockItemToolbar.appendToolbarItem(left);
599 dockItemToolbar.appendToolbarItem(bottom);
600 dockItemToolbar.appendToolbarItem(right);
Joel Einbinder57b9fad2019-02-08 23:31:35601 dockItemElement.addEventListener('keydown', event => {
602 let dir = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:34603 if (event.key === 'ArrowLeft') {
Joel Einbinder57b9fad2019-02-08 23:31:35604 dir = -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:34605 } else if (event.key === 'ArrowRight') {
Joel Einbinder57b9fad2019-02-08 23:31:35606 dir = 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:34607 } else {
Joel Einbinder57b9fad2019-02-08 23:31:35608 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34609 }
Joel Einbinder57b9fad2019-02-08 23:31:35610
611 const buttons = [undock, left, bottom, right];
612 let index = buttons.findIndex(button => button.element.hasFocus());
613 index = Number.constrain(index + dir, 0, buttons.length - 1);
614
615 buttons[index].element.focus();
616 event.consume(true);
617 });
Blink Reformat4c46d092018-04-07 15:32:37618 contextMenu.headerSection().appendCustomItem(dockItemElement);
619 }
620
Jan Scheffler53de0572019-10-16 12:31:18621
622 const button = this._item.element;
623
Blink Reformat4c46d092018-04-07 15:32:37624 /**
625 * @param {string} side
Jan Scheffler53de0572019-10-16 12:31:18626 * @suppressGlobalPropertiesCheck
Blink Reformat4c46d092018-04-07 15:32:37627 */
628 function setDockSide(side) {
Jan Scheffler53de0572019-10-16 12:31:18629 const hadKeyboardFocus = document.deepActiveElement().hasAttribute('data-keyboard-focus');
630 Components.dockController.once(Components.DockController.Events.AfterDockSideChanged).then(() => {
631 button.focus();
632 if (hadKeyboardFocus) {
633 UI.markAsFocusedByKeyboard(button);
634 }
635 });
Blink Reformat4c46d092018-04-07 15:32:37636 Components.dockController.setDockSide(side);
637 contextMenu.discard();
638 }
639
640 if (Components.dockController.dockSide() === Components.DockController.State.Undocked &&
Tim van der Lippe1d6e57a2019-09-30 11:55:34641 SDK.targetManager.mainTarget() && SDK.targetManager.mainTarget().type() === SDK.Target.Type.Frame) {
Blink Reformat4c46d092018-04-07 15:32:37642 contextMenu.defaultSection().appendAction('inspector_main.focus-debuggee', Common.UIString('Focus debuggee'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34643 }
Blink Reformat4c46d092018-04-07 15:32:37644
645 contextMenu.defaultSection().appendAction(
646 'main.toggle-drawer',
647 UI.inspectorView.drawerVisible() ? Common.UIString('Hide console drawer') :
648 Common.UIString('Show console drawer'));
649 contextMenu.appendItemsAtLocation('mainMenu');
650 const moreTools = contextMenu.defaultSection().appendSubMenuItem(Common.UIString('More tools'));
651 const extensions = self.runtime.extensions('view', undefined, true);
652 for (const extension of extensions) {
653 const descriptor = extension.descriptor();
Tim van der Lippe1d6e57a2019-09-30 11:55:34654 if (descriptor['persistence'] !== 'closeable') {
Blink Reformat4c46d092018-04-07 15:32:37655 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34656 }
657 if (descriptor['location'] !== 'drawer-view' && descriptor['location'] !== 'panel') {
Blink Reformat4c46d092018-04-07 15:32:37658 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34659 }
Blink Reformat4c46d092018-04-07 15:32:37660 moreTools.defaultSection().appendItem(
661 extension.title(), UI.viewManager.showView.bind(UI.viewManager, descriptor['id']));
662 }
663
664 const helpSubMenu = contextMenu.footerSection().appendSubMenuItem(Common.UIString('Help'));
665 helpSubMenu.appendItemsAtLocation('mainMenuHelp');
666 }
Paul Lewisc1d99fa2019-12-10 16:26:28667}
Blink Reformat4c46d092018-04-07 15:32:37668
669/**
670 * @unrestricted
671 */
Paul Lewisc1d99fa2019-12-10 16:26:28672export class PauseListener {
Blink Reformat4c46d092018-04-07 15:32:37673 constructor() {
674 SDK.targetManager.addModelListener(
675 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
676 }
677
678 /**
679 * @param {!Common.Event} event
680 */
681 _debuggerPaused(event) {
682 SDK.targetManager.removeModelListener(
683 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
684 const debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.data);
685 const debuggerPausedDetails = debuggerModel.debuggerPausedDetails();
686 UI.context.setFlavor(SDK.Target, debuggerModel.target());
687 Common.Revealer.reveal(debuggerPausedDetails);
688 }
Paul Lewisc1d99fa2019-12-10 16:26:28689}
Blink Reformat4c46d092018-04-07 15:32:37690
Tim van der Lippe4221a1a2019-11-05 12:54:17691/**
692 * @param {string} method
693 * @param {?Object} params
694 * @return {!Promise}
695 */
Paul Lewisc1d99fa2019-12-10 16:26:28696export function sendOverProtocol(method, params) {
Tim van der Lippe4221a1a2019-11-05 12:54:17697 return new Promise((resolve, reject) => {
698 Protocol.test.sendRawMessage(method, params, (err, ...results) => {
699 if (err) {
700 return reject(err);
701 }
702 return resolve(results);
703 });
704 });
Paul Lewisc1d99fa2019-12-10 16:26:28705}
Tim van der Lippe4221a1a2019-11-05 12:54:17706
707/**
708 * @implements {UI.ActionDelegate}
709 * @unrestricted
710 */
Paul Lewisc1d99fa2019-12-10 16:26:28711export class ReloadActionDelegate {
Tim van der Lippe4221a1a2019-11-05 12:54:17712 /**
713 * @override
714 * @param {!UI.Context} context
715 * @param {string} actionId
716 * @return {boolean}
717 */
718 handleAction(context, actionId) {
719 switch (actionId) {
720 case 'main.debug-reload':
721 Components.reload();
722 return true;
723 }
724 return false;
725 }
Paul Lewisc1d99fa2019-12-10 16:26:28726}
Tim van der Lippe4221a1a2019-11-05 12:54:17727
Paul Lewisc1d99fa2019-12-10 16:26:28728new MainImpl();
729
730/* Legacy exported object */
731self.Main = self.Main || {};
732
733/* Legacy exported object */
734Main = Main || {};
735
736/**
737 * @constructor
738 */
739Main.Main = MainImpl;
740
741/**
742 * @constructor
743 */
744Main.Main.ZoomActionDelegate = ZoomActionDelegate;
745
746/**
747 * @constructor
748 */
749Main.Main.SearchActionDelegate = SearchActionDelegate;
750
751/**
752 * @constructor
753 */
754Main.Main.MainMenuItem = MainMenuItem;
755
756/**
757 * @constructor
758 */
759Main.Main.PauseListener = PauseListener;
760
761/**
762 * @constructor
763 */
764Main.ReloadActionDelegate = ReloadActionDelegate;
765Main.sendOverProtocol = sendOverProtocol;