blob: 61a98c405393b2b800ba4edaf311afffcacd140f [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');
Alexei Filippovfdfefe02019-03-09 00:33:24109 Runtime.experiments.register('sourcesPrettyPrint', 'Automatically pretty print in the Sources Panel');
Rayan Kanso8fe8ee22019-03-04 14:58:46110 Runtime.experiments.register('backgroundServices', 'Background web platform feature events', true);
Blink Reformat4c46d092018-04-07 15:32:37111 Runtime.experiments.register('blackboxJSFramesOnTimeline', 'Blackbox JavaScript frames on Timeline', true);
Blink Reformat4c46d092018-04-07 15:32:37112 Runtime.experiments.register('emptySourceMapAutoStepping', 'Empty sourcemap auto-stepping');
113 Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true);
Alexei Filippovfdfefe02019-03-09 00:33:24114 Runtime.experiments.register('liveHeapProfile', 'Live heap profile', true);
Blink Reformat4c46d092018-04-07 15:32:37115 Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true);
Blink Reformat4c46d092018-04-07 15:32:37116 Runtime.experiments.register('protocolMonitor', 'Protocol Monitor');
Alexei Filippov6d2eb592018-10-25 21:48:56117 Runtime.experiments.register('samplingHeapProfilerTimeline', 'Sampling heap profiler timeline', true);
Blink Reformat4c46d092018-04-07 15:32:37118 Runtime.experiments.register('sourceDiff', 'Source diff');
Pavel Feldmanc9060ea2018-04-30 04:42:18119 Runtime.experiments.register('splitInDrawer', 'Split in drawer', true);
Joey Arharaef93562019-03-15 23:49:59120 Runtime.experiments.register('spotlight', 'Spotlight', true);
Blink Reformat4c46d092018-04-07 15:32:37121 Runtime.experiments.register('terminalInDrawer', 'Terminal in drawer', true);
122
123 // Timeline
124 Runtime.experiments.register('timelineEventInitiators', 'Timeline: event initiators');
125 Runtime.experiments.register('timelineFlowEvents', 'Timeline: flow events', true);
126 Runtime.experiments.register('timelineInvalidationTracking', 'Timeline: invalidation tracking', true);
Blink Reformat4c46d092018-04-07 15:32:37127 Runtime.experiments.register('timelineShowAllEvents', 'Timeline: show all events', true);
Blink Reformat4c46d092018-04-07 15:32:37128 Runtime.experiments.register('timelineV8RuntimeCallStats', 'Timeline: V8 Runtime Call Stats on Timeline', true);
Alexei Filippov57ccafb2018-08-14 20:59:05129 Runtime.experiments.register('timelineWebGL', 'Timeline: WebGL-based flamechart');
Blink Reformat4c46d092018-04-07 15:32:37130
131 Runtime.experiments.cleanUpStaleExperiments();
Pavel Feldmandb310912019-01-30 00:31:20132 Runtime.experiments.setDefaultExperiments([]);
Alexei Filippovfdfefe02019-03-09 00:33:24133
134 if (Host.isUnderTest() && Runtime.queryParam('test').includes('live-line-level-heap-profile.js'))
135 Runtime.experiments.enableForTest('liveHeapProfile');
Blink Reformat4c46d092018-04-07 15:32:37136 }
137
138 /**
139 * @suppressGlobalPropertiesCheck
140 */
141 async _createAppUI() {
142 Main.Main.time('Main._createAppUI');
143
144 UI.viewManager = new UI.ViewManager();
145
146 // Request filesystems early, we won't create connections until callback is fired. Things will happen in parallel.
147 Persistence.isolatedFileSystemManager = new Persistence.IsolatedFileSystemManager();
148
149 const themeSetting = Common.settings.createSetting('uiTheme', 'default');
150 UI.initializeUIUtils(document, themeSetting);
151 themeSetting.addChangeListener(Components.reload.bind(Components));
152
153 UI.installComponentRootStyles(/** @type {!Element} */ (document.body));
154
155 this._addMainEventListeners(document);
156
157 const canDock = !!Runtime.queryParam('can_dock');
158 UI.zoomManager = new UI.ZoomManager(window, InspectorFrontendHost);
159 UI.inspectorView = UI.InspectorView.instance();
160 UI.ContextMenu.initialize();
161 UI.ContextMenu.installHandler(document);
162 UI.Tooltip.installHandler(document);
163 Components.dockController = new Components.DockController(canDock);
164 SDK.consoleModel = new SDK.ConsoleModel();
165 SDK.multitargetNetworkManager = new SDK.MultitargetNetworkManager();
166 SDK.domDebuggerManager = new SDK.DOMDebuggerManager();
167 SDK.targetManager.addEventListener(
168 SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged.bind(this));
169
170 UI.shortcutsScreen = new UI.ShortcutsScreen();
171 // set order of some sections explicitly
172 UI.shortcutsScreen.section(Common.UIString('Elements Panel'));
173 UI.shortcutsScreen.section(Common.UIString('Styles Pane'));
174 UI.shortcutsScreen.section(Common.UIString('Debugger'));
175 UI.shortcutsScreen.section(Common.UIString('Console'));
176
177 Workspace.fileManager = new Workspace.FileManager();
178 Workspace.workspace = new Workspace.Workspace();
179
180 Bindings.networkProjectManager = new Bindings.NetworkProjectManager();
181 Bindings.resourceMapping = new Bindings.ResourceMapping(SDK.targetManager, Workspace.workspace);
182 new Bindings.PresentationConsoleMessageManager();
183 Bindings.cssWorkspaceBinding = new Bindings.CSSWorkspaceBinding(SDK.targetManager, Workspace.workspace);
184 Bindings.debuggerWorkspaceBinding = new Bindings.DebuggerWorkspaceBinding(SDK.targetManager, Workspace.workspace);
185 Bindings.breakpointManager =
186 new Bindings.BreakpointManager(Workspace.workspace, SDK.targetManager, Bindings.debuggerWorkspaceBinding);
187 Extensions.extensionServer = new Extensions.ExtensionServer();
188
189 new Persistence.FileSystemWorkspaceBinding(Persistence.isolatedFileSystemManager, Workspace.workspace);
190 Persistence.persistence = new Persistence.Persistence(Workspace.workspace, Bindings.breakpointManager);
191 Persistence.networkPersistenceManager = new Persistence.NetworkPersistenceManager(Workspace.workspace);
192
193 new Main.ExecutionContextSelector(SDK.targetManager, UI.context);
194 Bindings.blackboxManager = new Bindings.BlackboxManager(Bindings.debuggerWorkspaceBinding);
195
196 new Main.Main.PauseListener();
197
198 UI.actionRegistry = new UI.ActionRegistry();
199 UI.shortcutRegistry = new UI.ShortcutRegistry(UI.actionRegistry, document);
200 UI.ShortcutsScreen.registerShortcuts();
201 this._registerForwardedShortcuts();
202 this._registerMessageSinkListener();
203
204 Main.Main.timeEnd('Main._createAppUI');
205 this._showAppUI(await self.runtime.extension(Common.AppProvider).instance());
206 }
207
208 /**
209 * @param {!Object} appProvider
210 * @suppressGlobalPropertiesCheck
211 */
212 _showAppUI(appProvider) {
213 Main.Main.time('Main._showAppUI');
214 const app = /** @type {!Common.AppProvider} */ (appProvider).createApp();
215 // It is important to kick controller lifetime after apps are instantiated.
216 Components.dockController.initialize();
217 app.presentUI(document);
218
219 const toggleSearchNodeAction = UI.actionRegistry.action('elements.toggle-element-search');
220 // TODO: we should not access actions from other modules.
221 if (toggleSearchNodeAction) {
222 InspectorFrontendHost.events.addEventListener(
223 InspectorFrontendHostAPI.Events.EnterInspectElementMode,
224 toggleSearchNodeAction.execute.bind(toggleSearchNodeAction), this);
225 }
226 InspectorFrontendHost.events.addEventListener(
227 InspectorFrontendHostAPI.Events.RevealSourceLine, this._revealSourceLine, this);
228
229 UI.inspectorView.createToolbars();
230 InspectorFrontendHost.loadCompleted();
231
232 const extensions = self.runtime.extensions(Common.QueryParamHandler);
233 for (const extension of extensions) {
234 const value = Runtime.queryParam(extension.descriptor()['name']);
235 if (value !== null)
236 extension.instance().then(handleQueryParam.bind(null, value));
237 }
238
239 /**
240 * @param {string} value
241 * @param {!Common.QueryParamHandler} handler
242 */
243 function handleQueryParam(value, handler) {
244 handler.handleQueryParam(value);
245 }
246
247 // Allow UI cycles to repaint prior to creating connection.
248 setTimeout(this._initializeTarget.bind(this), 0);
249 Main.Main.timeEnd('Main._showAppUI');
250 }
251
252 async _initializeTarget() {
253 Main.Main.time('Main._initializeTarget');
254 const instances =
255 await Promise.all(self.runtime.extensions('early-initialization').map(extension => extension.instance()));
256 for (const instance of instances)
Pavel Feldman07ef9722018-12-13 23:52:22257 await /** @type {!Common.Runnable} */ (instance).run();
Blink Reformat4c46d092018-04-07 15:32:37258 // Used for browser tests.
259 InspectorFrontendHost.readyForTest();
260 // Asynchronously run the extensions.
261 setTimeout(this._lateInitialization.bind(this), 100);
262 Main.Main.timeEnd('Main._initializeTarget');
263 }
264
265 _lateInitialization() {
266 Main.Main.time('Main._lateInitialization');
267 this._registerShortcuts();
268 Extensions.extensionServer.initializeExtensions();
Alexei Filippovfdfefe02019-03-09 00:33:24269 for (const extension of self.runtime.extensions('late-initialization'))
270 extension.instance().then(instance => (/** @type {!Common.Runnable} */ (instance)).run());
Blink Reformat4c46d092018-04-07 15:32:37271 Main.Main.timeEnd('Main._lateInitialization');
272 }
273
274 _registerForwardedShortcuts() {
275 /** @const */ const forwardedActions = [
276 'main.toggle-dock', 'debugger.toggle-breakpoints-active', 'debugger.toggle-pause', 'commandMenu.show',
277 'console.show'
278 ];
279 const actionKeys =
280 UI.shortcutRegistry.keysForActions(forwardedActions).map(UI.KeyboardShortcut.keyCodeAndModifiersFromKey);
281 InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
282 }
283
284 _registerMessageSinkListener() {
285 Common.console.addEventListener(Common.Console.Events.MessageAdded, messageAdded);
286
287 /**
288 * @param {!Common.Event} event
289 */
290 function messageAdded(event) {
291 const message = /** @type {!Common.Console.Message} */ (event.data);
292 if (message.show)
293 Common.console.show();
294 }
295 }
296
297 /**
298 * @param {!Common.Event} event
299 */
300 _revealSourceLine(event) {
301 const url = /** @type {string} */ (event.data['url']);
302 const lineNumber = /** @type {number} */ (event.data['lineNumber']);
303 const columnNumber = /** @type {number} */ (event.data['columnNumber']);
304
305 const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
306 if (uiSourceCode) {
307 Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
308 return;
309 }
310
311 /**
312 * @param {!Common.Event} event
313 */
314 function listener(event) {
315 const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
316 if (uiSourceCode.url() === url) {
317 Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
318 Workspace.workspace.removeEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
319 }
320 }
321
322 Workspace.workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
323 }
324
325 _registerShortcuts() {
326 const shortcut = UI.KeyboardShortcut;
327 const section = UI.shortcutsScreen.section(Common.UIString('All Panels'));
328 let keys = [
329 shortcut.makeDescriptor('[', shortcut.Modifiers.CtrlOrMeta),
330 shortcut.makeDescriptor(']', shortcut.Modifiers.CtrlOrMeta)
331 ];
332 section.addRelatedKeys(keys, Common.UIString('Go to the panel to the left/right'));
333
334 const toggleConsoleLabel = Common.UIString('Show console');
335 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Tilde, shortcut.Modifiers.Ctrl), toggleConsoleLabel);
336 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Esc), Common.UIString('Toggle drawer'));
337 if (Components.dockController.canDock()) {
338 section.addKey(
339 shortcut.makeDescriptor('M', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
340 Common.UIString('Toggle device mode'));
341 section.addKey(
342 shortcut.makeDescriptor('D', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
343 Common.UIString('Toggle dock side'));
344 }
345 section.addKey(shortcut.makeDescriptor('f', shortcut.Modifiers.CtrlOrMeta), Common.UIString('Search'));
346
347 const advancedSearchShortcutModifier = Host.isMac() ?
348 UI.KeyboardShortcut.Modifiers.Meta | UI.KeyboardShortcut.Modifiers.Alt :
349 UI.KeyboardShortcut.Modifiers.Ctrl | UI.KeyboardShortcut.Modifiers.Shift;
350 const advancedSearchShortcut = shortcut.makeDescriptor('f', advancedSearchShortcutModifier);
351 section.addKey(advancedSearchShortcut, Common.UIString('Search across all sources'));
352
353 const inspectElementModeShortcuts =
354 UI.shortcutRegistry.shortcutDescriptorsForAction('elements.toggle-element-search');
355 if (inspectElementModeShortcuts.length)
356 section.addKey(inspectElementModeShortcuts[0], Common.UIString('Select node to inspect'));
357
358 const openResourceShortcut = UI.KeyboardShortcut.makeDescriptor('p', UI.KeyboardShortcut.Modifiers.CtrlOrMeta);
359 section.addKey(openResourceShortcut, Common.UIString('Go to source'));
360
361 if (Host.isMac()) {
362 keys = [
363 shortcut.makeDescriptor('g', shortcut.Modifiers.Meta),
364 shortcut.makeDescriptor('g', shortcut.Modifiers.Meta | shortcut.Modifiers.Shift)
365 ];
366 section.addRelatedKeys(keys, Common.UIString('Find next/previous'));
367 }
368 }
369
370 _postDocumentKeyDown(event) {
Joel Einbindera66e5bf2018-05-31 01:26:37371 if (!event.handled)
372 UI.shortcutRegistry.handleShortcut(event);
Blink Reformat4c46d092018-04-07 15:32:37373 }
374
375 /**
376 * @param {!Event} event
377 */
378 _redispatchClipboardEvent(event) {
379 const eventCopy = new CustomEvent('clipboard-' + event.type, {bubbles: true});
380 eventCopy['original'] = event;
381 const document = event.target && event.target.ownerDocument;
382 const target = document ? document.deepActiveElement() : null;
383 if (target)
384 target.dispatchEvent(eventCopy);
385 if (eventCopy.handled)
386 event.preventDefault();
387 }
388
389 _contextMenuEventFired(event) {
390 if (event.handled || event.target.classList.contains('popup-glasspane'))
391 event.preventDefault();
392 }
393
394 /**
395 * @param {!Document} document
396 */
397 _addMainEventListeners(document) {
398 document.addEventListener('keydown', this._postDocumentKeyDown.bind(this), false);
399 document.addEventListener('beforecopy', this._redispatchClipboardEvent.bind(this), true);
400 document.addEventListener('copy', this._redispatchClipboardEvent.bind(this), false);
401 document.addEventListener('cut', this._redispatchClipboardEvent.bind(this), false);
402 document.addEventListener('paste', this._redispatchClipboardEvent.bind(this), false);
403 document.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), true);
404 }
405
406 _onSuspendStateChanged() {
407 const suspended = SDK.targetManager.allTargetsSuspended();
408 UI.inspectorView.onSuspendStateChanged(suspended);
409 }
410};
411
412/**
413 * @implements {UI.ActionDelegate}
414 * @unrestricted
415 */
416Main.Main.ZoomActionDelegate = class {
417 /**
418 * @override
419 * @param {!UI.Context} context
420 * @param {string} actionId
421 * @return {boolean}
422 */
423 handleAction(context, actionId) {
424 if (InspectorFrontendHost.isHostedMode())
425 return false;
426
427 switch (actionId) {
428 case 'main.zoom-in':
429 InspectorFrontendHost.zoomIn();
430 return true;
431 case 'main.zoom-out':
432 InspectorFrontendHost.zoomOut();
433 return true;
434 case 'main.zoom-reset':
435 InspectorFrontendHost.resetZoom();
436 return true;
437 }
438 return false;
439 }
440};
441
442/**
443 * @implements {UI.ActionDelegate}
444 * @unrestricted
445 */
446Main.Main.SearchActionDelegate = class {
447 /**
448 * @override
449 * @param {!UI.Context} context
450 * @param {string} actionId
451 * @return {boolean}
452 * @suppressGlobalPropertiesCheck
453 */
454 handleAction(context, actionId) {
455 const searchableView = UI.SearchableView.fromElement(document.deepActiveElement()) ||
456 UI.inspectorView.currentPanelDeprecated().searchableView();
457 if (!searchableView)
458 return false;
459 switch (actionId) {
460 case 'main.search-in-panel.find':
461 return searchableView.handleFindShortcut();
462 case 'main.search-in-panel.cancel':
463 return searchableView.handleCancelSearchShortcut();
464 case 'main.search-in-panel.find-next':
465 return searchableView.handleFindNextShortcut();
466 case 'main.search-in-panel.find-previous':
467 return searchableView.handleFindPreviousShortcut();
468 }
469 return false;
470 }
471};
472
473/**
474 * @implements {UI.ToolbarItem.Provider}
475 */
476Main.Main.MainMenuItem = class {
477 constructor() {
478 this._item = new UI.ToolbarMenuButton(this._handleContextMenu.bind(this), true);
479 this._item.setTitle(Common.UIString('Customize and control DevTools'));
480 }
481
482 /**
483 * @override
484 * @return {?UI.ToolbarItem}
485 */
486 item() {
487 return this._item;
488 }
489
490 /**
491 * @param {!UI.ContextMenu} contextMenu
492 */
493 _handleContextMenu(contextMenu) {
494 if (Components.dockController.canDock()) {
495 const dockItemElement = createElementWithClass('div', 'flex-centered flex-auto');
Joel Einbinder57b9fad2019-02-08 23:31:35496 dockItemElement.tabIndex = -1;
Blink Reformat4c46d092018-04-07 15:32:37497 const titleElement = dockItemElement.createChild('span', 'flex-auto');
498 titleElement.textContent = Common.UIString('Dock side');
499 const toggleDockSideShorcuts = UI.shortcutRegistry.shortcutDescriptorsForAction('main.toggle-dock');
500 titleElement.title = Common.UIString(
501 'Placement of DevTools relative to the page. (%s to restore last position)', toggleDockSideShorcuts[0].name);
502 dockItemElement.appendChild(titleElement);
503 const dockItemToolbar = new UI.Toolbar('', dockItemElement);
Joel Einbinder9a6bead2018-08-06 18:02:35504 if (Host.isMac() && !UI.themeSupport.hasTheme())
505 dockItemToolbar.makeBlueOnHover();
Blink Reformat4c46d092018-04-07 15:32:37506 const undock = new UI.ToolbarToggle(Common.UIString('Undock into separate window'), 'largeicon-undock');
507 const bottom = new UI.ToolbarToggle(Common.UIString('Dock to bottom'), 'largeicon-dock-to-bottom');
508 const right = new UI.ToolbarToggle(Common.UIString('Dock to right'), 'largeicon-dock-to-right');
509 const left = new UI.ToolbarToggle(Common.UIString('Dock to left'), 'largeicon-dock-to-left');
510 undock.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
511 bottom.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
512 right.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
513 left.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
514 undock.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35515 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.Undocked));
Blink Reformat4c46d092018-04-07 15:32:37516 bottom.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35517 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToBottom));
Blink Reformat4c46d092018-04-07 15:32:37518 right.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35519 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToRight));
Blink Reformat4c46d092018-04-07 15:32:37520 left.addEventListener(
Joel Einbinder57b9fad2019-02-08 23:31:35521 UI.ToolbarButton.Events.Click, setDockSide.bind(null, Components.DockController.State.DockedToLeft));
Blink Reformat4c46d092018-04-07 15:32:37522 undock.setToggled(Components.dockController.dockSide() === Components.DockController.State.Undocked);
523 bottom.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToBottom);
524 right.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToRight);
525 left.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToLeft);
526 dockItemToolbar.appendToolbarItem(undock);
527 dockItemToolbar.appendToolbarItem(left);
528 dockItemToolbar.appendToolbarItem(bottom);
529 dockItemToolbar.appendToolbarItem(right);
Joel Einbinder57b9fad2019-02-08 23:31:35530 dockItemElement.addEventListener('keydown', event => {
531 let dir = 0;
532 if (event.key === 'ArrowLeft')
533 dir = -1;
534 else if (event.key === 'ArrowRight')
535 dir = 1;
536 else
537 return;
538
539 const buttons = [undock, left, bottom, right];
540 let index = buttons.findIndex(button => button.element.hasFocus());
541 index = Number.constrain(index + dir, 0, buttons.length - 1);
542
543 buttons[index].element.focus();
544 event.consume(true);
545 });
Blink Reformat4c46d092018-04-07 15:32:37546 contextMenu.headerSection().appendCustomItem(dockItemElement);
547 }
548
549 /**
550 * @param {string} side
551 */
552 function setDockSide(side) {
553 Components.dockController.setDockSide(side);
554 contextMenu.discard();
555 }
556
557 if (Components.dockController.dockSide() === Components.DockController.State.Undocked &&
Dmitry Gozmanb24fcc22018-10-31 23:42:42558 SDK.targetManager.mainTarget() && SDK.targetManager.mainTarget().type() === SDK.Target.Type.Frame)
Blink Reformat4c46d092018-04-07 15:32:37559 contextMenu.defaultSection().appendAction('inspector_main.focus-debuggee', Common.UIString('Focus debuggee'));
560
561 contextMenu.defaultSection().appendAction(
562 'main.toggle-drawer',
563 UI.inspectorView.drawerVisible() ? Common.UIString('Hide console drawer') :
564 Common.UIString('Show console drawer'));
565 contextMenu.appendItemsAtLocation('mainMenu');
566 const moreTools = contextMenu.defaultSection().appendSubMenuItem(Common.UIString('More tools'));
567 const extensions = self.runtime.extensions('view', undefined, true);
568 for (const extension of extensions) {
569 const descriptor = extension.descriptor();
570 if (descriptor['persistence'] !== 'closeable')
571 continue;
572 if (descriptor['location'] !== 'drawer-view' && descriptor['location'] !== 'panel')
573 continue;
574 moreTools.defaultSection().appendItem(
575 extension.title(), UI.viewManager.showView.bind(UI.viewManager, descriptor['id']));
576 }
577
578 const helpSubMenu = contextMenu.footerSection().appendSubMenuItem(Common.UIString('Help'));
579 helpSubMenu.appendItemsAtLocation('mainMenuHelp');
580 }
581};
582
583/**
584 * @unrestricted
585 */
586Main.Main.PauseListener = class {
587 constructor() {
588 SDK.targetManager.addModelListener(
589 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
590 }
591
592 /**
593 * @param {!Common.Event} event
594 */
595 _debuggerPaused(event) {
596 SDK.targetManager.removeModelListener(
597 SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
598 const debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.data);
599 const debuggerPausedDetails = debuggerModel.debuggerPausedDetails();
600 UI.context.setFlavor(SDK.Target, debuggerModel.target());
601 Common.Revealer.reveal(debuggerPausedDetails);
602 }
603};
604
605/**
606 * @param {string} method
607 * @param {?Object} params
608 * @return {!Promise}
609 */
610Main.sendOverProtocol = function(method, params) {
611 return new Promise((resolve, reject) => {
Dmitry Gozman99d7a6c2018-11-12 17:55:11612 Protocol.test.sendRawMessage(method, params, (err, ...results) => {
Blink Reformat4c46d092018-04-07 15:32:37613 if (err)
614 return reject(err);
615 return resolve(results);
616 });
617 });
618};
619
620/**
621 * @implements {UI.ActionDelegate}
622 * @unrestricted
623 */
624Main.ReloadActionDelegate = class {
625 /**
626 * @override
627 * @param {!UI.Context} context
628 * @param {string} actionId
629 * @return {boolean}
630 */
631 handleAction(context, actionId) {
632 switch (actionId) {
633 case 'main.debug-reload':
634 Components.reload();
635 return true;
636 }
637 return false;
638 }
639};
640
641new Main.Main();