script/dom/
domparser.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use js::rust::HandleObject;
7use script_traits::DocumentActivity;
8
9use crate::document_loader::DocumentLoader;
10use crate::dom::bindings::codegen::Bindings::DOMParserBinding;
11use crate::dom::bindings::codegen::Bindings::DOMParserBinding::DOMParserMethods;
12use crate::dom::bindings::codegen::Bindings::DOMParserBinding::SupportedType::{
13    Application_xhtml_xml, Application_xml, Image_svg_xml, Text_html, Text_xml,
14};
15use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentReadyState;
16use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
17use crate::dom::bindings::codegen::UnionTypes::TrustedHTMLOrString;
18use crate::dom::bindings::error::Fallible;
19use crate::dom::bindings::reflector::{Reflector, reflect_dom_object_with_proto};
20use crate::dom::bindings::root::{Dom, DomRoot};
21use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
22use crate::dom::servoparser::ServoParser;
23use crate::dom::trustedhtml::TrustedHTML;
24use crate::dom::window::Window;
25use crate::script_runtime::CanGc;
26
27#[dom_struct]
28pub(crate) struct DOMParser {
29    reflector_: Reflector,
30    window: Dom<Window>, // XXXjdm Document instead?
31}
32
33impl DOMParser {
34    fn new_inherited(window: &Window) -> DOMParser {
35        DOMParser {
36            reflector_: Reflector::new(),
37            window: Dom::from_ref(window),
38        }
39    }
40
41    fn new(window: &Window, proto: Option<HandleObject>, can_gc: CanGc) -> DomRoot<DOMParser> {
42        reflect_dom_object_with_proto(
43            Box::new(DOMParser::new_inherited(window)),
44            window,
45            proto,
46            can_gc,
47        )
48    }
49}
50
51impl DOMParserMethods<crate::DomTypeHolder> for DOMParser {
52    /// <https://html.spec.whatwg.org/multipage/#dom-domparser-constructor>
53    fn Constructor(
54        window: &Window,
55        proto: Option<HandleObject>,
56        can_gc: CanGc,
57    ) -> Fallible<DomRoot<DOMParser>> {
58        Ok(DOMParser::new(window, proto, can_gc))
59    }
60
61    /// <https://html.spec.whatwg.org/multipage/#dom-domparser-parsefromstring>
62    fn ParseFromString(
63        &self,
64        s: TrustedHTMLOrString,
65        ty: DOMParserBinding::SupportedType,
66        can_gc: CanGc,
67    ) -> Fallible<DomRoot<Document>> {
68        // Step 1. Let compliantString be the result of invoking the
69        // Get Trusted Type compliant string algorithm with TrustedHTML,
70        // this's relevant global object, string, "DOMParser parseFromString", and "script".
71        let compliant_string = TrustedHTML::get_trusted_script_compliant_string(
72            self.window.as_global_scope(),
73            s,
74            "DOMParser parseFromString",
75            can_gc,
76        )?;
77        let url = self.window.get_url();
78        let content_type = ty
79            .as_str()
80            .parse()
81            .expect("Supported type is not a MIME type");
82        let doc = self.window.Document();
83        let loader = DocumentLoader::new(&doc.loader());
84        // Step 3. Switch on type:
85        let document = match ty {
86            Text_html => {
87                // Step 2. Let document be a new Document, whose content type is type
88                // and URL is this's relevant global object's associated Document's URL.
89                let document = Document::new(
90                    &self.window,
91                    HasBrowsingContext::No,
92                    Some(url.clone()),
93                    doc.origin().clone(),
94                    IsHTMLDocument::HTMLDocument,
95                    Some(content_type),
96                    None,
97                    DocumentActivity::Inactive,
98                    DocumentSource::FromParser,
99                    loader,
100                    None,
101                    None,
102                    Default::default(),
103                    false,
104                    false,
105                    Some(doc.insecure_requests_policy()),
106                    doc.has_trustworthy_ancestor_or_current_origin(),
107                    doc.custom_element_reaction_stack(),
108                    can_gc,
109                );
110                // Step switch-1. Parse HTML from a string given document and compliantString.
111                ServoParser::parse_html_document(&document, Some(compliant_string), url, can_gc);
112                document
113            },
114            Text_xml | Application_xml | Application_xhtml_xml | Image_svg_xml => {
115                // Step 2. Let document be a new Document, whose content type is type
116                // and URL is this's relevant global object's associated Document's URL.
117                let document = Document::new(
118                    &self.window,
119                    HasBrowsingContext::No,
120                    Some(url.clone()),
121                    doc.origin().clone(),
122                    IsHTMLDocument::NonHTMLDocument,
123                    Some(content_type),
124                    None,
125                    DocumentActivity::Inactive,
126                    DocumentSource::FromParser,
127                    loader,
128                    None,
129                    None,
130                    Default::default(),
131                    false,
132                    false,
133                    Some(doc.insecure_requests_policy()),
134                    doc.has_trustworthy_ancestor_or_current_origin(),
135                    doc.custom_element_reaction_stack(),
136                    can_gc,
137                );
138                // Step switch-1. Create an XML parser parser, associated with document,
139                // and with XML scripting support disabled.
140                ServoParser::parse_xml_document(&document, Some(compliant_string), url, can_gc);
141                document
142            },
143        };
144        // Step 4. Return document.
145        document.set_ready_state(DocumentReadyState::Complete, can_gc);
146        Ok(document)
147    }
148}