diff options
author | Josh Matthews <josh@joshmatthews.net> | 2015-07-20 16:15:13 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2016-02-10 09:20:00 -0500 |
commit | e9b98ad5fa5380096700712839cc49edf46d2e93 (patch) | |
tree | 57ad73c327ffe952579de122df6baf5fd2658724 /components/script/dom/htmliframeelement.rs | |
parent | fc3f93235e9264a6379e370b635ae8a98e41a1be (diff) | |
download | servo-e9b98ad5fa5380096700712839cc49edf46d2e93.tar.gz servo-e9b98ad5fa5380096700712839cc49edf46d2e93.zip |
Make iframes block the enclosing document's load event. Fixes #6663.
Diffstat (limited to 'components/script/dom/htmliframeelement.rs')
-rw-r--r-- | components/script/dom/htmliframeelement.rs | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 2221147ecad..630b36e14e9 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -2,7 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use document_loader::{LoadType, LoadBlocker}; use dom::attr::{Attr, AttrValue}; +use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserElementIconChangeEventDetail; use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserElementSecurityChangeDetail; use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserShowModalPromptEventDetail; @@ -21,7 +23,7 @@ use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers}; use dom::event::Event; use dom::eventtarget::EventTarget; use dom::htmlelement::HTMLElement; -use dom::node::{Node, UnbindContext, window_from_node}; +use dom::node::{Node, UnbindContext, window_from_node, document_from_node}; use dom::urlhelper::UrlHelper; use dom::virtualmethods::VirtualMethods; use dom::window::{ReflowReason, Window}; @@ -64,6 +66,7 @@ pub struct HTMLIFrameElement { subpage_id: Cell<Option<SubpageId>>, containing_page_pipeline_id: Cell<Option<PipelineId>>, sandbox: Cell<Option<u8>>, + load_blocker: DOMRefCell<Option<LoadBlocker>>, } impl HTMLIFrameElement { @@ -101,6 +104,20 @@ impl HTMLIFrameElement { IFrameUnsandboxed }; + 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); + + //TODO(#9592): Deal with the case where an iframe is being reloaded so url is None. + // The iframe should always have access to the nested context's active + // document URL through the browsing context. + if let Some(ref url) = url { + *load_blocker = Some(LoadBlocker::new(&*document, LoadType::Subframe(url.clone()))); + } + let window = window_from_node(self); let window = window.r(); let (new_subpage_id, old_subpage_id) = self.generate_new_subpage_id(); @@ -173,6 +190,7 @@ impl HTMLIFrameElement { subpage_id: Cell::new(None), containing_page_pipeline_id: Cell::new(None), sandbox: Cell::new(None), + load_blocker: DOMRefCell::new(None), } } @@ -204,7 +222,11 @@ impl HTMLIFrameElement { } /// https://html.spec.whatwg.org/multipage/#iframe-load-event-steps steps 1-4 - pub fn iframe_load_event_steps(&self) { + pub fn iframe_load_event_steps(&self, loaded_pipeline: PipelineId) { + // TODO(#9592): assert that the load blocker is present at all times when we + // can guarantee that it's created for the case of iframe.reload(). + assert_eq!(loaded_pipeline, self.pipeline().unwrap()); + // TODO A cross-origin child document would not be easily accessible // from this script thread. It's unclear how to implement // steps 2, 3, and 5 efficiently in this case. @@ -213,6 +235,10 @@ impl HTMLIFrameElement { // Step 4 self.upcast::<EventTarget>().fire_simple_event("load"); + + let mut blocker = self.load_blocker.borrow_mut(); + LoadBlocker::terminate(&mut blocker); + // TODO Step 5 - unset child document `mut iframe load` flag let window = window_from_node(self); @@ -510,6 +536,9 @@ impl VirtualMethods for HTMLIFrameElement { fn unbind_from_tree(&self, context: &UnbindContext) { self.super_type().unwrap().unbind_from_tree(context); + let mut blocker = self.load_blocker.borrow_mut(); + LoadBlocker::terminate(&mut blocker); + // https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded if let Some(pipeline_id) = self.pipeline_id.get() { let window = window_from_node(self); |