| /* |
| * Copyright (C) 2007, 2008 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. |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. |
| */ |
| /** |
| * @implements {Common.ContentProvider} |
| * @unrestricted |
| */ |
| SDK.Resource = class { |
| /** |
| * @param {!SDK.ResourceTreeModel} resourceTreeModel |
| * @param {?SDK.NetworkRequest} request |
| * @param {string} url |
| * @param {string} documentURL |
| * @param {!Protocol.Page.FrameId} frameId |
| * @param {!Protocol.Network.LoaderId} loaderId |
| * @param {!Common.ResourceType} type |
| * @param {string} mimeType |
| * @param {?Date} lastModified |
| * @param {?number} contentSize |
| */ |
| constructor( |
| resourceTreeModel, request, url, documentURL, frameId, loaderId, type, mimeType, lastModified, contentSize) { |
| this._resourceTreeModel = resourceTreeModel; |
| this._request = request; |
| this.url = url; |
| this._documentURL = documentURL; |
| this._frameId = frameId; |
| this._loaderId = loaderId; |
| this._type = type || Common.resourceTypes.Other; |
| this._mimeType = mimeType; |
| |
| this._lastModified = lastModified && lastModified.isValid() ? lastModified : null; |
| this._contentSize = contentSize; |
| |
| /** @type {?string} */ this._content; |
| /** @type {boolean} */ this._contentEncoded; |
| this._pendingContentCallbacks = []; |
| if (this._request && !this._request.finished) |
| this._request.addEventListener(SDK.NetworkRequest.Events.FinishedLoading, this._requestFinished, this); |
| } |
| |
| /** |
| * @return {?Date} |
| */ |
| lastModified() { |
| if (this._lastModified || !this._request) |
| return this._lastModified; |
| const lastModifiedHeader = this._request.responseLastModified(); |
| const date = lastModifiedHeader ? new Date(lastModifiedHeader) : null; |
| this._lastModified = date && date.isValid() ? date : null; |
| return this._lastModified; |
| } |
| |
| /** |
| * @return {?number} |
| */ |
| contentSize() { |
| if (typeof this._contentSize === 'number' || !this._request) |
| return this._contentSize; |
| return this._request.resourceSize; |
| } |
| |
| /** |
| * @return {?SDK.NetworkRequest} |
| */ |
| get request() { |
| return this._request; |
| } |
| |
| /** |
| * @return {string} |
| */ |
| get url() { |
| return this._url; |
| } |
| |
| /** |
| * @param {string} x |
| */ |
| set url(x) { |
| this._url = x; |
| this._parsedURL = new Common.ParsedURL(x); |
| } |
| |
| get parsedURL() { |
| return this._parsedURL; |
| } |
| |
| /** |
| * @return {string} |
| */ |
| get documentURL() { |
| return this._documentURL; |
| } |
| |
| /** |
| * @return {!Protocol.Page.FrameId} |
| */ |
| get frameId() { |
| return this._frameId; |
| } |
| |
| /** |
| * @return {!Protocol.Network.LoaderId} |
| */ |
| get loaderId() { |
| return this._loaderId; |
| } |
| |
| /** |
| * @return {string} |
| */ |
| get displayName() { |
| return this._parsedURL.displayName; |
| } |
| |
| /** |
| * @return {!Common.ResourceType} |
| */ |
| resourceType() { |
| return this._request ? this._request.resourceType() : this._type; |
| } |
| |
| /** |
| * @return {string} |
| */ |
| get mimeType() { |
| return this._request ? this._request.mimeType : this._mimeType; |
| } |
| |
| /** |
| * @return {?string} |
| */ |
| get content() { |
| return this._content; |
| } |
| |
| /** |
| * @override |
| * @return {string} |
| */ |
| contentURL() { |
| return this._url; |
| } |
| |
| /** |
| * @override |
| * @return {!Common.ResourceType} |
| */ |
| contentType() { |
| if (this.resourceType() === Common.resourceTypes.Document && this.mimeType.indexOf('javascript') !== -1) |
| return Common.resourceTypes.Script; |
| return this.resourceType(); |
| } |
| |
| /** |
| * @override |
| * @return {!Promise<boolean>} |
| */ |
| async contentEncoded() { |
| await this.requestContent(); |
| return this._contentEncoded; |
| } |
| |
| /** |
| * @override |
| * @return {!Promise<?string>} |
| */ |
| requestContent() { |
| if (typeof this._content !== 'undefined') |
| return Promise.resolve(this._content); |
| |
| let callback; |
| const promise = new Promise(fulfill => callback = fulfill); |
| this._pendingContentCallbacks.push(callback); |
| if (!this._request || this._request.finished) |
| this._innerRequestContent(); |
| return promise; |
| } |
| |
| /** |
| * @return {string} |
| */ |
| canonicalMimeType() { |
| return this.contentType().canonicalMimeType() || this.mimeType; |
| } |
| |
| /** |
| * @override |
| * @param {string} query |
| * @param {boolean} caseSensitive |
| * @param {boolean} isRegex |
| * @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>} |
| */ |
| async searchInContent(query, caseSensitive, isRegex) { |
| if (!this.frameId) |
| return []; |
| if (this.request) |
| return this.request.searchInContent(query, caseSensitive, isRegex); |
| const result = await this._resourceTreeModel.target().pageAgent().searchInResource( |
| this.frameId, this.url, query, caseSensitive, isRegex); |
| return result || []; |
| } |
| |
| /** |
| * @param {!Element} image |
| */ |
| populateImageSource(image) { |
| /** |
| * @param {?string} content |
| * @this {SDK.Resource} |
| */ |
| function onResourceContent(content) { |
| let imageSrc = Common.ContentProvider.contentAsDataURL(content, this._mimeType, true); |
| if (imageSrc === null) |
| imageSrc = this._url; |
| image.src = imageSrc; |
| } |
| |
| this.requestContent().then(onResourceContent.bind(this)); |
| } |
| |
| _requestFinished() { |
| this._request.removeEventListener(SDK.NetworkRequest.Events.FinishedLoading, this._requestFinished, this); |
| if (this._pendingContentCallbacks.length) |
| this._innerRequestContent(); |
| } |
| |
| async _innerRequestContent() { |
| if (this._contentRequested) |
| return; |
| this._contentRequested = true; |
| |
| if (this.request) { |
| const contentData = await this.request.contentData(); |
| this._content = contentData.content; |
| this._contentEncoded = contentData.encoded; |
| } else { |
| const response = await this._resourceTreeModel.target().pageAgent().invoke_getResourceContent( |
| {frameId: this.frameId, url: this.url}); |
| this._content = response[Protocol.Error] ? null : response.content; |
| this._contentEncoded = response.base64Encoded; |
| } |
| |
| if (this._content === null) |
| this._contentEncoded = false; |
| |
| for (const callback of this._pendingContentCallbacks.splice(0)) |
| callback(this._content); |
| delete this._contentRequested; |
| } |
| |
| /** |
| * @return {boolean} |
| */ |
| hasTextContent() { |
| if (this._type.isTextType()) |
| return true; |
| if (this._type === Common.resourceTypes.Other) |
| return !!this._content && !this._contentEncoded; |
| return false; |
| } |
| |
| /** |
| * @return {!SDK.ResourceTreeFrame} |
| */ |
| frame() { |
| return this._resourceTreeModel.frameForId(this._frameId); |
| } |
| }; |