ScriptRequestProcessor
using AngleSharp.Dom;
using AngleSharp.Dom.Html;
using AngleSharp.Extensions;
using AngleSharp.Html;
using AngleSharp.Services;
using AngleSharp.Services.Scripting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AngleSharp.Network.RequestProcessors
{
internal sealed class ScriptRequestProcessor : IRequestProcessor
{
private readonly HtmlScriptElement _script;
private readonly Document _document;
private readonly IResourceLoader _loader;
private IResponse _response;
private IScriptEngine _engine;
public IDownload Download { get; set; }
public IScriptEngine Engine => _engine ?? (_engine = _document.Options.GetScriptEngine(ScriptLanguage));
public string AlternativeLanguage {
get {
string ownAttribute = _script.GetOwnAttribute(AttributeNames.Language);
if (ownAttribute == null)
return null;
return "text/" + ownAttribute;
}
}
public string ScriptLanguage {
get {
string text = _script.Type ?? AlternativeLanguage;
if (!string.IsNullOrEmpty(text))
return text;
return MimeTypeNames.DefaultJavaScript;
}
}
private ScriptRequestProcessor(HtmlScriptElement script, Document document, IResourceLoader loader)
{
_script = script;
_document = document;
_loader = loader;
}
internal static ScriptRequestProcessor Create(HtmlScriptElement script)
{
Document owner = script.Owner;
IResourceLoader loader = owner.Loader;
return new ScriptRequestProcessor(script, owner, loader);
}
public async Task RunAsync(CancellationToken cancel)
{
IDownload download = Download;
if (download != null)
try {
IResponse response2 = _response;
IResponse response = _response = await download.Task.ConfigureAwait(false);
} catch (Exception) {
FireErrorEvent();
}
if (_response != null && !_script.FireSimpleEvent(EventNames.BeforeScriptExecute, false, true)) {
ScriptOptions options = CreateOptions();
int insert = _document.Source.Index;
try {
await _engine.EvaluateScriptAsync(_response, options, cancel).ConfigureAwait(false);
} catch {
}
_document.Source.Index = insert;
FireAfterScriptExecuteEvent();
_document.QueueTask(FireLoadEvent);
_response.Dispose();
_response = null;
}
}
public void Process(string content)
{
if (Engine != null)
_response = VirtualResponse.Create(delegate(VirtualResponse res) {
res.Content(content).Address(_script.BaseUri);
});
}
public Task ProcessAsync(ResourceRequest request)
{
if (_loader != null && Engine != null) {
Download = _loader.FetchWithCors(new CorsRequest(request) {
Behavior = OriginBehavior.Taint,
Setting = _script.CrossOrigin.ToEnum(CorsSetting.None),
Integrity = _document.Options.GetProvider<IIntegrityProvider>()
});
return Download.Task;
}
return null;
}
private ScriptOptions CreateOptions()
{
return new ScriptOptions(_document) {
Element = _script,
Encoding = TextEncoding.Resolve(_script.CharacterSet)
};
}
private void FireLoadEvent()
{
_script.FireSimpleEvent(EventNames.Load, false, false);
}
private void FireErrorEvent()
{
_script.FireSimpleEvent(EventNames.Error, false, false);
}
private void FireAfterScriptExecuteEvent()
{
_script.FireSimpleEvent(EventNames.AfterScriptExecute, true, false);
}
}
}