| /* |
| * Copyright (C) 2013-2021 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| WI.ContentView = class ContentView extends WI.View |
| { |
| constructor(representedObject, extraArguments) |
| { |
| // Concrete object instantiation. |
| console.assert(!representedObject || WI.ContentView.isViewable(representedObject), representedObject); |
| |
| super(); |
| |
| this._representedObject = representedObject; |
| |
| this.element.classList.add("content-view"); |
| |
| this._parentContainer = null; |
| this._isClosed = false; |
| this._visible = false; |
| } |
| |
| // Static |
| |
| static shouldNotRemoveFromDOMWhenHidden() |
| { |
| // Implemented by subclasses. |
| // Returns true if the content view should *not* be detached from the DOM when hidden. |
| return false; |
| } |
| |
| static createFromRepresentedObject(representedObject, extraArguments) |
| { |
| console.assert(representedObject); |
| |
| if (representedObject instanceof WI.Frame) |
| return new WI.ResourceClusterContentView(representedObject.mainResource, extraArguments); |
| |
| if (representedObject instanceof WI.Resource) |
| return new WI.ResourceClusterContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.Script) |
| return new WI.ScriptContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.CSSStyleSheet) |
| return new WI.TextResourceContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.Canvas) |
| return new WI.CanvasContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.ShaderProgram) |
| return new WI.ShaderProgramContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.TimelineRecording) |
| return new WI.TimelineRecordingContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.Timeline) { |
| var timelineType = representedObject.type; |
| if (timelineType === WI.TimelineRecord.Type.Network) |
| return new WI.NetworkTimelineView(representedObject, extraArguments); |
| |
| if (timelineType === WI.TimelineRecord.Type.Layout) |
| return new WI.LayoutTimelineView(representedObject, extraArguments); |
| |
| if (timelineType === WI.TimelineRecord.Type.Script) |
| return new WI.ScriptClusterTimelineView(representedObject, extraArguments); |
| |
| if (timelineType === WI.TimelineRecord.Type.RenderingFrame) |
| return new WI.RenderingFrameTimelineView(representedObject, extraArguments); |
| |
| if (timelineType === WI.TimelineRecord.Type.CPU) |
| return new WI.CPUTimelineView(representedObject, extraArguments); |
| |
| if (timelineType === WI.TimelineRecord.Type.Memory) |
| return new WI.MemoryTimelineView(representedObject, extraArguments); |
| |
| if (timelineType === WI.TimelineRecord.Type.HeapAllocations) |
| return new WI.HeapAllocationsTimelineView(representedObject, extraArguments); |
| |
| if (timelineType === WI.TimelineRecord.Type.Media) |
| return new WI.MediaTimelineView(representedObject, extraArguments); |
| } |
| |
| if (representedObject instanceof WI.JavaScriptBreakpoint || representedObject instanceof WI.IssueMessage) { |
| if (representedObject.sourceCodeLocation) |
| return WI.ContentView.createFromRepresentedObject(representedObject.sourceCodeLocation.displaySourceCode, extraArguments); |
| } |
| |
| if (representedObject instanceof WI.LocalResourceOverride) { |
| if (representedObject.type === WI.LocalResourceOverride.InterceptType.Request) |
| return new WI.LocalResourceOverrideRequestContentView(representedObject); |
| return WI.ContentView.createFromRepresentedObject(representedObject.localResource); |
| } |
| |
| if (representedObject instanceof WI.DOMStorageObject) |
| return new WI.DOMStorageContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.CookieStorageObject) |
| return new WI.CookieStorageContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.DatabaseTableObject) |
| return new WI.DatabaseTableContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.DatabaseObject) |
| return new WI.DatabaseContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.IndexedDatabase) |
| return new WI.IndexedDatabaseContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.IndexedDatabaseObjectStore) |
| return new WI.IndexedDatabaseObjectStoreContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.IndexedDatabaseObjectStoreIndex) |
| return new WI.IndexedDatabaseObjectStoreContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.ApplicationCacheFrame) |
| return new WI.ApplicationCacheFrameContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.DOMTree) |
| return new WI.FrameDOMTreeContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.DOMSearchMatchObject) { |
| var resultView = new WI.FrameDOMTreeContentView(WI.networkManager.mainFrame.domTree, extraArguments); |
| resultView.restoreFromCookie({nodeToSelect: representedObject.domNode}); |
| return resultView; |
| } |
| |
| if (representedObject instanceof WI.DOMNode) { |
| if (representedObject.frame) { |
| let resultView = WI.ContentView.createFromRepresentedObject(representedObject.frame, extraArguments); |
| resultView.restoreFromCookie({nodeToSelect: representedObject}); |
| return resultView; |
| } |
| } |
| |
| if (representedObject instanceof WI.SourceCodeSearchMatchObject) { |
| var resultView; |
| if (representedObject.sourceCode instanceof WI.Resource) |
| resultView = new WI.ResourceClusterContentView(representedObject.sourceCode, extraArguments); |
| else if (representedObject.sourceCode instanceof WI.Script) |
| resultView = new WI.ScriptContentView(representedObject.sourceCode, extraArguments); |
| else |
| console.error("Unknown SourceCode", representedObject.sourceCode); |
| |
| var textRangeToSelect = representedObject.sourceCodeTextRange.formattedTextRange; |
| var startPosition = textRangeToSelect.startPosition(); |
| resultView.restoreFromCookie({lineNumber: startPosition.lineNumber, columnNumber: startPosition.columnNumber}); |
| |
| return resultView; |
| } |
| |
| if (representedObject instanceof WI.LogObject) |
| return new WI.LogContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.CallingContextTree) |
| return new WI.ProfileView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.HeapSnapshotProxy || representedObject instanceof WI.HeapSnapshotDiffProxy) |
| return new WI.HeapSnapshotClusterContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.Recording) |
| return new WI.RecordingContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.ResourceCollection) |
| return new WI.ResourceCollectionContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.AuditTestCase || representedObject instanceof WI.AuditTestCaseResult) |
| return new WI.AuditTestCaseContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.AuditTestGroup || representedObject instanceof WI.AuditTestGroupResult) |
| return new WI.AuditTestGroupContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.Animation) |
| return new WI.AnimationContentView(representedObject, extraArguments); |
| |
| if (representedObject instanceof WI.Collection) |
| return new WI.CollectionContentView(representedObject, extraArguments); |
| |
| if (typeof representedObject === "string" || representedObject instanceof String) |
| return new WI.TextContentView(representedObject, extraArguments); |
| |
| console.assert(!WI.ContentView.isViewable(representedObject)); |
| |
| throw new Error("Can't make a ContentView for an unknown representedObject of type: " + representedObject.constructor.name); |
| } |
| |
| static contentViewForRepresentedObject(representedObject, onlyExisting, extraArguments) |
| { |
| console.assert(representedObject); |
| |
| // Some represented objects attempt to resolve a better represented object. |
| // This may result in null, for example a Breakpoint which doesn't have a SourceCode. |
| let resolvedRepresentedObject = WI.ContentView.resolvedRepresentedObjectForRepresentedObject(representedObject); |
| if (!resolvedRepresentedObject) |
| return null; |
| |
| let existingContentView = resolvedRepresentedObject[WI.ContentView.ContentViewForRepresentedObjectSymbol]; |
| console.assert(!existingContentView || existingContentView instanceof WI.ContentView); |
| if (existingContentView) |
| return existingContentView; |
| |
| if (onlyExisting) |
| return null; |
| |
| let newContentView = WI.ContentView.createFromRepresentedObject(representedObject, extraArguments); |
| console.assert(newContentView instanceof WI.ContentView); |
| if (!newContentView) |
| return null; |
| |
| console.assert(newContentView.representedObject === resolvedRepresentedObject, "createFromRepresentedObject and resolvedRepresentedObjectForRepresentedObject are out of sync for type", representedObject.constructor.name); |
| if (typeof resolvedRepresentedObject === "object") |
| newContentView.representedObject[WI.ContentView.ContentViewForRepresentedObjectSymbol] = newContentView; |
| return newContentView; |
| } |
| |
| static closedContentViewForRepresentedObject(representedObject) |
| { |
| let resolvedRepresentedObject = WI.ContentView.resolvedRepresentedObjectForRepresentedObject(representedObject); |
| if (typeof resolvedRepresentedObject === "object") |
| resolvedRepresentedObject[WI.ContentView.ContentViewForRepresentedObjectSymbol] = null; |
| } |
| |
| static resolvedRepresentedObjectForRepresentedObject(representedObject) |
| { |
| if (representedObject instanceof WI.Frame) |
| return representedObject.mainResource; |
| |
| if (representedObject instanceof WI.JavaScriptBreakpoint || representedObject instanceof WI.IssueMessage) { |
| if (representedObject.sourceCodeLocation) |
| return representedObject.sourceCodeLocation.displaySourceCode; |
| return representedObject; |
| } |
| |
| if (representedObject instanceof WI.DOMBreakpoint) { |
| if (representedObject.domNode) |
| return WI.ContentView.resolvedRepresentedObjectForRepresentedObject(representedObject.domNode); |
| return representedObject; |
| } |
| |
| if (representedObject instanceof WI.DOMNode) { |
| if (representedObject.frame) |
| return WI.ContentView.resolvedRepresentedObjectForRepresentedObject(representedObject.frame); |
| return representedObject; |
| } |
| |
| if (representedObject instanceof WI.DOMSearchMatchObject) |
| return WI.networkManager.mainFrame.domTree; |
| |
| if (representedObject instanceof WI.SourceCodeSearchMatchObject) |
| return representedObject.sourceCode; |
| |
| if (representedObject instanceof WI.LocalResourceOverride) { |
| if (representedObject.type !== WI.LocalResourceOverride.InterceptType.Request) |
| return representedObject.localResource; |
| return representedObject; |
| } |
| |
| return representedObject; |
| } |
| |
| static isViewable(representedObject) |
| { |
| if (representedObject instanceof WI.Frame) |
| return true; |
| if (representedObject instanceof WI.Resource) |
| return true; |
| if (representedObject instanceof WI.Script) |
| return true; |
| if (representedObject instanceof WI.CSSStyleSheet) |
| return true; |
| if (representedObject instanceof WI.Canvas) |
| return true; |
| if (representedObject instanceof WI.ShaderProgram) |
| return true; |
| if (representedObject instanceof WI.TimelineRecording) |
| return true; |
| if (representedObject instanceof WI.Timeline) |
| return true; |
| if (representedObject instanceof WI.JavaScriptBreakpoint || representedObject instanceof WI.IssueMessage) |
| return representedObject.sourceCodeLocation; |
| if (representedObject instanceof WI.LocalResourceOverride) |
| return true; |
| if (representedObject instanceof WI.DOMStorageObject) |
| return true; |
| if (representedObject instanceof WI.CookieStorageObject) |
| return true; |
| if (representedObject instanceof WI.DatabaseTableObject) |
| return true; |
| if (representedObject instanceof WI.DatabaseObject) |
| return true; |
| if (representedObject instanceof WI.IndexedDatabase) |
| return true; |
| if (representedObject instanceof WI.IndexedDatabaseObjectStore) |
| return true; |
| if (representedObject instanceof WI.IndexedDatabaseObjectStoreIndex) |
| return true; |
| if (representedObject instanceof WI.ApplicationCacheFrame) |
| return true; |
| if (representedObject instanceof WI.DOMTree) |
| return true; |
| if (representedObject instanceof WI.DOMSearchMatchObject) |
| return true; |
| if (representedObject instanceof WI.SourceCodeSearchMatchObject) |
| return true; |
| if (representedObject instanceof WI.LogObject) |
| return true; |
| if (representedObject instanceof WI.CallingContextTree) |
| return true; |
| if (representedObject instanceof WI.HeapSnapshotProxy || representedObject instanceof WI.HeapSnapshotDiffProxy) |
| return true; |
| if (representedObject instanceof WI.Recording) |
| return true; |
| if (representedObject instanceof WI.AuditTestCase || representedObject instanceof WI.AuditTestGroup |
| || representedObject instanceof WI.AuditTestCaseResult || representedObject instanceof WI.AuditTestGroupResult) |
| return true; |
| if (representedObject instanceof WI.Animation) |
| return true; |
| if (representedObject instanceof WI.Collection) |
| return true; |
| if (typeof representedObject === "string" || representedObject instanceof String) |
| return true; |
| if (representedObject[WI.ContentView.isViewableSymbol]) |
| return true; |
| return false; |
| } |
| |
| // Public |
| |
| get isClosed() { return this._isClosed; } |
| |
| get visible() |
| { |
| return !this.isClosed && this._visible; |
| } |
| |
| set visible(value) |
| { |
| this._visible = !!value; |
| this.element.classList.toggle("not-visible", !this._visible); |
| } |
| |
| get representedObject() |
| { |
| return this._representedObject; |
| } |
| |
| get navigationItems() |
| { |
| // Navigation items that will be displayed by the ContentBrowser instance, |
| // meant to be subclassed. Implemented by subclasses. |
| return []; |
| } |
| |
| get parentContainer() |
| { |
| return this._parentContainer; |
| } |
| |
| get scrollableElements() |
| { |
| // Implemented by subclasses. |
| return []; |
| } |
| |
| get shouldKeepElementsScrolledToBottom() |
| { |
| // Implemented by subclasses. |
| return false; |
| } |
| |
| get shouldSaveStateWhenHidden() |
| { |
| return false; |
| } |
| |
| get selectionPathComponents() |
| { |
| // Implemented by subclasses. |
| return []; |
| } |
| |
| get supplementalRepresentedObjects() |
| { |
| // Implemented by subclasses. |
| return []; |
| } |
| |
| get supportsSplitContentBrowser() |
| { |
| // Implemented by subclasses. |
| return WI.dockedConfigurationSupportsSplitContentBrowser(); |
| } |
| |
| closed() |
| { |
| // Implemented by subclasses. |
| this._isClosed = true; |
| } |
| |
| saveToCookie(cookie) |
| { |
| // Implemented by subclasses. |
| } |
| |
| restoreFromCookie(cookie) |
| { |
| // Implemented by subclasses. |
| } |
| |
| canGoBack() |
| { |
| // Implemented by subclasses. |
| return false; |
| } |
| |
| canGoForward() |
| { |
| // Implemented by subclasses. |
| return false; |
| } |
| |
| goBack() |
| { |
| // Implemented by subclasses. |
| } |
| |
| goForward() |
| { |
| // Implemented by subclasses. |
| } |
| |
| get supportsSearch() |
| { |
| // Implemented by subclasses. |
| return false; |
| } |
| |
| get supportsCustomFindBanner() |
| { |
| // Implemented by subclasses. |
| return false; |
| } |
| |
| showCustomFindBanner() |
| { |
| // Implemented by subclasses. |
| } |
| |
| get numberOfSearchResults() |
| { |
| // Implemented by subclasses. |
| return null; |
| } |
| |
| get hasPerformedSearch() |
| { |
| // Implemented by subclasses. |
| return false; |
| } |
| |
| set automaticallyRevealFirstSearchResult(reveal) |
| { |
| // Implemented by subclasses. |
| } |
| |
| performSearch(query) |
| { |
| // Implemented by subclasses. |
| } |
| |
| searchHidden() |
| { |
| // Implemented by subclasses. |
| } |
| |
| searchCleared() |
| { |
| // Implemented by subclasses. |
| } |
| |
| searchQueryWithSelection() |
| { |
| let selection = window.getSelection(); |
| if (selection.isCollapsed) |
| return null; |
| |
| return selection.toString().removeWordBreakCharacters(); |
| } |
| |
| revealPreviousSearchResult(changeFocus) |
| { |
| // Implemented by subclasses. |
| } |
| |
| revealNextSearchResult(changeFocus) |
| { |
| // Implemented by subclasses. |
| } |
| }; |
| |
| WI.ContentView.Event = { |
| SelectionPathComponentsDidChange: "content-view-selection-path-components-did-change", |
| SupplementalRepresentedObjectsDidChange: "content-view-supplemental-represented-objects-did-change", |
| NumberOfSearchResultsDidChange: "content-view-number-of-search-results-did-change", |
| NavigationItemsDidChange: "content-view-navigation-items-did-change" |
| }; |
| |
| WI.ContentView.isViewableSymbol = Symbol("is-viewable"); |
| WI.ContentView.ContentViewForRepresentedObjectSymbol = Symbol("content-view-for-represented-object"); |