mirror of
https://github.com/servo/servo.git
synced 2025-06-17 21:04:28 +00:00
Report errors using the top-level frame id rather than the pipeline id.
This commit is contained in:
parent
22aebdf5d4
commit
c228a4cf03
9 changed files with 203 additions and 195 deletions
|
@ -419,9 +419,9 @@ impl Log for FromScriptLogger {
|
||||||
fn log(&self, record: &LogRecord) {
|
fn log(&self, record: &LogRecord) {
|
||||||
if let Some(entry) = log_entry(record) {
|
if let Some(entry) = log_entry(record) {
|
||||||
debug!("Sending log entry {:?}.", entry);
|
debug!("Sending log entry {:?}.", entry);
|
||||||
let pipeline_id = PipelineId::installed();
|
let top_level_frame_id = FrameId::installed();
|
||||||
let thread_name = thread::current().name().map(ToOwned::to_owned);
|
let thread_name = thread::current().name().map(ToOwned::to_owned);
|
||||||
let msg = FromScriptMsg::LogEntry(pipeline_id, thread_name, entry);
|
let msg = FromScriptMsg::LogEntry(top_level_frame_id, thread_name, entry);
|
||||||
let chan = self.constellation_chan.lock().unwrap_or_else(|err| err.into_inner());
|
let chan = self.constellation_chan.lock().unwrap_or_else(|err| err.into_inner());
|
||||||
let _ = chan.send(msg);
|
let _ = chan.send(msg);
|
||||||
}
|
}
|
||||||
|
@ -457,9 +457,9 @@ impl Log for FromCompositorLogger {
|
||||||
fn log(&self, record: &LogRecord) {
|
fn log(&self, record: &LogRecord) {
|
||||||
if let Some(entry) = log_entry(record) {
|
if let Some(entry) = log_entry(record) {
|
||||||
debug!("Sending log entry {:?}.", entry);
|
debug!("Sending log entry {:?}.", entry);
|
||||||
let pipeline_id = PipelineId::installed();
|
let top_level_frame_id = FrameId::installed();
|
||||||
let thread_name = thread::current().name().map(ToOwned::to_owned);
|
let thread_name = thread::current().name().map(ToOwned::to_owned);
|
||||||
let msg = FromCompositorMsg::LogEntry(pipeline_id, thread_name, entry);
|
let msg = FromCompositorMsg::LogEntry(top_level_frame_id, thread_name, entry);
|
||||||
let chan = self.constellation_chan.lock().unwrap_or_else(|err| err.into_inner());
|
let chan = self.constellation_chan.lock().unwrap_or_else(|err| err.into_inner());
|
||||||
let _ = chan.send(msg);
|
let _ = chan.send(msg);
|
||||||
}
|
}
|
||||||
|
@ -605,9 +605,18 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: think about the case where the child pipeline is created
|
||||||
|
// before the parent is part of the frame tree.
|
||||||
|
let top_level_frame_id = match parent_info {
|
||||||
|
Some((_, FrameType::MozBrowserIFrame)) => frame_id,
|
||||||
|
Some((parent_id, _)) => self.get_top_level_frame_for_pipeline(parent_id),
|
||||||
|
None => self.root_frame_id,
|
||||||
|
};
|
||||||
|
|
||||||
let result = Pipeline::spawn::<Message, LTF, STF>(InitialPipelineState {
|
let result = Pipeline::spawn::<Message, LTF, STF>(InitialPipelineState {
|
||||||
id: pipeline_id,
|
id: pipeline_id,
|
||||||
frame_id: frame_id,
|
frame_id: frame_id,
|
||||||
|
top_level_frame_id: top_level_frame_id,
|
||||||
parent_info: parent_info,
|
parent_info: parent_info,
|
||||||
constellation_chan: self.script_sender.clone(),
|
constellation_chan: self.script_sender.clone(),
|
||||||
layout_to_constellation_chan: self.layout_sender.clone(),
|
layout_to_constellation_chan: self.layout_sender.clone(),
|
||||||
|
@ -847,8 +856,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
debug!("constellation got reload message");
|
debug!("constellation got reload message");
|
||||||
self.handle_reload_msg();
|
self.handle_reload_msg();
|
||||||
}
|
}
|
||||||
FromCompositorMsg::LogEntry(pipeline_id, thread_name, entry) => {
|
FromCompositorMsg::LogEntry(top_level_frame_id, thread_name, entry) => {
|
||||||
self.handle_log_entry(pipeline_id, thread_name, entry);
|
self.handle_log_entry(top_level_frame_id, thread_name, entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -999,8 +1008,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
FromScriptMsg::Exit => {
|
FromScriptMsg::Exit => {
|
||||||
self.compositor_proxy.send(ToCompositorMsg::Exit);
|
self.compositor_proxy.send(ToCompositorMsg::Exit);
|
||||||
}
|
}
|
||||||
FromScriptMsg::LogEntry(pipeline_id, thread_name, entry) => {
|
FromScriptMsg::LogEntry(top_level_frame_id, thread_name, entry) => {
|
||||||
self.handle_log_entry(pipeline_id, thread_name, entry);
|
self.handle_log_entry(top_level_frame_id, thread_name, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
FromScriptMsg::SetTitle(pipeline_id, title) => {
|
FromScriptMsg::SetTitle(pipeline_id, title) => {
|
||||||
|
@ -1172,10 +1181,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
fn handle_send_error(&mut self, pipeline_id: PipelineId, err: IOError) {
|
fn handle_send_error(&mut self, pipeline_id: PipelineId, err: IOError) {
|
||||||
// Treat send error the same as receiving a panic message
|
// Treat send error the same as receiving a panic message
|
||||||
debug!("Pipeline {:?} send error ({}).", pipeline_id, err);
|
debug!("Pipeline {:?} send error ({}).", pipeline_id, err);
|
||||||
self.handle_panic(Some(pipeline_id), format!("Send failed ({})", err), None);
|
let top_level_frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);
|
||||||
|
let reason = format!("Send failed ({})", err);
|
||||||
|
self.handle_panic(top_level_frame_id, reason, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_panic(&mut self, pipeline_id: Option<PipelineId>, reason: String, backtrace: Option<String>) {
|
fn handle_panic(&mut self, top_level_frame_id: FrameId, reason: String, backtrace: Option<String>) {
|
||||||
if opts::get().hard_fail {
|
if opts::get().hard_fail {
|
||||||
// It's quite difficult to make Servo exit cleanly if some threads have failed.
|
// It's quite difficult to make Servo exit cleanly if some threads have failed.
|
||||||
// Hard fail exists for test runners so we crash and that's good enough.
|
// Hard fail exists for test runners so we crash and that's good enough.
|
||||||
|
@ -1183,26 +1194,18 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Panic handler for pipeline {:?}: {}.", pipeline_id, reason);
|
debug!("Panic handler for top-level frame {}: {}.", top_level_frame_id, reason);
|
||||||
|
|
||||||
// Notify the browser chrome that the pipeline has failed
|
// Notify the browser chrome that the pipeline has failed
|
||||||
self.trigger_mozbrowsererror(pipeline_id, reason, backtrace);
|
self.trigger_mozbrowsererror(top_level_frame_id, reason, backtrace);
|
||||||
|
|
||||||
if let Some(pipeline_id) = pipeline_id {
|
let frame_id = FrameId::from(top_level_frame_id);
|
||||||
let pipeline_url = self.pipelines.get(&pipeline_id).map(|pipeline| pipeline.url.clone());
|
let pipeline_id = self.frames.get(&frame_id).map(|frame| frame.current.pipeline_id);
|
||||||
let parent_info = self.pipelines.get(&pipeline_id).and_then(|pipeline| pipeline.parent_info);
|
let pipeline_url = pipeline_id.and_then(|id| self.pipelines.get(&id).map(|pipeline| pipeline.url.clone()));
|
||||||
let window_size = self.pipelines.get(&pipeline_id).and_then(|pipeline| pipeline.size);
|
let parent_info = pipeline_id.and_then(|id| self.pipelines.get(&id).and_then(|pipeline| pipeline.parent_info));
|
||||||
let frame_id = self.pipelines.get(&pipeline_id).map(|pipeline| pipeline.frame_id);
|
let window_size = pipeline_id.and_then(|id| self.pipelines.get(&id).and_then(|pipeline| pipeline.size));
|
||||||
|
|
||||||
self.close_pipeline(pipeline_id, ExitPipelineMode::Force);
|
self.close_frame_children(frame_id, ExitPipelineMode::Force);
|
||||||
self.pipelines.remove(&pipeline_id);
|
|
||||||
|
|
||||||
while let Some(pending_pipeline_id) = self.pending_frames.iter().find(|pending| {
|
|
||||||
pending.old_pipeline_id == Some(pipeline_id)
|
|
||||||
}).map(|frame| frame.new_pipeline_id) {
|
|
||||||
warn!("removing pending frame change for failed pipeline");
|
|
||||||
self.close_pipeline(pending_pipeline_id, ExitPipelineMode::Force);
|
|
||||||
}
|
|
||||||
|
|
||||||
let failure_url = ServoUrl::parse("about:failure").expect("infallible");
|
let failure_url = ServoUrl::parse("about:failure").expect("infallible");
|
||||||
|
|
||||||
|
@ -1214,27 +1217,27 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
|
|
||||||
warn!("creating replacement pipeline for about:failure");
|
warn!("creating replacement pipeline for about:failure");
|
||||||
|
|
||||||
if let Some(frame_id) = frame_id {
|
|
||||||
let new_pipeline_id = PipelineId::new();
|
let new_pipeline_id = PipelineId::new();
|
||||||
let load_data = LoadData::new(failure_url, None, None);
|
let load_data = LoadData::new(failure_url, None, None);
|
||||||
self.new_pipeline(new_pipeline_id, frame_id, parent_info, Some(pipeline_id),
|
self.new_pipeline(new_pipeline_id, frame_id, parent_info, pipeline_id,
|
||||||
window_size, None, load_data, false);
|
window_size, None, load_data, false);
|
||||||
|
|
||||||
self.pending_frames.push(FrameChange {
|
self.pending_frames.push(FrameChange {
|
||||||
frame_id: frame_id,
|
frame_id: frame_id,
|
||||||
old_pipeline_id: Some(pipeline_id),
|
old_pipeline_id: pipeline_id,
|
||||||
new_pipeline_id: new_pipeline_id,
|
new_pipeline_id: new_pipeline_id,
|
||||||
document_ready: false,
|
document_ready: false,
|
||||||
replace: false,
|
replace: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_log_entry(&mut self, pipeline_id: Option<PipelineId>, thread_name: Option<String>, entry: LogEntry) {
|
fn handle_log_entry(&mut self, top_level_frame_id: Option<FrameId>, thread_name: Option<String>, entry: LogEntry) {
|
||||||
debug!("Received log entry {:?}.", entry);
|
debug!("Received log entry {:?}.", entry);
|
||||||
match entry {
|
match entry {
|
||||||
LogEntry::Panic(reason, backtrace) => self.handle_panic(pipeline_id, reason, Some(backtrace)),
|
LogEntry::Panic(reason, backtrace) => {
|
||||||
|
let top_level_frame_id = top_level_frame_id.unwrap_or(self.root_frame_id);
|
||||||
|
self.handle_panic(top_level_frame_id, reason, Some(backtrace));
|
||||||
|
},
|
||||||
LogEntry::Error(reason) | LogEntry::Warn(reason) => {
|
LogEntry::Error(reason) | LogEntry::Warn(reason) => {
|
||||||
// VecDeque::truncate is unstable
|
// VecDeque::truncate is unstable
|
||||||
if WARNINGS_BUFFER_SIZE <= self.handled_warnings.len() {
|
if WARNINGS_BUFFER_SIZE <= self.handled_warnings.len() {
|
||||||
|
@ -1291,25 +1294,24 @@ 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 (frame_id, parent_info) = match self.pipelines.get(&pipeline_id) {
|
let (frame_id, parent_id) = match self.pipelines.get(&pipeline_id) {
|
||||||
Some(pipeline) => (pipeline.frame_id, pipeline.parent_info),
|
Some(pipeline) => match pipeline.parent_info {
|
||||||
None => return warn!("Pipeline {:?} loaded after closure.", pipeline_id),
|
Some((parent_id, _)) => (pipeline.frame_id, parent_id),
|
||||||
};
|
None => return warn!("Pipeline {} has no parent.", pipeline_id),
|
||||||
let subframe_parent_id = match parent_info {
|
},
|
||||||
Some(ref parent) => parent.0,
|
None => return warn!("Pipeline {} loaded after closure.", pipeline_id),
|
||||||
None => return warn!("Pipeline {:?} has no parent.", pipeline_id),
|
|
||||||
};
|
};
|
||||||
let msg = ConstellationControlMsg::DispatchFrameLoadEvent {
|
let msg = ConstellationControlMsg::DispatchFrameLoadEvent {
|
||||||
target: frame_id,
|
target: frame_id,
|
||||||
parent: subframe_parent_id,
|
parent: parent_id,
|
||||||
child: pipeline_id,
|
child: pipeline_id,
|
||||||
};
|
};
|
||||||
let result = match self.pipelines.get(&subframe_parent_id) {
|
let result = match self.pipelines.get(&parent_id) {
|
||||||
Some(pipeline) => pipeline.script_chan.send(msg),
|
Some(parent) => parent.script_chan.send(msg),
|
||||||
None => return warn!("Pipeline {:?} subframe loaded after closure.", subframe_parent_id),
|
None => return warn!("Parent {} frame loaded after closure.", parent_id),
|
||||||
};
|
};
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
self.handle_send_error(subframe_parent_id, e);
|
self.handle_send_error(parent_id, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1371,7 +1373,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
(load_data, script_chan, window_size, is_private)
|
(load_data, script_chan, window_size, is_private)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Create the new pipeline, attached to the parent and push to pending frames
|
// Create the new pipeline, attached to the parent and push to pending frames
|
||||||
self.new_pipeline(load_info.new_pipeline_id,
|
self.new_pipeline(load_info.new_pipeline_id,
|
||||||
load_info.frame_id,
|
load_info.frame_id,
|
||||||
|
@ -1428,37 +1429,27 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
message: String,
|
message: String,
|
||||||
sender: IpcSender<bool>) {
|
sender: IpcSender<bool>) {
|
||||||
let display_alert_dialog = if PREFS.is_mozbrowser_enabled() {
|
let pipeline_isnt_root = self.pipelines.get(&pipeline_id).and_then(|pipeline| pipeline.parent_info).is_some();
|
||||||
let parent_pipeline_info = self.pipelines.get(&pipeline_id).and_then(|source| source.parent_info);
|
let mozbrowser_modal_prompt = pipeline_isnt_root && PREFS.is_mozbrowser_enabled();
|
||||||
if parent_pipeline_info.is_some() {
|
|
||||||
let root_pipeline_id = self.frames.get(&self.root_frame_id)
|
|
||||||
.map(|root_frame| root_frame.current.pipeline_id);
|
|
||||||
|
|
||||||
let ancestor_info = self.get_mozbrowser_ancestor_info(pipeline_id);
|
if mozbrowser_modal_prompt {
|
||||||
if let Some((ancestor_id, mozbrowser_iframe_id)) = ancestor_info {
|
|
||||||
if root_pipeline_id == Some(ancestor_id) {
|
|
||||||
match root_pipeline_id.and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) {
|
|
||||||
Some(root_pipeline) => {
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsershowmodalprompt
|
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsershowmodalprompt
|
||||||
let event = MozBrowserEvent::ShowModalPrompt("alert".to_owned(), "Alert".to_owned(),
|
let prompt_type = String::from("alert");
|
||||||
String::from(message), "".to_owned());
|
let title = String::from("Alert");
|
||||||
root_pipeline.trigger_mozbrowser_event(Some(mozbrowser_iframe_id), event);
|
let return_value = String::from("");
|
||||||
}
|
let event = MozBrowserEvent::ShowModalPrompt(prompt_type, title, message, return_value);
|
||||||
None => return warn!("Alert sent to Pipeline {:?} after closure.", root_pipeline_id),
|
let top_level_frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn!("A non-current frame is trying to show an alert.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = sender.send(display_alert_dialog);
|
match self.frames.get(&self.root_frame_id) {
|
||||||
|
None => warn!("Alert sent after root frame closure."),
|
||||||
|
Some(root_frame) => match self.pipelines.get(&root_frame.current.pipeline_id) {
|
||||||
|
None => warn!("Alert sent after root pipeline closure."),
|
||||||
|
Some(root_pipeline) => root_pipeline.trigger_mozbrowser_event(Some(top_level_frame_id), event),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = sender.send(!mozbrowser_modal_prompt);
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
self.handle_send_error(pipeline_id, e);
|
self.handle_send_error(pipeline_id, e);
|
||||||
}
|
}
|
||||||
|
@ -1546,7 +1537,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_load_start_msg(&mut self, pipeline_id: PipelineId) {
|
fn handle_load_start_msg(&mut self, pipeline_id: PipelineId) {
|
||||||
let frame_id = self.get_top_level_frame_for_pipeline(Some(pipeline_id));
|
let frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);
|
||||||
let forward = !self.joint_session_future_is_empty(frame_id);
|
let forward = !self.joint_session_future_is_empty(frame_id);
|
||||||
let back = !self.joint_session_past_is_empty(frame_id);
|
let back = !self.joint_session_past_is_empty(frame_id);
|
||||||
self.compositor_proxy.send(ToCompositorMsg::LoadStart(back, forward));
|
self.compositor_proxy.send(ToCompositorMsg::LoadStart(back, forward));
|
||||||
|
@ -1564,7 +1555,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
if webdriver_reset {
|
if webdriver_reset {
|
||||||
self.webdriver.load_channel = None;
|
self.webdriver.load_channel = None;
|
||||||
}
|
}
|
||||||
let frame_id = self.get_top_level_frame_for_pipeline(Some(pipeline_id));
|
let frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);
|
||||||
let forward = !self.joint_session_future_is_empty(frame_id);
|
let forward = !self.joint_session_future_is_empty(frame_id);
|
||||||
let back = !self.joint_session_past_is_empty(frame_id);
|
let back = !self.joint_session_past_is_empty(frame_id);
|
||||||
let root = self.root_frame_id == frame_id;
|
let root = self.root_frame_id == frame_id;
|
||||||
|
@ -1575,13 +1566,15 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
fn handle_traverse_history_msg(&mut self,
|
fn handle_traverse_history_msg(&mut self,
|
||||||
pipeline_id: Option<PipelineId>,
|
pipeline_id: Option<PipelineId>,
|
||||||
direction: TraversalDirection) {
|
direction: TraversalDirection) {
|
||||||
let frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);
|
let top_level_frame_id = pipeline_id
|
||||||
|
.map(|pipeline_id| self.get_top_level_frame_for_pipeline(pipeline_id))
|
||||||
|
.unwrap_or(self.root_frame_id);
|
||||||
|
|
||||||
let mut traversal_info = HashMap::new();
|
let mut traversal_info = HashMap::new();
|
||||||
|
|
||||||
match direction {
|
match direction {
|
||||||
TraversalDirection::Forward(delta) => {
|
TraversalDirection::Forward(delta) => {
|
||||||
let mut future = self.joint_session_future(frame_id);
|
let mut future = self.joint_session_future(top_level_frame_id);
|
||||||
for _ in 0..delta {
|
for _ in 0..delta {
|
||||||
match future.pop() {
|
match future.pop() {
|
||||||
Some((_, frame_id, pipeline_id)) => {
|
Some((_, frame_id, pipeline_id)) => {
|
||||||
|
@ -1592,7 +1585,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TraversalDirection::Back(delta) => {
|
TraversalDirection::Back(delta) => {
|
||||||
let mut past = self.joint_session_past(frame_id);
|
let mut past = self.joint_session_past(top_level_frame_id);
|
||||||
for _ in 0..delta {
|
for _ in 0..delta {
|
||||||
match past.pop() {
|
match past.pop() {
|
||||||
Some((_, frame_id, pipeline_id)) => {
|
Some((_, frame_id, pipeline_id)) => {
|
||||||
|
@ -1609,7 +1602,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_joint_session_history_length(&self, pipeline_id: PipelineId, sender: IpcSender<u32>) {
|
fn handle_joint_session_history_length(&self, pipeline_id: PipelineId, sender: IpcSender<u32>) {
|
||||||
let frame_id = self.get_top_level_frame_for_pipeline(Some(pipeline_id));
|
let frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);
|
||||||
|
|
||||||
// Initialize length at 1 to count for the current active entry
|
// Initialize length at 1 to count for the current active entry
|
||||||
let mut length = 1;
|
let mut length = 1;
|
||||||
|
@ -1966,11 +1959,21 @@ 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, mut pipeline_id: PipelineId) -> FrameId {
|
||||||
if PREFS.is_mozbrowser_enabled() {
|
if PREFS.is_mozbrowser_enabled() {
|
||||||
pipeline_id.and_then(|id| self.get_mozbrowser_ancestor_info(id))
|
loop {
|
||||||
.map(|(_, mozbrowser_iframe_id)| mozbrowser_iframe_id)
|
match self.pipelines.get(&pipeline_id) {
|
||||||
.unwrap_or(self.root_frame_id)
|
Some(pipeline) => match pipeline.parent_info {
|
||||||
|
Some((_, FrameType::MozBrowserIFrame)) => return pipeline.frame_id,
|
||||||
|
Some((parent_id, _)) => pipeline_id = parent_id,
|
||||||
|
None => return self.root_frame_id,
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
warn!("Finding top-level ancestor for pipeline {} after closure.", pipeline_id);
|
||||||
|
return 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
|
||||||
self.root_frame_id
|
self.root_frame_id
|
||||||
|
@ -2025,7 +2028,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
// This is the result of a link being clicked and a navigation completing.
|
// This is the result of a link being clicked and a navigation completing.
|
||||||
self.trigger_mozbrowserlocationchange(frame_change.new_pipeline_id);
|
self.trigger_mozbrowserlocationchange(frame_change.new_pipeline_id);
|
||||||
|
|
||||||
let top_level_frame_id = self.get_top_level_frame_for_pipeline(Some(frame_change.new_pipeline_id));
|
let top_level_frame_id = self.get_top_level_frame_for_pipeline(frame_change.new_pipeline_id);
|
||||||
self.clear_joint_session_future(top_level_frame_id);
|
self.clear_joint_session_future(top_level_frame_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2262,30 +2265,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
|
|
||||||
// Close a frame (and all children)
|
// Close a frame (and all children)
|
||||||
fn close_frame(&mut self, frame_id: FrameId, exit_mode: ExitPipelineMode) {
|
fn close_frame(&mut self, frame_id: FrameId, exit_mode: ExitPipelineMode) {
|
||||||
debug!("Closing frame {:?}.", frame_id);
|
debug!("Closing frame {}.", frame_id);
|
||||||
// Store information about the pipelines to be closed. Then close the
|
|
||||||
// pipelines, before removing ourself from the frames hash map. This
|
|
||||||
// ordering is vital - so that if close_pipeline() ends up closing
|
|
||||||
// any child frames, they can be removed from the parent frame correctly.
|
|
||||||
let parent_info = self.frames.get(&frame_id)
|
let parent_info = self.frames.get(&frame_id)
|
||||||
.and_then(|frame| self.pipelines.get(&frame.current.pipeline_id))
|
.and_then(|frame| self.pipelines.get(&frame.current.pipeline_id))
|
||||||
.and_then(|pipeline| pipeline.parent_info);
|
.and_then(|pipeline| pipeline.parent_info);
|
||||||
|
|
||||||
let pipelines_to_close = {
|
self.close_frame_children(frame_id, exit_mode);
|
||||||
let mut pipelines_to_close = vec!();
|
|
||||||
|
|
||||||
if let Some(frame) = self.frames.get(&frame_id) {
|
|
||||||
pipelines_to_close.extend_from_slice(&frame.next);
|
|
||||||
pipelines_to_close.push(frame.current.clone());
|
|
||||||
pipelines_to_close.extend_from_slice(&frame.prev);
|
|
||||||
}
|
|
||||||
|
|
||||||
pipelines_to_close
|
|
||||||
};
|
|
||||||
|
|
||||||
for entry in pipelines_to_close {
|
|
||||||
self.close_pipeline(entry.pipeline_id, exit_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.frames.remove(&frame_id).is_none() {
|
if self.frames.remove(&frame_id).is_none() {
|
||||||
warn!("Closing frame {:?} twice.", frame_id);
|
warn!("Closing frame {:?} twice.", frame_id);
|
||||||
|
@ -2301,6 +2286,31 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
debug!("Closed frame {:?}.", frame_id);
|
debug!("Closed frame {:?}.", frame_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the children of a frame
|
||||||
|
fn close_frame_children(&mut self, frame_id: FrameId, exit_mode: ExitPipelineMode) {
|
||||||
|
debug!("Closing frame children {}.", frame_id);
|
||||||
|
// Store information about the pipelines to be closed. Then close the
|
||||||
|
// pipelines, before removing ourself from the frames hash map. This
|
||||||
|
// ordering is vital - so that if close_pipeline() ends up closing
|
||||||
|
// any child frames, they can be removed from the parent frame correctly.
|
||||||
|
let mut pipelines_to_close: Vec<PipelineId> = self.pending_frames.iter()
|
||||||
|
.filter(|frame_change| frame_change.frame_id == frame_id)
|
||||||
|
.map(|frame_change| frame_change.new_pipeline_id)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if let Some(frame) = self.frames.get(&frame_id) {
|
||||||
|
pipelines_to_close.extend(frame.next.iter().map(|state| state.pipeline_id));
|
||||||
|
pipelines_to_close.push(frame.current.pipeline_id);
|
||||||
|
pipelines_to_close.extend(frame.prev.iter().map(|state| state.pipeline_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
for pipeline_id in pipelines_to_close {
|
||||||
|
self.close_pipeline(pipeline_id, exit_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Closed frame children {}.", frame_id);
|
||||||
|
}
|
||||||
|
|
||||||
// Close all pipelines at and beneath a given frame
|
// Close all pipelines at and beneath a given frame
|
||||||
fn close_pipeline(&mut self, pipeline_id: PipelineId, exit_mode: ExitPipelineMode) {
|
fn close_pipeline(&mut self, pipeline_id: PipelineId, exit_mode: ExitPipelineMode) {
|
||||||
debug!("Closing pipeline {:?}.", pipeline_id);
|
debug!("Closing pipeline {:?}.", pipeline_id);
|
||||||
|
@ -2410,49 +2420,29 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For a given pipeline, determine the mozbrowser iframe that transitively contains
|
|
||||||
/// it. There could be arbitrary levels of nested iframes in between them.
|
|
||||||
fn get_mozbrowser_ancestor_info(&self, original_pipeline_id: PipelineId) -> Option<(PipelineId, FrameId)> {
|
|
||||||
let mut pipeline_id = original_pipeline_id;
|
|
||||||
loop {
|
|
||||||
match self.pipelines.get(&pipeline_id) {
|
|
||||||
Some(pipeline) => match pipeline.parent_info {
|
|
||||||
Some((parent_id, FrameType::MozBrowserIFrame)) => return Some((parent_id, pipeline.frame_id)),
|
|
||||||
Some((parent_id, _)) => pipeline_id = parent_id,
|
|
||||||
None => return None,
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
warn!("Finding mozbrowser ancestor for pipeline {} after closure.", pipeline_id);
|
|
||||||
return None;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserlocationchange
|
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserlocationchange
|
||||||
// Note that this is a no-op if the pipeline is not a mozbrowser iframe
|
// Note that this is a no-op if the pipeline is not a mozbrowser iframe
|
||||||
fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) {
|
fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) {
|
||||||
if !PREFS.is_mozbrowser_enabled() { return; }
|
match self.pipelines.get(&pipeline_id) {
|
||||||
|
Some(pipeline) => if let Some((parent_id, FrameType::MozBrowserIFrame)) = pipeline.parent_info {
|
||||||
let url = match self.pipelines.get(&pipeline_id) {
|
match self.pipelines.get(&parent_id) {
|
||||||
Some(pipeline) => pipeline.url.to_string(),
|
Some(parent) => {
|
||||||
None => return warn!("triggered mozbrowser location change on closed pipeline {:?}", pipeline_id),
|
let can_go_forward = !self.joint_session_future_is_empty(pipeline.frame_id);
|
||||||
};
|
let can_go_back = !self.joint_session_past_is_empty(pipeline.frame_id);
|
||||||
|
let url = pipeline.url.to_string();
|
||||||
// If this is a mozbrowser iframe, then send the event with new url
|
|
||||||
if let Some((ancestor_id, mozbrowser_frame_id)) = self.get_mozbrowser_ancestor_info(pipeline_id) {
|
|
||||||
if let Some(ancestor) = self.pipelines.get(&ancestor_id) {
|
|
||||||
let can_go_forward = !self.joint_session_future(mozbrowser_frame_id).is_empty();
|
|
||||||
let can_go_back = !self.joint_session_past(mozbrowser_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);
|
parent.trigger_mozbrowser_event(Some(pipeline.frame_id), event);
|
||||||
|
},
|
||||||
|
None => warn!("triggered mozbrowser location change on closed parent {}", parent_id),
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
None => warn!("triggered mozbrowser location change on closed pipeline {}", pipeline_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsererror
|
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsererror
|
||||||
// Note that this does not require the pipeline to be an immediate child of the root
|
// Note that this does not require the pipeline to be an immediate child of the root
|
||||||
fn trigger_mozbrowsererror(&mut self, pipeline_id: Option<PipelineId>, reason: String, backtrace: Option<String>) {
|
fn trigger_mozbrowsererror(&mut self, top_level_frame_id: FrameId, reason: String, backtrace: Option<String>) {
|
||||||
if !PREFS.is_mozbrowser_enabled() { return; }
|
if !PREFS.is_mozbrowser_enabled() { return; }
|
||||||
|
|
||||||
let mut report = String::new();
|
let mut report = String::new();
|
||||||
|
@ -2474,21 +2464,19 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
|
|
||||||
let event = MozBrowserEvent::Error(MozBrowserErrorType::Fatal, reason, report);
|
let event = MozBrowserEvent::Error(MozBrowserErrorType::Fatal, reason, report);
|
||||||
|
|
||||||
if let Some(pipeline_id) = pipeline_id {
|
match self.frames.get(&top_level_frame_id) {
|
||||||
if let Some((ancestor_id, mozbrowser_iframe_id)) = self.get_mozbrowser_ancestor_info(pipeline_id) {
|
None => warn!("Mozbrowser error after top-level frame closed."),
|
||||||
if let Some(ancestor) = self.pipelines.get(&ancestor_id) {
|
Some(frame) => match self.pipelines.get(&frame.current.pipeline_id) {
|
||||||
return ancestor.trigger_mozbrowser_event(Some(mozbrowser_iframe_id), event);
|
None => warn!("Mozbrowser error after top-level pipeline closed."),
|
||||||
}
|
Some(pipeline) => match pipeline.parent_info {
|
||||||
}
|
None => pipeline.trigger_mozbrowser_event(None, event),
|
||||||
}
|
Some((parent_id, _)) => match self.pipelines.get(&parent_id) {
|
||||||
|
None => warn!("Mozbrowser error after root pipeline closed."),
|
||||||
if let Some(root_frame) = self.frames.get(&self.root_frame_id) {
|
Some(parent) => parent.trigger_mozbrowser_event(Some(top_level_frame_id), event),
|
||||||
if let Some(root_pipeline) = self.pipelines.get(&root_frame.current.pipeline_id) {
|
},
|
||||||
return root_pipeline.trigger_mozbrowser_event(None, event);
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
warn!("Mozbrowser error after root pipeline closed.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focused_pipeline_in_tree(&self, frame_id: FrameId) -> bool {
|
fn focused_pipeline_in_tree(&self, frame_id: FrameId) -> bool {
|
||||||
|
|
|
@ -82,6 +82,8 @@ pub struct InitialPipelineState {
|
||||||
pub id: PipelineId,
|
pub id: PipelineId,
|
||||||
/// The ID of the frame that contains this Pipeline.
|
/// The ID of the frame that contains this Pipeline.
|
||||||
pub frame_id: FrameId,
|
pub frame_id: FrameId,
|
||||||
|
/// The ID of the top-level frame that contains this Pipeline.
|
||||||
|
pub top_level_frame_id: FrameId,
|
||||||
/// The ID of the parent pipeline and frame type, if any.
|
/// The ID of the parent pipeline and frame type, if any.
|
||||||
/// If `None`, this is the root.
|
/// If `None`, this is the root.
|
||||||
pub parent_info: Option<(PipelineId, FrameType)>,
|
pub parent_info: Option<(PipelineId, FrameType)>,
|
||||||
|
@ -204,6 +206,7 @@ impl Pipeline {
|
||||||
let unprivileged_pipeline_content = UnprivilegedPipelineContent {
|
let unprivileged_pipeline_content = UnprivilegedPipelineContent {
|
||||||
id: state.id,
|
id: state.id,
|
||||||
frame_id: state.frame_id,
|
frame_id: state.frame_id,
|
||||||
|
top_level_frame_id: state.top_level_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,
|
||||||
|
@ -381,6 +384,7 @@ impl Pipeline {
|
||||||
pub struct UnprivilegedPipelineContent {
|
pub struct UnprivilegedPipelineContent {
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
frame_id: FrameId,
|
frame_id: FrameId,
|
||||||
|
top_level_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>,
|
||||||
|
@ -416,6 +420,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,
|
frame_id: self.frame_id,
|
||||||
|
top_level_frame_id: self.top_level_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,
|
||||||
|
@ -433,6 +438,7 @@ impl UnprivilegedPipelineContent {
|
||||||
}, self.load_data.clone());
|
}, self.load_data.clone());
|
||||||
|
|
||||||
LTF::create(self.id,
|
LTF::create(self.id,
|
||||||
|
Some(self.top_level_frame_id),
|
||||||
self.load_data.url,
|
self.load_data.url,
|
||||||
self.parent_info.is_some(),
|
self.parent_info.is_some(),
|
||||||
layout_pair,
|
layout_pair,
|
||||||
|
|
|
@ -42,7 +42,6 @@ extern crate selectors;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate servo_url;
|
extern crate servo_url;
|
||||||
extern crate style;
|
extern crate style;
|
||||||
extern crate style_traits;
|
|
||||||
extern crate util;
|
extern crate util;
|
||||||
extern crate webrender_traits;
|
extern crate webrender_traits;
|
||||||
|
|
||||||
|
@ -80,7 +79,7 @@ use layout::webrender_helpers::{WebRenderDisplayListConverter, WebRenderFrameBui
|
||||||
use layout::wrapper::LayoutNodeLayoutData;
|
use layout::wrapper::LayoutNodeLayoutData;
|
||||||
use layout::wrapper::drop_style_and_layout_data;
|
use layout::wrapper::drop_style_and_layout_data;
|
||||||
use layout_traits::LayoutThreadFactory;
|
use layout_traits::LayoutThreadFactory;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::{FrameId, PipelineId};
|
||||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
|
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
|
||||||
use net_traits::image_cache_thread::UsePlaceholder;
|
use net_traits::image_cache_thread::UsePlaceholder;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
@ -235,6 +234,7 @@ impl LayoutThreadFactory for LayoutThread {
|
||||||
|
|
||||||
/// Spawns a new layout thread.
|
/// Spawns a new layout thread.
|
||||||
fn create(id: PipelineId,
|
fn create(id: PipelineId,
|
||||||
|
top_level_frame_id: Option<FrameId>,
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
is_iframe: bool,
|
is_iframe: bool,
|
||||||
chan: (Sender<Msg>, Receiver<Msg>),
|
chan: (Sender<Msg>, Receiver<Msg>),
|
||||||
|
@ -251,7 +251,11 @@ impl LayoutThreadFactory for LayoutThread {
|
||||||
thread::spawn_named(format!("LayoutThread {:?}", id),
|
thread::spawn_named(format!("LayoutThread {:?}", id),
|
||||||
move || {
|
move || {
|
||||||
thread_state::initialize(thread_state::LAYOUT);
|
thread_state::initialize(thread_state::LAYOUT);
|
||||||
PipelineId::install(id);
|
|
||||||
|
if let Some(top_level_frame_id) = top_level_frame_id {
|
||||||
|
FrameId::install(top_level_frame_id);
|
||||||
|
}
|
||||||
|
|
||||||
{ // Ensures layout thread is destroyed before we send shutdown message
|
{ // Ensures layout thread is destroyed before we send shutdown message
|
||||||
let sender = chan.0;
|
let sender = chan.0;
|
||||||
let layout = LayoutThread::new(id,
|
let layout = LayoutThread::new(id,
|
||||||
|
@ -718,6 +722,7 @@ impl LayoutThread {
|
||||||
|
|
||||||
fn create_layout_thread(&self, info: NewLayoutThreadInfo) {
|
fn create_layout_thread(&self, info: NewLayoutThreadInfo) {
|
||||||
LayoutThread::create(info.id,
|
LayoutThread::create(info.id,
|
||||||
|
FrameId::installed(),
|
||||||
info.url.clone(),
|
info.url.clone(),
|
||||||
info.is_parent,
|
info.is_parent,
|
||||||
info.layout_pair,
|
info.layout_pair,
|
||||||
|
|
|
@ -20,7 +20,7 @@ extern crate webrender_traits;
|
||||||
|
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
use gfx::font_cache_thread::FontCacheThread;
|
||||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::{FrameId, PipelineId};
|
||||||
use net_traits::image_cache_thread::ImageCacheThread;
|
use net_traits::image_cache_thread::ImageCacheThread;
|
||||||
use profile_traits::{mem, time};
|
use profile_traits::{mem, time};
|
||||||
use script_traits::{ConstellationControlMsg, LayoutControlMsg};
|
use script_traits::{ConstellationControlMsg, LayoutControlMsg};
|
||||||
|
@ -33,6 +33,7 @@ use std::sync::mpsc::{Receiver, Sender};
|
||||||
pub trait LayoutThreadFactory {
|
pub trait LayoutThreadFactory {
|
||||||
type Message;
|
type Message;
|
||||||
fn create(id: PipelineId,
|
fn create(id: PipelineId,
|
||||||
|
top_level_frame_id: Option<FrameId>,
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
is_iframe: bool,
|
is_iframe: bool,
|
||||||
chan: (Sender<Self::Message>, Receiver<Self::Message>),
|
chan: (Sender<Self::Message>, Receiver<Self::Message>),
|
||||||
|
|
|
@ -217,8 +217,6 @@ impl PipelineNamespace {
|
||||||
|
|
||||||
thread_local!(pub static PIPELINE_NAMESPACE: Cell<Option<PipelineNamespace>> = Cell::new(None));
|
thread_local!(pub static PIPELINE_NAMESPACE: Cell<Option<PipelineNamespace>> = Cell::new(None));
|
||||||
|
|
||||||
thread_local!(pub static PIPELINE_ID: Cell<Option<PipelineId>> = Cell::new(None));
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||||
pub struct PipelineNamespaceId(pub u32);
|
pub struct PipelineNamespaceId(pub u32);
|
||||||
|
|
||||||
|
@ -246,15 +244,6 @@ impl PipelineId {
|
||||||
let PipelineIndex(index) = self.index;
|
let PipelineIndex(index) = self.index;
|
||||||
webrender_traits::PipelineId(namespace_id, index)
|
webrender_traits::PipelineId(namespace_id, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn install(id: PipelineId) {
|
|
||||||
PIPELINE_ID.with(|tls| tls.set(Some(id)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn installed() -> Option<PipelineId> {
|
|
||||||
PIPELINE_ID.with(|tls| tls.get())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PipelineId {
|
impl fmt::Display for PipelineId {
|
||||||
|
@ -265,6 +254,8 @@ impl fmt::Display for PipelineId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread_local!(pub static TOP_LEVEL_FRAME_ID: Cell<Option<FrameId>> = Cell::new(None));
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||||
pub struct FrameIndex(pub u32);
|
pub struct FrameIndex(pub u32);
|
||||||
|
|
||||||
|
@ -283,6 +274,16 @@ impl FrameId {
|
||||||
new_frame_id
|
new_frame_id
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Each script and layout thread should have the top-level frame id installed,
|
||||||
|
/// since it is used by crash reporting.
|
||||||
|
pub fn install(id: FrameId) {
|
||||||
|
TOP_LEVEL_FRAME_ID.with(|tls| tls.set(Some(id)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn installed() -> Option<FrameId> {
|
||||||
|
TOP_LEVEL_FRAME_ID.with(|tls| tls.get())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for FrameId {
|
impl fmt::Display for FrameId {
|
||||||
|
|
|
@ -26,7 +26,7 @@ use js::jsapi::{HandleValue, JS_SetInterruptCallback};
|
||||||
use js::jsapi::{JSAutoCompartment, JSContext};
|
use js::jsapi::{JSAutoCompartment, JSContext};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::FrameId;
|
||||||
use net_traits::{IpcSend, load_whole_resource};
|
use net_traits::{IpcSend, load_whole_resource};
|
||||||
use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType};
|
use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType};
|
||||||
use rand::random;
|
use rand::random;
|
||||||
|
@ -158,9 +158,14 @@ impl DedicatedWorkerGlobalScope {
|
||||||
closing: Arc<AtomicBool>) {
|
closing: Arc<AtomicBool>) {
|
||||||
let serialized_worker_url = worker_url.to_string();
|
let serialized_worker_url = worker_url.to_string();
|
||||||
let name = format!("WebWorker for {}", serialized_worker_url);
|
let name = format!("WebWorker for {}", serialized_worker_url);
|
||||||
|
let top_level_frame_id = FrameId::installed();
|
||||||
|
|
||||||
spawn_named(name, move || {
|
spawn_named(name, move || {
|
||||||
thread_state::initialize(thread_state::SCRIPT | thread_state::IN_WORKER);
|
thread_state::initialize(thread_state::SCRIPT | thread_state::IN_WORKER);
|
||||||
PipelineId::install(init.pipeline_id);
|
|
||||||
|
if let Some(top_level_frame_id) = top_level_frame_id {
|
||||||
|
FrameId::install(top_level_frame_id);
|
||||||
|
}
|
||||||
|
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let _stack_roots_tls = StackRootTLS::new(&roots);
|
let _stack_roots_tls = StackRootTLS::new(&roots);
|
||||||
|
|
|
@ -517,8 +517,8 @@ impl ScriptThreadFactory for ScriptThread {
|
||||||
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(state.id);
|
|
||||||
PipelineNamespace::install(state.pipeline_namespace_id);
|
PipelineNamespace::install(state.pipeline_namespace_id);
|
||||||
|
FrameId::install(state.top_level_frame_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;
|
||||||
|
|
|
@ -442,6 +442,8 @@ pub struct InitialScriptState {
|
||||||
pub parent_info: Option<(PipelineId, FrameType)>,
|
pub parent_info: Option<(PipelineId, FrameType)>,
|
||||||
/// The ID of the frame this script is part of.
|
/// The ID of the frame this script is part of.
|
||||||
pub frame_id: FrameId,
|
pub frame_id: FrameId,
|
||||||
|
/// The ID of the top-level frame this script is part of.
|
||||||
|
pub top_level_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.
|
||||||
|
@ -699,8 +701,8 @@ pub enum ConstellationMsg {
|
||||||
WebDriverCommand(WebDriverCommandMsg),
|
WebDriverCommand(WebDriverCommandMsg),
|
||||||
/// Reload the current page.
|
/// Reload the current page.
|
||||||
Reload,
|
Reload,
|
||||||
/// A log entry, with the pipeline id and thread name
|
/// A log entry, with the top-level frame id and thread name
|
||||||
LogEntry(Option<PipelineId>, Option<String>, LogEntry),
|
LogEntry(Option<FrameId>, Option<String>, LogEntry),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resources required by workerglobalscopes
|
/// Resources required by workerglobalscopes
|
||||||
|
|
|
@ -15,8 +15,8 @@ use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use euclid::point::Point2D;
|
use euclid::point::Point2D;
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
|
use msg::constellation_msg::{FrameId, PipelineId, TraversalDirection};
|
||||||
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
|
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
|
||||||
use msg::constellation_msg::{PipelineId, TraversalDirection};
|
|
||||||
use net_traits::CoreResourceMsg;
|
use net_traits::CoreResourceMsg;
|
||||||
use net_traits::storage_thread::StorageType;
|
use net_traits::storage_thread::StorageType;
|
||||||
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
||||||
|
@ -131,8 +131,8 @@ pub enum ScriptMsg {
|
||||||
ResizeTo(Size2D<u32>),
|
ResizeTo(Size2D<u32>),
|
||||||
/// Script has handled a touch event, and either prevented or allowed default actions.
|
/// Script has handled a touch event, and either prevented or allowed default actions.
|
||||||
TouchEventProcessed(EventResult),
|
TouchEventProcessed(EventResult),
|
||||||
/// A log entry, with the pipeline id and thread name
|
/// A log entry, with the top-level frame id and thread name
|
||||||
LogEntry(Option<PipelineId>, Option<String>, LogEntry),
|
LogEntry(Option<FrameId>, Option<String>, LogEntry),
|
||||||
/// Notifies the constellation that this pipeline has exited.
|
/// Notifies the constellation that this pipeline has exited.
|
||||||
PipelineExited(PipelineId),
|
PipelineExited(PipelineId),
|
||||||
/// Send messages from postMessage calls from serviceworker
|
/// Send messages from postMessage calls from serviceworker
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue