Changeset 283859 in webkit
- Timestamp:
- Oct 8, 2021 6:40:57 PM (9 months ago)
- Location:
- trunk/Source/WebInspectorUI
- Files:
-
- 9 edited
-
ChangeLog (modified) (1 diff)
-
UserInterface/Base/Main.js (modified) (1 diff)
-
UserInterface/Controllers/WebInspectorExtensionController.js (modified) (4 diffs)
-
UserInterface/Controllers/WebInspectorExtensionController.js.orig (modified) (6 diffs)
-
UserInterface/Views/ContentView.css (modified) (2 diffs)
-
UserInterface/Views/ContentView.js (modified) (2 diffs)
-
UserInterface/Views/ContentViewContainer.js (modified) (4 diffs)
-
UserInterface/Views/TabBrowser.js (modified) (2 diffs)
-
UserInterface/Views/WebInspectorExtensionTabContentView.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebInspectorUI/ChangeLog
r283857 r283859 1 2021-10-08 BJ Burg <bburg@apple.com> 2 3 Web Inspector: add TabBar context menu support for WI.WebInspectorExtensionTabContentView 4 https://bugs.webkit.org/show_bug.cgi?id=231181 5 <rdar://74698241> 6 7 Reviewed by Devin Rousso. 8 9 The existing TabBar/TabBrowser system relies on the fact that each tab class can 10 be instantiated once. This is no longer true with extension tabs, as all of them 11 are instances of the same WI.WebInspectorExtensionTabContentView class. 12 13 The new approach builds on bug 230758 by introducing a 'visible' property on ContentView. 14 This is necessary to mark extension tabs as "attached by not showing" due to the 15 override of shouldNotRemoveFromDOMWhenHidden(). 16 17 * UserInterface/Base/Main.js: 18 (WI._createTabContentViewForType): 19 (WI.isNewTabWithTypeAllowed): 20 List WebInspectorExtensionTabContentView as a known tab class. But do not allow 21 this tab class to be instantiated directly. Extension tabs are intended to be 22 created using WebInspectorExtensionController.createTabForExtension(). 23 24 * UserInterface/Controllers/WebInspectorExtensionController.js: 25 (WI.WebInspectorExtensionController.prototype.unregisterExtension): 26 (WI.WebInspectorExtensionController.prototype.createTabForExtension): 27 Drive-by, suppress animations when extension tabs are created and destroyed. Otherwise 28 there is a lot of unnecessary and glitchy animation when multiple extension tabs are 29 created upon loading Web Inspector the first time. 30 31 (WI.WebInspectorExtensionController.prototype.showExtensionTab): 32 (WI.WebInspectorExtensionController.prototype.hideExtensionTab): Added. 33 These methods are counterparts. They toggle tabContentView.visible to make the tab 34 visible and not visible. Note that 'hiding' does not actually close/destroy the 35 extension tab. Extension tabs are hidden by setting .not-visible ('display:none') and 36 removing the tab's TabBarItem from the TabBar. 37 38 (WI.WebInspectorExtensionController.prototype.addContextMenuItemsForClosedExtensionTabs): 39 (WI.WebInspectorExtensionController.prototype.addContextMenuItemsForAllExtensionTabs): 40 Added. TabBar delegates the creation of extension tab context menu items to this class. 41 The first method only shows hidden extension tabs (for the Reopen Closed Tabs + item). 42 The second method shows visible and not visible extension tabs and feeds the main context menu. 43 44 * UserInterface/Views/ContentView.css: 45 (.content-view.not-visible): 46 * UserInterface/Views/ContentViewContainer.css: 47 (.content-view-container > .content-view): 48 (.content-view-container > .content-view.not-visible): Deleted. 49 This style class is now managed by ContentView.js. So, move the style declaration. 50 51 * UserInterface/Views/ContentView.js: 52 (WI.ContentView): 53 (WI.ContentView.prototype.get visible): 54 (WI.ContentView.prototype.set visible): 55 Add a flag so that clients can determine when the content view is not visible and not closed. 56 This can be true if a subclass overrides shouldNotRemoveFromDOMWhenHidden() to return true. 57 58 * UserInterface/Views/ContentViewContainer.js: 59 (WI.ContentViewContainer.prototype._disassociateFromContentView): 60 Fix this code to not detach extension tabs that are hidden. 61 62 (WI.ContentViewContainer.prototype._showEntry): 63 (WI.ContentViewContainer.prototype._hideEntry): 64 Adopt new setter for ContentView.prototype.hidden. 65 66 * UserInterface/Views/TabBar.js: 67 (WI.TabBar.prototype._handleAddClosedTabsTabBarItemMouseDown): 68 Don't add generic context menu items for WebInspectorExtensionTabContentView. Call out 69 to WebInspectorExtensionController to create the appropriate extension tab context menu items. 70 (WI.TabBar.prototype._handleTabContainerContextMenu): 71 (WI.TabBar): 72 73 * UserInterface/Views/WebInspectorExtensionTabContentView.js: 74 (WI.WebInspectorExtensionTabContentView.isTabAllowed): Drive-by, gate creation of this class 75 on Web Extensions being enabled (InspectorFrontendHost.supportsWebExtensions). 76 1 77 2021-10-08 BJ Burg <bburg@apple.com> 2 78 -
trunk/Source/WebInspectorUI/UserInterface/Base/Main.js
r281182 r283859 673 673 } 674 674 675 console.assert(tabClass !== WI.WebInspectorExtensionTabContentView, "Extension tabs must be created via WebInspectorExtensionController.createTabForExtension()."); 676 if (tabClass === WI.WebInspectorExtensionTabContentView) 677 return null; 678 675 679 console.assert(WI.TabContentView.isPrototypeOf(tabClass)); 676 680 return new tabClass; -
trunk/Source/WebInspectorUI/UserInterface/Controllers/WebInspectorExtensionController.js
r283857 r283859 69 69 for (let extensionTabID of extensionTabIDsToRemove) { 70 70 let tabContentView = this._extensionTabContentViewForExtensionTabIDMap.take(extensionTabID); 71 WI.tabBrowser.closeTabForContentView(tabContentView );71 WI.tabBrowser.closeTabForContentView(tabContentView, {suppressAnimations: true}); 72 72 } 73 73 … … 88 88 this._tabIDsForExtensionIDMap.add(extensionID, extensionTabID); 89 89 this._extensionTabContentViewForExtensionTabIDMap.set(extensionTabID, tabContentView); 90 WI.tabBrowser.addTabForContentView(tabContentView );90 WI.tabBrowser.addTabForContentView(tabContentView, {suppressAnimations: true}); 91 91 92 92 // The calling convention is to return an error string or a result object. … … 169 169 } 170 170 171 tabContentView.visible = true; 171 172 let success = WI.tabBrowser.showTabForContentView(tabContentView, { 172 173 initiatorHint: WI.TabBrowser.TabNavigationInitiator.FrontendAPI, … … 176 177 WI.reportInternalError("Unable to show extension tab with extensionTabID: " + extensionTabID); 177 178 return WI.WebInspectorExtension.ErrorCode.InternalError; 179 } 180 } 181 182 hideExtensionTab(extensionTabID, options = {}) 183 { 184 let tabContentView = this._extensionTabContentViewForExtensionTabIDMap.get(extensionTabID); 185 if (!tabContentView) { 186 WI.reportInternalError("Unable to show extension tab with unknown extensionTabID: " + extensionTabID); 187 return WI.WebInspectorExtension.ErrorCode.InvalidRequest; 188 } 189 190 tabContentView.visible = false; 191 WI.tabBrowser.closeTabForContentView(tabContentView, options); 192 193 console.assert(!tabContentView.visible); 194 console.assert(!tabContentView.isClosed); 195 } 196 197 addContextMenuItemsForClosedExtensionTabs(contextMenu) 198 { 199 contextMenu.appendSeparator(); 200 201 for (let tabContentView of this._extensionTabContentViewForExtensionTabIDMap.values()) { 202 // If the extension tab has been unchecked in the TabBar context menu, then the tabBarItem 203 // for the extension tab will not be connected to a parent TabBar. 204 let shouldIncludeTab = !tabContentView.visible || !tabContentView.tabBarItem.parentTabBar; 205 if (!shouldIncludeTab) 206 continue; 207 208 contextMenu.appendItem(tabContentView.tabInfo().displayName, () => { 209 this.showExtensionTab(tabContentView.extensionTabID); 210 }); 211 } 212 } 213 214 addContextMenuItemsForAllExtensionTabs(contextMenu) 215 { 216 contextMenu.appendSeparator(); 217 218 for (let tabContentView of this._extensionTabContentViewForExtensionTabIDMap.values()) { 219 let checked = tabContentView.visible || !!tabContentView.tabBarItem.parentTabBar; 220 contextMenu.appendCheckboxItem(tabContentView.tabInfo().displayName, () => { 221 if (!checked) 222 this.showExtensionTab(tabContentView.extensionTabID); 223 else 224 this.hideExtensionTab(tabContentView.extensionTabID); 225 }, checked); 178 226 } 179 227 } -
trunk/Source/WebInspectorUI/UserInterface/Controllers/WebInspectorExtensionController.js.orig
r283857 r283859 34 34 this._tabIDsForExtensionIDMap = new Multimap; 35 35 this._nextExtensionTabID = 1; 36 37 WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._handleMainResourceDidChange, this); 36 38 } 37 39 … … 67 69 for (let extensionTabID of extensionTabIDsToRemove) { 68 70 let tabContentView = this._extensionTabContentViewForExtensionTabIDMap.take(extensionTabID); 69 WI.tabBrowser.closeTabForContentView(tabContentView , {suppressAnimations: true});71 WI.tabBrowser.closeTabForContentView(tabContentView); 70 72 } 71 73 … … 86 88 this._tabIDsForExtensionIDMap.add(extensionID, extensionTabID); 87 89 this._extensionTabContentViewForExtensionTabIDMap.set(extensionTabID, tabContentView); 88 WI.tabBrowser.addTabForContentView(tabContentView , {suppressAnimations: true});90 WI.tabBrowser.addTabForContentView(tabContentView); 89 91 90 92 // The calling convention is to return an error string or a result object. … … 167 169 } 168 170 169 tabContentView.visible = true;170 171 let success = WI.tabBrowser.showTabForContentView(tabContentView, { 171 172 initiatorHint: WI.TabBrowser.TabNavigationInitiator.FrontendAPI, … … 175 176 WI.reportInternalError("Unable to show extension tab with extensionTabID: " + extensionTabID); 176 177 return WI.WebInspectorExtension.ErrorCode.InternalError; 177 }178 }179 180 hideExtensionTab(extensionTabID, options = {})181 {182 let tabContentView = this._extensionTabContentViewForExtensionTabIDMap.get(extensionTabID);183 if (!tabContentView) {184 WI.reportInternalError("Unable to show extension tab with unknown extensionTabID: " + extensionTabID);185 return WI.WebInspectorExtension.ErrorCode.InvalidRequest;186 }187 188 tabContentView.visible = false;189 WI.tabBrowser.closeTabForContentView(tabContentView, options);190 191 console.assert(!tabContentView.visible);192 console.assert(!tabContentView.isClosed);193 }194 195 addContextMenuItemsForClosedExtensionTabs(contextMenu)196 {197 contextMenu.appendSeparator();198 199 for (let tabContentView of this._extensionTabContentViewForExtensionTabIDMap.values()) {200 // If the extension tab has been unchecked in the TabBar context menu, then the tabBarItem201 // for the extension tab will not be connected to a parent TabBar.202 let shouldIncludeTab = !tabContentView.visible || !tabContentView.tabBarItem.parentTabBar;203 if (!shouldIncludeTab)204 continue;205 206 contextMenu.appendItem(tabContentView.tabInfo().displayName, () => {207 this.showExtensionTab(tabContentView.extensionTabID);208 });209 }210 }211 212 addContextMenuItemsForAllExtensionTabs(contextMenu)213 {214 contextMenu.appendSeparator();215 216 for (let tabContentView of this._extensionTabContentViewForExtensionTabIDMap.values()) {217 let checked = tabContentView.visible || !!tabContentView.tabBarItem.parentTabBar;218 contextMenu.appendCheckboxItem(tabContentView.tabInfo().displayName, () => {219 if (!checked)220 this.showExtensionTab(tabContentView.extensionTabID);221 else222 this.hideExtensionTab(tabContentView.extensionTabID);223 }, checked);224 178 } 225 179 } … … 245 199 } 246 200 } 201 202 // Private 203 204 _handleMainResourceDidChange(event) 205 { 206 if (!event.target.isMainFrame()) 207 return; 208 209 // Don't fire the event unless one or more extensions are registered. 210 if (!this._extensionForExtensionIDMap.size) 211 return; 212 213 InspectorFrontendHost.inspectedPageDidNavigate(WI.networkManager.mainFrame.url); 214 } 247 215 }; 248 216 -
trunk/Source/WebInspectorUI/UserInterface/Views/ContentView.css
r226076 r283859 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 67 67 line-height: 22px; 68 68 } 69 70 .content-view.not-visible { 71 display: none; 72 } -
trunk/Source/WebInspectorUI/UserInterface/Views/ContentView.js
r283728 r283859 39 39 this._parentContainer = null; 40 40 this._isClosed = false; 41 this._visible = false; 41 42 } 42 43 … … 349 350 get isClosed() { return this._isClosed; } 350 351 352 get visible() 353 { 354 return !this.isClosed && this._visible; 355 } 356 357 set visible(value) 358 { 359 this._visible = !!value; 360 this.element.classList.toggle("not-visible", !this._visible); 361 } 362 351 363 get representedObject() 352 364 { -
trunk/Source/WebInspectorUI/UserInterface/Views/ContentViewContainer.js
r283728 r283859 1 1 /* 2 * Copyright (C) 2013 , 2015Apple Inc. All rights reserved.2 * Copyright (C) 2013–2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 422 422 } 423 423 424 // Deselected extension tabs are still attached to the DOM via `this.element`, 425 // so this is the last chance to actually remove the subview and detach from the DOM. 426 if (contentView.constructor.shouldNotRemoveFromDOMWhenHidden() && contentView.isAttached) 427 this.removeSubview(contentView); 424 // Hidden/non-visible extension tabs must remain attached to the DOM to avoid reloading. 425 if (contentView.constructor.shouldNotRemoveFromDOMWhenHidden() && !contentView.visible) 426 return; 427 428 this.removeSubview(contentView); 428 429 429 430 console.assert(!contentView.isAttached); … … 464 465 this.addSubview(entry.contentView); 465 466 else if (entry.contentView.constructor.shouldNotRemoveFromDOMWhenHidden()) { 466 entry.contentView. element.classList.remove("hidden-simulating-dom-detached");467 entry.contentView.visible = true; 467 468 entry.contentView._didMoveToParent(this); 468 469 } … … 483 484 if (this.subviews.includes(entry.contentView)) { 484 485 if (entry.contentView.constructor.shouldNotRemoveFromDOMWhenHidden()) { 485 entry.contentView. element.classList.add("hidden-simulating-dom-detached");486 entry.contentView.visible = false; 486 487 entry.contentView._didMoveToParent(null); 487 488 } else -
trunk/Source/WebInspectorUI/UserInterface/Views/TabBrowser.js
r283728 r283859 211 211 this._tabBar.removeTabBarItem(tabContentView.tabBarItem, options); 212 212 213 let shouldSaveTab = this.selectedTabContentView?.constructor.shouldSaveTab() || this.selectedTabContentView?.constructor.shouldPinTab(); 213 214 console.assert(this._recentTabContentViews.length === this._tabBar.tabCount); 214 console.assert(!this.selectedTabContentView || this.selectedTabContentView === this._recentTabContentViews[0] );215 console.assert(!this.selectedTabContentView || this.selectedTabContentView === this._recentTabContentViews[0] || !shouldSaveTab); 215 216 216 217 return true; … … 297 298 this._contentViewContainer.closeContentView(tabContentView); 298 299 300 let shouldSaveTab = this.selectedTabContentView?.constructor.shouldSaveTab() || this.selectedTabContentView?.constructor.shouldPinTab(); 299 301 console.assert(this._recentTabContentViews.length === this._tabBar.tabCount); 300 console.assert(!this.selectedTabContentView || this.selectedTabContentView === this._recentTabContentViews[0] );302 console.assert(!this.selectedTabContentView || this.selectedTabContentView === this._recentTabContentViews[0] || !shouldSaveTab); 301 303 } 302 304 -
trunk/Source/WebInspectorUI/UserInterface/Views/WebInspectorExtensionTabContentView.js
r283728 r283859 46 46 47 47 this._frameContentDidLoad = false; 48 } 49 50 // Static 51 52 static shouldSaveTab() { return false; } 53 static shouldNotRemoveFromDOMWhenHidden() { return true; } 54 55 static isTabAllowed() 56 { 57 return InspectorFrontendHost.supportsWebExtensions; 48 58 } 49 59
Note: See TracChangeset
for help on using the changeset viewer.