Document
abstract class Document : Node, IDocument, INode, IEventTarget, IMarkupFormattable, IParentNode, IGlobalEventHandlers, IDocumentStyle, INonElementParentNode, IDisposable
Represents a document node.
using AngleSharp.Dom.Collections;
using AngleSharp.Dom.Events;
using AngleSharp.Dom.Html;
using AngleSharp.Dom.Mathml;
using AngleSharp.Dom.Svg;
using AngleSharp.Extensions;
using AngleSharp.Html;
using AngleSharp.Network;
using AngleSharp.Services;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace AngleSharp.Dom
{
internal abstract class Document : Node, IDocument, INode, IEventTarget, IMarkupFormattable, IParentNode, IGlobalEventHandlers, IDocumentStyle, INonElementParentNode, IDisposable
{
private static readonly ConditionalWeakTable<Document, List<WeakReference>> AttachedReferences = new ConditionalWeakTable<Document, List<WeakReference>>();
private readonly Queue<HtmlScriptElement> _loadingScripts;
private readonly MutationHost _mutations;
private readonly IBrowsingContext _context;
private readonly IEventLoop _loop;
private readonly Window _view;
private readonly IResourceLoader _loader;
private readonly Location _location;
private readonly TextSource _source;
private QuirksMode _quirksMode;
private Sandboxes _sandbox;
private bool _async;
private bool _designMode;
private bool _shown;
private bool _salvageable;
private bool _firedUnload;
private DocumentReadyState _ready;
private IElement _focus;
private HtmlAllCollection _all;
private HtmlCollection<IHtmlAnchorElement> _anchors;
private HtmlCollection<IElement> _children;
private DomImplementation _implementation;
private IStringList _styleSheetSets;
private HtmlCollection<IHtmlImageElement> _images;
private HtmlCollection<IHtmlScriptElement> _scripts;
private HtmlCollection<IHtmlEmbedElement> _plugins;
private HtmlCollection<IElement> _commands;
private HtmlCollection<IElement> _links;
private IStyleSheetList _styleSheets;
private HttpStatusCode _statusCode;
public TextSource Source => _source;
public IDocument ImportAncestor { get; set; }
public IEventLoop Loop => _loop;
public string DesignMode {
get {
if (!_designMode)
return Keywords.Off;
return Keywords.On;
}
set {
_designMode = value.Isi(Keywords.On);
}
}
public IHtmlAllCollection All => _all ?? (_all = new HtmlAllCollection(this));
public IHtmlCollection<IHtmlAnchorElement> Anchors => _anchors ?? (_anchors = new HtmlCollection<IHtmlAnchorElement>(this, true, IsAnchor));
public int ChildElementCount => base.ChildNodes.OfType<Element>().Count();
public IHtmlCollection<IElement> Children => _children ?? (_children = new HtmlCollection<IElement>(base.ChildNodes.OfType<Element>()));
public IElement FirstElementChild {
get {
NodeList childNodes = base.ChildNodes;
int length = childNodes.Length;
for (int i = 0; i < length; i++) {
IElement element = childNodes[i] as IElement;
if (element != null)
return element;
}
return null;
}
}
public IElement LastElementChild {
get {
NodeList childNodes = base.ChildNodes;
for (int num = childNodes.Length - 1; num >= 0; num--) {
IElement element = childNodes[num] as IElement;
if (element != null)
return element;
}
return null;
}
}
public bool IsAsync => _async;
public IHtmlScriptElement CurrentScript {
get {
if (_loadingScripts.Count <= 0)
return null;
return _loadingScripts.Peek();
}
}
public IImplementation Implementation => _implementation ?? (_implementation = new DomImplementation(this));
public string LastModified { get; set; }
public IDocumentType Doctype => this.FindChild<DocumentType>();
public string ContentType { get; set; }
public DocumentReadyState ReadyState {
get {
return _ready;
}
protected set {
_ready = value;
this.FireSimpleEvent(EventNames.ReadyStateChanged, false, false);
}
}
public IStyleSheetList StyleSheets => _styleSheets ?? (_styleSheets = this.CreateStyleSheets());
public IStringList StyleSheetSets => _styleSheetSets ?? (_styleSheetSets = this.CreateStyleSheetSets());
public string Referrer { get; set; }
public ILocation Location => _location;
public string DocumentUri {
get {
return _location.Href;
}
protected set {
_location.Changed -= LocationChanged;
_location.Href = value;
_location.Changed += LocationChanged;
}
}
public Url DocumentUrl => _location.Original;
public IWindow DefaultView => _view;
public string Direction {
get {
return ((DocumentElement as IHtmlElement) ?? new HtmlHtmlElement(this, null)).Direction;
}
set {
((DocumentElement as IHtmlElement) ?? new HtmlHtmlElement(this, null)).Direction = value;
}
}
public string CharacterSet => _source.CurrentEncoding.WebName;
public abstract IElement DocumentElement { get; }
public IElement ActiveElement => (from m in All
where m.IsFocused
select m).FirstOrDefault();
public string CompatMode => _quirksMode.GetCompatiblity();
public string Url => _location.Href;
public IHtmlCollection<IHtmlFormElement> Forms => new HtmlCollection<IHtmlFormElement>(this, true, null);
public IHtmlCollection<IHtmlImageElement> Images => _images ?? (_images = new HtmlCollection<IHtmlImageElement>(this, true, null));
public IHtmlCollection<IHtmlScriptElement> Scripts => _scripts ?? (_scripts = new HtmlCollection<IHtmlScriptElement>(this, true, null));
public IHtmlCollection<IHtmlEmbedElement> Plugins => _plugins ?? (_plugins = new HtmlCollection<IHtmlEmbedElement>(this, true, null));
public IHtmlCollection<IElement> Commands => _commands ?? (_commands = new HtmlCollection<IElement>(this, true, IsCommand));
public IHtmlCollection<IElement> Links => _links ?? (_links = new HtmlCollection<IElement>(this, true, IsLink));
public string Title {
get {
return GetTitle();
}
set {
SetTitle(value);
}
}
public IHtmlHeadElement Head => DocumentElement.FindChild<IHtmlHeadElement>();
public IHtmlElement Body {
get {
IElement documentElement = DocumentElement;
if (documentElement != null) {
foreach (INode childNode in documentElement.ChildNodes) {
HtmlBodyElement htmlBodyElement = childNode as HtmlBodyElement;
if (htmlBodyElement != null)
return htmlBodyElement;
HtmlFrameSetElement htmlFrameSetElement = childNode as HtmlFrameSetElement;
if (htmlFrameSetElement != null)
return htmlFrameSetElement;
}
}
return null;
}
set {
if (!(value is IHtmlBodyElement) && !(value is HtmlFrameSetElement))
throw new DomException(DomError.HierarchyRequest);
IHtmlElement body = Body;
if (body != value) {
if (body == null) {
IElement documentElement = DocumentElement;
if (documentElement == null)
throw new DomException(DomError.HierarchyRequest);
documentElement.AppendChild(value);
} else
ReplaceChild(value, body);
}
}
}
public IBrowsingContext Context => _context;
public HttpStatusCode StatusCode {
get {
return _statusCode;
}
private set {
_statusCode = value;
}
}
public string Cookie {
get {
return Options.GetCookie(_location.Origin);
}
set {
Options.SetCookie(_location.Origin, value);
}
}
public string Domain {
get {
if (!string.IsNullOrEmpty(DocumentUri))
return new Uri(DocumentUri).Host;
return string.Empty;
}
set {
if (_location != null)
_location.Host = value;
}
}
public string Origin => _location.Origin;
public string SelectedStyleSheetSet {
get {
IEnumerable<string> enabledStyleSheetSets = StyleSheets.GetEnabledStyleSheetSets();
string enabledName = enabledStyleSheetSets.FirstOrDefault();
IEnumerable<IStyleSheet> source = StyleSheets.Where(delegate(IStyleSheet m) {
if (!string.IsNullOrEmpty(m.Title))
return !m.IsDisabled;
return false;
});
if (enabledStyleSheetSets.Count() == 1 && !source.Any((IStyleSheet m) => !m.Title.Is(enabledName)))
return enabledName;
if (source.Any())
return null;
return string.Empty;
}
set {
if (value != null) {
StyleSheets.EnableStyleSheetSet(value);
LastStyleSheetSet = value;
}
}
}
public string LastStyleSheetSet { get; set; }
public string PreferredStyleSheetSet => (from m in All.OfType<IHtmlLinkElement>()
where m.IsPreferred()
select m.Title).FirstOrDefault();
public bool IsReady => ReadyState == DocumentReadyState.Complete;
public bool IsLoading => ReadyState == DocumentReadyState.Loading;
internal MutationHost Mutations => _mutations;
internal IConfiguration Options => _context.Configuration;
internal QuirksMode QuirksMode {
get {
return _quirksMode;
}
set {
_quirksMode = value;
}
}
internal Sandboxes ActiveSandboxing {
get {
return _sandbox;
}
set {
_sandbox = value;
}
}
internal bool IsInBrowsingContext => _context.Active != null;
internal bool IsToBePrinted => false;
internal IElement FocusElement => _focus;
internal IResourceLoader Loader => _loader;
public event DomEventHandler ReadyStateChanged {
add {
AddEventListener(EventNames.ReadyStateChanged, value, false);
}
remove {
RemoveEventListener(EventNames.ReadyStateChanged, value, false);
}
}
public event DomEventHandler Aborted {
add {
AddEventListener(EventNames.Abort, value, false);
}
remove {
RemoveEventListener(EventNames.Abort, value, false);
}
}
public event DomEventHandler Blurred {
add {
AddEventListener(EventNames.Blur, value, false);
}
remove {
RemoveEventListener(EventNames.Blur, value, false);
}
}
public event DomEventHandler Cancelled {
add {
AddEventListener(EventNames.Cancel, value, false);
}
remove {
RemoveEventListener(EventNames.Cancel, value, false);
}
}
public event DomEventHandler CanPlay {
add {
AddEventListener(EventNames.CanPlay, value, false);
}
remove {
RemoveEventListener(EventNames.CanPlay, value, false);
}
}
public event DomEventHandler CanPlayThrough {
add {
AddEventListener(EventNames.CanPlayThrough, value, false);
}
remove {
RemoveEventListener(EventNames.CanPlayThrough, value, false);
}
}
public event DomEventHandler Changed {
add {
AddEventListener(EventNames.Change, value, false);
}
remove {
RemoveEventListener(EventNames.Change, value, false);
}
}
public event DomEventHandler Clicked {
add {
AddEventListener(EventNames.Click, value, false);
}
remove {
RemoveEventListener(EventNames.Click, value, false);
}
}
public event DomEventHandler CueChanged {
add {
AddEventListener(EventNames.CueChange, value, false);
}
remove {
RemoveEventListener(EventNames.CueChange, value, false);
}
}
public event DomEventHandler DoubleClick {
add {
AddEventListener(EventNames.DblClick, value, false);
}
remove {
RemoveEventListener(EventNames.DblClick, value, false);
}
}
public event DomEventHandler Drag {
add {
AddEventListener(EventNames.Drag, value, false);
}
remove {
RemoveEventListener(EventNames.Drag, value, false);
}
}
public event DomEventHandler DragEnd {
add {
AddEventListener(EventNames.DragEnd, value, false);
}
remove {
RemoveEventListener(EventNames.DragEnd, value, false);
}
}
public event DomEventHandler DragEnter {
add {
AddEventListener(EventNames.DragEnter, value, false);
}
remove {
RemoveEventListener(EventNames.DragEnter, value, false);
}
}
public event DomEventHandler DragExit {
add {
AddEventListener(EventNames.DragExit, value, false);
}
remove {
RemoveEventListener(EventNames.DragExit, value, false);
}
}
public event DomEventHandler DragLeave {
add {
AddEventListener(EventNames.DragLeave, value, false);
}
remove {
RemoveEventListener(EventNames.DragLeave, value, false);
}
}
public event DomEventHandler DragOver {
add {
AddEventListener(EventNames.DragOver, value, false);
}
remove {
RemoveEventListener(EventNames.DragOver, value, false);
}
}
public event DomEventHandler DragStart {
add {
AddEventListener(EventNames.DragStart, value, false);
}
remove {
RemoveEventListener(EventNames.DragStart, value, false);
}
}
public event DomEventHandler Dropped {
add {
AddEventListener(EventNames.Drop, value, false);
}
remove {
RemoveEventListener(EventNames.Drop, value, false);
}
}
public event DomEventHandler DurationChanged {
add {
AddEventListener(EventNames.DurationChange, value, false);
}
remove {
RemoveEventListener(EventNames.DurationChange, value, false);
}
}
public event DomEventHandler Emptied {
add {
AddEventListener(EventNames.Emptied, value, false);
}
remove {
RemoveEventListener(EventNames.Emptied, value, false);
}
}
public event DomEventHandler Ended {
add {
AddEventListener(EventNames.Ended, value, false);
}
remove {
RemoveEventListener(EventNames.Ended, value, false);
}
}
public event DomEventHandler Error {
add {
AddEventListener(EventNames.Error, value, false);
}
remove {
RemoveEventListener(EventNames.Error, value, false);
}
}
public event DomEventHandler Focused {
add {
AddEventListener(EventNames.Focus, value, false);
}
remove {
RemoveEventListener(EventNames.Focus, value, false);
}
}
public event DomEventHandler Input {
add {
AddEventListener(EventNames.Input, value, false);
}
remove {
RemoveEventListener(EventNames.Input, value, false);
}
}
public event DomEventHandler Invalid {
add {
AddEventListener(EventNames.Invalid, value, false);
}
remove {
RemoveEventListener(EventNames.Invalid, value, false);
}
}
public event DomEventHandler KeyDown {
add {
AddEventListener(EventNames.Keydown, value, false);
}
remove {
RemoveEventListener(EventNames.Keydown, value, false);
}
}
public event DomEventHandler KeyPress {
add {
AddEventListener(EventNames.Keypress, value, false);
}
remove {
RemoveEventListener(EventNames.Keypress, value, false);
}
}
public event DomEventHandler KeyUp {
add {
AddEventListener(EventNames.Keyup, value, false);
}
remove {
RemoveEventListener(EventNames.Keyup, value, false);
}
}
public event DomEventHandler Loaded {
add {
AddEventListener(EventNames.Load, value, false);
}
remove {
RemoveEventListener(EventNames.Load, value, false);
}
}
public event DomEventHandler LoadedData {
add {
AddEventListener(EventNames.LoadedData, value, false);
}
remove {
RemoveEventListener(EventNames.LoadedData, value, false);
}
}
public event DomEventHandler LoadedMetadata {
add {
AddEventListener(EventNames.LoadedMetaData, value, false);
}
remove {
RemoveEventListener(EventNames.LoadedMetaData, value, false);
}
}
public event DomEventHandler Loading {
add {
AddEventListener(EventNames.LoadStart, value, false);
}
remove {
RemoveEventListener(EventNames.LoadStart, value, false);
}
}
public event DomEventHandler MouseDown {
add {
AddEventListener(EventNames.Mousedown, value, false);
}
remove {
RemoveEventListener(EventNames.Mousedown, value, false);
}
}
public event DomEventHandler MouseEnter {
add {
AddEventListener(EventNames.Mouseenter, value, false);
}
remove {
RemoveEventListener(EventNames.Mouseenter, value, false);
}
}
public event DomEventHandler MouseLeave {
add {
AddEventListener(EventNames.Mouseleave, value, false);
}
remove {
RemoveEventListener(EventNames.Mouseleave, value, false);
}
}
public event DomEventHandler MouseMove {
add {
AddEventListener(EventNames.Mousemove, value, false);
}
remove {
RemoveEventListener(EventNames.Mousemove, value, false);
}
}
public event DomEventHandler MouseOut {
add {
AddEventListener(EventNames.Mouseout, value, false);
}
remove {
RemoveEventListener(EventNames.Mouseout, value, false);
}
}
public event DomEventHandler MouseOver {
add {
AddEventListener(EventNames.Mouseover, value, false);
}
remove {
RemoveEventListener(EventNames.Mouseover, value, false);
}
}
public event DomEventHandler MouseUp {
add {
AddEventListener(EventNames.Mouseup, value, false);
}
remove {
RemoveEventListener(EventNames.Mouseup, value, false);
}
}
public event DomEventHandler MouseWheel {
add {
AddEventListener(EventNames.Wheel, value, false);
}
remove {
RemoveEventListener(EventNames.Wheel, value, false);
}
}
public event DomEventHandler Paused {
add {
AddEventListener(EventNames.Pause, value, false);
}
remove {
RemoveEventListener(EventNames.Pause, value, false);
}
}
public event DomEventHandler Played {
add {
AddEventListener(EventNames.Play, value, false);
}
remove {
RemoveEventListener(EventNames.Play, value, false);
}
}
public event DomEventHandler Playing {
add {
AddEventListener(EventNames.Playing, value, false);
}
remove {
RemoveEventListener(EventNames.Playing, value, false);
}
}
public event DomEventHandler Progress {
add {
AddEventListener(EventNames.Progress, value, false);
}
remove {
RemoveEventListener(EventNames.Progress, value, false);
}
}
public event DomEventHandler RateChanged {
add {
AddEventListener(EventNames.RateChange, value, false);
}
remove {
RemoveEventListener(EventNames.RateChange, value, false);
}
}
public event DomEventHandler Resetted {
add {
AddEventListener(EventNames.Reset, value, false);
}
remove {
RemoveEventListener(EventNames.Reset, value, false);
}
}
public event DomEventHandler Resized {
add {
AddEventListener(EventNames.Resize, value, false);
}
remove {
RemoveEventListener(EventNames.Resize, value, false);
}
}
public event DomEventHandler Scrolled {
add {
AddEventListener(EventNames.Scroll, value, false);
}
remove {
RemoveEventListener(EventNames.Scroll, value, false);
}
}
public event DomEventHandler Seeked {
add {
AddEventListener(EventNames.Seeked, value, false);
}
remove {
RemoveEventListener(EventNames.Seeked, value, false);
}
}
public event DomEventHandler Seeking {
add {
AddEventListener(EventNames.Seeking, value, false);
}
remove {
RemoveEventListener(EventNames.Seeking, value, false);
}
}
public event DomEventHandler Selected {
add {
AddEventListener(EventNames.Select, value, false);
}
remove {
RemoveEventListener(EventNames.Select, value, false);
}
}
public event DomEventHandler Shown {
add {
AddEventListener(EventNames.Show, value, false);
}
remove {
RemoveEventListener(EventNames.Show, value, false);
}
}
public event DomEventHandler Stalled {
add {
AddEventListener(EventNames.Stalled, value, false);
}
remove {
RemoveEventListener(EventNames.Stalled, value, false);
}
}
public event DomEventHandler Submitted {
add {
AddEventListener(EventNames.Submit, value, false);
}
remove {
RemoveEventListener(EventNames.Submit, value, false);
}
}
public event DomEventHandler Suspended {
add {
AddEventListener(EventNames.Suspend, value, false);
}
remove {
RemoveEventListener(EventNames.Suspend, value, false);
}
}
public event DomEventHandler TimeUpdated {
add {
AddEventListener(EventNames.TimeUpdate, value, false);
}
remove {
RemoveEventListener(EventNames.TimeUpdate, value, false);
}
}
public event DomEventHandler Toggled {
add {
AddEventListener(EventNames.Toggle, value, false);
}
remove {
RemoveEventListener(EventNames.Toggle, value, false);
}
}
public event DomEventHandler VolumeChanged {
add {
AddEventListener(EventNames.VolumeChange, value, false);
}
remove {
RemoveEventListener(EventNames.VolumeChange, value, false);
}
}
public event DomEventHandler Waiting {
add {
AddEventListener(EventNames.Waiting, value, false);
}
remove {
RemoveEventListener(EventNames.Waiting, value, false);
}
}
internal Document(IBrowsingContext context, TextSource source)
: base(null, "#document", NodeType.Document, NodeFlags.None)
{
AttachedReferences.Add(this, new List<WeakReference>());
Referrer = string.Empty;
ContentType = MimeTypeNames.ApplicationXml;
_async = true;
_designMode = false;
_firedUnload = false;
_salvageable = true;
_shown = false;
_context = context;
_source = source;
_ready = DocumentReadyState.Loading;
_sandbox = Sandboxes.None;
_quirksMode = QuirksMode.Off;
_loadingScripts = new Queue<HtmlScriptElement>();
_location = new Location("about:blank");
_location.Changed += LocationChanged;
_view = new Window(this);
_loader = context.CreateService<IResourceLoader>();
_loop = context.CreateService<IEventLoop>();
_mutations = new MutationHost(_loop);
_statusCode = HttpStatusCode.OK;
}
internal void AddScript(HtmlScriptElement script)
{
_loadingScripts.Enqueue(script);
}
public void Dispose()
{
ReplaceAll(null, true);
_loop.CancelAll();
_loadingScripts.Clear();
_source.Dispose();
}
public void EnableStyleSheetsForSet(string name)
{
if (name != null)
StyleSheets.EnableStyleSheetSet(name);
}
public IDocument Open(string type = "text/html", string replace = null)
{
if (!ContentType.Is(MimeTypeNames.Html))
throw new DomException(DomError.InvalidState);
if (!IsInBrowsingContext || _context.Active == this) {
IDocument document = _context?.Parent.Active;
if (document != null && !document.Origin.Is(Origin))
throw new DomException(DomError.Security);
if (!_firedUnload && _loadingScripts.Count == 0) {
bool num = replace.Isi(Keywords.Replace);
IHistory sessionHistory = _context.SessionHistory;
int num2 = type?.IndexOf(';') ?? (-1);
if (!num && sessionHistory != null) {
bool num3 = sessionHistory.Length == 1 && sessionHistory[0].Url.Is("about:blank");
}
_salvageable = false;
if (!PromptToUnloadAsync().Result)
return this;
Unload(true);
Abort(false);
RemoveEventListeners();
foreach (Element item in this.Descendents<Element>()) {
item.RemoveEventListeners();
}
_loop.CancelAll();
ReplaceAll(null, true);
_source.CurrentEncoding = TextEncoding.Utf8;
_salvageable = true;
_ready = DocumentReadyState.Loading;
if (type.Isi(Keywords.Replace))
type = MimeTypeNames.Html;
else if (num2 >= 0) {
type = type.Substring(0, num2);
}
type = type.StripLeadingTrailingSpaces();
type.Isi(MimeTypeNames.Html);
ContentType = type;
_firedUnload = false;
_source.Index = _source.Length;
}
return this;
}
return null;
}
public void Load(string url)
{
Location.Href = url;
}
void IDocument.Close()
{
if (IsLoading)
FinishLoadingAsync().Wait();
}
public void Write(string content)
{
if (IsReady) {
string content2 = content ?? string.Empty;
Open("text/html", null).Write(content2);
} else
_source.InsertText(content);
}
public void WriteLine(string content)
{
Write(content + "\n");
}
public IHtmlCollection<IElement> GetElementsByName(string name)
{
List<IElement> list = new List<IElement>();
base.ChildNodes.GetElementsByName(name, list);
return new HtmlCollection<IElement>(list);
}
public INode Import(INode externalNode, bool deep = true)
{
if (externalNode.NodeType == NodeType.Document)
throw new DomException(DomError.NotSupported);
return externalNode.Clone(deep);
}
public INode Adopt(INode externalNode)
{
if (externalNode.NodeType == NodeType.Document)
throw new DomException(DomError.NotSupported);
this.AdoptNode(externalNode);
return externalNode;
}
public Event CreateEvent(string type)
{
Event event = Options.GetFactory<IEventFactory>().Create(type);
if (event == null)
throw new DomException(DomError.NotSupported);
return event;
}
public INodeIterator CreateNodeIterator(INode root, FilterSettings settings = FilterSettings.All, NodeFilter filter = null)
{
return new NodeIterator(root, settings, filter);
}
public ITreeWalker CreateTreeWalker(INode root, FilterSettings settings = FilterSettings.All, NodeFilter filter = null)
{
return new TreeWalker(root, settings, filter);
}
public IRange CreateRange()
{
AngleSharp.Dom.Collections.Range range = new AngleSharp.Dom.Collections.Range(this);
AttachReference(range);
return range;
}
public void Prepend(params INode[] nodes)
{
this.PrependNodes(nodes);
}
public void Append(params INode[] nodes)
{
this.AppendNodes(nodes);
}
public IElement CreateElement(string localName)
{
if (localName.IsXmlName()) {
HtmlElement htmlElement = Options.GetFactory<IElementFactory<HtmlElement>>().Create(this, localName, null);
htmlElement.SetupElement();
return htmlElement;
}
throw new DomException(DomError.InvalidCharacter);
}
public IElement CreateElement(string namespaceUri, string qualifiedName)
{
string localName = null;
string prefix = null;
Node.GetPrefixAndLocalName(qualifiedName, ref namespaceUri, out prefix, out localName);
if (namespaceUri.Is(NamespaceNames.HtmlUri)) {
HtmlElement htmlElement = Options.GetFactory<IElementFactory<HtmlElement>>().Create(this, localName, prefix);
htmlElement.SetupElement();
return htmlElement;
}
if (namespaceUri.Is(NamespaceNames.SvgUri)) {
SvgElement svgElement = Options.GetFactory<IElementFactory<SvgElement>>().Create(this, localName, prefix);
svgElement.SetupElement();
return svgElement;
}
if (namespaceUri.Is(NamespaceNames.MathMlUri)) {
MathElement mathElement = Options.GetFactory<IElementFactory<MathElement>>().Create(this, localName, prefix);
mathElement.SetupElement();
return mathElement;
}
Element element = new Element(this, localName, prefix, namespaceUri, NodeFlags.None);
element.SetupElement();
return element;
}
public IComment CreateComment(string data)
{
return new Comment(this, data);
}
public IDocumentFragment CreateDocumentFragment()
{
return new DocumentFragment(this);
}
public IProcessingInstruction CreateProcessingInstruction(string target, string data)
{
if (!target.IsXmlName() || data.Contains("?>"))
throw new DomException(DomError.InvalidCharacter);
return new ProcessingInstruction(this, target) {
Data = data
};
}
public IText CreateTextNode(string data)
{
return new TextNode(this, data);
}
public IElement GetElementById(string elementId)
{
return base.ChildNodes.GetElementById(elementId);
}
public IElement QuerySelector(string selectors)
{
return base.ChildNodes.QuerySelector(selectors);
}
public IHtmlCollection<IElement> QuerySelectorAll(string selectors)
{
return base.ChildNodes.QuerySelectorAll(selectors);
}
public IHtmlCollection<IElement> GetElementsByClassName(string classNames)
{
return base.ChildNodes.GetElementsByClassName(classNames);
}
public IHtmlCollection<IElement> GetElementsByTagName(string tagName)
{
return base.ChildNodes.GetElementsByTagName(tagName);
}
public IHtmlCollection<IElement> GetElementsByTagName(string namespaceURI, string tagName)
{
return base.ChildNodes.GetElementsByTagName(namespaceURI, tagName);
}
public abstract override INode Clone(bool deep = true);
public override void ToHtml(TextWriter writer, IMarkupFormatter formatter)
{
base.ChildNodes.ToHtml(writer, formatter);
}
public bool HasFocus()
{
return _context.Active == this;
}
public IAttr CreateAttribute(string localName)
{
if (!localName.IsXmlName())
throw new DomException(DomError.InvalidCharacter);
return new Attr(localName);
}
public IAttr CreateAttribute(string namespaceUri, string qualifiedName)
{
string localName = null;
string prefix = null;
Node.GetPrefixAndLocalName(qualifiedName, ref namespaceUri, out prefix, out localName);
return new Attr(prefix, localName, string.Empty, namespaceUri);
}
internal IEnumerable<T> GetAttachedReferences<T>() where T : class
{
List<WeakReference> value = null;
AttachedReferences.TryGetValue(this, out value);
return from m in value.Select(delegate(WeakReference entry) {
if (!entry.IsAlive)
return null;
return entry.Target as T;
})
where m != null
select m;
}
internal void AttachReference(object value)
{
List<WeakReference> value2 = null;
AttachedReferences.TryGetValue(this, out value2);
value2.Add(new WeakReference(value));
}
internal void DelayLoad(Task task)
{
if (!IsReady && task != null && !task.IsCompleted)
AttachReference(task);
}
internal void SetFocus(IElement element)
{
_focus = element;
}
internal async Task FinishLoadingAsync()
{
Task[] tasks = GetAttachedReferences<Task>().ToArray();
ReadyState = DocumentReadyState.Interactive;
while (_loadingScripts.Count > 0) {
await this.WaitForReadyAsync().ConfigureAwait(false);
await _loadingScripts.Dequeue().RunAsync(CancellationToken.None).ConfigureAwait(false);
}
this.QueueTask(RaiseDomContentLoaded);
await TaskEx.WhenAll(tasks).ConfigureAwait(false);
this.QueueTask(RaiseLoadedEvent);
if (IsInBrowsingContext)
this.QueueTask(ShowPage);
this.QueueTask(EmptyAppCache);
if (IsToBePrinted)
await PrintAsync().ConfigureAwait(false);
}
internal async Task<bool> PromptToUnloadAsync()
{
IEnumerable<IBrowsingContext> descendants = GetAttachedReferences<IBrowsingContext>();
if (_view.HasEventListener(EventNames.BeforeUnload)) {
Event eventData = new Event(EventNames.BeforeUnload, false, true);
bool num = _view.Fire(eventData);
_salvageable = false;
if (num) {
var data = new {
Document = this,
IsCancelled = true
};
await _context.FireAsync(EventNames.ConfirmUnload, data).ConfigureAwait(false);
if (data.IsCancelled)
return false;
}
}
foreach (IBrowsingContext item in descendants) {
Document active = item.Active as Document;
if (active != null) {
if (!(await active.PromptToUnloadAsync().ConfigureAwait(false)))
return false;
_salvageable = (_salvageable && active._salvageable);
}
}
return true;
}
internal void Unload(bool recycle)
{
IEnumerable<IBrowsingContext> attachedReferences = GetAttachedReferences<IBrowsingContext>();
if (_shown) {
_shown = false;
this.Fire(delegate(PageTransitionEvent ev) {
ev.Init(EventNames.PageHide, false, false, _salvageable);
}, _view);
}
if (_view.HasEventListener(EventNames.Unload)) {
if (!_firedUnload) {
_view.FireSimpleEvent(EventNames.Unload, false, false);
_firedUnload = true;
}
_salvageable = false;
}
CancelTasks();
foreach (IBrowsingContext item in attachedReferences) {
Document document = item.Active as Document;
if (document != null) {
document.Unload(false);
_salvageable = (_salvageable && document._salvageable);
}
}
if (!recycle && !_salvageable && _context.Active == this)
_context.Active = null;
}
bool IDocument.ExecuteCommand(string commandId, bool showUserInterface, string value)
{
return Options.GetCommand(commandId)?.Execute(this, showUserInterface, value) ?? false;
}
bool IDocument.IsCommandEnabled(string commandId)
{
return Options.GetCommand(commandId)?.IsEnabled(this) ?? false;
}
bool IDocument.IsCommandIndeterminate(string commandId)
{
return Options.GetCommand(commandId)?.IsIndeterminate(this) ?? false;
}
bool IDocument.IsCommandExecuted(string commandId)
{
return Options.GetCommand(commandId)?.IsExecuted(this) ?? false;
}
bool IDocument.IsCommandSupported(string commandId)
{
return Options.GetCommand(commandId)?.IsSupported(this) ?? false;
}
string IDocument.GetCommandValue(string commandId)
{
return Options.GetCommand(commandId)?.GetValue(this);
}
private void Abort(bool fromUser = false)
{
if (fromUser && _context.Active == this)
this.QueueTask(delegate {
_view.FireSimpleEvent(EventNames.Abort, false, false);
});
foreach (IBrowsingContext attachedReference in GetAttachedReferences<IBrowsingContext>()) {
Document document = attachedReference.Active as Document;
if (document != null) {
document.Abort(false);
_salvageable = (_salvageable && document._salvageable);
}
}
foreach (IDownload item in from m in _loader.GetDownloads()
where !m.IsCompleted
select m) {
item.Cancel();
_salvageable = false;
}
}
private void CancelTasks()
{
foreach (CancellationTokenSource attachedReference in GetAttachedReferences<CancellationTokenSource>()) {
if (!attachedReference.IsCancellationRequested)
attachedReference.Cancel();
}
}
private static bool IsCommand(IElement element)
{
if (!(element is IHtmlMenuItemElement) && !(element is IHtmlButtonElement))
return element is IHtmlAnchorElement;
return true;
}
private static bool IsLink(IElement element)
{
if (element is IHtmlAnchorElement || element is IHtmlAreaElement)
return element.Attributes.Any((IAttr m) => m.Name.Is(AttributeNames.Href));
return false;
}
private static bool IsAnchor(IHtmlAnchorElement element)
{
return element.Attributes.Any((IAttr m) => m.Name.Is(AttributeNames.Name));
}
private void RaiseDomContentLoaded()
{
this.FireSimpleEvent(EventNames.DomContentLoaded, false, false);
}
private void RaiseLoadedEvent()
{
ReadyState = DocumentReadyState.Complete;
this.FireSimpleEvent(EventNames.Load, false, false);
}
private void EmptyAppCache()
{
}
private async Task PrintAsync()
{
var data = new {
Document = this
};
this.FireSimpleEvent(EventNames.BeforePrint, false, false);
await _context.FireAsync(EventNames.Print, data).ConfigureAwait(false);
this.FireSimpleEvent(EventNames.AfterPrint, false, false);
}
private void ShowPage()
{
if (!_shown) {
_shown = true;
this.Fire(delegate(PageTransitionEvent ev) {
ev.Init(EventNames.PageShow, false, false, false);
}, _view);
}
}
private async void LocationChanged(object sender, Location.LocationChangedEventArgs e)
{
if (e.IsHashChanged) {
HashChangedEvent hashChangedEvent = new HashChangedEvent();
hashChangedEvent.Init(EventNames.HashChange, false, false, e.PreviousLocation, e.CurrentLocation);
hashChangedEvent.IsTrusted = true;
hashChangedEvent.Dispatch(this);
} else {
DocumentRequest request = DocumentRequest.Get(new Url(e.CurrentLocation), this, DocumentUri);
await _context.OpenAsync(request, CancellationToken.None);
}
}
protected void Setup(CreateDocumentOptions options)
{
ContentType = options.ContentType.Content;
StatusCode = options.Response.StatusCode;
Referrer = options.Response.Headers.GetOrDefault(HeaderNames.Referer, string.Empty);
DocumentUri = options.Response.Address.Href;
Cookie = options.Response.Headers.GetOrDefault(HeaderNames.SetCookie, string.Empty);
ImportAncestor = options.ImportAncestor;
ReadyState = DocumentReadyState.Loading;
}
protected sealed override string LocateNamespace(string prefix)
{
IElement documentElement = DocumentElement;
if (documentElement == null)
return null;
return documentElement.LocateNamespaceFor(prefix);
}
protected sealed override string LocatePrefix(string namespaceUri)
{
IElement documentElement = DocumentElement;
if (documentElement == null)
return null;
return documentElement.LocatePrefixFor(namespaceUri);
}
protected void CloneDocument(Document document, bool deep)
{
CloneNode(document, deep);
document._ready = _ready;
document.Referrer = Referrer;
document._location.Href = _location.Href;
document._quirksMode = _quirksMode;
document._sandbox = _sandbox;
document._async = _async;
document.ContentType = ContentType;
}
protected virtual string GetTitle()
{
return string.Empty;
}
protected abstract void SetTitle(string value);
}
}