blob: 04d62f0e73c996c8cd37354a673477ec28b94e85 [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 */
34Main.Main = class {
35 /**
36 * @suppressGlobalPropertiesCheck
37 */
38 constructor() {
39 Main.Main._instanceForTest = this;
40 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);
Blink Reformat4c46d092018-04-07 15:32:3768 InspectorFrontendHost.getPreferences(this._gotPreferences.bind(this));
69 }
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(
105 prefs, InspectorFrontendHost.setPreference, InspectorFrontendHost.removePreference,
106 InspectorFrontendHost.clearPreferences, storagePrefix);
107 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);
132 Root.Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true);
133 Root.Runtime.experiments.register('protocolMonitor', 'Protocol Monitor');
134 Root.Runtime.experiments.register(
135 'recordCoverageWithPerformanceTracing', 'Record coverage while performance tracing');
136 Root.Runtime.experiments.register('samplingHeapProfilerTimeline', 'Sampling heap profiler timeline', true);
137 Root.Runtime.experiments.register('sourceDiff', 'Source diff');
138 Root.Runtime.experiments.register('splitInDrawer', 'Split in drawer', true);
139 Root.Runtime.experiments.register('spotlight', 'Spotlight', true);
140 Root.Runtime.experiments.register('terminalInDrawer', 'Terminal in drawer', true);
Blink Reformat4c46d092018-04-07 15:32:37141
142 // Timeline
Tim van der Lippe99e59b82019-09-30 20:00:59143 Root.Runtime.experiments.register('timelineEventInitiators', 'Timeline: event initiators');
144 Root.Runtime.experiments.register('timelineFlowEvents', 'Timeline: flow events', true);
145 Root.Runtime.experiments.register('timelineInvalidationTracking', 'Timeline: invalidation tracking', true);
146 Root.Runtime.experiments.register('timelineShowAllEvents', 'Timeline: show all events', true);
147 Root.Runtime.experiments.register(
148 'timelineV8RuntimeCallStats', 'Timeline: V8 Runtime Call Stats on Timeline', true);
149 Root.Runtime.experiments.register('timelineWebGL', 'Timeline: WebGL-based flamechart');
Blink Reformat4c46d092018-04-07 15:32:37150
Tim van der Lippe99e59b82019-09-30 20:00:59151 Root.Runtime.experiments.cleanUpStaleExperiments();
152 const enabledExperiments = Root.Runtime.queryParam('enabledExperiments');
Tim van der Lippe1d6e57a2019-09-30 11:55:34153 if (enabledExperiments) {
Tim van der Lippe99e59b82019-09-30 20:00:59154 Root.Runtime.experiments.setServerEnabledExperiments(enabledExperiments.split(';'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34155 }
Tim van der Lippe99e59b82019-09-30 20:00:59156 Root.Runtime.experiments.setDefaultExperiments([
Rayan Kanso93bacf72019-08-28 12:33:23157 'backgroundServices',
158 'backgroundServicesNotifications',
159 'backgroundServicesPushMessaging',
160 'backgroundServicesPaymentHandler',
161 ]);
Alexei Filippovfdfefe02019-03-09 00:33:24162
Tim van der Lippe99e59b82019-09-30 20:00:59163 if (Host.isUnderTest() && Root.Runtime.queryParam('test').includes('live-line-level-heap-profile.js')) {
164 Root.Runtime.experiments.enableForTest('liveHeapProfile');
Tim van der Lippe1d6e57a2019-09-30 11:55:34165 }
Blink Reformat4c46d092018-04-07 15:32:37166 }
167
168 /**
169 * @suppressGlobalPropertiesCheck
170 */
171 async _createAppUI() {
172 Main.Main.time('Main._createAppUI');
173
174 UI.viewManager = new UI.ViewManager();
175
176 // Request filesystems early, we won't create connections until callback is fired. Things will happen in parallel.
177 Persistence.isolatedFileSystemManager = new Persistence.IsolatedFileSystemManager();
178
Erik Luo9adba992019-06-26 01:17:52179 const themeSetting = Common.settings.createSetting('uiTheme', 'systemPreferred');
Blink Reformat4c46d092018-04-07 15:32:37180 UI.initializeUIUtils(document, themeSetting);
181 themeSetting.addChangeListener(Components.reload.bind(Components));
182
183 UI.installComponentRootStyles(/** @type {!Element} */ (document.body));
184
185 this._addMainEventListeners(document);
186
Tim van der Lippe99e59b82019-09-30 20:00:59187 const canDock = !!Root.Runtime.queryParam('can_dock');
Blink Reformat4c46d092018-04-07 15:32:37188 UI.zoomManager = new UI.ZoomManager(window, InspectorFrontendHost);
189 UI.inspectorView = UI.InspectorView.instance();
190 UI.ContextMenu.initialize();
191 UI.ContextMenu.installHandler(document);
192 UI.Tooltip.installHandler(document);
193 Components.dockController = new Components.DockController(canDock);
194 SDK.consoleModel = new SDK.ConsoleModel();
195 SDK.multitargetNetworkManager = new SDK.MultitargetNetworkManager();
196 SDK.domDebuggerManager = new SDK.DOMDebuggerManager();
197 SDK.targetManager.addEventListener(
198 SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged.bind(this));
199
200 UI.shortcutsScreen = new UI.ShortcutsScreen();
201 // set order of some sections explicitly
202 UI.shortcutsScreen.section(Common.UIString('Elements Panel'));
203 UI.shortcutsScreen.section(Common.UIString('Styles Pane'));
204 UI.shortcutsScreen.section(Common.UIString('Debugger'));
205 UI.shortcutsScreen.section(Common.UIString('Console'));
206
207 Workspace.fileManager = new Workspace.FileManager();
208 Workspace.workspace = new Workspace.Workspace();
209
210 Bindings.networkProjectManager = new Bindings.NetworkProjectManager();
211 Bindings.resourceMapping = new Bindings.ResourceMapping(SDK.targetManager, Workspace.workspace);
212 new Bindings.PresentationConsoleMessageManager();
213 Bindings.cssWorkspaceBinding = new Bindings.CSSWorkspaceBinding(SDK.targetManager, Workspace.workspace);
214 Bindings.debuggerWorkspaceBinding = new Bindings.DebuggerWorkspaceBinding(SDK.targetManager, Workspace.workspace);
215 Bindings.breakpointManager =
216 new Bindings.BreakpointManager(Workspace.workspace, SDK.targetManager, Bindings.debuggerWorkspaceBinding);
217 Extensions.extensionServer = new Extensions.ExtensionServer();
218
219 new Persistence.FileSystemWorkspaceBinding(Persistence.isolatedFileSystemManager, Workspace.workspace);
220 Persistence.persistence = new Persistence.Persistence(Workspace.workspace, Bindings.breakpointManager);
221 Persistence.networkPersistenceManager = new Persistence.NetworkPersistenceManager(Workspace.workspace);
222
223 new Main.ExecutionContextSelector(SDK.targetManager, UI.context);
224 Bindings.blackboxManager = new Bindings.BlackboxManager(Bindings.debuggerWorkspaceBinding);
225
226 new Main.Main.PauseListener();
227
228 UI.actionRegistry = new UI.ActionRegistry();
229 UI.shortcutRegistry = new UI.ShortcutRegistry(UI.actionRegistry, document);
230 UI.ShortcutsScreen.registerShortcuts();
231 this._registerForwardedShortcuts();
232 this._registerMessageSinkListener();
233
234 Main.Main.timeEnd('Main._createAppUI');
235 this._showAppUI(await self.runtime.extension(Common.AppProvider).instance());
236 }
237
238 /**
239 * @param {!Object} appProvider
240 * @suppressGlobalPropertiesCheck
241 */
242 _showAppUI(appProvider) {
243 Main.Main.time('Main._showAppUI');
244 const app = /** @type {!Common.AppProvider} */ (appProvider).createApp();
245 // It is important to kick controller lifetime after apps are instantiated.
246 Components.dockController.initialize();
247 app.presentUI(document);
248
249 const toggleSearchNodeAction = UI.actionRegistry.action('elements.toggle-element-search');
250 // TODO: we should not access actions from other modules.
251 if (toggleSearchNodeAction) {
252 InspectorFrontendHost.events.addEventListener(
Tim van der Lippe7b190162019-09-27 15:10:44253 Host.InspectorFrontendHostAPI.Events.EnterInspectElementMode,
Blink Reformat4c46d092018-04-07 15:32:37254 toggleSearchNodeAction.execute.bind(toggleSearchNodeAction), this);
255 }
256 InspectorFrontendHost.events.addEventListener(
Tim van der Lippe7b190162019-09-27 15:10:44257 Host.InspectorFrontendHostAPI.Events.RevealSourceLine, this._revealSourceLine, this);
Blink Reformat4c46d092018-04-07 15:32:37258
259 UI.inspectorView.createToolbars();
260 InspectorFrontendHost.loadCompleted();
261
262 const extensions = self.runtime.extensions(Common.QueryParamHandler);
263 for (const extension of extensions) {
Tim van der Lippe99e59b82019-09-30 20:00:59264 const value = Root.Runtime.queryParam(extension.descriptor()['name']);
Tim van der Lippe1d6e57a2019-09-30 11:55:34265 if (value !== null) {
Blink Reformat4c46d092018-04-07 15:32:37266 extension.instance().then(handleQueryParam.bind(null, value));
Tim van der Lippe1d6e57a2019-09-30 11:55:34267 }
Blink Reformat4c46d092018-04-07 15:32:37268 }
269
270 /**
271 * @param {string} value
272 * @param {!Common.QueryParamHandler} handler
273 */
274 function handleQueryParam(value, handler) {
275 handler.handleQueryParam(value);
276 }
277
278 // Allow UI cycles to repaint prior to creating connection.
279 setTimeout(this._initializeTarget.bind(this), 0);
280 Main.Main.timeEnd('Main._showAppUI');
281 }
282
283 async _initializeTarget() {
284 Main.Main.time('Main._initializeTarget');
285 const instances =
286 await Promise.all(self.runtime.extensions('early-initialization').map(extension => extension.instance()));
Tim van der Lippe1d6e57a2019-09-30 11:55:34287 for (const instance of instances) {
Pavel Feldman07ef9722018-12-13 23:52:22288 await /** @type {!Common.Runnable} */ (instance).run();
Tim van der Lippe1d6e57a2019-09-30 11:55:34289 }
Blink Reformat4c46d092018-04-07 15:32:37290 // Used for browser tests.
291 InspectorFrontendHost.readyForTest();
292 // Asynchronously run the extensions.
293 setTimeout(this._lateInitialization.bind(this), 100);
294 Main.Main.timeEnd('Main._initializeTarget');
295 }
296
297 _lateInitialization() {
298 Main.Main.time('Main._lateInitialization');
299 this._registerShortcuts();
300 Extensions.extensionServer.initializeExtensions();
Alexei Filippov19be5102019-04-16 20:40:24301 const extensions = self.runtime.extensions('late-initialization');
302 const promises = [];
303 for (const extension of extensions) {
304 const setting = extension.descriptor()['setting'];
305 if (!setting || Common.settings.moduleSetting(setting).get()) {
306 promises.push(extension.instance().then(instance => (/** @type {!Common.Runnable} */ (instance)).run()));
307 continue;
308 }
309 /**
310 * @param {!Common.Event} event
311 */
312 async function changeListener(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34313 if (!event.data) {
Alexei Filippov19be5102019-04-16 20:40:24314 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34315 }
Alexei Filippov19be5102019-04-16 20:40:24316 Common.settings.moduleSetting(setting).removeChangeListener(changeListener);
317 (/** @type {!Common.Runnable} */ (await extension.instance())).run();
318 }
319 Common.settings.moduleSetting(setting).addChangeListener(changeListener);
320 }
321 this._lateInitDonePromise = Promise.all(promises);
Blink Reformat4c46d092018-04-07 15:32:37322 Main.Main.timeEnd('Main._lateInitialization');
323 }
324
Alexei Filippov19be5102019-04-16 20:40:24325 /**
326 * @return {!Promise}
327 */
328 lateInitDonePromiseForTest() {
329 return this._lateInitDonePromise;
330 }
331
Blink Reformat4c46d092018-04-07 15:32:37332 _registerForwardedShortcuts() {
333 /** @const */ const forwardedActions = [
334 'main.toggle-dock', 'debugger.toggle-breakpoints-active', 'debugger.toggle-pause', 'commandMenu.show',
335 'console.show'
336 ];
337 const actionKeys =
338 UI.shortcutRegistry.keysForActions(forwardedActions).map(UI.KeyboardShortcut.keyCodeAndModifiersFromKey);
339 InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
340 }
341
342 _registerMessageSinkListener() {
343 Common.console.addEventListener(Common.Console.Events.MessageAdded, messageAdded);
344
345 /**
346 * @param {!Common.Event} event
347 */
348 function messageAdded(event) {
349 const message = /** @type {!Common.Console.Message} */ (event.data);
Tim van der Lippe1d6e57a2019-09-30 11:55:34350 if (message.show) {
Blink Reformat4c46d092018-04-07 15:32:37351 Common.console.show();
Tim van der Lippe1d6e57a2019-09-30 11:55:34352 }
Blink Reformat4c46d092018-04-07 15:32:37353 }
354 }
355
356 /**
357 * @param {!Common.Event} event
358 */
359 _revealSourceLine(event) {
360 const url = /** @type {string} */ (event.data['url']);
361 const lineNumber = /** @type {number} */ (event.data['lineNumber']);
362 const columnNumber = /** @type {number} */ (event.data['columnNumber']);
363
364 const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
365 if (uiSourceCode) {
366 Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
367 return;
368 }
369
370 /**
371 * @param {!Common.Event} event
372 */
373 function listener(event) {
374 const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
375 if (uiSourceCode.url() === url) {
376 Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
377 Workspace.workspace.removeEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
378 }
379 }
380
381 Workspace.workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
382 }
383
384 _registerShortcuts() {
385 const shortcut = UI.KeyboardShortcut;
386 const section = UI.shortcutsScreen.section(Common.UIString('All Panels'));
387 let keys = [
388 shortcut.makeDescriptor('[', shortcut.Modifiers.CtrlOrMeta),
389 shortcut.makeDescriptor(']', shortcut.Modifiers.CtrlOrMeta)
390 ];
391 section.addRelatedKeys(keys, Common.UIString('Go to the panel to the left/right'));
392
393 const toggleConsoleLabel = Common.UIString('Show console');
394 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Tilde, shortcut.Modifiers.Ctrl), toggleConsoleLabel);
395 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Esc), Common.UIString('Toggle drawer'));
396 if (Components.dockController.canDock()) {
397 section.addKey(
398 shortcut.makeDescriptor('M', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
399 Common.UIString('Toggle device mode'));
400 section.addKey(
401 shortcut.makeDescriptor('D', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
402 Common.UIString('Toggle dock side'));
403 }
404 section.addKey(shortcut.makeDescriptor('f', shortcut.Modifiers.CtrlOrMeta), Common.UIString('Search'));
405
406 const advancedSearchShortcutModifier = Host.isMac() ?
407 UI.KeyboardShortcut.Modifiers.Meta | UI.KeyboardShortcut.Modifiers.Alt :
408 UI.KeyboardShortcut.Modifiers.Ctrl | UI.KeyboardShortcut.Modifiers.Shift;
409 const advancedSearchShortcut = shortcut.makeDescriptor('f', advancedSearchShortcutModifier);
410 section.addKey(advancedSearchShortcut, Common.UIString('Search across all sources'));
411
412 const inspectElementModeShortcuts =
413 UI.shortcutRegistry.shortcutDescriptorsForAction('elements.toggle-element-search');
Tim van der Lippe1d6e57a2019-09-30 11:55:34414 if (inspectElementModeShortcuts.length) {
Blink Reformat4c46d092018-04-07 15:32:37415 section.addKey(inspectElementModeShortcuts[0], Common.UIString('Select node to inspect'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34416 }
Blink Reformat4c46d092018-04-07 15:32:37417
418 const openResourceShortcut = UI.KeyboardShortcut.makeDescriptor('p', UI.KeyboardShortcut.Modifiers.CtrlOrMeta);
419 section.addKey(openResourceShortcut, Common.UIString('Go to source'));
420
421 if (Host.isMac()) {
422 keys = [
423 shortcut.makeDescriptor('g', shortcut.Modifiers.Meta),
424 shortcut.makeDescriptor('g', shortcut.Modifiers.Meta | shortcut.Modifiers.Shift)
425 ];
426 section.addRelatedKeys(keys, Common.UIString('Find next/previous'));
427 }
428 }
429
430 _postDocumentKeyDown(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34431 if (!event.handled) {
Joel Einbindera66e5bf2018-05-31 01:26:37432 UI.shortcutRegistry.handleShortcut(event);
Tim van der Lippe1d6e57a2019-09-30 11:55:34433 }
Blink Reformat4c46d092018-04-07 15:32:37434 }
435
436 /**
437 * @param {!Event} event
438 */
439 _redispatchClipboardEvent(event) {
440 const eventCopy = new CustomEvent('clipboard-' + event.type, {bubbles: true});
441 eventCopy['original'] = event;
442 const document = event.target && event.target.ownerDocument;
443 const target = document ? document.deepActiveElement() : null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34444 if (target) {
Blink Reformat4c46d092018-04-07 15:32:37445 target.dispatchEvent(eventCopy);
Tim van der Lippe1d6e57a2019-09-30 11:55:34446 }
447 if (eventCopy.handled) {
Blink Reformat4c46d092018-04-07 15:32:37448 event.preventDefault();
Tim van der Lippe1d6e57a2019-09-30 11:55:34449 }
Blink Reformat4c46d092018-04-07 15:32:37450 }
451
452 _contextMenuEventFired(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34453 if (event.handled || event.target.classList.contains('popup-glasspane')) {
Blink Reformat4c46d092018-04-07 15:32:37454 event.preventDefault();
Tim van der Lippe1d6e57a2019-09-30 11:55:34455 }
Blink Reformat4c46d092018-04-07 15:32:37456 }
457
458 /**
459 * @param {!Document} document
460 */
461 _addMainEventListeners(document) {
462 document.addEventListener('keydown', this._postDocumentKeyDown.bind(this), false);
463 document.addEventListener('beforecopy', this._redispatchClipboardEvent.bind(this), true);
464 document.addEventListener('copy', this._redispatchClipboardEvent.bind(this), false);
465 document.addEventListener('cut', this._redispatchClipboardEvent.bind(this), false);
466 document.addEventListener('paste', this._redispatchClipboardEvent.bind(this), false);
467 document.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), true);
468 }
469
470 _onSuspendStateChanged() {
471 const suspended = SDK.targetManager.allTargetsSuspended();
472 UI.inspectorView.onSuspendStateChanged(suspended);
473 }
474};
475
476/**
477 * @implements {UI.ActionDelegate}
478 * @unrestricted
479 */
480Main.Main.ZoomActionDelegate = class {
481 /**
482 * @override
483 * @param {!UI.Context} context
484 * @param {string} actionId
485 * @return {boolean}
486 */
487 handleAction(context, actionId) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34488 if (InspectorFrontendHost.isHostedMode()) {
Blink Reformat4c46d092018-04-07 15:32:37489 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34490 }
Blink Reformat4c46d092018-04-07 15:32:37491
492 switch (actionId) {
493 case 'main.zoom-in':
494 InspectorFrontendHost.zoomIn();
495 return true;
496 case 'main.zoom-out':
497 InspectorFrontendHost.zoomOut();
498 return true;
499 case 'main.zoom-reset':
500 InspectorFrontendHost.resetZoom();
501 return true;
502 }
503 return false;
504 }
505};
506
507/**
508 * @implements {UI.ActionDelegate}
509 * @unrestricted
510 */
511Main.Main.SearchActionDelegate = class {
512 /**
513 * @override
514 * @param {!UI.Context} context
515 * @param {string} actionId
516 * @return {boolean}
517 * @suppressGlobalPropertiesCheck
518 */
519 handleAction(context, actionId) {
520 const searchableView = UI.SearchableView.fromElement(document.deepActiveElement()) ||
521 UI.inspectorView.currentPanelDeprecated().searchableView();
Tim van der Lippe1d6e57a2019-09-30 11:55:34522 if (!searchableView) {
Blink Reformat4c46d092018-04-07 15:32:37523 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34524 }
Blink Reformat4c46d092018-04-07 15:32:37525 switch (actionId) {
526 case 'main.search-in-panel.find':
527 return searchableView.handleFindShortcut();
528 case 'main.search-in-panel.cancel':
529 return searchableView.handleCancelSearchShortcut();
530 case 'main.search-in-panel.find-next':
531 return searchableView.handleFindNextShortcut();
532 case 'main.search-in-panel.find-previous':
533 return searchableView.handleFindPreviousShortcut();
534 }
535 return false;
536 }
537};
538
539/**
540 * @implements {UI.ToolbarItem.Provider}
541 */
542Main.Main.MainMenuItem = class {
543 constructor() {
544 this._item = new UI.ToolbarMenuButton(this._handleContextMenu.bind(this), true);
545 this._item.setTitle(Common.UIString('Customize and control DevTools'));
546 }
547
548 /**
549 * @override
550 * @return {?UI.ToolbarItem}
551 */
552 item() {
553 return this._item;
554 }
555
556 /**
557 * @param {!UI.ContextMenu} contextMenu
558 */
559 _handleContextMenu(contextMenu) {
560 if (Components.dockController.canDock()) {
561 const dockItemElement = createElementWithClass('div', 'flex-centered flex-auto');
Joel Einbinder57b9fad2019-02-08 23:31:35562 dockItemElement.tabIndex = -1;
Blink Reformat4c46d092018-04-07 15:32:37563 const titleElement = dockItemElement.createChild('span', 'flex-auto');
564 titleElement.textContent = Common.UIString('Dock side');
565 const toggleDockSideShorcuts = UI.shortcutRegistry.shortcutDescriptorsForAction('main.toggle-dock');
566 titleElement.title = Common.UIString(
567 'Placement of DevTools relative to the page. (%s to restore last position)', toggleDockSideShorcuts[0].name);
568 dockItemElement.appendChild(titleElement);
569 const dockItemToolbar = new UI.Toolbar('', dockItemElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34570 if (Host.isMac() && !UI.themeSupport.hasTheme()) {
Joel Einbinder9a6bead2018-08-06 18:02:35571 dockItemToolbar.makeBlueOnHover();
Tim van der Lippe1d6e57a2019-09-30 11:55:34572 }
Blink Reformat4c46d092018-04-07 15:32:37573 const undock = new UI.ToolbarToggle(Common.UIString('Undock into separate window'), 'largeicon-undock');
574 const bottom = new UI.ToolbarToggle(Common.UIString('Dock to bottom'), 'largeicon-dock-to-bottom');
575 const right = new UI.ToolbarToggle(Common.UIString('Dock to right'), 'largeicon-dock-to-right');
576 const left = new UI.ToolbarToggle(Common.UIString('Dock to left'), 'largeicon-dock-to-left');
577 undock.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
578 bottom.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
579 right.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
580 left.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
581 undock.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35582 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.Undocked));
Blink Reformat4c46d092018-04-07 15:32:37583 bottom.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35584 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToBottom));
Blink Reformat4c46d092018-04-07 15:32:37585 right.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35586 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToRight));
Blink Reformat4c46d092018-04-07 15:32:37587 left.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35588 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToLeft));
Blink Reformat4c46d092018-04-07 15:32:37589 undock.setToggled(Components.dockController.dockSide() === Components.DockController.State.Undocked);
590 bottom.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToBottom);
591 right.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToRight);
592 left.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToLeft);
593 dockItemToolbar.appendToolbarItem(undock);
594 dockItemToolbar.appendToolbarItem(left);
595 dockItemToolbar.appendToolbarItem(bottom);
596 dockItemToolbar.appendToolbarItem(right);
Joel Einbinder57b9fad2019-02-08 23:31:35597 dockItemElement.addEventListener('keydown', event => {
598 let dir = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:34599 if (event.key === 'ArrowLeft') {
Joel Einbinder57b9fad2019-02-08 23:31:35600 dir = -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:34601 } else if (event.key === 'ArrowRight') {
Joel Einbinder57b9fad2019-02-08 23:31:35602 dir = 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:34603 } else {
Joel Einbinder57b9fad2019-02-08 23:31:35604 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34605 }
Joel Einbinder57b9fad2019-02-08 23:31:35606
607 const buttons = [undock, left, bottom, right];
608 let index = buttons.findIndex(button => button.element.hasFocus());
609 index = Number.constrain(index + dir, 0, buttons.length - 1);
610
611 buttons[index].element.focus();
612 event.consume(true);
613 });
Blink Reformat4c46d092018-04-07 15:32:37614 contextMenu.headerSection().appendCustomItem(dockItemElement);
615 }
616
617 /**
618 * @param {string} side
619 */
620 function setDockSide(side) {
621 Components.dockController.setDockSide(side);
622 contextMenu.discard();
623 }
624
625 if (Components.dockController.dockSide() === Components.DockController.State.Undocked &&
Tim van der Lippe1d6e57a2019-09-30 11:55:34626 SDK.targetManager.mainTarget() && SDK.targetManager.mainTarget().type() === SDK.Target.Type.Frame) {
Blink Reformat4c46d092018-04-07 15:32:37627 contextMenu.defaultSection().appendAction('inspector_main.focus-debuggee', Common.UIString('Focus debuggee'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34628 }
Blink Reformat4c46d092018-04-07 15:32:37629
630 contextMenu.defaultSection().appendAction(
631 'main.toggle-drawer',
632 UI.inspectorView.drawerVisible() ? Common.UIString('Hide console drawer') :
633 Common.UIString('Show console drawer'));
634 contextMenu.appendItemsAtLocation('mainMenu');
635 const moreTools = contextMenu.defaultSection().appendSubMenuItem(Common.UIString('More tools'));
636 const extensions = self.runtime.extensions('view', undefined, true);
637 for (const extension of extensions) {
638 const descriptor = extension.descriptor();
Tim van der Lippe1d6e57a2019-09-30 11:55:34639 if (descriptor['persistence'] !== 'closeable') {
Blink Reformat4c46d092018-04-07 15:32:37640 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34641 }
642 if (descriptor['location'] !== 'drawer-view' && descriptor['location'] !== 'panel') {
Blink Reformat4c46d092018-04-07 15:32:37643 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34644 }
Blink Reformat4c46d092018-04-07 15:32:37645 moreTools.defaultSection().appendItem(
646 extension.title(), UI.viewManager.showView.bind(UI.viewManager, descriptor['id']));
647 }
648
649 const helpSubMenu = contextMenu.footerSection().appendSubMenuItem(Common.UIString('Help'));
650 helpSubMenu.appendItemsAtLocation('mainMenuHelp');
651 }
652};
653
654/**
655 * @unrestricted
656 */
657Main.Main.PauseListener = class {
658 constructor() {
659 SDK.targetManager.addModelListener(
660 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
661 }
662
663 /**
664 * @param {!Common.Event} event
665 */
666 _debuggerPaused(event) {
667 SDK.targetManager.removeModelListener(
668 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
669 const debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.data);
670 const debuggerPausedDetails = debuggerModel.debuggerPausedDetails();
671 UI.context.setFlavor(SDK.Target, debuggerModel.target());
672 Common.Revealer.reveal(debuggerPausedDetails);
673 }
674};
675
676/**
677 * @param {string} method
678 * @param {?Object} params
679 * @return {!Promise}
680 */
681Main.sendOverProtocol = function(method, params) {
682 return new Promise((resolve, reject) => {
Dmitry Gozman99d7a6c2018-11-12 17:55:11683 Protocol.test.sendRawMessage(method, params, (err, ...results) => {
Tim van der Lippe1d6e57a2019-09-30 11:55:34684 if (err) {
Blink Reformat4c46d092018-04-07 15:32:37685 return reject(err);
Tim van der Lippe1d6e57a2019-09-30 11:55:34686 }
Blink Reformat4c46d092018-04-07 15:32:37687 return resolve(results);
688 });
689 });
690};
691
692/**
693 * @implements {UI.ActionDelegate}
694 * @unrestricted
695 */
696Main.ReloadActionDelegate = class {
697 /**
698 * @override
699 * @param {!UI.Context} context
700 * @param {string} actionId
701 * @return {boolean}
702 */
703 handleAction(context, actionId) {
704 switch (actionId) {
705 case 'main.debug-reload':
706 Components.reload();
707 return true;
708 }
709 return false;
710 }
711};
712
713new Main.Main();