blob: 6f1c7e5e34031c8f9e82c21e22a703fff46ec54c [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) {
47 if (Host.isUnderTest())
48 return;
49 console.time(label);
50 }
51
52 /**
53 * @param {string} label
54 */
55 static timeEnd(label) {
56 if (Host.isUnderTest())
57 return;
58 console.timeEnd(label);
59 }
60
61 async _loaded() {
62 console.timeStamp('Main._loaded');
Pavel Feldman63e89eb2018-11-25 05:47:0963 await Runtime.appStarted();
Blink Reformat4c46d092018-04-07 15:32:3764 Runtime.setPlatform(Host.platform());
65 InspectorFrontendHost.getPreferences(this._gotPreferences.bind(this));
66 }
67
68 /**
69 * @param {!Object<string, string>} prefs
70 */
71 _gotPreferences(prefs) {
72 console.timeStamp('Main._gotPreferences');
73 if (Host.isUnderTest(prefs))
74 self.runtime.useTestBase();
75 this._createSettings(prefs);
76 this._createAppUI();
77 }
78
79 /**
80 * @param {!Object<string, string>} prefs
81 * Note: this function is called from testSettings in Tests.js.
82 */
83 _createSettings(prefs) {
84 this._initializeExperiments();
85 let storagePrefix = '';
86 if (Host.isCustomDevtoolsFrontend())
87 storagePrefix = '__custom__';
88 else if (!Runtime.queryParam('can_dock') && !!Runtime.queryParam('debugFrontend') && !Host.isUnderTest())
89 storagePrefix = '__bundled__';
90
91 let localStorage;
92 if (!Host.isUnderTest() && window.localStorage) {
93 localStorage = new Common.SettingsStorage(
94 window.localStorage, undefined, undefined, () => window.localStorage.clear(), storagePrefix);
95 } else {
96 localStorage = new Common.SettingsStorage({}, undefined, undefined, undefined, storagePrefix);
97 }
98 const globalStorage = new Common.SettingsStorage(
99 prefs, InspectorFrontendHost.setPreference, InspectorFrontendHost.removePreference,
100 InspectorFrontendHost.clearPreferences, storagePrefix);
101 Common.settings = new Common.Settings(globalStorage, localStorage);
102 if (!Host.isUnderTest())
103 new Common.VersionController().updateVersion();
104 }
105
106 _initializeExperiments() {
107 // Keep this sorted alphabetically: both keys and values.
108 Runtime.experiments.register('applyCustomStylesheet', 'Allow custom UI themes');
109 Runtime.experiments.register('blackboxJSFramesOnTimeline', 'Blackbox JavaScript frames on Timeline', true);
110 Runtime.experiments.register('colorContrastRatio', 'Color contrast ratio line in color picker', true);
Erik Luo39452ff2018-09-01 01:08:07111 Runtime.experiments.register('consoleBelowPrompt', 'Console eager evaluation');
112 Runtime.experiments.register('consoleKeyboardNavigation', 'Console keyboard navigation', true);
Blink Reformat4c46d092018-04-07 15:32:37113 Runtime.experiments.register('emptySourceMapAutoStepping', 'Empty sourcemap auto-stepping');
114 Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true);
115 Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true);
116 Runtime.experiments.register('networkSearch', 'Network search');
117 Runtime.experiments.register('oopifInlineDOM', 'OOPIF: inline DOM ', true);
Erik Luo6294d3b2018-07-12 21:54:16118 Runtime.experiments.register('pinnedExpressions', 'Pinned expressions in Console', true);
Blink Reformat4c46d092018-04-07 15:32:37119 Runtime.experiments.register('protocolMonitor', 'Protocol Monitor');
Alexei Filippov6d2eb592018-10-25 21:48:56120 Runtime.experiments.register('samplingHeapProfilerTimeline', 'Sampling heap profiler timeline', true);
Blink Reformat4c46d092018-04-07 15:32:37121 Runtime.experiments.register('sourceDiff', 'Source diff');
Erik Luo5b2b7522018-12-03 20:35:06122 Runtime.experiments.register('sourcesLogpoints', 'Sources: logpoints');
Joel Einbinderd7595c72018-05-15 17:41:54123 Runtime.experiments.register('sourcesPrettyPrint', 'Automatically pretty print in the Sources Panel');
Blink Reformat4c46d092018-04-07 15:32:37124 Runtime.experiments.register(
125 'stepIntoAsync', 'Introduce separate step action, stepInto becomes powerful enough to go inside async call');
Pavel Feldmanc9060ea2018-04-30 04:42:18126 Runtime.experiments.register('splitInDrawer', 'Split in drawer', true);
Blink Reformat4c46d092018-04-07 15:32:37127 Runtime.experiments.register('terminalInDrawer', 'Terminal in drawer', true);
128
129 // Timeline
130 Runtime.experiments.register('timelineEventInitiators', 'Timeline: event initiators');
131 Runtime.experiments.register('timelineFlowEvents', 'Timeline: flow events', true);
132 Runtime.experiments.register('timelineInvalidationTracking', 'Timeline: invalidation tracking', true);
Blink Reformat4c46d092018-04-07 15:32:37133 Runtime.experiments.register('timelineShowAllEvents', 'Timeline: show all events', true);
Blink Reformat4c46d092018-04-07 15:32:37134 Runtime.experiments.register('timelineTracingJSProfile', 'Timeline: tracing based JS profiler', true);
135 Runtime.experiments.register('timelineV8RuntimeCallStats', 'Timeline: V8 Runtime Call Stats on Timeline', true);
Alexei Filippov57ccafb2018-08-14 20:59:05136 Runtime.experiments.register('timelineWebGL', 'Timeline: WebGL-based flamechart');
Blink Reformat4c46d092018-04-07 15:32:37137
138 Runtime.experiments.cleanUpStaleExperiments();
139
140 if (Host.isUnderTest()) {
141 const testPath = Runtime.queryParam('test');
142 // Enable experiments for testing.
143 if (testPath.indexOf('oopif/') !== -1)
144 Runtime.experiments.enableForTest('oopifInlineDOM');
145 if (testPath.indexOf('network/') !== -1)
146 Runtime.experiments.enableForTest('networkSearch');
Erik Luo0f7f85b2018-04-17 03:06:58147 if (testPath.indexOf('console/viewport-testing/') !== -1)
Erik Luo39452ff2018-09-01 01:08:07148 Runtime.experiments.enableForTest('consoleKeyboardNavigation');
Erik Luod8eee2b2018-07-24 01:36:18149 if (testPath.indexOf('console/') !== -1)
150 Runtime.experiments.enableForTest('pinnedExpressions');
Blink Reformat4c46d092018-04-07 15:32:37151 }
152
Erik Luod3aea5d2018-08-28 02:55:39153 Runtime.experiments.setDefaultExperiments([
154 'colorContrastRatio', 'stepIntoAsync', 'oopifInlineDOM', 'consoleBelowPrompt', 'timelineTracingJSProfile',
Erik Luo336b9a02018-12-06 18:37:44155 'pinnedExpressions', 'consoleKeyboardNavigation'
Erik Luod3aea5d2018-08-28 02:55:39156 ]);
Blink Reformat4c46d092018-04-07 15:32:37157 }
158
159 /**
160 * @suppressGlobalPropertiesCheck
161 */
162 async _createAppUI() {
163 Main.Main.time('Main._createAppUI');
164
165 UI.viewManager = new UI.ViewManager();
166
167 // Request filesystems early, we won't create connections until callback is fired. Things will happen in parallel.
168 Persistence.isolatedFileSystemManager = new Persistence.IsolatedFileSystemManager();
169
170 const themeSetting = Common.settings.createSetting('uiTheme', 'default');
171 UI.initializeUIUtils(document, themeSetting);
172 themeSetting.addChangeListener(Components.reload.bind(Components));
173
174 UI.installComponentRootStyles(/** @type {!Element} */ (document.body));
175
176 this._addMainEventListeners(document);
177
178 const canDock = !!Runtime.queryParam('can_dock');
179 UI.zoomManager = new UI.ZoomManager(window, InspectorFrontendHost);
180 UI.inspectorView = UI.InspectorView.instance();
181 UI.ContextMenu.initialize();
182 UI.ContextMenu.installHandler(document);
183 UI.Tooltip.installHandler(document);
184 Components.dockController = new Components.DockController(canDock);
185 SDK.consoleModel = new SDK.ConsoleModel();
186 SDK.multitargetNetworkManager = new SDK.MultitargetNetworkManager();
187 SDK.domDebuggerManager = new SDK.DOMDebuggerManager();
188 SDK.targetManager.addEventListener(
189 SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged.bind(this));
190
191 UI.shortcutsScreen = new UI.ShortcutsScreen();
192 // set order of some sections explicitly
193 UI.shortcutsScreen.section(Common.UIString('Elements Panel'));
194 UI.shortcutsScreen.section(Common.UIString('Styles Pane'));
195 UI.shortcutsScreen.section(Common.UIString('Debugger'));
196 UI.shortcutsScreen.section(Common.UIString('Console'));
197
198 Workspace.fileManager = new Workspace.FileManager();
199 Workspace.workspace = new Workspace.Workspace();
200
201 Bindings.networkProjectManager = new Bindings.NetworkProjectManager();
202 Bindings.resourceMapping = new Bindings.ResourceMapping(SDK.targetManager, Workspace.workspace);
203 new Bindings.PresentationConsoleMessageManager();
204 Bindings.cssWorkspaceBinding = new Bindings.CSSWorkspaceBinding(SDK.targetManager, Workspace.workspace);
205 Bindings.debuggerWorkspaceBinding = new Bindings.DebuggerWorkspaceBinding(SDK.targetManager, Workspace.workspace);
206 Bindings.breakpointManager =
207 new Bindings.BreakpointManager(Workspace.workspace, SDK.targetManager, Bindings.debuggerWorkspaceBinding);
208 Extensions.extensionServer = new Extensions.ExtensionServer();
209
210 new Persistence.FileSystemWorkspaceBinding(Persistence.isolatedFileSystemManager, Workspace.workspace);
211 Persistence.persistence = new Persistence.Persistence(Workspace.workspace, Bindings.breakpointManager);
212 Persistence.networkPersistenceManager = new Persistence.NetworkPersistenceManager(Workspace.workspace);
213
214 new Main.ExecutionContextSelector(SDK.targetManager, UI.context);
215 Bindings.blackboxManager = new Bindings.BlackboxManager(Bindings.debuggerWorkspaceBinding);
216
217 new Main.Main.PauseListener();
218
219 UI.actionRegistry = new UI.ActionRegistry();
220 UI.shortcutRegistry = new UI.ShortcutRegistry(UI.actionRegistry, document);
221 UI.ShortcutsScreen.registerShortcuts();
222 this._registerForwardedShortcuts();
223 this._registerMessageSinkListener();
224
225 Main.Main.timeEnd('Main._createAppUI');
226 this._showAppUI(await self.runtime.extension(Common.AppProvider).instance());
227 }
228
229 /**
230 * @param {!Object} appProvider
231 * @suppressGlobalPropertiesCheck
232 */
233 _showAppUI(appProvider) {
234 Main.Main.time('Main._showAppUI');
235 const app = /** @type {!Common.AppProvider} */ (appProvider).createApp();
236 // It is important to kick controller lifetime after apps are instantiated.
237 Components.dockController.initialize();
238 app.presentUI(document);
239
240 const toggleSearchNodeAction = UI.actionRegistry.action('elements.toggle-element-search');
241 // TODO: we should not access actions from other modules.
242 if (toggleSearchNodeAction) {
243 InspectorFrontendHost.events.addEventListener(
244 InspectorFrontendHostAPI.Events.EnterInspectElementMode,
245 toggleSearchNodeAction.execute.bind(toggleSearchNodeAction), this);
246 }
247 InspectorFrontendHost.events.addEventListener(
248 InspectorFrontendHostAPI.Events.RevealSourceLine, this._revealSourceLine, this);
249
250 UI.inspectorView.createToolbars();
251 InspectorFrontendHost.loadCompleted();
252
253 const extensions = self.runtime.extensions(Common.QueryParamHandler);
254 for (const extension of extensions) {
255 const value = Runtime.queryParam(extension.descriptor()['name']);
256 if (value !== null)
257 extension.instance().then(handleQueryParam.bind(null, value));
258 }
259
260 /**
261 * @param {string} value
262 * @param {!Common.QueryParamHandler} handler
263 */
264 function handleQueryParam(value, handler) {
265 handler.handleQueryParam(value);
266 }
267
268 // Allow UI cycles to repaint prior to creating connection.
269 setTimeout(this._initializeTarget.bind(this), 0);
270 Main.Main.timeEnd('Main._showAppUI');
271 }
272
273 async _initializeTarget() {
274 Main.Main.time('Main._initializeTarget');
275 const instances =
276 await Promise.all(self.runtime.extensions('early-initialization').map(extension => extension.instance()));
277 for (const instance of instances)
Pavel Feldman07ef9722018-12-13 23:52:22278 await /** @type {!Common.Runnable} */ (instance).run();
Blink Reformat4c46d092018-04-07 15:32:37279 // Used for browser tests.
280 InspectorFrontendHost.readyForTest();
281 // Asynchronously run the extensions.
282 setTimeout(this._lateInitialization.bind(this), 100);
283 Main.Main.timeEnd('Main._initializeTarget');
284 }
285
286 _lateInitialization() {
287 Main.Main.time('Main._lateInitialization');
288 this._registerShortcuts();
289 Extensions.extensionServer.initializeExtensions();
290 if (!Host.isUnderTest()) {
291 for (const extension of self.runtime.extensions('late-initialization'))
292 extension.instance().then(instance => (/** @type {!Common.Runnable} */ (instance)).run());
293 }
294 Main.Main.timeEnd('Main._lateInitialization');
295 }
296
297 _registerForwardedShortcuts() {
298 /** @const */ const forwardedActions = [
299 'main.toggle-dock', 'debugger.toggle-breakpoints-active', 'debugger.toggle-pause', 'commandMenu.show',
300 'console.show'
301 ];
302 const actionKeys =
303 UI.shortcutRegistry.keysForActions(forwardedActions).map(UI.KeyboardShortcut.keyCodeAndModifiersFromKey);
304 InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
305 }
306
307 _registerMessageSinkListener() {
308 Common.console.addEventListener(Common.Console.Events.MessageAdded, messageAdded);
309
310 /**
311 * @param {!Common.Event} event
312 */
313 function messageAdded(event) {
314 const message = /** @type {!Common.Console.Message} */ (event.data);
315 if (message.show)
316 Common.console.show();
317 }
318 }
319
320 /**
321 * @param {!Common.Event} event
322 */
323 _revealSourceLine(event) {
324 const url = /** @type {string} */ (event.data['url']);
325 const lineNumber = /** @type {number} */ (event.data['lineNumber']);
326 const columnNumber = /** @type {number} */ (event.data['columnNumber']);
327
328 const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
329 if (uiSourceCode) {
330 Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
331 return;
332 }
333
334 /**
335 * @param {!Common.Event} event
336 */
337 function listener(event) {
338 const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
339 if (uiSourceCode.url() === url) {
340 Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
341 Workspace.workspace.removeEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
342 }
343 }
344
345 Workspace.workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
346 }
347
348 _registerShortcuts() {
349 const shortcut = UI.KeyboardShortcut;
350 const section = UI.shortcutsScreen.section(Common.UIString('All Panels'));
351 let keys = [
352 shortcut.makeDescriptor('[', shortcut.Modifiers.CtrlOrMeta),
353 shortcut.makeDescriptor(']', shortcut.Modifiers.CtrlOrMeta)
354 ];
355 section.addRelatedKeys(keys, Common.UIString('Go to the panel to the left/right'));
356
357 const toggleConsoleLabel = Common.UIString('Show console');
358 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Tilde, shortcut.Modifiers.Ctrl), toggleConsoleLabel);
359 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Esc), Common.UIString('Toggle drawer'));
360 if (Components.dockController.canDock()) {
361 section.addKey(
362 shortcut.makeDescriptor('M', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
363 Common.UIString('Toggle device mode'));
364 section.addKey(
365 shortcut.makeDescriptor('D', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
366 Common.UIString('Toggle dock side'));
367 }
368 section.addKey(shortcut.makeDescriptor('f', shortcut.Modifiers.CtrlOrMeta), Common.UIString('Search'));
369
370 const advancedSearchShortcutModifier = Host.isMac() ?
371 UI.KeyboardShortcut.Modifiers.Meta | UI.KeyboardShortcut.Modifiers.Alt :
372 UI.KeyboardShortcut.Modifiers.Ctrl | UI.KeyboardShortcut.Modifiers.Shift;
373 const advancedSearchShortcut = shortcut.makeDescriptor('f', advancedSearchShortcutModifier);
374 section.addKey(advancedSearchShortcut, Common.UIString('Search across all sources'));
375
376 const inspectElementModeShortcuts =
377 UI.shortcutRegistry.shortcutDescriptorsForAction('elements.toggle-element-search');
378 if (inspectElementModeShortcuts.length)
379 section.addKey(inspectElementModeShortcuts[0], Common.UIString('Select node to inspect'));
380
381 const openResourceShortcut = UI.KeyboardShortcut.makeDescriptor('p', UI.KeyboardShortcut.Modifiers.CtrlOrMeta);
382 section.addKey(openResourceShortcut, Common.UIString('Go to source'));
383
384 if (Host.isMac()) {
385 keys = [
386 shortcut.makeDescriptor('g', shortcut.Modifiers.Meta),
387 shortcut.makeDescriptor('g', shortcut.Modifiers.Meta | shortcut.Modifiers.Shift)
388 ];
389 section.addRelatedKeys(keys, Common.UIString('Find next/previous'));
390 }
391 }
392
393 _postDocumentKeyDown(event) {
Joel Einbindera66e5bf2018-05-31 01:26:37394 if (!event.handled)
395 UI.shortcutRegistry.handleShortcut(event);
Blink Reformat4c46d092018-04-07 15:32:37396 }
397
398 /**
399 * @param {!Event} event
400 */
401 _redispatchClipboardEvent(event) {
402 const eventCopy = new CustomEvent('clipboard-' + event.type, {bubbles: true});
403 eventCopy['original'] = event;
404 const document = event.target && event.target.ownerDocument;
405 const target = document ? document.deepActiveElement() : null;
406 if (target)
407 target.dispatchEvent(eventCopy);
408 if (eventCopy.handled)
409 event.preventDefault();
410 }
411
412 _contextMenuEventFired(event) {
413 if (event.handled || event.target.classList.contains('popup-glasspane'))
414 event.preventDefault();
415 }
416
417 /**
418 * @param {!Document} document
419 */
420 _addMainEventListeners(document) {
421 document.addEventListener('keydown', this._postDocumentKeyDown.bind(this), false);
422 document.addEventListener('beforecopy', this._redispatchClipboardEvent.bind(this), true);
423 document.addEventListener('copy', this._redispatchClipboardEvent.bind(this), false);
424 document.addEventListener('cut', this._redispatchClipboardEvent.bind(this), false);
425 document.addEventListener('paste', this._redispatchClipboardEvent.bind(this), false);
426 document.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), true);
427 }
428
429 _onSuspendStateChanged() {
430 const suspended = SDK.targetManager.allTargetsSuspended();
431 UI.inspectorView.onSuspendStateChanged(suspended);
432 }
433};
434
435/**
436 * @implements {UI.ActionDelegate}
437 * @unrestricted
438 */
439Main.Main.ZoomActionDelegate = class {
440 /**
441 * @override
442 * @param {!UI.Context} context
443 * @param {string} actionId
444 * @return {boolean}
445 */
446 handleAction(context, actionId) {
447 if (InspectorFrontendHost.isHostedMode())
448 return false;
449
450 switch (actionId) {
451 case 'main.zoom-in':
452 InspectorFrontendHost.zoomIn();
453 return true;
454 case 'main.zoom-out':
455 InspectorFrontendHost.zoomOut();
456 return true;
457 case 'main.zoom-reset':
458 InspectorFrontendHost.resetZoom();
459 return true;
460 }
461 return false;
462 }
463};
464
465/**
466 * @implements {UI.ActionDelegate}
467 * @unrestricted
468 */
469Main.Main.SearchActionDelegate = class {
470 /**
471 * @override
472 * @param {!UI.Context} context
473 * @param {string} actionId
474 * @return {boolean}
475 * @suppressGlobalPropertiesCheck
476 */
477 handleAction(context, actionId) {
478 const searchableView = UI.SearchableView.fromElement(document.deepActiveElement()) ||
479 UI.inspectorView.currentPanelDeprecated().searchableView();
480 if (!searchableView)
481 return false;
482 switch (actionId) {
483 case 'main.search-in-panel.find':
484 return searchableView.handleFindShortcut();
485 case 'main.search-in-panel.cancel':
486 return searchableView.handleCancelSearchShortcut();
487 case 'main.search-in-panel.find-next':
488 return searchableView.handleFindNextShortcut();
489 case 'main.search-in-panel.find-previous':
490 return searchableView.handleFindPreviousShortcut();
491 }
492 return false;
493 }
494};
495
496/**
497 * @implements {UI.ToolbarItem.Provider}
498 */
499Main.Main.MainMenuItem = class {
500 constructor() {
501 this._item = new UI.ToolbarMenuButton(this._handleContextMenu.bind(this), true);
502 this._item.setTitle(Common.UIString('Customize and control DevTools'));
503 }
504
505 /**
506 * @override
507 * @return {?UI.ToolbarItem}
508 */
509 item() {
510 return this._item;
511 }
512
513 /**
514 * @param {!UI.ContextMenu} contextMenu
515 */
516 _handleContextMenu(contextMenu) {
517 if (Components.dockController.canDock()) {
518 const dockItemElement = createElementWithClass('div', 'flex-centered flex-auto');
519 const titleElement = dockItemElement.createChild('span', 'flex-auto');
520 titleElement.textContent = Common.UIString('Dock side');
521 const toggleDockSideShorcuts = UI.shortcutRegistry.shortcutDescriptorsForAction('main.toggle-dock');
522 titleElement.title = Common.UIString(
523 'Placement of DevTools relative to the page. (%s to restore last position)', toggleDockSideShorcuts[0].name);
524 dockItemElement.appendChild(titleElement);
525 const dockItemToolbar = new UI.Toolbar('', dockItemElement);
Joel Einbinder9a6bead2018-08-06 18:02:35526 if (Host.isMac() && !UI.themeSupport.hasTheme())
527 dockItemToolbar.makeBlueOnHover();
Blink Reformat4c46d092018-04-07 15:32:37528 const undock = new UI.ToolbarToggle(Common.UIString('Undock into separate window'), 'largeicon-undock');
529 const bottom = new UI.ToolbarToggle(Common.UIString('Dock to bottom'), 'largeicon-dock-to-bottom');
530 const right = new UI.ToolbarToggle(Common.UIString('Dock to right'), 'largeicon-dock-to-right');
531 const left = new UI.ToolbarToggle(Common.UIString('Dock to left'), 'largeicon-dock-to-left');
532 undock.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
533 bottom.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
534 right.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
535 left.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
536 undock.addEventListener(
537 UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.Undocked));
538 bottom.addEventListener(
539 UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.DockedToBottom));
540 right.addEventListener(
541 UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.DockedToRight));
542 left.addEventListener(
543 UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.DockedToLeft));
544 undock.setToggled(Components.dockController.dockSide() === Components.DockController.State.Undocked);
545 bottom.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToBottom);
546 right.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToRight);
547 left.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToLeft);
548 dockItemToolbar.appendToolbarItem(undock);
549 dockItemToolbar.appendToolbarItem(left);
550 dockItemToolbar.appendToolbarItem(bottom);
551 dockItemToolbar.appendToolbarItem(right);
552 contextMenu.headerSection().appendCustomItem(dockItemElement);
553 }
554
555 /**
556 * @param {string} side
557 */
558 function setDockSide(side) {
559 Components.dockController.setDockSide(side);
560 contextMenu.discard();
561 }
562
563 if (Components.dockController.dockSide() === Components.DockController.State.Undocked &&
Dmitry Gozmanb24fcc22018-10-31 23:42:42564 SDK.targetManager.mainTarget() && SDK.targetManager.mainTarget().type() === SDK.Target.Type.Frame)
Blink Reformat4c46d092018-04-07 15:32:37565 contextMenu.defaultSection().appendAction('inspector_main.focus-debuggee', Common.UIString('Focus debuggee'));
566
567 contextMenu.defaultSection().appendAction(
568 'main.toggle-drawer',
569 UI.inspectorView.drawerVisible() ? Common.UIString('Hide console drawer') :
570 Common.UIString('Show console drawer'));
571 contextMenu.appendItemsAtLocation('mainMenu');
572 const moreTools = contextMenu.defaultSection().appendSubMenuItem(Common.UIString('More tools'));
573 const extensions = self.runtime.extensions('view', undefined, true);
574 for (const extension of extensions) {
575 const descriptor = extension.descriptor();
576 if (descriptor['persistence'] !== 'closeable')
577 continue;
578 if (descriptor['location'] !== 'drawer-view' && descriptor['location'] !== 'panel')
579 continue;
580 moreTools.defaultSection().appendItem(
581 extension.title(), UI.viewManager.showView.bind(UI.viewManager, descriptor['id']));
582 }
583
584 const helpSubMenu = contextMenu.footerSection().appendSubMenuItem(Common.UIString('Help'));
585 helpSubMenu.appendItemsAtLocation('mainMenuHelp');
586 }
587};
588
589/**
590 * @unrestricted
591 */
592Main.Main.PauseListener = class {
593 constructor() {
594 SDK.targetManager.addModelListener(
595 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
596 }
597
598 /**
599 * @param {!Common.Event} event
600 */
601 _debuggerPaused(event) {
602 SDK.targetManager.removeModelListener(
603 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
604 const debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.data);
605 const debuggerPausedDetails = debuggerModel.debuggerPausedDetails();
606 UI.context.setFlavor(SDK.Target, debuggerModel.target());
607 Common.Revealer.reveal(debuggerPausedDetails);
608 }
609};
610
611/**
612 * @param {string} method
613 * @param {?Object} params
614 * @return {!Promise}
615 */
616Main.sendOverProtocol = function(method, params) {
617 return new Promise((resolve, reject) => {
Dmitry Gozman99d7a6c2018-11-12 17:55:11618 Protocol.test.sendRawMessage(method, params, (err, ...results) => {
Blink Reformat4c46d092018-04-07 15:32:37619 if (err)
620 return reject(err);
621 return resolve(results);
622 });
623 });
624};
625
626/**
627 * @implements {UI.ActionDelegate}
628 * @unrestricted
629 */
630Main.ReloadActionDelegate = class {
631 /**
632 * @override
633 * @param {!UI.Context} context
634 * @param {string} actionId
635 * @return {boolean}
636 */
637 handleAction(context, actionId) {
638 switch (actionId) {
639 case 'main.debug-reload':
640 Components.reload();
641 return true;
642 }
643 return false;
644 }
645};
646
647new Main.Main();