mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Auto merge of #13646 - asajeffrey:script-lookup-iframes-by-frameid, r=ConnorGBrewster
Script lookup iframes by frameid <!-- Please describe your changes on the following line: --> Lookup iframes by `FrameId` rather than `PipelineId`. This should make lookup much more reliable, since the frame id doesn't change. cc @ConnorGBrewster @aneeshusa --- <!-- 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 do not require tests because refactoring <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13646) <!-- Reviewable:end -->
This commit is contained in:
commit
ce725c9475
13 changed files with 187 additions and 164 deletions
|
@ -739,6 +739,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
fn set_frame_tree(&mut self,
|
fn set_frame_tree(&mut self,
|
||||||
frame_tree: &SendableFrameTree,
|
frame_tree: &SendableFrameTree,
|
||||||
response_chan: IpcSender<()>) {
|
response_chan: IpcSender<()>) {
|
||||||
|
debug!("Setting the frame tree for pipeline {}", frame_tree.pipeline.id);
|
||||||
if let Err(e) = response_chan.send(()) {
|
if let Err(e) = response_chan.send(()) {
|
||||||
warn!("Sending reponse to set frame tree failed ({}).", e);
|
warn!("Sending reponse to set frame tree failed ({}).", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -668,13 +668,16 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
// Create a new frame and update the internal bookkeeping.
|
// Create a new frame and update the internal bookkeeping.
|
||||||
fn new_frame(&mut self, frame_id: FrameId, pipeline_id: PipelineId) {
|
fn new_frame(&mut self, frame_id: FrameId, pipeline_id: PipelineId) {
|
||||||
let frame = Frame::new(frame_id, pipeline_id);
|
let frame = Frame::new(frame_id, pipeline_id);
|
||||||
|
|
||||||
match self.pipelines.get_mut(&pipeline_id) {
|
|
||||||
Some(pipeline) => pipeline.is_mature = true,
|
|
||||||
None => return warn!("Pipeline {} matured after closure.", pipeline_id),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.frames.insert(frame_id, frame);
|
self.frames.insert(frame_id, frame);
|
||||||
|
|
||||||
|
// If a child frame, add it to the parent pipeline.
|
||||||
|
let parent_info = self.pipelines.get(&pipeline_id)
|
||||||
|
.and_then(|pipeline| pipeline.parent_info);
|
||||||
|
if let Some((parent_id, _)) = parent_info {
|
||||||
|
if let Some(parent) = self.pipelines.get_mut(&parent_id) {
|
||||||
|
parent.add_child(frame_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles loading pages, navigation, and granting access to the compositor
|
/// Handles loading pages, navigation, and granting access to the compositor
|
||||||
|
@ -777,6 +780,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
FromCompositorMsg::IsReadyToSaveImage(pipeline_states) => {
|
FromCompositorMsg::IsReadyToSaveImage(pipeline_states) => {
|
||||||
let is_ready = self.handle_is_ready_to_save_image(pipeline_states);
|
let is_ready = self.handle_is_ready_to_save_image(pipeline_states);
|
||||||
|
debug!("Ready to save image {:?}.", is_ready);
|
||||||
if opts::get().is_running_problem_test {
|
if opts::get().is_running_problem_test {
|
||||||
println!("got ready to save image query, result is {:?}", is_ready);
|
println!("got ready to save image query, result is {:?}", is_ready);
|
||||||
}
|
}
|
||||||
|
@ -1022,8 +1026,31 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
self.shutting_down = true;
|
self.shutting_down = true;
|
||||||
|
|
||||||
// TODO: exit before the root frame is initialized?
|
// TODO: exit before the root frame is initialized?
|
||||||
|
debug!("Removing root frame.");
|
||||||
let root_frame_id = self.root_frame_id;
|
let root_frame_id = self.root_frame_id;
|
||||||
self.close_frame(root_frame_id, ExitPipelineMode::Normal);
|
self.close_frame(root_frame_id, ExitPipelineMode::Normal);
|
||||||
|
|
||||||
|
// Close any pending frames and pipelines
|
||||||
|
while let Some(pending) = self.pending_frames.pop() {
|
||||||
|
debug!("Removing pending frame {}.", pending.frame_id);
|
||||||
|
self.close_frame(pending.frame_id, ExitPipelineMode::Normal);
|
||||||
|
debug!("Removing pending pipeline {}.", pending.new_pipeline_id);
|
||||||
|
self.close_pipeline(pending.new_pipeline_id, ExitPipelineMode::Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case there are frames which weren't attached to the frame tree, we close them.
|
||||||
|
let frame_ids: Vec<FrameId> = self.frames.keys().cloned().collect();
|
||||||
|
for frame_id in frame_ids {
|
||||||
|
debug!("Removing detached frame {}.", frame_id);
|
||||||
|
self.close_frame(frame_id, ExitPipelineMode::Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case there are pipelines which weren't attached to the pipeline tree, we close them.
|
||||||
|
let pipeline_ids: Vec<PipelineId> = self.pipelines.keys().cloned().collect();
|
||||||
|
for pipeline_id in pipeline_ids {
|
||||||
|
debug!("Removing detached pipeline {}.", pipeline_id);
|
||||||
|
self.close_pipeline(pipeline_id, ExitPipelineMode::Normal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_shutdown(&mut self) {
|
fn handle_shutdown(&mut self) {
|
||||||
|
@ -1208,8 +1235,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_subframe_loaded(&mut self, pipeline_id: PipelineId) {
|
fn handle_subframe_loaded(&mut self, pipeline_id: PipelineId) {
|
||||||
let parent_info = match self.pipelines.get(&pipeline_id) {
|
let (frame_id, parent_info) = match self.pipelines.get(&pipeline_id) {
|
||||||
Some(pipeline) => pipeline.parent_info,
|
Some(pipeline) => (pipeline.frame_id, pipeline.parent_info),
|
||||||
None => return warn!("Pipeline {:?} loaded after closure.", pipeline_id),
|
None => return warn!("Pipeline {:?} loaded after closure.", pipeline_id),
|
||||||
};
|
};
|
||||||
let subframe_parent_id = match parent_info {
|
let subframe_parent_id = match parent_info {
|
||||||
|
@ -1217,8 +1244,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
None => return warn!("Pipeline {:?} has no parent.", pipeline_id),
|
None => return warn!("Pipeline {:?} has no parent.", pipeline_id),
|
||||||
};
|
};
|
||||||
let msg = ConstellationControlMsg::DispatchFrameLoadEvent {
|
let msg = ConstellationControlMsg::DispatchFrameLoadEvent {
|
||||||
target: pipeline_id,
|
target: frame_id,
|
||||||
parent: subframe_parent_id,
|
parent: subframe_parent_id,
|
||||||
|
child: pipeline_id,
|
||||||
};
|
};
|
||||||
let result = match self.pipelines.get(&subframe_parent_id) {
|
let result = match self.pipelines.get(&subframe_parent_id) {
|
||||||
Some(pipeline) => pipeline.script_chan.send(msg),
|
Some(pipeline) => pipeline.script_chan.send(msg),
|
||||||
|
@ -1392,13 +1420,19 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
// requested change so it can update its internal state.
|
// requested change so it can update its internal state.
|
||||||
//
|
//
|
||||||
// If replace is true, the current entry is replaced instead of a new entry being added.
|
// If replace is true, the current entry is replaced instead of a new entry being added.
|
||||||
let parent_info = self.pipelines.get(&source_id).and_then(|source| source.parent_info);
|
let (frame_id, parent_info) = match self.pipelines.get(&source_id) {
|
||||||
|
Some(pipeline) => (pipeline.frame_id, pipeline.parent_info),
|
||||||
|
None => {
|
||||||
|
warn!("Pipeline {:?} loaded after closure.", source_id);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
match parent_info {
|
match parent_info {
|
||||||
Some((parent_pipeline_id, _)) => {
|
Some((parent_pipeline_id, _)) => {
|
||||||
self.handle_load_start_msg(source_id);
|
self.handle_load_start_msg(source_id);
|
||||||
// Message the constellation to find the script thread for this iframe
|
// Message the constellation to find the script thread for this iframe
|
||||||
// and issue an iframe load through there.
|
// and issue an iframe load through there.
|
||||||
let msg = ConstellationControlMsg::Navigate(parent_pipeline_id, source_id, load_data, replace);
|
let msg = ConstellationControlMsg::Navigate(parent_pipeline_id, frame_id, load_data, replace);
|
||||||
let result = match self.pipelines.get(&parent_pipeline_id) {
|
let result = match self.pipelines.get(&parent_pipeline_id) {
|
||||||
Some(parent_pipeline) => parent_pipeline.script_chan.send(msg),
|
Some(parent_pipeline) => parent_pipeline.script_chan.send(msg),
|
||||||
None => {
|
None => {
|
||||||
|
@ -1586,16 +1620,17 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
|
|
||||||
fn handle_mozbrowser_event_msg(&mut self,
|
fn handle_mozbrowser_event_msg(&mut self,
|
||||||
parent_pipeline_id: PipelineId,
|
parent_pipeline_id: PipelineId,
|
||||||
pipeline_id: Option<PipelineId>,
|
pipeline_id: PipelineId,
|
||||||
event: MozBrowserEvent) {
|
event: MozBrowserEvent) {
|
||||||
assert!(PREFS.is_mozbrowser_enabled());
|
assert!(PREFS.is_mozbrowser_enabled());
|
||||||
|
let frame_id = self.pipelines.get(&pipeline_id).map(|pipeline| pipeline.frame_id);
|
||||||
|
|
||||||
// Find the script channel for the given parent pipeline,
|
// Find the script channel for the given parent pipeline,
|
||||||
// and pass the event to that script thread.
|
// and pass the event to that script thread.
|
||||||
// If the pipeline lookup fails, it is because we have torn down the pipeline,
|
// If the pipeline lookup fails, it is because we have torn down the pipeline,
|
||||||
// so it is reasonable to silently ignore the event.
|
// so it is reasonable to silently ignore the event.
|
||||||
match self.pipelines.get(&parent_pipeline_id) {
|
match self.pipelines.get(&parent_pipeline_id) {
|
||||||
Some(pipeline) => pipeline.trigger_mozbrowser_event(pipeline_id, event),
|
Some(pipeline) => pipeline.trigger_mozbrowser_event(frame_id, event),
|
||||||
None => warn!("Pipeline {:?} handling mozbrowser event after closure.", parent_pipeline_id),
|
None => warn!("Pipeline {:?} handling mozbrowser event after closure.", parent_pipeline_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1626,8 +1661,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_parent_pipeline(&mut self, pipeline_id: PipelineId) {
|
fn focus_parent_pipeline(&mut self, pipeline_id: PipelineId) {
|
||||||
let parent_info = match self.pipelines.get(&pipeline_id) {
|
let (frame_id, parent_info) = match self.pipelines.get(&pipeline_id) {
|
||||||
Some(pipeline) => pipeline.parent_info,
|
Some(pipeline) => (pipeline.frame_id, pipeline.parent_info),
|
||||||
None => return warn!("Pipeline {:?} focus parent after closure.", pipeline_id),
|
None => return warn!("Pipeline {:?} focus parent after closure.", pipeline_id),
|
||||||
};
|
};
|
||||||
let (parent_pipeline_id, _) = match parent_info {
|
let (parent_pipeline_id, _) = match parent_info {
|
||||||
|
@ -1637,7 +1672,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
|
|
||||||
// Send a message to the parent of the provided pipeline (if it exists)
|
// Send a message to the parent of the provided pipeline (if it exists)
|
||||||
// telling it to mark the iframe element as focused.
|
// telling it to mark the iframe element as focused.
|
||||||
let msg = ConstellationControlMsg::FocusIFrame(parent_pipeline_id, pipeline_id);
|
let msg = ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id);
|
||||||
let result = match self.pipelines.get(&parent_pipeline_id) {
|
let result = match self.pipelines.get(&parent_pipeline_id) {
|
||||||
Some(pipeline) => pipeline.script_chan.send(msg),
|
Some(pipeline) => pipeline.script_chan.send(msg),
|
||||||
None => return warn!("Pipeline {:?} focus after closure.", parent_pipeline_id),
|
None => return warn!("Pipeline {:?} focus after closure.", parent_pipeline_id),
|
||||||
|
@ -1691,10 +1726,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_visibility_change_complete(&mut self, pipeline_id: PipelineId, visibility: bool) {
|
fn handle_visibility_change_complete(&mut self, pipeline_id: PipelineId, visibility: bool) {
|
||||||
let parent_pipeline_info = self.pipelines.get(&pipeline_id).and_then(|source| source.parent_info);
|
let (frame_id, parent_pipeline_info) = match self.pipelines.get(&pipeline_id) {
|
||||||
|
None => return warn!("Visibity change for closed pipeline {:?}.", pipeline_id),
|
||||||
|
Some(pipeline) => (pipeline.frame_id, pipeline.parent_info),
|
||||||
|
};
|
||||||
if let Some((parent_pipeline_id, _)) = parent_pipeline_info {
|
if let Some((parent_pipeline_id, _)) = parent_pipeline_info {
|
||||||
let visibility_msg = ConstellationControlMsg::NotifyVisibilityChange(parent_pipeline_id,
|
let visibility_msg = ConstellationControlMsg::NotifyVisibilityChange(parent_pipeline_id,
|
||||||
pipeline_id,
|
frame_id,
|
||||||
visibility);
|
visibility);
|
||||||
let result = match self.pipelines.get(&parent_pipeline_id) {
|
let result = match self.pipelines.get(&parent_pipeline_id) {
|
||||||
None => return warn!("Parent pipeline {:?} closed", parent_pipeline_id),
|
None => return warn!("Parent pipeline {:?} closed", parent_pipeline_id),
|
||||||
|
@ -1856,7 +1894,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
// This makes things like contentDocument work correctly.
|
// This makes things like contentDocument work correctly.
|
||||||
if let Some((parent_pipeline_id, _)) = pipeline_info {
|
if let Some((parent_pipeline_id, _)) = pipeline_info {
|
||||||
let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
|
let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
|
||||||
prev_pipeline_id,
|
frame_id,
|
||||||
next_pipeline_id);
|
next_pipeline_id);
|
||||||
let result = match self.pipelines.get(&parent_pipeline_id) {
|
let result = match self.pipelines.get(&parent_pipeline_id) {
|
||||||
None => return warn!("Pipeline {:?} child traversed after closure.", parent_pipeline_id),
|
None => return warn!("Pipeline {:?} child traversed after closure.", parent_pipeline_id),
|
||||||
|
@ -1875,8 +1913,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
fn get_top_level_frame_for_pipeline(&self, pipeline_id: Option<PipelineId>) -> FrameId {
|
fn get_top_level_frame_for_pipeline(&self, pipeline_id: Option<PipelineId>) -> FrameId {
|
||||||
if PREFS.is_mozbrowser_enabled() {
|
if PREFS.is_mozbrowser_enabled() {
|
||||||
pipeline_id.and_then(|id| self.get_mozbrowser_ancestor_info(id))
|
pipeline_id.and_then(|id| self.get_mozbrowser_ancestor_info(id))
|
||||||
.and_then(|pipeline_info| self.pipelines.get(&pipeline_info.1))
|
.map(|(_, mozbrowser_iframe_id)| mozbrowser_iframe_id)
|
||||||
.map(|pipeline| pipeline.frame_id)
|
|
||||||
.unwrap_or(self.root_frame_id)
|
.unwrap_or(self.root_frame_id)
|
||||||
} else {
|
} else {
|
||||||
// If mozbrowser is not enabled, the root frame is the only top-level frame
|
// If mozbrowser is not enabled, the root frame is the only top-level frame
|
||||||
|
@ -1910,11 +1947,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.frames.contains_key(&frame_change.frame_id) {
|
if self.frames.contains_key(&frame_change.frame_id) {
|
||||||
// Mature the new pipeline, and return frames evicted from history.
|
|
||||||
if let Some(ref mut pipeline) = self.pipelines.get_mut(&frame_change.new_pipeline_id) {
|
|
||||||
pipeline.is_mature = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if frame_change.replace {
|
if frame_change.replace {
|
||||||
let evicted = self.frames.get_mut(&frame_change.frame_id).map(|frame| {
|
let evicted = self.frames.get_mut(&frame_change.frame_id).map(|frame| {
|
||||||
frame.replace_current(frame_change.new_pipeline_id)
|
frame.replace_current(frame_change.new_pipeline_id)
|
||||||
|
@ -1930,16 +1962,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
} else {
|
} else {
|
||||||
// The new pipeline is in a new frame with no history
|
// The new pipeline is in a new frame with no history
|
||||||
self.new_frame(frame_change.frame_id, frame_change.new_pipeline_id);
|
self.new_frame(frame_change.frame_id, frame_change.new_pipeline_id);
|
||||||
|
|
||||||
// If a child frame, add it to the parent pipeline. Otherwise
|
|
||||||
// it must surely be the root frame being created!
|
|
||||||
let parent_info = self.pipelines.get(&frame_change.new_pipeline_id)
|
|
||||||
.and_then(|pipeline| pipeline.parent_info);
|
|
||||||
if let Some((parent_id, _)) = parent_info {
|
|
||||||
if let Some(parent) = self.pipelines.get_mut(&parent_id) {
|
|
||||||
parent.add_child(frame_change.frame_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !frame_change.replace {
|
if !frame_change.replace {
|
||||||
|
@ -1958,49 +1980,25 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
fn handle_activate_document_msg(&mut self, pipeline_id: PipelineId) {
|
fn handle_activate_document_msg(&mut self, pipeline_id: PipelineId) {
|
||||||
debug!("Document ready to activate {:?}", pipeline_id);
|
debug!("Document ready to activate {:?}", pipeline_id);
|
||||||
|
|
||||||
if let Some(ref child_pipeline) = self.pipelines.get(&pipeline_id) {
|
// Notify the parent (if there is one).
|
||||||
if let Some(ref parent_info) = child_pipeline.parent_info {
|
if let Some(pipeline) = self.pipelines.get(&pipeline_id) {
|
||||||
if let Some(parent_pipeline) = self.pipelines.get(&parent_info.0) {
|
if let Some((parent_pipeline_id, _)) = pipeline.parent_info {
|
||||||
let _ = parent_pipeline.script_chan
|
if let Some(parent_pipeline) = self.pipelines.get(&parent_pipeline_id) {
|
||||||
.send(ConstellationControlMsg::FramedContentChanged(
|
let msg = ConstellationControlMsg::FramedContentChanged(parent_pipeline_id, pipeline.frame_id);
|
||||||
parent_info.0,
|
let _ = parent_pipeline.script_chan.send(msg);
|
||||||
pipeline_id));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this pipeline is already part of the current frame tree,
|
|
||||||
// we don't need to do anything.
|
|
||||||
if self.pipeline_is_in_current_frame(pipeline_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the pending frame change whose new pipeline id is pipeline_id.
|
// Find the pending frame change whose new pipeline id is pipeline_id.
|
||||||
// If it is found, mark this pending frame as ready to be enabled.
|
|
||||||
let pending_index = self.pending_frames.iter().rposition(|frame_change| {
|
let pending_index = self.pending_frames.iter().rposition(|frame_change| {
|
||||||
frame_change.new_pipeline_id == pipeline_id
|
frame_change.new_pipeline_id == pipeline_id
|
||||||
});
|
});
|
||||||
if let Some(pending_index) = pending_index {
|
|
||||||
self.pending_frames[pending_index].document_ready = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a bit complex. We need to loop through pending frames and find
|
// If it is found, remove it from the pending frames, and make it
|
||||||
// ones that can be swapped. A frame can be swapped (enabled) once it is
|
// the active document of its frame.
|
||||||
// ready to layout (has document_ready set), and also is mature
|
if let Some(pending_index) = pending_index {
|
||||||
// (i.e. the pipeline it is replacing has been enabled and now has a frame).
|
let frame_change = self.pending_frames.swap_remove(pending_index);
|
||||||
// The outer loop is required because any time a pipeline is enabled, that
|
|
||||||
// may affect whether other pending frames are now able to be enabled. On the
|
|
||||||
// other hand, if no frames can be enabled after looping through all pending
|
|
||||||
// frames, we can safely exit the loop, knowing that we will need to wait on
|
|
||||||
// a dependent pipeline to be ready to paint.
|
|
||||||
while let Some(valid_frame_change) = self.pending_frames.iter().rposition(|frame_change| {
|
|
||||||
let frame_is_mature = frame_change.old_pipeline_id
|
|
||||||
.and_then(|old_pipeline_id| self.pipelines.get(&old_pipeline_id))
|
|
||||||
.map(|old_pipeline| old_pipeline.is_mature)
|
|
||||||
.unwrap_or(true);
|
|
||||||
frame_change.document_ready && frame_is_mature
|
|
||||||
}) {
|
|
||||||
let frame_change = self.pending_frames.swap_remove(valid_frame_change);
|
|
||||||
self.add_or_replace_pipeline_in_frame_tree(frame_change);
|
self.add_or_replace_pipeline_in_frame_tree(frame_change);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2100,6 +2098,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
// screenshot can safely be written.
|
// screenshot can safely be written.
|
||||||
for frame in self.current_frame_tree_iter(self.root_frame_id) {
|
for frame in self.current_frame_tree_iter(self.root_frame_id) {
|
||||||
let pipeline_id = frame.current.pipeline_id;
|
let pipeline_id = frame.current.pipeline_id;
|
||||||
|
debug!("Checking readiness of frame {}, pipeline {}.", frame.id, pipeline_id);
|
||||||
|
|
||||||
let pipeline = match self.pipelines.get(&pipeline_id) {
|
let pipeline = match self.pipelines.get(&pipeline_id) {
|
||||||
None => {
|
None => {
|
||||||
|
@ -2265,7 +2264,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
self.close_frame(*child_frame, exit_mode);
|
self.close_frame(*child_frame, exit_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pipeline = match self.pipelines.get_mut(&pipeline_id) {
|
// Note, we don't remove the pipeline now, we wait for the message to come back from
|
||||||
|
// the pipeline.
|
||||||
|
let pipeline = match self.pipelines.get(&pipeline_id) {
|
||||||
Some(pipeline) => pipeline,
|
Some(pipeline) => pipeline,
|
||||||
None => return warn!("Closing pipeline {:?} twice.", pipeline_id),
|
None => return warn!("Closing pipeline {:?} twice.", pipeline_id),
|
||||||
};
|
};
|
||||||
|
@ -2337,6 +2338,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
// Note that this function can panic, due to ipc-channel creation failure.
|
// Note that this function can panic, due to ipc-channel creation failure.
|
||||||
// avoiding this panic would require a mechanism for dealing
|
// avoiding this panic would require a mechanism for dealing
|
||||||
// with low-resource scenarios.
|
// with low-resource scenarios.
|
||||||
|
debug!("Sending frame tree for frame {}.", self.root_frame_id);
|
||||||
if let Some(frame_tree) = self.frame_to_sendable(self.root_frame_id) {
|
if let Some(frame_tree) = self.frame_to_sendable(self.root_frame_id) {
|
||||||
let (chan, port) = ipc::channel().expect("Failed to create IPC channel!");
|
let (chan, port) = ipc::channel().expect("Failed to create IPC channel!");
|
||||||
self.compositor_proxy.send(ToCompositorMsg::SetFrameTree(frame_tree,
|
self.compositor_proxy.send(ToCompositorMsg::SetFrameTree(frame_tree,
|
||||||
|
@ -2350,12 +2352,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
|
|
||||||
/// For a given pipeline, determine the mozbrowser iframe that transitively contains
|
/// For a given pipeline, determine the mozbrowser iframe that transitively contains
|
||||||
/// it. There could be arbitrary levels of nested iframes in between them.
|
/// it. There could be arbitrary levels of nested iframes in between them.
|
||||||
fn get_mozbrowser_ancestor_info(&self, original_pipeline_id: PipelineId) -> Option<(PipelineId, PipelineId)> {
|
fn get_mozbrowser_ancestor_info(&self, original_pipeline_id: PipelineId) -> Option<(PipelineId, FrameId)> {
|
||||||
let mut pipeline_id = original_pipeline_id;
|
let mut pipeline_id = original_pipeline_id;
|
||||||
loop {
|
loop {
|
||||||
match self.pipelines.get(&pipeline_id) {
|
match self.pipelines.get(&pipeline_id) {
|
||||||
Some(pipeline) => match pipeline.parent_info {
|
Some(pipeline) => match pipeline.parent_info {
|
||||||
Some((parent_id, FrameType::MozBrowserIFrame)) => return Some((parent_id, pipeline_id)),
|
Some((parent_id, FrameType::MozBrowserIFrame)) => return Some((parent_id, pipeline.frame_id)),
|
||||||
Some((parent_id, _)) => pipeline_id = parent_id,
|
Some((parent_id, _)) => pipeline_id = parent_id,
|
||||||
None => return None,
|
None => return None,
|
||||||
},
|
},
|
||||||
|
@ -2378,14 +2380,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
};
|
};
|
||||||
|
|
||||||
// If this is a mozbrowser iframe, then send the event with new url
|
// If this is a mozbrowser iframe, then send the event with new url
|
||||||
if let Some((ancestor_id, mozbrowser_iframe_id)) = self.get_mozbrowser_ancestor_info(pipeline_id) {
|
if let Some((ancestor_id, mozbrowser_frame_id)) = self.get_mozbrowser_ancestor_info(pipeline_id) {
|
||||||
if let Some(ancestor) = self.pipelines.get(&ancestor_id) {
|
if let Some(ancestor) = self.pipelines.get(&ancestor_id) {
|
||||||
if let Some(pipeline) = self.pipelines.get(&mozbrowser_iframe_id) {
|
let can_go_forward = !self.joint_session_future(mozbrowser_frame_id).is_empty();
|
||||||
let can_go_forward = !self.joint_session_future(pipeline.frame_id).is_empty();
|
let can_go_back = !self.joint_session_past(mozbrowser_frame_id).is_empty();
|
||||||
let can_go_back = !self.joint_session_past(pipeline.frame_id).is_empty();
|
let event = MozBrowserEvent::LocationChange(url, can_go_back, can_go_forward);
|
||||||
let event = MozBrowserEvent::LocationChange(url, can_go_back, can_go_forward);
|
ancestor.trigger_mozbrowser_event(Some(mozbrowser_frame_id), event);
|
||||||
ancestor.trigger_mozbrowser_event(Some(mozbrowser_iframe_id), event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,9 +69,6 @@ pub struct Pipeline {
|
||||||
/// Whether this pipeline should be treated as visible for the purposes of scheduling and
|
/// Whether this pipeline should be treated as visible for the purposes of scheduling and
|
||||||
/// resource management.
|
/// resource management.
|
||||||
pub visible: bool,
|
pub visible: bool,
|
||||||
/// Whether this pipeline is has matured or not.
|
|
||||||
/// A pipeline is considered mature when it has an associated frame.
|
|
||||||
pub is_mature: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initial setup data needed to construct a pipeline.
|
/// Initial setup data needed to construct a pipeline.
|
||||||
|
@ -152,6 +149,7 @@ impl Pipeline {
|
||||||
let new_layout_info = NewLayoutInfo {
|
let new_layout_info = NewLayoutInfo {
|
||||||
parent_pipeline_id: parent_pipeline_id,
|
parent_pipeline_id: parent_pipeline_id,
|
||||||
new_pipeline_id: state.id,
|
new_pipeline_id: state.id,
|
||||||
|
frame_id: state.frame_id,
|
||||||
frame_type: frame_type,
|
frame_type: frame_type,
|
||||||
load_data: state.load_data.clone(),
|
load_data: state.load_data.clone(),
|
||||||
pipeline_port: pipeline_port,
|
pipeline_port: pipeline_port,
|
||||||
|
@ -203,6 +201,7 @@ impl Pipeline {
|
||||||
|
|
||||||
let unprivileged_pipeline_content = UnprivilegedPipelineContent {
|
let unprivileged_pipeline_content = UnprivilegedPipelineContent {
|
||||||
id: state.id,
|
id: state.id,
|
||||||
|
frame_id: state.frame_id,
|
||||||
parent_info: state.parent_info,
|
parent_info: state.parent_info,
|
||||||
constellation_chan: state.constellation_chan,
|
constellation_chan: state.constellation_chan,
|
||||||
scheduler_chan: state.scheduler_chan,
|
scheduler_chan: state.scheduler_chan,
|
||||||
|
@ -281,7 +280,6 @@ impl Pipeline {
|
||||||
running_animations: false,
|
running_animations: false,
|
||||||
visible: visible,
|
visible: visible,
|
||||||
is_private: is_private,
|
is_private: is_private,
|
||||||
is_mature: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +346,7 @@ impl Pipeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trigger_mozbrowser_event(&self,
|
pub fn trigger_mozbrowser_event(&self,
|
||||||
child_id: Option<PipelineId>,
|
child_id: Option<FrameId>,
|
||||||
event: MozBrowserEvent) {
|
event: MozBrowserEvent) {
|
||||||
assert!(PREFS.is_mozbrowser_enabled());
|
assert!(PREFS.is_mozbrowser_enabled());
|
||||||
|
|
||||||
|
@ -380,6 +378,7 @@ impl Pipeline {
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct UnprivilegedPipelineContent {
|
pub struct UnprivilegedPipelineContent {
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
|
frame_id: FrameId,
|
||||||
parent_info: Option<(PipelineId, FrameType)>,
|
parent_info: Option<(PipelineId, FrameType)>,
|
||||||
constellation_chan: IpcSender<ScriptMsg>,
|
constellation_chan: IpcSender<ScriptMsg>,
|
||||||
layout_to_constellation_chan: IpcSender<LayoutMsg>,
|
layout_to_constellation_chan: IpcSender<LayoutMsg>,
|
||||||
|
@ -414,6 +413,7 @@ impl UnprivilegedPipelineContent {
|
||||||
{
|
{
|
||||||
let layout_pair = STF::create(InitialScriptState {
|
let layout_pair = STF::create(InitialScriptState {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
|
frame_id: self.frame_id,
|
||||||
parent_info: self.parent_info,
|
parent_info: self.parent_info,
|
||||||
control_chan: self.script_chan.clone(),
|
control_chan: self.script_chan.clone(),
|
||||||
control_port: self.script_port,
|
control_port: self.script_port,
|
||||||
|
|
|
@ -784,7 +784,7 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
if log_enabled!(log::LogLevel::Info) {
|
if log_enabled!(log::LogLevel::Info) {
|
||||||
info!("{}", method);
|
info!("{} {}", method, connection_url);
|
||||||
for header in headers.iter() {
|
for header in headers.iter() {
|
||||||
info!(" - {}", header);
|
info!(" - {}", header);
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,7 @@ impl DocumentLoader {
|
||||||
|
|
||||||
pub fn new_with_threads(resource_threads: ResourceThreads,
|
pub fn new_with_threads(resource_threads: ResourceThreads,
|
||||||
initial_load: Option<Url>) -> DocumentLoader {
|
initial_load: Option<Url>) -> DocumentLoader {
|
||||||
|
debug!("Initial blocking load {:?}.", initial_load);
|
||||||
let initial_loads = initial_load.into_iter().map(LoadType::PageSource).collect();
|
let initial_loads = initial_load.into_iter().map(LoadType::PageSource).collect();
|
||||||
|
|
||||||
DocumentLoader {
|
DocumentLoader {
|
||||||
|
@ -105,6 +106,7 @@ impl DocumentLoader {
|
||||||
|
|
||||||
/// Add a load to the list of blocking loads.
|
/// Add a load to the list of blocking loads.
|
||||||
fn add_blocking_load(&mut self, load: LoadType) {
|
fn add_blocking_load(&mut self, load: LoadType) {
|
||||||
|
debug!("Adding blocking load {:?} ({}).", load, self.blocking_loads.len());
|
||||||
self.blocking_loads.push(load);
|
self.blocking_loads.push(load);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +121,7 @@ impl DocumentLoader {
|
||||||
|
|
||||||
/// Mark an in-progress network request complete.
|
/// Mark an in-progress network request complete.
|
||||||
pub fn finish_load(&mut self, load: &LoadType) {
|
pub fn finish_load(&mut self, load: &LoadType) {
|
||||||
|
debug!("Removing blocking load {:?} ({}).", load, self.blocking_loads.len());
|
||||||
let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == *load);
|
let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == *load);
|
||||||
self.blocking_loads.remove(idx.expect(&format!("unknown completed load {:?}", load)));
|
self.blocking_loads.remove(idx.expect(&format!("unknown completed load {:?}", load)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,8 +96,8 @@ use ipc_channel::ipc::{self, IpcSender};
|
||||||
use js::jsapi::{JSContext, JSObject, JSRuntime};
|
use js::jsapi::{JSContext, JSObject, JSRuntime};
|
||||||
use js::jsapi::JS_GetRuntime;
|
use js::jsapi::JS_GetRuntime;
|
||||||
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
|
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
|
||||||
|
use msg::constellation_msg::{FrameId, ReferrerPolicy};
|
||||||
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
|
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
|
||||||
use net_traits::{FetchResponseMsg, IpcSend};
|
use net_traits::{FetchResponseMsg, IpcSend};
|
||||||
use net_traits::CookieSource::NonHTTP;
|
use net_traits::CookieSource::NonHTTP;
|
||||||
use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl};
|
use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl};
|
||||||
|
@ -1400,7 +1400,7 @@ impl Document {
|
||||||
if let Some((parent_pipeline_id, _)) = self.window.parent_info() {
|
if let Some((parent_pipeline_id, _)) = self.window.parent_info() {
|
||||||
let global_scope = self.window.upcast::<GlobalScope>();
|
let global_scope = self.window.upcast::<GlobalScope>();
|
||||||
let event = ConstellationMsg::MozBrowserEvent(parent_pipeline_id,
|
let event = ConstellationMsg::MozBrowserEvent(parent_pipeline_id,
|
||||||
Some(global_scope.pipeline_id()),
|
global_scope.pipeline_id(),
|
||||||
event);
|
event);
|
||||||
global_scope.constellation_chan().send(event).unwrap();
|
global_scope.constellation_chan().send(event).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1513,8 +1513,10 @@ impl Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let loader = self.loader.borrow();
|
if !self.loader.borrow().is_blocked() && !self.loader.borrow().events_inhibited() {
|
||||||
if !loader.is_blocked() && !loader.events_inhibited() {
|
// Schedule a task to fire a "load" event (if no blocking loads have arrived in the mean time)
|
||||||
|
// NOTE: we can end up executing this code more than once, in case more blocking loads arrive.
|
||||||
|
debug!("Document loads are complete.");
|
||||||
let win = self.window();
|
let win = self.window();
|
||||||
let msg = MainThreadScriptMsg::DocumentLoadsComplete(
|
let msg = MainThreadScriptMsg::DocumentLoadsComplete(
|
||||||
win.upcast::<GlobalScope>().pipeline_id());
|
win.upcast::<GlobalScope>().pipeline_id());
|
||||||
|
@ -1630,11 +1632,11 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find an iframe element in the document.
|
/// Find an iframe element in the document.
|
||||||
pub fn find_iframe(&self, pipeline: PipelineId) -> Option<Root<HTMLIFrameElement>> {
|
pub fn find_iframe(&self, frame_id: FrameId) -> Option<Root<HTMLIFrameElement>> {
|
||||||
self.upcast::<Node>()
|
self.upcast::<Node>()
|
||||||
.traverse_preorder()
|
.traverse_preorder()
|
||||||
.filter_map(Root::downcast::<HTMLIFrameElement>)
|
.filter_map(Root::downcast::<HTMLIFrameElement>)
|
||||||
.find(|node| node.pipeline_id() == Some(pipeline))
|
.find(|node| node.frame_id() == frame_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_dom_loading(&self) -> u64 {
|
pub fn get_dom_loading(&self) -> u64 {
|
||||||
|
|
|
@ -207,6 +207,11 @@ impl HTMLIFrameElement {
|
||||||
self.pipeline_id.get()
|
self.pipeline_id.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn frame_id(&self) -> FrameId {
|
||||||
|
self.frame_id
|
||||||
|
}
|
||||||
|
|
||||||
pub fn change_visibility_status(&self, visibility: bool) {
|
pub fn change_visibility_status(&self, visibility: bool) {
|
||||||
if self.visibility.get() != visibility {
|
if self.visibility.get() != visibility {
|
||||||
self.visibility.set(visibility);
|
self.visibility.set(visibility);
|
||||||
|
|
|
@ -72,7 +72,7 @@ use js::jsval::UndefinedValue;
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use layout_wrapper::ServoLayoutNode;
|
use layout_wrapper::ServoLayoutNode;
|
||||||
use mem::heap_size_of_self_and_children;
|
use mem::heap_size_of_self_and_children;
|
||||||
use msg::constellation_msg::{FrameType, PipelineId, PipelineNamespace, ReferrerPolicy};
|
use msg::constellation_msg::{FrameId, FrameType, PipelineId, PipelineNamespace, ReferrerPolicy};
|
||||||
use net_traits::{CoreResourceMsg, IpcSend, Metadata, ResourceThreads};
|
use net_traits::{CoreResourceMsg, IpcSend, Metadata, ResourceThreads};
|
||||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
|
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
|
||||||
use net_traits::request::{CredentialsMode, Destination, RequestInit};
|
use net_traits::request::{CredentialsMode, Destination, RequestInit};
|
||||||
|
@ -135,6 +135,8 @@ pub unsafe fn trace_thread(tr: *mut JSTracer) {
|
||||||
struct InProgressLoad {
|
struct InProgressLoad {
|
||||||
/// The pipeline which requested this load.
|
/// The pipeline which requested this load.
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
|
/// The frame being loaded into.
|
||||||
|
frame_id: FrameId,
|
||||||
/// The parent pipeline and frame type associated with this load, if any.
|
/// The parent pipeline and frame type associated with this load, if any.
|
||||||
parent_info: Option<(PipelineId, FrameType)>,
|
parent_info: Option<(PipelineId, FrameType)>,
|
||||||
/// The current window size associated with this pipeline.
|
/// The current window size associated with this pipeline.
|
||||||
|
@ -154,12 +156,14 @@ struct InProgressLoad {
|
||||||
impl InProgressLoad {
|
impl InProgressLoad {
|
||||||
/// Create a new InProgressLoad object.
|
/// Create a new InProgressLoad object.
|
||||||
fn new(id: PipelineId,
|
fn new(id: PipelineId,
|
||||||
|
frame_id: FrameId,
|
||||||
parent_info: Option<(PipelineId, FrameType)>,
|
parent_info: Option<(PipelineId, FrameType)>,
|
||||||
layout_chan: Sender<message::Msg>,
|
layout_chan: Sender<message::Msg>,
|
||||||
window_size: Option<WindowSizeData>,
|
window_size: Option<WindowSizeData>,
|
||||||
url: Url) -> InProgressLoad {
|
url: Url) -> InProgressLoad {
|
||||||
InProgressLoad {
|
InProgressLoad {
|
||||||
pipeline_id: id,
|
pipeline_id: id,
|
||||||
|
frame_id: frame_id,
|
||||||
parent_info: parent_info,
|
parent_info: parent_info,
|
||||||
layout_chan: layout_chan,
|
layout_chan: layout_chan,
|
||||||
window_size: window_size,
|
window_size: window_size,
|
||||||
|
@ -452,15 +456,15 @@ impl ScriptThreadFactory for ScriptThread {
|
||||||
|
|
||||||
let (sender, receiver) = channel();
|
let (sender, receiver) = channel();
|
||||||
let layout_chan = sender.clone();
|
let layout_chan = sender.clone();
|
||||||
let pipeline_id = state.id;
|
|
||||||
thread::spawn_named(format!("ScriptThread {:?}", state.id),
|
thread::spawn_named(format!("ScriptThread {:?}", state.id),
|
||||||
move || {
|
move || {
|
||||||
thread_state::initialize(thread_state::SCRIPT);
|
thread_state::initialize(thread_state::SCRIPT);
|
||||||
PipelineId::install(pipeline_id);
|
PipelineId::install(state.id);
|
||||||
PipelineNamespace::install(state.pipeline_namespace_id);
|
PipelineNamespace::install(state.pipeline_namespace_id);
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let _stack_roots_tls = StackRootTLS::new(&roots);
|
let _stack_roots_tls = StackRootTLS::new(&roots);
|
||||||
let id = state.id;
|
let id = state.id;
|
||||||
|
let frame_id = state.frame_id;
|
||||||
let parent_info = state.parent_info;
|
let parent_info = state.parent_info;
|
||||||
let mem_profiler_chan = state.mem_profiler_chan.clone();
|
let mem_profiler_chan = state.mem_profiler_chan.clone();
|
||||||
let window_size = state.window_size;
|
let window_size = state.window_size;
|
||||||
|
@ -474,7 +478,7 @@ impl ScriptThreadFactory for ScriptThread {
|
||||||
|
|
||||||
let mut failsafe = ScriptMemoryFailsafe::new(&script_thread);
|
let mut failsafe = ScriptMemoryFailsafe::new(&script_thread);
|
||||||
|
|
||||||
let new_load = InProgressLoad::new(id, parent_info, layout_chan, window_size,
|
let new_load = InProgressLoad::new(id, frame_id, parent_info, layout_chan, window_size,
|
||||||
load_data.url.clone());
|
load_data.url.clone());
|
||||||
script_thread.start_page_load(new_load, load_data);
|
script_thread.start_page_load(new_load, load_data);
|
||||||
|
|
||||||
|
@ -888,8 +892,8 @@ impl ScriptThread {
|
||||||
|
|
||||||
fn handle_msg_from_constellation(&self, msg: ConstellationControlMsg) {
|
fn handle_msg_from_constellation(&self, msg: ConstellationControlMsg) {
|
||||||
match msg {
|
match msg {
|
||||||
ConstellationControlMsg::Navigate(parent_pipeline_id, pipeline_id, load_data, replace) =>
|
ConstellationControlMsg::Navigate(parent_pipeline_id, frame_id, load_data, replace) =>
|
||||||
self.handle_navigate(parent_pipeline_id, Some(pipeline_id), load_data, replace),
|
self.handle_navigate(parent_pipeline_id, Some(frame_id), load_data, replace),
|
||||||
ConstellationControlMsg::SendEvent(id, event) =>
|
ConstellationControlMsg::SendEvent(id, event) =>
|
||||||
self.handle_event(id, event),
|
self.handle_event(id, event),
|
||||||
ConstellationControlMsg::ResizeInactive(id, new_size) =>
|
ConstellationControlMsg::ResizeInactive(id, new_size) =>
|
||||||
|
@ -902,22 +906,22 @@ impl ScriptThread {
|
||||||
self.handle_thaw_msg(pipeline_id),
|
self.handle_thaw_msg(pipeline_id),
|
||||||
ConstellationControlMsg::ChangeFrameVisibilityStatus(pipeline_id, visible) =>
|
ConstellationControlMsg::ChangeFrameVisibilityStatus(pipeline_id, visible) =>
|
||||||
self.handle_visibility_change_msg(pipeline_id, visible),
|
self.handle_visibility_change_msg(pipeline_id, visible),
|
||||||
ConstellationControlMsg::NotifyVisibilityChange(parent_pipeline_id, pipeline_id, visible) =>
|
ConstellationControlMsg::NotifyVisibilityChange(parent_pipeline_id, frame_id, visible) =>
|
||||||
self.handle_visibility_change_complete_msg(parent_pipeline_id, pipeline_id, visible),
|
self.handle_visibility_change_complete_msg(parent_pipeline_id, frame_id, visible),
|
||||||
ConstellationControlMsg::MozBrowserEvent(parent_pipeline_id,
|
ConstellationControlMsg::MozBrowserEvent(parent_pipeline_id,
|
||||||
pipeline_id,
|
frame_id,
|
||||||
event) =>
|
event) =>
|
||||||
self.handle_mozbrowser_event_msg(parent_pipeline_id,
|
self.handle_mozbrowser_event_msg(parent_pipeline_id,
|
||||||
pipeline_id,
|
frame_id,
|
||||||
event),
|
event),
|
||||||
ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
|
ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
|
||||||
old_pipeline_id,
|
frame_id,
|
||||||
new_pipeline_id) =>
|
new_pipeline_id) =>
|
||||||
self.handle_update_pipeline_id(parent_pipeline_id,
|
self.handle_update_pipeline_id(parent_pipeline_id,
|
||||||
old_pipeline_id,
|
frame_id,
|
||||||
new_pipeline_id),
|
new_pipeline_id),
|
||||||
ConstellationControlMsg::FocusIFrame(parent_pipeline_id, pipeline_id) =>
|
ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id) =>
|
||||||
self.handle_focus_iframe_msg(parent_pipeline_id, pipeline_id),
|
self.handle_focus_iframe_msg(parent_pipeline_id, frame_id),
|
||||||
ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) =>
|
ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) =>
|
||||||
self.handle_webdriver_msg(pipeline_id, msg),
|
self.handle_webdriver_msg(pipeline_id, msg),
|
||||||
ConstellationControlMsg::TickAllAnimations(pipeline_id) =>
|
ConstellationControlMsg::TickAllAnimations(pipeline_id) =>
|
||||||
|
@ -927,10 +931,10 @@ impl ScriptThread {
|
||||||
ConstellationControlMsg::WebFontLoaded(pipeline_id) =>
|
ConstellationControlMsg::WebFontLoaded(pipeline_id) =>
|
||||||
self.handle_web_font_loaded(pipeline_id),
|
self.handle_web_font_loaded(pipeline_id),
|
||||||
ConstellationControlMsg::DispatchFrameLoadEvent {
|
ConstellationControlMsg::DispatchFrameLoadEvent {
|
||||||
target: pipeline_id, parent: parent_pipeline_id } =>
|
target: frame_id, parent: parent_id, child: child_id } =>
|
||||||
self.handle_frame_load_event(parent_pipeline_id, pipeline_id),
|
self.handle_frame_load_event(parent_id, frame_id, child_id),
|
||||||
ConstellationControlMsg::FramedContentChanged(parent_pipeline_id, pipeline_id) =>
|
ConstellationControlMsg::FramedContentChanged(parent_pipeline_id, frame_id) =>
|
||||||
self.handle_framed_content_changed(parent_pipeline_id, pipeline_id),
|
self.handle_framed_content_changed(parent_pipeline_id, frame_id),
|
||||||
ConstellationControlMsg::ReportCSSError(pipeline_id, filename, line, column, msg) =>
|
ConstellationControlMsg::ReportCSSError(pipeline_id, filename, line, column, msg) =>
|
||||||
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
|
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
|
||||||
ConstellationControlMsg::Reload(pipeline_id) =>
|
ConstellationControlMsg::Reload(pipeline_id) =>
|
||||||
|
@ -1139,6 +1143,7 @@ impl ScriptThread {
|
||||||
let NewLayoutInfo {
|
let NewLayoutInfo {
|
||||||
parent_pipeline_id,
|
parent_pipeline_id,
|
||||||
new_pipeline_id,
|
new_pipeline_id,
|
||||||
|
frame_id,
|
||||||
frame_type,
|
frame_type,
|
||||||
load_data,
|
load_data,
|
||||||
pipeline_port,
|
pipeline_port,
|
||||||
|
@ -1175,7 +1180,7 @@ impl ScriptThread {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Kick off the fetch for the new resource.
|
// Kick off the fetch for the new resource.
|
||||||
let new_load = InProgressLoad::new(new_pipeline_id, Some((parent_pipeline_id, frame_type)),
|
let new_load = InProgressLoad::new(new_pipeline_id, frame_id, Some((parent_pipeline_id, frame_type)),
|
||||||
layout_chan, parent_window.window_size(),
|
layout_chan, parent_window.window_size(),
|
||||||
load_data.url.clone());
|
load_data.url.clone());
|
||||||
self.start_page_load(new_load, load_data);
|
self.start_page_load(new_load, load_data);
|
||||||
|
@ -1187,12 +1192,15 @@ impl ScriptThread {
|
||||||
None => return warn!("Message sent to closed pipeline {}.", pipeline),
|
None => return warn!("Message sent to closed pipeline {}.", pipeline),
|
||||||
};
|
};
|
||||||
if doc.loader().is_blocked() {
|
if doc.loader().is_blocked() {
|
||||||
|
debug!("Script thread got loads complete while loader is blocked.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.mut_loader().inhibit_events();
|
doc.mut_loader().inhibit_events();
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#the-end step 7
|
// https://html.spec.whatwg.org/multipage/#the-end step 7
|
||||||
|
// Schedule a task to fire a "load" event (if no blocking loads have arrived in the mean time)
|
||||||
|
// NOTE: we can end up executing this code more than once, in case more blocking loads arrive.
|
||||||
let handler = box DocumentProgressHandler::new(Trusted::new(&doc));
|
let handler = box DocumentProgressHandler::new(Trusted::new(&doc));
|
||||||
self.dom_manipulation_task_source.queue(handler, doc.window().upcast()).unwrap();
|
self.dom_manipulation_task_source.queue(handler, doc.window().upcast()).unwrap();
|
||||||
|
|
||||||
|
@ -1259,7 +1267,7 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates iframe element after a change in visibility
|
/// Updates iframe element after a change in visibility
|
||||||
fn handle_visibility_change_complete_msg(&self, parent_pipeline_id: PipelineId, id: PipelineId, visible: bool) {
|
fn handle_visibility_change_complete_msg(&self, parent_pipeline_id: PipelineId, id: FrameId, visible: bool) {
|
||||||
if let Some(root_context) = self.browsing_context.get() {
|
if let Some(root_context) = self.browsing_context.get() {
|
||||||
if let Some(ref inner_context) = root_context.find(parent_pipeline_id) {
|
if let Some(ref inner_context) = root_context.find(parent_pipeline_id) {
|
||||||
if let Some(iframe) = inner_context.active_document().find_iframe(id) {
|
if let Some(iframe) = inner_context.active_document().find_iframe(id) {
|
||||||
|
@ -1328,12 +1336,12 @@ impl ScriptThread {
|
||||||
|
|
||||||
fn handle_focus_iframe_msg(&self,
|
fn handle_focus_iframe_msg(&self,
|
||||||
parent_pipeline_id: PipelineId,
|
parent_pipeline_id: PipelineId,
|
||||||
pipeline_id: PipelineId) {
|
frame_id: FrameId) {
|
||||||
let borrowed_context = self.root_browsing_context();
|
let borrowed_context = self.root_browsing_context();
|
||||||
let context = borrowed_context.find(parent_pipeline_id).unwrap();
|
let context = borrowed_context.find(parent_pipeline_id).unwrap();
|
||||||
|
|
||||||
let doc = context.active_document();
|
let doc = context.active_document();
|
||||||
let frame_element = doc.find_iframe(pipeline_id);
|
let frame_element = doc.find_iframe(frame_id);
|
||||||
|
|
||||||
if let Some(ref frame_element) = frame_element {
|
if let Some(ref frame_element) = frame_element {
|
||||||
doc.begin_focus_transaction();
|
doc.begin_focus_transaction();
|
||||||
|
@ -1344,11 +1352,11 @@ impl ScriptThread {
|
||||||
|
|
||||||
fn handle_framed_content_changed(&self,
|
fn handle_framed_content_changed(&self,
|
||||||
parent_pipeline_id: PipelineId,
|
parent_pipeline_id: PipelineId,
|
||||||
pipeline_id: PipelineId) {
|
frame_id: FrameId) {
|
||||||
let root_context = self.root_browsing_context();
|
let root_context = self.root_browsing_context();
|
||||||
let context = root_context.find(parent_pipeline_id).unwrap();
|
let context = root_context.find(parent_pipeline_id).unwrap();
|
||||||
let doc = context.active_document();
|
let doc = context.active_document();
|
||||||
let frame_element = doc.find_iframe(pipeline_id);
|
let frame_element = doc.find_iframe(frame_id);
|
||||||
if let Some(ref frame_element) = frame_element {
|
if let Some(ref frame_element) = frame_element {
|
||||||
frame_element.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
frame_element.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||||
let window = context.active_window();
|
let window = context.active_window();
|
||||||
|
@ -1362,14 +1370,14 @@ impl ScriptThread {
|
||||||
/// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
|
/// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
|
||||||
fn handle_mozbrowser_event_msg(&self,
|
fn handle_mozbrowser_event_msg(&self,
|
||||||
parent_pipeline_id: PipelineId,
|
parent_pipeline_id: PipelineId,
|
||||||
pipeline_id: Option<PipelineId>,
|
frame_id: Option<FrameId>,
|
||||||
event: MozBrowserEvent) {
|
event: MozBrowserEvent) {
|
||||||
match self.root_browsing_context().find(parent_pipeline_id) {
|
match self.root_browsing_context().find(parent_pipeline_id) {
|
||||||
None => warn!("Mozbrowser event after pipeline {:?} closed.", parent_pipeline_id),
|
None => warn!("Mozbrowser event after pipeline {:?} closed.", parent_pipeline_id),
|
||||||
Some(context) => match pipeline_id {
|
Some(context) => match frame_id {
|
||||||
None => context.active_window().dispatch_mozbrowser_event(event),
|
None => context.active_window().dispatch_mozbrowser_event(event),
|
||||||
Some(pipeline_id) => match context.active_document().find_iframe(pipeline_id) {
|
Some(frame_id) => match context.active_document().find_iframe(frame_id) {
|
||||||
None => warn!("Mozbrowser event after iframe {:?}/{:?} closed.", parent_pipeline_id, pipeline_id),
|
None => warn!("Mozbrowser event after iframe {:?}/{:?} closed.", parent_pipeline_id, frame_id),
|
||||||
Some(frame_element) => frame_element.dispatch_mozbrowser_event(event),
|
Some(frame_element) => frame_element.dispatch_mozbrowser_event(event),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1378,13 +1386,13 @@ impl ScriptThread {
|
||||||
|
|
||||||
fn handle_update_pipeline_id(&self,
|
fn handle_update_pipeline_id(&self,
|
||||||
parent_pipeline_id: PipelineId,
|
parent_pipeline_id: PipelineId,
|
||||||
old_pipeline_id: PipelineId,
|
frame_id: FrameId,
|
||||||
new_pipeline_id: PipelineId) {
|
new_pipeline_id: PipelineId) {
|
||||||
let borrowed_context = self.root_browsing_context();
|
let borrowed_context = self.root_browsing_context();
|
||||||
|
|
||||||
let frame_element = borrowed_context.find(parent_pipeline_id).and_then(|context| {
|
let frame_element = borrowed_context.find(parent_pipeline_id).and_then(|context| {
|
||||||
let doc = context.active_document();
|
let doc = context.active_document();
|
||||||
doc.find_iframe(old_pipeline_id)
|
doc.find_iframe(frame_id)
|
||||||
});
|
});
|
||||||
|
|
||||||
frame_element.unwrap().update_pipeline_id(new_pipeline_id);
|
frame_element.unwrap().update_pipeline_id(new_pipeline_id);
|
||||||
|
@ -1567,13 +1575,15 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Notify the containing document of a child frame that has completed loading.
|
/// Notify the containing document of a child frame that has completed loading.
|
||||||
fn handle_frame_load_event(&self, parent_pipeline_id: PipelineId, id: PipelineId) {
|
fn handle_frame_load_event(&self, parent_id: PipelineId, frame_id: FrameId, child_id: PipelineId) {
|
||||||
let document = match self.root_browsing_context().find(parent_pipeline_id) {
|
let document = match self.root_browsing_context().find(parent_id) {
|
||||||
Some(browsing_context) => browsing_context.active_document(),
|
Some(browsing_context) => browsing_context.active_document(),
|
||||||
None => return warn!("Message sent to closed pipeline {}.", parent_pipeline_id),
|
None => return warn!("Message sent to closed pipeline {}.", parent_id),
|
||||||
};
|
};
|
||||||
if let Some(iframe) = document.find_iframe(id) {
|
if let Some(iframe) = document.find_iframe(frame_id) {
|
||||||
iframe.iframe_load_event_steps(id);
|
if iframe.pipeline_id() == Some(child_id) {
|
||||||
|
iframe.iframe_load_event_steps(child_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1609,7 +1619,7 @@ impl ScriptThread {
|
||||||
root_context.and_then(|root_context| {
|
root_context.and_then(|root_context| {
|
||||||
root_context.find(parent_id).and_then(|context| {
|
root_context.find(parent_id).and_then(|context| {
|
||||||
let doc = context.active_document();
|
let doc = context.active_document();
|
||||||
doc.find_iframe(incomplete.pipeline_id)
|
doc.find_iframe(incomplete.frame_id)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -2033,7 +2043,7 @@ impl ScriptThread {
|
||||||
/// The entry point for content to notify that a new load has been requested
|
/// The entry point for content to notify that a new load has been requested
|
||||||
/// for the given pipeline (specifically the "navigate" algorithm).
|
/// for the given pipeline (specifically the "navigate" algorithm).
|
||||||
fn handle_navigate(&self, parent_pipeline_id: PipelineId,
|
fn handle_navigate(&self, parent_pipeline_id: PipelineId,
|
||||||
pipeline_id: Option<PipelineId>,
|
frame_id: Option<FrameId>,
|
||||||
load_data: LoadData,
|
load_data: LoadData,
|
||||||
replace: bool) {
|
replace: bool) {
|
||||||
// Step 7.
|
// Step 7.
|
||||||
|
@ -2053,12 +2063,12 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match pipeline_id {
|
match frame_id {
|
||||||
Some(pipeline_id) => {
|
Some(frame_id) => {
|
||||||
let root_context = self.root_browsing_context();
|
let root_context = self.root_browsing_context();
|
||||||
let iframe = root_context.find(parent_pipeline_id).and_then(|context| {
|
let iframe = root_context.find(parent_pipeline_id).and_then(|context| {
|
||||||
let doc = context.active_document();
|
let doc = context.active_document();
|
||||||
doc.find_iframe(pipeline_id)
|
doc.find_iframe(frame_id)
|
||||||
});
|
});
|
||||||
if let Some(iframe) = iframe.r() {
|
if let Some(iframe) = iframe.r() {
|
||||||
iframe.navigate_or_reload_child_browsing_context(Some(load_data), replace);
|
iframe.navigate_or_reload_child_browsing_context(Some(load_data), replace);
|
||||||
|
|
|
@ -168,7 +168,9 @@ pub struct NewLayoutInfo {
|
||||||
pub parent_pipeline_id: PipelineId,
|
pub parent_pipeline_id: PipelineId,
|
||||||
/// Id of the newly-created pipeline.
|
/// Id of the newly-created pipeline.
|
||||||
pub new_pipeline_id: PipelineId,
|
pub new_pipeline_id: PipelineId,
|
||||||
/// Type of the new frame associated with this pipeline.
|
/// Id of the frame associated with this pipeline.
|
||||||
|
pub frame_id: FrameId,
|
||||||
|
/// Type of the frame associated with this pipeline.
|
||||||
pub frame_type: FrameType,
|
pub frame_type: FrameType,
|
||||||
/// Network request data which will be initiated by the script thread.
|
/// Network request data which will be initiated by the script thread.
|
||||||
pub load_data: LoadData,
|
pub load_data: LoadData,
|
||||||
|
@ -208,22 +210,20 @@ pub enum ConstellationControlMsg {
|
||||||
/// Notifies script thread whether frame is visible
|
/// Notifies script thread whether frame is visible
|
||||||
ChangeFrameVisibilityStatus(PipelineId, bool),
|
ChangeFrameVisibilityStatus(PipelineId, bool),
|
||||||
/// Notifies script thread that frame visibility change is complete
|
/// Notifies script thread that frame visibility change is complete
|
||||||
/// First PipelineId is for the parent, second PipelineId is for the actual pipeline.
|
/// PipelineId is for the parent, FrameId is for the actual frame.
|
||||||
NotifyVisibilityChange(PipelineId, PipelineId, bool),
|
NotifyVisibilityChange(PipelineId, FrameId, bool),
|
||||||
/// Notifies script thread that a url should be loaded in this iframe.
|
/// Notifies script thread that a url should be loaded in this iframe.
|
||||||
/// First PipelineId is for the parent, second PipelineId is for the actual pipeline.
|
/// PipelineId is for the parent, FrameId is for the actual frame.
|
||||||
Navigate(PipelineId, PipelineId, LoadData, bool),
|
Navigate(PipelineId, FrameId, LoadData, bool),
|
||||||
/// Requests the script thread forward a mozbrowser event to an iframe it owns,
|
/// Requests the script thread forward a mozbrowser event to an iframe it owns,
|
||||||
/// or to the window if no child pipeline id is provided.
|
/// or to the window if no child frame id is provided.
|
||||||
/// First PipelineId is for the parent, second PipelineId is for the actual pipeline.
|
MozBrowserEvent(PipelineId, Option<FrameId>, MozBrowserEvent),
|
||||||
MozBrowserEvent(PipelineId, Option<PipelineId>, MozBrowserEvent),
|
|
||||||
/// Updates the current pipeline ID of a given iframe.
|
/// Updates the current pipeline ID of a given iframe.
|
||||||
/// First PipelineId is for the parent, second is the old PipelineId for the frame,
|
/// First PipelineId is for the parent, second is the new PipelineId for the frame.
|
||||||
/// third is the new PipelineId for the frame.
|
UpdatePipelineId(PipelineId, FrameId, PipelineId),
|
||||||
UpdatePipelineId(PipelineId, PipelineId, PipelineId),
|
|
||||||
/// Set an iframe to be focused. Used when an element in an iframe gains focus.
|
/// Set an iframe to be focused. Used when an element in an iframe gains focus.
|
||||||
/// First PipelineId is for the parent, second PipelineId is for the actual pipeline.
|
/// PipelineId is for the parent, FrameId is for the actual frame.
|
||||||
FocusIFrame(PipelineId, PipelineId),
|
FocusIFrame(PipelineId, FrameId),
|
||||||
/// Passes a webdriver command to the script thread for execution
|
/// Passes a webdriver command to the script thread for execution
|
||||||
WebDriverScriptCommand(PipelineId, WebDriverScriptCommand),
|
WebDriverScriptCommand(PipelineId, WebDriverScriptCommand),
|
||||||
/// Notifies script thread that all animations are done
|
/// Notifies script thread that all animations are done
|
||||||
|
@ -235,14 +235,16 @@ pub enum ConstellationControlMsg {
|
||||||
WebFontLoaded(PipelineId),
|
WebFontLoaded(PipelineId),
|
||||||
/// Cause a `load` event to be dispatched at the appropriate frame element.
|
/// Cause a `load` event to be dispatched at the appropriate frame element.
|
||||||
DispatchFrameLoadEvent {
|
DispatchFrameLoadEvent {
|
||||||
/// The pipeline that has been marked as loaded.
|
/// The frame that has been marked as loaded.
|
||||||
target: PipelineId,
|
target: FrameId,
|
||||||
/// The pipeline that contains a frame loading the target pipeline.
|
/// The pipeline that contains a frame loading the target pipeline.
|
||||||
parent: PipelineId,
|
parent: PipelineId,
|
||||||
|
/// The pipeline that has completed loading.
|
||||||
|
child: PipelineId,
|
||||||
},
|
},
|
||||||
/// Notifies a parent frame that one of its child frames is now active.
|
/// Notifies a parent pipeline that one of its child frames is now active.
|
||||||
/// First PipelineId is for the parent, second PipelineId is for the actual pipeline.
|
/// PipelineId is for the parent, FrameId is the child frame.
|
||||||
FramedContentChanged(PipelineId, PipelineId),
|
FramedContentChanged(PipelineId, FrameId),
|
||||||
/// Report an error from a CSS parser for the given pipeline
|
/// Report an error from a CSS parser for the given pipeline
|
||||||
ReportCSSError(PipelineId, String, usize, usize, String),
|
ReportCSSError(PipelineId, String, usize, usize, String),
|
||||||
/// Reload the given page.
|
/// Reload the given page.
|
||||||
|
@ -430,6 +432,8 @@ pub struct InitialScriptState {
|
||||||
/// The subpage ID of this pipeline to create in its pipeline parent.
|
/// The subpage ID of this pipeline to create in its pipeline parent.
|
||||||
/// If `None`, this is the root.
|
/// If `None`, this is the root.
|
||||||
pub parent_info: Option<(PipelineId, FrameType)>,
|
pub parent_info: Option<(PipelineId, FrameType)>,
|
||||||
|
/// The ID of the frame this script is part of.
|
||||||
|
pub frame_id: FrameId,
|
||||||
/// A channel with which messages can be sent to us (the script thread).
|
/// A channel with which messages can be sent to us (the script thread).
|
||||||
pub control_chan: IpcSender<ConstellationControlMsg>,
|
pub control_chan: IpcSender<ConstellationControlMsg>,
|
||||||
/// A port on which messages sent by the constellation to script can be received.
|
/// A port on which messages sent by the constellation to script can be received.
|
||||||
|
|
|
@ -83,10 +83,9 @@ pub enum ScriptMsg {
|
||||||
/// A new load has been requested, with an option to replace the current entry once loaded
|
/// A new load has been requested, with an option to replace the current entry once loaded
|
||||||
/// instead of adding a new entry.
|
/// instead of adding a new entry.
|
||||||
LoadUrl(PipelineId, LoadData, bool),
|
LoadUrl(PipelineId, LoadData, bool),
|
||||||
/// Dispatch a mozbrowser event to a given iframe,
|
/// Dispatch a mozbrowser event to the parent of this pipeline.
|
||||||
/// or to the window if no subpage id is provided.
|
/// The first PipelineId is for the parent, the second is for the originating pipeline.
|
||||||
/// First PipelineId is for the parent, second PipelineId is for the actual pipeline.
|
MozBrowserEvent(PipelineId, PipelineId, MozBrowserEvent),
|
||||||
MozBrowserEvent(PipelineId, Option<PipelineId>, MozBrowserEvent),
|
|
||||||
/// HTMLIFrameElement Forward or Back traversal.
|
/// HTMLIFrameElement Forward or Back traversal.
|
||||||
TraverseHistory(Option<PipelineId>, TraversalDirection),
|
TraverseHistory(Option<PipelineId>, TraversalDirection),
|
||||||
/// Gets the length of the joint session history from the constellation.
|
/// Gets the length of the joint session history from the constellation.
|
||||||
|
|
|
@ -38,7 +38,7 @@ async_test(function(t) {
|
||||||
|
|
||||||
var action_idx = 0;
|
var action_idx = 0;
|
||||||
|
|
||||||
iframe.addEventListener("mozbrowserlocationchange", e => {
|
iframe.addEventListener("mozbrowserlocationchange", t.step_func(e => {
|
||||||
received_events.push(e.detail.url);
|
received_events.push(e.detail.url);
|
||||||
received_events.push(e.detail.canGoBack);
|
received_events.push(e.detail.canGoBack);
|
||||||
received_events.push(e.detail.canGoForward);
|
received_events.push(e.detail.canGoForward);
|
||||||
|
@ -49,7 +49,7 @@ async_test(function(t) {
|
||||||
assert_array_equals(received_events, expected_events);
|
assert_array_equals(received_events, expected_events);
|
||||||
t.done();
|
t.done();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
|
|
||||||
document.body.appendChild(iframe);
|
document.body.appendChild(iframe);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
parent._ping(window.location.href)
|
parent._ping(window.location.href)
|
||||||
location.reload();
|
if (parent._pingCount < 5) { location.reload(); }
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -15,18 +15,17 @@
|
||||||
async_test(function(t) {
|
async_test(function(t) {
|
||||||
|
|
||||||
var url = new URL("./location_reload-iframe.html", window.location).href;
|
var url = new URL("./location_reload-iframe.html", window.location).href;
|
||||||
var pingCount = 0;
|
|
||||||
|
|
||||||
|
window._pingCount = 0;
|
||||||
window._ping = t.step_func(function(innerURL) {
|
window._ping = t.step_func(function(innerURL) {
|
||||||
// Some browsers keep 'about:blank' in the session history
|
// Some browsers keep 'about:blank' in the session history
|
||||||
if (pingCount == 0) {
|
if (_pingCount == 0) {
|
||||||
history_length = history.length;
|
history_length = history.length;
|
||||||
}
|
}
|
||||||
assert_equals(url, innerURL, "iframe url (" + pingCount + ")");
|
assert_equals(url, innerURL, "iframe url (" + _pingCount + ")");
|
||||||
assert_equals(history_length, history.length, "history length (" + pingCount + ")");
|
assert_equals(history_length, history.length, "history length (" + _pingCount + ")");
|
||||||
pingCount++;
|
_pingCount++;
|
||||||
if (pingCount == 5) {
|
if (_pingCount == 5) {
|
||||||
iframe.src = 'about:blank';
|
|
||||||
t.done();
|
t.done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue