blob: ef4867a3f53be8597fe1d9e16063d2b871dd5b8c [file] [log] [blame]
/*
* Copyright (C) 2013, 2015 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.ResourceContentView = class ResourceContentView extends WI.ContentView
{
constructor(resource, styleClassName)
{
console.assert(resource instanceof WI.Resource || resource instanceof WI.CSSStyleSheet, resource);
console.assert(typeof styleClassName === "string");
super(resource);
this._resource = resource;
this.element.classList.add(styleClassName, "resource");
this._spinnerTimeout = setTimeout(() => {
// Append a spinner while waiting for contentAvailable. Subclasses are responsible for
// removing the spinner before showing the resource content by calling removeLoadingIndicator.
let spinner = new WI.IndeterminateProgressSpinner;
this.element.appendChild(spinner.element);
this._spinnerTimeout = undefined;
}, 100);
this.element.addEventListener("click", this._mouseWasClicked.bind(this), false);
// Request content last so the spinner will always be removed in case the content is immediately available.
resource.requestContent().then(this._contentAvailable.bind(this)).catch(this.showGenericErrorMessage.bind(this));
if (!this.managesOwnIssues) {
WI.consoleManager.addEventListener(WI.ConsoleManager.Event.IssueAdded, this._issueWasAdded, this);
var issues = WI.consoleManager.issuesForSourceCode(resource);
for (var i = 0; i < issues.length; ++i)
this.addIssue(issues[i]);
}
}
// Public
get resource()
{
return this._resource;
}
get supportsSave()
{
return this._resource.finished;
}
get saveData()
{
return {url: this._resource.url, content: this._resource.content};
}
contentAvailable(content, base64Encoded)
{
throw WI.NotImplementedError.subclassMustOverride();
}
showGenericNoContentMessage()
{
this.showMessage(WI.UIString("Resource has no content"));
this.dispatchEventToListeners(WI.ResourceContentView.Event.ContentError);
}
showGenericErrorMessage()
{
this._contentError(WI.UIString("An error occurred trying to load the resource."));
}
showMessage(message)
{
this.element.removeChildren();
this.element.appendChild(WI.createMessageTextView(message));
}
addIssue(issue)
{
// This generically shows only the last issue, subclasses can override for better handling.
this.element.removeChildren();
this.element.appendChild(WI.createMessageTextView(issue.text, issue.level === WI.IssueMessage.Level.Error));
}
closed()
{
super.closed();
if (!this.managesOwnIssues)
WI.consoleManager.removeEventListener(null, null, this);
}
// Protected
removeLoadingIndicator()
{
if (this._spinnerTimeout) {
clearTimeout(this._spinnerTimeout);
this._spinnerTimeout = undefined;
}
this.element.removeChildren();
}
// Private
_contentAvailable(parameters)
{
if (parameters.error) {
this._contentError(parameters.error);
return;
}
// Content is ready to show, call the public method now.
console.assert(!this._hasContent());
console.assert(parameters.sourceCode === this._resource);
this.contentAvailable(parameters.sourceCode.content, parameters.base64Encoded);
}
_contentError(error)
{
if (this._hasContent())
return;
this.removeLoadingIndicator();
this.element.appendChild(WI.createMessageTextView(error, true));
this.dispatchEventToListeners(WI.ResourceContentView.Event.ContentError);
}
_hasContent()
{
return this.element.hasChildNodes() && !this.element.querySelector(".indeterminate-progress-spinner");
}
_issueWasAdded(event)
{
console.assert(!this.managesOwnIssues);
var issue = event.data.issue;
if (!WI.ConsoleManager.issueMatchSourceCode(issue, this.resource))
return;
this.addIssue(issue);
}
_mouseWasClicked(event)
{
WI.handlePossibleLinkClick(event, this.resource.parentFrame);
}
};
WI.ResourceContentView.Event = {
ContentError: "resource-content-view-content-error",
};