aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorjaymodi98 <jaymodi98@gmail.com>2019-10-28 17:21:45 -0400
committerJosh Matthews <josh@joshmatthews.net>2019-11-12 13:57:54 -0500
commitbf69b6fea7c7eed2ba3b96e5c77573f25b7929ed (patch)
treefb0632e7edc62d80dcd133ef9adeb1b093c923ce /components
parent944c1e9f976a4daf5ba640d889f0b00a06d15a17 (diff)
downloadservo-bf69b6fea7c7eed2ba3b96e5c77573f25b7929ed.tar.gz
servo-bf69b6fea7c7eed2ba3b96e5c77573f25b7929ed.zip
Implement srcdoc support for iframes.
Diffstat (limited to 'components')
-rw-r--r--components/script/dom/htmliframeelement.rs49
-rw-r--r--components/script/dom/webidls/HTMLIFrameElement.webidl4
-rw-r--r--components/script/script_thread.rs24
-rw-r--r--components/script_traits/lib.rs4
4 files changed, 76 insertions, 5 deletions
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index e58e65ea5bb..df94aeb361c 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -229,7 +229,30 @@ impl HTMLIFrameElement {
/// <https://html.spec.whatwg.org/multipage/#process-the-iframe-attributes>
fn process_the_iframe_attributes(&self, mode: ProcessingMode) {
- // TODO: srcdoc
+ if self
+ .upcast::<Element>()
+ .has_attribute(&local_name!("srcdoc"))
+ {
+ let url = ServoUrl::parse("about:srcdoc").unwrap();
+ let document = document_from_node(self);
+ let window = window_from_node(self);
+ let pipeline_id = Some(window.upcast::<GlobalScope>().pipeline_id());
+ let mut load_data = LoadData::new(
+ LoadOrigin::Script(document.origin().immutable().clone()),
+ url,
+ pipeline_id,
+ Some(Referrer::ReferrerUrl(document.url())),
+ document.get_referrer_policy(),
+ );
+ let element = self.upcast::<Element>();
+ load_data.srcdoc = String::from(element.get_string_attribute(&local_name!("srcdoc")));
+ self.navigate_or_reload_child_browsing_context(
+ load_data,
+ NavigationType::InitialAboutBlank,
+ HistoryEntryReplacement::Disabled,
+ );
+ return;
+ }
let window = window_from_node(self);
@@ -480,6 +503,12 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
// https://html.spec.whatwg.org/multipage/#dom-iframe-src
make_url_setter!(SetSrc, "src");
+ // https://html.spec.whatwg.org/multipage/#dom-iframe-srcdoc
+ make_getter!(Srcdoc, "srcdoc");
+
+ // https://html.spec.whatwg.org/multipage/#dom-iframe-srcdoc
+ make_setter!(SetSrcdoc, "srcdoc");
+
// https://html.spec.whatwg.org/multipage/#dom-iframe-sandbox
fn Sandbox(&self) -> DomRoot<DOMTokenList> {
self.sandbox
@@ -580,13 +609,29 @@ impl VirtualMethods for HTMLIFrameElement {
modes
}));
},
+ &local_name!("srcdoc") => {
+ // https://html.spec.whatwg.org/multipage/#the-iframe-element:the-iframe-element-9
+ // "Whenever an iframe element with a non-null nested browsing context has its
+ // srcdoc attribute set, changed, or removed, the user agent must process the
+ // iframe attributes."
+ // but we can't check that directly, since the child browsing context
+ // may be in a different script thread. Instead, we check to see if the parent
+ // is in a document tree and has a browsing context, which is what causes
+ // the child browsing context to be created.
+
+ // trigger the processing of iframe attributes whenever "srcdoc" attribute is set, changed or removed
+ if self.upcast::<Node>().is_connected_with_browsing_context() {
+ debug!("iframe srcdoc modified while in browsing context.");
+ self.process_the_iframe_attributes(ProcessingMode::NotFirstTime);
+ }
+ },
&local_name!("src") => {
// https://html.spec.whatwg.org/multipage/#the-iframe-element
// "Similarly, whenever an iframe element with a non-null nested browsing context
// but with no srcdoc attribute specified has its src attribute set, changed, or removed,
// the user agent must process the iframe attributes,"
// but we can't check that directly, since the child browsing context
- // may be in a different script thread. Instread, we check to see if the parent
+ // may be in a different script thread. Instead, we check to see if the parent
// is in a document tree and has a browsing context, which is what causes
// the child browsing context to be created.
if self.upcast::<Node>().is_connected_with_browsing_context() {
diff --git a/components/script/dom/webidls/HTMLIFrameElement.webidl b/components/script/dom/webidls/HTMLIFrameElement.webidl
index acc4f0f201d..b9dd97bdea6 100644
--- a/components/script/dom/webidls/HTMLIFrameElement.webidl
+++ b/components/script/dom/webidls/HTMLIFrameElement.webidl
@@ -9,8 +9,8 @@ interface HTMLIFrameElement : HTMLElement {
[CEReactions]
attribute USVString src;
- // [CEReactions]
- // attribute DOMString srcdoc;
+ [CEReactions]
+ attribute DOMString srcdoc;
[CEReactions]
attribute DOMString name;
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 191df335ec5..20ac88b7bc1 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -2430,6 +2430,8 @@ impl ScriptThread {
);
if load_data.url.as_str() == "about:blank" {
self.start_page_load_about_blank(new_load, load_data.js_eval_result);
+ } else if load_data.url.as_str() == "about:srcdoc" {
+ self.page_load_about_srcdoc(new_load, load_data.srcdoc);
} else {
self.pre_page_load(new_load, load_data);
}
@@ -3177,7 +3179,8 @@ impl ScriptThread {
self.timer_event_chan.clone(),
);
- let origin = if final_url.as_str() == "about:blank" {
+ let origin = if final_url.as_str() == "about:blank" || final_url.as_str() == "about:srcdoc"
+ {
incomplete.origin.clone()
} else {
MutableOrigin::new(final_url.origin())
@@ -3838,6 +3841,25 @@ impl ScriptThread {
context.process_response_eof(Ok(ResourceFetchTiming::new(ResourceTimingType::None)));
}
+ /// Synchronously parse a srcdoc document from a giving HTML string.
+ fn page_load_about_srcdoc(&self, incomplete: InProgressLoad, src_doc: String) {
+ let id = incomplete.pipeline_id;
+
+ self.incomplete_loads.borrow_mut().push(incomplete);
+
+ let url = ServoUrl::parse("about:srcdoc").unwrap();
+ let mut context = ParserContext::new(id, url.clone());
+
+ let mut meta = Metadata::default(url);
+ meta.set_content_type(Some(&mime::TEXT_HTML));
+
+ let chunk = src_doc.into_bytes();
+
+ context.process_response(Ok(FetchMetadata::Unfiltered(meta)));
+ context.process_response_chunk(chunk);
+ context.process_response_eof(Ok(ResourceFetchTiming::new(ResourceTimingType::None)));
+ }
+
fn handle_css_error_reporting(
&self,
pipeline_id: PipelineId,
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 468cfb19fb3..1b1a0e80e65 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -163,6 +163,9 @@ pub struct LoadData {
pub referrer: Option<Referrer>,
/// The referrer policy.
pub referrer_policy: Option<ReferrerPolicy>,
+
+ /// The source to use instead of a network response for a srcdoc document.
+ pub srcdoc: String,
}
/// The result of evaluating a javascript scheme url.
@@ -194,6 +197,7 @@ impl LoadData {
js_eval_result: None,
referrer: referrer,
referrer_policy: referrer_policy,
+ srcdoc: "".to_string(),
}
}
}