aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/compositing/constellation.rs16
-rw-r--r--components/msg/constellation_msg.rs2
-rw-r--r--components/script/dom/document.rs24
-rw-r--r--components/script/dom/htmliframeelement.rs25
-rw-r--r--components/script/script_task.rs12
-rw-r--r--components/script_traits/lib.rs7
6 files changed, 71 insertions, 15 deletions
diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs
index 3abb1d5a54e..22a22d459e7 100644
--- a/components/compositing/constellation.rs
+++ b/components/compositing/constellation.rs
@@ -758,6 +758,20 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
})).unwrap();
}
+ fn handle_subframe_loaded(&mut self, pipeline_id: PipelineId) {
+ let subframe_pipeline = self.pipeline(pipeline_id);
+ let subframe_parent = match subframe_pipeline.parent_info {
+ Some(ref parent) => parent,
+ None => return,
+ };
+ let parent_pipeline = self.pipeline(subframe_parent.0);
+ let msg = ConstellationControlMsg::DispatchFrameLoadEvent {
+ target: pipeline_id,
+ parent: subframe_parent.0
+ };
+ parent_pipeline.script_chan.send(msg).unwrap();
+ }
+
// The script task associated with pipeline_id has loaded a URL in an iframe via script. This
// will result in a new pipeline being spawned and a frame tree being added to
// containing_page_pipeline_id's frame tree's children. This message is never the result of a
@@ -908,6 +922,8 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
if webdriver_reset {
self.webdriver.load_channel = None;
}
+
+ self.handle_subframe_loaded(pipeline_id);
}
fn handle_navigate_msg(&mut self,
diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs
index af44eac4c1b..027d8efddd8 100644
--- a/components/msg/constellation_msg.rs
+++ b/components/msg/constellation_msg.rs
@@ -277,6 +277,8 @@ pub enum ScriptMsg {
GLContextAttributes,
IpcSender<Result<(IpcSender<CanvasMsg>, usize), String>>),
/// Dispatched after the DOM load event has fired on a document
+ /// Causes a `load` event to be dispatched to any enclosing frame context element
+ /// for the given pipeline.
DOMLoad(PipelineId),
Failure(Failure),
/// Notifies the constellation that this frame has received focus.
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 31f67f33801..92942012def 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -58,7 +58,7 @@ use dom::keyboardevent::KeyboardEvent;
use dom::location::Location;
use dom::messageevent::MessageEvent;
use dom::mouseevent::MouseEvent;
-use dom::node::{self, CloneChildrenFlag, Node, NodeDamage, window_from_node};
+use dom::node::{self, CloneChildrenFlag, Node, NodeDamage};
use dom::nodeiterator::NodeIterator;
use dom::nodelist::NodeList;
use dom::processinginstruction::ProcessingInstruction;
@@ -79,9 +79,9 @@ use layout_interface::{HitTestResponse, MouseOverResponse};
use layout_interface::{LayoutChan, Msg};
use layout_interface::{ReflowGoal, ReflowQueryType};
use msg::compositor_msg::ScriptToCompositorMsg;
-use msg::constellation_msg::AnimationState;
use msg::constellation_msg::ScriptMsg as ConstellationMsg;
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
+use msg::constellation_msg::{AnimationState, PipelineId};
use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyModifiers, KeyState, MozBrowserEvent, SubpageId};
use net_traits::ControlMsg::{GetCookiesForUrl, SetCookiesForUrl};
use net_traits::CookieSource::NonHTTP;
@@ -1333,6 +1333,14 @@ impl Document {
.find(|node| node.subpage_id() == Some(subpage_id))
}
+ /// Find an iframe element in the document.
+ pub fn find_iframe_by_pipeline(&self, pipeline: PipelineId) -> Option<Root<HTMLIFrameElement>> {
+ self.upcast::<Node>()
+ .traverse_preorder()
+ .filter_map(Root::downcast::<HTMLIFrameElement>)
+ .find(|node| node.pipeline() == Some(pipeline))
+ }
+
pub fn get_dom_loading(&self) -> u64 {
self.dom_loading.get()
}
@@ -2433,18 +2441,6 @@ impl DocumentProgressHandler {
event.set_trusted(true);
let _ = wintarget.dispatch_event_with_target(document.upcast(), &event);
- let browsing_context = window.browsing_context();
- let browsing_context = browsing_context.as_ref().unwrap();
-
- if let Some(frame_element) = browsing_context.frame_element() {
- let frame_window = window_from_node(frame_element);
- let event = Event::new(GlobalRef::Window(frame_window.r()),
- DOMString::from("load"),
- EventBubbles::DoesNotBubble,
- EventCancelable::NotCancelable);
- event.fire(frame_element.upcast());
- };
-
document.notify_constellation_load();
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadend
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index 66bade67a7d..78400b6d49a 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -16,7 +16,7 @@ use dom::bindings::reflector::Reflectable;
use dom::customevent::CustomEvent;
use dom::document::Document;
use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
-use dom::event::Event;
+use dom::event::{Event, EventBubbles, EventCancelable};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, window_from_node};
use dom::urlhelper::UrlHelper;
@@ -189,6 +189,29 @@ impl HTMLIFrameElement {
pub fn subpage_id(&self) -> Option<SubpageId> {
self.subpage_id.get()
}
+
+ pub fn pipeline(&self) -> Option<PipelineId> {
+ self.pipeline_id.get()
+ }
+
+ /// https://html.spec.whatwg.org/multipage/#iframe-load-event-steps steps 1-4
+ pub fn iframe_load_event_steps(&self) {
+ // 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.
+ // TODO Step 2 - check child document `mute iframe load` flag
+ // TODO Step 3 - set child document `mut iframe load` flag
+
+ // Step 4
+ let window = window_from_node(self);
+ let event = Event::new(GlobalRef::Window(window.r()),
+ DOMString::from("load".to_owned()),
+ EventBubbles::DoesNotBubble,
+ EventCancelable::NotCancelable);
+ event.fire(self.upcast());
+
+ // TODO Step 5 - unset child document `mut iframe load` flag
+ }
}
pub trait HTMLIFrameElementLayoutMethods {
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 848f964d2c0..8b9800063e2 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -1006,6 +1006,9 @@ impl ScriptTask {
self.handle_tick_all_animations(pipeline_id),
ConstellationControlMsg::WebFontLoaded(pipeline_id) =>
self.handle_web_font_loaded(pipeline_id),
+ ConstellationControlMsg::DispatchFrameLoadEvent {
+ target: pipeline_id, parent: containing_id } =>
+ self.handle_frame_load_event(containing_id, pipeline_id),
ConstellationControlMsg::GetCurrentState(sender, pipeline_id) => {
let state = self.handle_get_current_state(pipeline_id);
sender.send(state).unwrap();
@@ -1535,6 +1538,15 @@ impl ScriptTask {
}
}
+ /// Notify the containing document of a child frame that has completed loading.
+ fn handle_frame_load_event(&self, containing_pipeline: PipelineId, id: PipelineId) {
+ let page = get_page(&self.root_page(), containing_pipeline);
+ let document = page.document();
+ if let Some(iframe) = document.find_iframe_by_pipeline(id) {
+ iframe.iframe_load_event_steps();
+ }
+ }
+
/// The entry point to document loading. Defines bindings, sets up the window and document
/// objects, parses HTML and CSS, and kicks off initial layout.
fn load(&self, metadata: Metadata, incomplete: InProgressLoad) -> Root<ServoHTMLParser> {
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 685e29c48ec..8a5ffcb459f 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -137,6 +137,13 @@ pub enum ConstellationControlMsg {
WebFontLoaded(PipelineId),
/// Get the current state of the script task for a given pipeline.
GetCurrentState(IpcSender<ScriptState>, PipelineId),
+ /// Cause a `load` event to be dispatched at the appropriate frame element.
+ DispatchFrameLoadEvent {
+ /// The pipeline that has been marked as loaded.
+ target: PipelineId,
+ /// The pipeline that contains a frame loading the target pipeline.
+ parent: PipelineId
+ },
}
/// The mouse button involved in the event.