Auto merge of #24576 - jaymodi98:iframe-srcdoc, r=jdm

Implement srcdoc support for iframes

<!-- Please describe your changes on the following line: -->
This PR contains changes related to adding srcdoc attribute parsing support for iframes in Servo. The following changes have been made:

- uncomment the [srcdoc](f63b404e0c/components/script/dom/webidls/HTMLIFrameElement.webidl (L10-L11)) WebIDL attribute, and implement the attribute getter.
- add a field to [LoadData](e6b271d329/components/script_traits/lib.rs (L137-L164)) for storing the srcdoc contents when loading a srcdoc iframe.
- (partially) implemented a new `page_load_about_srcdoc` method to `script_thread.rs` which loads the special `about:srcdoc` URL [per the specification](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#process-the-iframe-attributes) and takes the srcdoc contents as an argument
- call this new method from [handle_new_layout](e6b271d329/components/script/script_thread.rs (L2409-L2412)) when it's detected that a srcdoc iframe is being loaded
- (partially) in [attribute_mutated](e6b271d329/components/script/dom/htmliframeelement.rs (L560)), ensure that changing the `srcdoc` attribute of an iframe element [follows the specification](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:the-iframe-element-9).

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes are a part of fix #4767  (GitHub issue number if applicable)

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
bors-servo 2019-11-12 14:29:20 -05:00 committed by GitHub
commit bd0ae59ca9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 123 additions and 176 deletions

View file

@ -130,10 +130,12 @@ impl HTMLIFrameElement {
let document = document_from_node(self);
let mut load_blocker = self.load_blocker.borrow_mut();
// Any oustanding load is finished from the point of view of the blocked
// document; the new navigation will continue blocking it.
LoadBlocker::terminate(&mut load_blocker);
{
let mut load_blocker = self.load_blocker.borrow_mut();
// Any oustanding load is finished from the point of view of the blocked
// document; the new navigation will continue blocking it.
LoadBlocker::terminate(&mut load_blocker);
}
if load_data.url.scheme() == "javascript" {
let window_proxy = self.GetContentWindow();
@ -150,6 +152,7 @@ impl HTMLIFrameElement {
match load_data.js_eval_result {
Some(JsEvalResult::NoContent) => (),
_ => {
let mut load_blocker = self.load_blocker.borrow_mut();
*load_blocker = Some(LoadBlocker::new(
&*document,
LoadType::Subframe(load_data.url.clone()),
@ -229,7 +232,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 +506,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 +612,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() {

View file

@ -9,8 +9,8 @@ interface HTMLIFrameElement : HTMLElement {
[CEReactions]
attribute USVString src;
// [CEReactions]
// attribute DOMString srcdoc;
[CEReactions]
attribute DOMString srcdoc;
[CEReactions]
attribute DOMString name;

View file

@ -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,

View file

@ -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(),
}
}
}