servo: Merge #13996 - Implement synchronous about:blank loading (from servo:about-blank); r=Ms2ger,jdm,asajeffrey,nox

Based on initial work by jdm in <https://github.com/servo/servo/pull/8600>.

Source-Repo: https://github.com/servo/servo
Source-Revision: 0d896a8d820e31037d536f133b5a8b8c43c2e1a2
This commit is contained in:
Ms2ger 2016-12-01 00:35:12 -08:00
Родитель 4345821670
Коммит 96740ae66f
9 изменённых файлов: 270 добавлений и 91 удалений

Просмотреть файл

@ -42,7 +42,7 @@ use rand::{Rng, SeedableRng, StdRng, random};
use script_traits::{AnimationState, AnimationTickType, CompositorEvent};
use script_traits::{ConstellationControlMsg, ConstellationMsg as FromCompositorMsg};
use script_traits::{DocumentState, LayoutControlMsg, LoadData};
use script_traits::{IFrameLoadInfo, IFrameSandboxState, TimerEventRequest};
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, TimerEventRequest};
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
use script_traits::{LogEntry, ServiceWorkerMsg, webdriver_msg};
use script_traits::{MozBrowserErrorType, MozBrowserEvent, WebDriverCommandMsg, WindowSizeData};
@ -914,11 +914,17 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
FromScriptMsg::ScriptLoadedURLInIFrame(load_info) => {
debug!("constellation got iframe URL load message {:?} {:?} {:?}",
load_info.parent_pipeline_id,
load_info.info.parent_pipeline_id,
load_info.old_pipeline_id,
load_info.new_pipeline_id);
load_info.info.new_pipeline_id);
self.handle_script_loaded_url_in_iframe_msg(load_info);
}
FromScriptMsg::ScriptLoadedAboutBlankInIFrame(load_info, lc) => {
debug!("constellation got loaded `about:blank` in iframe message {:?} {:?}",
load_info.parent_pipeline_id,
load_info.new_pipeline_id);
self.handle_script_loaded_about_blank_in_iframe_msg(load_info, lc);
}
FromScriptMsg::ChangeRunningAnimationsState(pipeline_id, animation_state) => {
self.handle_change_running_animations_state(pipeline_id, animation_state)
}
@ -1363,14 +1369,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// will result in a new pipeline being spawned and a frame tree being added to
// parent_pipeline_id's frame tree's children. This message is never the result of a
// page navigation.
fn handle_script_loaded_url_in_iframe_msg(&mut self, load_info: IFrameLoadInfo) {
fn handle_script_loaded_url_in_iframe_msg(&mut self, load_info: IFrameLoadInfoWithData) {
let (load_data, window_size, is_private) = {
let old_pipeline = load_info.old_pipeline_id
.and_then(|old_pipeline_id| self.pipelines.get(&old_pipeline_id));
let source_pipeline = match self.pipelines.get(&load_info.parent_pipeline_id) {
let source_pipeline = match self.pipelines.get(&load_info.info.parent_pipeline_id) {
Some(source_pipeline) => source_pipeline,
None => return warn!("Script loaded url in closed iframe {}.", load_info.parent_pipeline_id),
None => return warn!("Script loaded url in closed iframe {}.", load_info.info.parent_pipeline_id),
};
// If no url is specified, reload.
@ -1384,7 +1390,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
LoadData::new(url, None, None)
});
let is_private = load_info.is_private || source_pipeline.is_private;
let is_private = load_info.info.is_private || source_pipeline.is_private;
let window_size = old_pipeline.and_then(|old_pipeline| old_pipeline.size);
@ -1396,20 +1402,65 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
};
// Create the new pipeline, attached to the parent and push to pending frames
self.new_pipeline(load_info.new_pipeline_id,
load_info.frame_id,
Some((load_info.parent_pipeline_id, load_info.frame_type)),
self.new_pipeline(load_info.info.new_pipeline_id,
load_info.info.frame_id,
Some((load_info.info.parent_pipeline_id, load_info.info.frame_type)),
window_size,
load_data,
load_info.sandbox,
is_private);
self.pending_frames.push(FrameChange {
frame_id: load_info.frame_id,
frame_id: load_info.info.frame_id,
old_pipeline_id: load_info.old_pipeline_id,
new_pipeline_id: load_info.new_pipeline_id,
new_pipeline_id: load_info.info.new_pipeline_id,
document_ready: false,
replace: load_info.replace,
replace: load_info.info.replace,
});
}
fn handle_script_loaded_about_blank_in_iframe_msg(&mut self,
load_info: IFrameLoadInfo,
layout_sender: IpcSender<LayoutControlMsg>) {
let IFrameLoadInfo {
parent_pipeline_id,
new_pipeline_id,
frame_type,
replace,
frame_id,
is_private,
} = load_info;
let pipeline = {
let parent_pipeline = match self.pipelines.get(&parent_pipeline_id) {
Some(parent_pipeline) => parent_pipeline,
None => return warn!("Script loaded url in closed iframe {}.", parent_pipeline_id),
};
let script_sender = parent_pipeline.script_chan.clone();
let url = ServoUrl::parse("about:blank").expect("infallible");
Pipeline::new(new_pipeline_id,
frame_id,
Some((parent_pipeline_id, frame_type)),
script_sender,
layout_sender,
self.compositor_proxy.clone_compositor_proxy(),
is_private || parent_pipeline.is_private,
url,
None,
parent_pipeline.visible)
};
assert!(!self.pipelines.contains_key(&new_pipeline_id));
self.pipelines.insert(new_pipeline_id, pipeline);
self.pending_frames.push(FrameChange {
frame_id: frame_id,
old_pipeline_id: None,
new_pipeline_id: new_pipeline_id,
document_ready: false,
replace: replace,
});
}

Просмотреть файл

@ -165,8 +165,7 @@ impl Pipeline {
load_data: state.load_data.clone(),
window_size: window_size,
pipeline_port: pipeline_port,
layout_to_constellation_chan: state.layout_to_constellation_chan.clone(),
content_process_shutdown_chan: layout_content_process_shutdown_chan.clone(),
content_process_shutdown_chan: Some(layout_content_process_shutdown_chan.clone()),
layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize,
};
@ -254,23 +253,23 @@ impl Pipeline {
state.window_size,
state.prev_visibility.unwrap_or(true));
pipeline.notify_visibility();
Ok((pipeline, child_process))
}
fn new(id: PipelineId,
frame_id: FrameId,
parent_info: Option<(PipelineId, FrameType)>,
script_chan: Rc<ScriptChan>,
layout_chan: IpcSender<LayoutControlMsg>,
compositor_proxy: Box<CompositorProxy + 'static + Send>,
is_private: bool,
url: ServoUrl,
size: Option<TypedSize2D<f32, PagePx>>,
visible: bool)
-> Pipeline {
Pipeline {
/// Creates a new `Pipeline`, after the script and layout threads have been
/// spawned.
pub fn new(id: PipelineId,
frame_id: FrameId,
parent_info: Option<(PipelineId, FrameType)>,
script_chan: Rc<ScriptChan>,
layout_chan: IpcSender<LayoutControlMsg>,
compositor_proxy: Box<CompositorProxy + 'static + Send>,
is_private: bool,
url: ServoUrl,
size: Option<TypedSize2D<f32, PagePx>>,
visible: bool)
-> Pipeline {
let pipeline = Pipeline {
id: id,
frame_id: frame_id,
parent_info: parent_info,
@ -284,7 +283,11 @@ impl Pipeline {
running_animations: false,
visible: visible,
is_private: is_private,
}
};
pipeline.notify_visibility();
pipeline
}
pub fn exit(&self) {
@ -424,6 +427,7 @@ impl UnprivilegedPipelineContent {
control_chan: self.script_chan.clone(),
control_port: self.script_port,
constellation_chan: self.constellation_chan,
layout_to_constellation_chan: self.layout_to_constellation_chan.clone(),
scheduler_chan: self.scheduler_chan,
bluetooth_thread: self.bluetooth_thread,
resource_threads: self.resource_threads,
@ -448,7 +452,7 @@ impl UnprivilegedPipelineContent {
self.font_cache_thread,
self.time_profiler_chan,
self.mem_profiler_chan,
self.layout_content_process_shutdown_chan,
Some(self.layout_content_process_shutdown_chan),
self.webrender_api_sender,
self.prefs.get("layout.threads").expect("exists").value()
.as_u64().expect("count") as usize);

Просмотреть файл

@ -246,7 +246,7 @@ impl LayoutThreadFactory for LayoutThread {
font_cache_thread: FontCacheThread,
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
content_process_shutdown_chan: IpcSender<()>,
content_process_shutdown_chan: Option<IpcSender<()>>,
webrender_api_sender: webrender_traits::RenderApiSender,
layout_threads: usize) {
thread::spawn_named(format!("LayoutThread {:?}", id),
@ -278,7 +278,9 @@ impl LayoutThreadFactory for LayoutThread {
layout.start();
}, reporter_name, sender, Msg::CollectReports);
}
let _ = content_process_shutdown_chan.send(());
if let Some(content_process_shutdown_chan) = content_process_shutdown_chan {
let _ = content_process_shutdown_chan.send(());
}
});
}
}

Просмотреть файл

@ -44,7 +44,7 @@ pub trait LayoutThreadFactory {
font_cache_thread: FontCacheThread,
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
content_process_shutdown_chan: IpcSender<()>,
content_process_shutdown_chan: Option<IpcSender<()>>,
webrender_api_sender: webrender_traits::RenderApiSender,
layout_threads: usize);
}

Просмотреть файл

@ -20,6 +20,7 @@ use dom::bindings::conversions::ToJSValConvertible;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root};
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
use dom::browsingcontext::BrowsingContext;
@ -42,14 +43,16 @@ use js::jsval::{NullValue, UndefinedValue};
use msg::constellation_msg::{FrameType, FrameId, PipelineId, TraversalDirection};
use net_traits::response::HttpsState;
use script_layout_interface::message::ReflowQueryType;
use script_thread::ScriptThread;
use script_traits::{IFrameLoadInfo, LoadData, MozBrowserEvent, ScriptMsg as ConstellationMsg};
use script_thread::{ScriptThread, Runnable};
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, LoadData};
use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg as ConstellationMsg};
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::cell::Cell;
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
use style::context::ReflowGoal;
use task_source::TaskSource;
use util::prefs::PREFS;
use util::servo_version;
@ -66,6 +69,12 @@ bitflags! {
}
}
#[derive(PartialEq)]
enum ProcessingMode {
FirstTime,
NotFirstTime,
}
#[dom_struct]
pub struct HTMLIFrameElement {
htmlelement: HTMLElement,
@ -131,20 +140,46 @@ impl HTMLIFrameElement {
let global_scope = window.upcast::<GlobalScope>();
let load_info = IFrameLoadInfo {
load_data: load_data,
parent_pipeline_id: global_scope.pipeline_id(),
frame_id: self.frame_id,
old_pipeline_id: old_pipeline_id,
new_pipeline_id: new_pipeline_id,
sandbox: sandboxed,
is_private: private_iframe,
frame_type: frame_type,
replace: replace,
};
global_scope
.constellation_chan()
.send(ConstellationMsg::ScriptLoadedURLInIFrame(load_info))
.unwrap();
if load_data.as_ref().map_or(false, |d| d.url.as_str() == "about:blank") {
let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
global_scope
.constellation_chan()
.send(ConstellationMsg::ScriptLoadedAboutBlankInIFrame(load_info, pipeline_sender))
.unwrap();
let new_layout_info = NewLayoutInfo {
parent_info: Some((global_scope.pipeline_id(), frame_type)),
new_pipeline_id: new_pipeline_id,
frame_id: self.frame_id,
load_data: load_data.unwrap(),
pipeline_port: pipeline_receiver,
content_process_shutdown_chan: None,
window_size: None,
layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize,
};
ScriptThread::process_attach_layout(new_layout_info);
} else {
let load_info = IFrameLoadInfoWithData {
info: load_info,
load_data: load_data,
old_pipeline_id: old_pipeline_id,
sandbox: sandboxed,
};
global_scope
.constellation_chan()
.send(ConstellationMsg::ScriptLoadedURLInIFrame(load_info))
.unwrap();
}
if PREFS.is_mozbrowser_enabled() {
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
@ -152,9 +187,23 @@ impl HTMLIFrameElement {
}
}
pub fn process_the_iframe_attributes(&self) {
/// https://html.spec.whatwg.org/multipage/#process-the-iframe-attributes
fn process_the_iframe_attributes(&self, mode: ProcessingMode) {
// TODO: srcdoc
// https://github.com/whatwg/html/issues/490
if mode == ProcessingMode::FirstTime && !self.upcast::<Element>().has_attribute(&local_name!("src")) {
let window = window_from_node(self);
let event_loop = window.dom_manipulation_task_source();
let _ = event_loop.queue(box IframeLoadEventSteps::new(self),
window.upcast());
return;
}
let url = self.get_url();
// TODO: check ancestor browsing contexts for same URL
let document = document_from_node(self);
self.navigate_or_reload_child_browsing_context(
Some(LoadData::new(url, document.get_referrer_policy(), Some(document.url()))), false);
@ -171,6 +220,16 @@ impl HTMLIFrameElement {
}
}
fn create_nested_browsing_context(&self) {
// Synchronously create a new context and navigate it to about:blank.
let url = ServoUrl::parse("about:blank").unwrap();
let document = document_from_node(self);
let load_data = LoadData::new(url,
document.get_referrer_policy(),
Some(document.url().clone()));
self.navigate_or_reload_child_browsing_context(Some(load_data), false);
}
pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId) {
self.pipeline_id.set(Some(new_pipeline_id));
@ -272,7 +331,11 @@ impl HTMLIFrameElement {
self.pipeline_id.get()
.and_then(|pipeline_id| ScriptThread::find_document(pipeline_id))
.and_then(|document| {
if self.global().get_url().origin() == document.global().get_url().origin() {
// FIXME(#10964): this should use the Document's origin and the
// origin of the incumbent settings object.
let contained_url = document.global().get_url();
if self.global().get_url().origin() == contained_url.origin() ||
contained_url.as_str() == "about:blank" {
Some(Root::from_ref(document.window()))
} else {
None
@ -458,18 +521,7 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
// https://html.spec.whatwg.org/multipage/#dom-iframe-contentdocument
fn GetContentDocument(&self) -> Option<Root<Document>> {
self.get_content_window().and_then(|window| {
// FIXME(#10964): this should use the Document's origin and the
// origin of the incumbent settings object.
let self_url = self.get_url();
let win_url = window_from_node(self).get_url();
if UrlHelper::SameOrigin(&self_url, &win_url) {
Some(window.Document())
} else {
None
}
})
self.get_content_window().map(|window| window.Document())
}
// Experimental mozbrowser implementation is based on the webidl
@ -601,19 +653,17 @@ impl VirtualMethods for HTMLIFrameElement {
}));
},
&local_name!("src") => {
if let AttributeMutation::Set(_) = mutation {
// https://html.spec.whatwg.org/multipage/#the-iframe-element
// "Similarly, whenever an iframe element with a non-null nested browsing context
// but with no srcdoc attribute specified has its src attribute set, changed, or removed,
// the user agent must process the iframe attributes,"
// but we can't check that directly, since the child browsing context
// may be in a different script thread. Instread, we check to see if the parent
// is in a document tree and has a browsing context, which is what causes
// the child browsing context to be created.
if self.upcast::<Node>().is_in_doc_with_browsing_context() {
debug!("iframe {} src set while in browsing context.", self.frame_id);
self.process_the_iframe_attributes();
}
// https://html.spec.whatwg.org/multipage/#the-iframe-element
// "Similarly, whenever an iframe element with a non-null nested browsing context
// but with no srcdoc attribute specified has its src attribute set, changed, or removed,
// the user agent must process the iframe attributes,"
// but we can't check that directly, since the child browsing context
// may be in a different script thread. Instread, we check to see if the parent
// is in a document tree and has a browsing context, which is what causes
// the child browsing context to be created.
if self.upcast::<Node>().is_in_doc_with_browsing_context() {
debug!("iframe {} src set while in browsing context.", self.frame_id);
self.process_the_iframe_attributes(ProcessingMode::NotFirstTime);
}
},
_ => {},
@ -642,7 +692,8 @@ impl VirtualMethods for HTMLIFrameElement {
// iframe attributes for the "first time"."
if self.upcast::<Node>().is_in_doc_with_browsing_context() {
debug!("iframe {} bound to browsing context.", self.frame_id);
self.process_the_iframe_attributes();
self.create_nested_browsing_context();
self.process_the_iframe_attributes(ProcessingMode::FirstTime);
}
}
@ -667,7 +718,7 @@ impl VirtualMethods for HTMLIFrameElement {
// HTMLIFrameElement::contentDocument.
let self_url = self.get_url();
let win_url = window_from_node(self).get_url();
UrlHelper::SameOrigin(&self_url, &win_url)
UrlHelper::SameOrigin(&self_url, &win_url) || self_url.as_str() == "about:blank"
};
let (sender, receiver) = if same_origin {
(None, None)
@ -690,3 +741,24 @@ impl VirtualMethods for HTMLIFrameElement {
}
}
}
struct IframeLoadEventSteps {
frame_element: Trusted<HTMLIFrameElement>,
pipeline_id: PipelineId,
}
impl IframeLoadEventSteps {
fn new(frame_element: &HTMLIFrameElement) -> IframeLoadEventSteps {
IframeLoadEventSteps {
frame_element: Trusted::new(frame_element),
pipeline_id: frame_element.pipeline_id().unwrap(),
}
}
}
impl Runnable for IframeLoadEventSteps {
fn handler(self: Box<IframeLoadEventSteps>) {
let this = self.frame_element.root();
this.iframe_load_event_steps(self.pipeline_id);
}
}

Просмотреть файл

@ -71,7 +71,8 @@ use js::rust::Runtime;
use layout_wrapper::ServoLayoutNode;
use mem::heap_size_of_self_and_children;
use msg::constellation_msg::{FrameId, FrameType, PipelineId, PipelineNamespace};
use net_traits::{CoreResourceMsg, IpcSend, Metadata, ReferrerPolicy, ResourceThreads};
use net_traits::{CoreResourceMsg, FetchMetadata, FetchResponseListener};
use net_traits::{IpcSend, Metadata, ReferrerPolicy, ResourceThreads};
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
use net_traits::request::{CredentialsMode, Destination, RequestInit};
use net_traits::storage_thread::StorageType;
@ -82,7 +83,7 @@ use script_layout_interface::message::{self, NewLayoutThreadInfo, ReflowQueryTyp
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory, EnqueuedPromiseCallback};
use script_runtime::{ScriptPort, StackRootTLS, get_reports, new_rt_and_cx, PromiseJobQueue};
use script_traits::{CompositorEvent, ConstellationControlMsg, EventResult};
use script_traits::{InitialScriptState, LoadData, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{InitialScriptState, LayoutMsg, LoadData, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg};
use script_traits::{ScriptThreadFactory, TimerEvent, TimerEventRequest, TimerSource};
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
@ -434,6 +435,9 @@ pub struct ScriptThread {
/// For communicating load url messages to the constellation
constellation_chan: IpcSender<ConstellationMsg>,
/// A sender for new layout threads to communicate to the constellation.
layout_to_constellation_chan: IpcSender<LayoutMsg>,
/// The port on which we receive messages from the image cache
image_cache_port: Receiver<ImageCacheResult>,
@ -602,6 +606,17 @@ impl ScriptThread {
});
}
pub fn process_attach_layout(new_layout_info: NewLayoutInfo) {
SCRIPT_THREAD_ROOT.with(|root| {
if let Some(script_thread) = root.get() {
let script_thread = unsafe { &*script_thread };
script_thread.profile_event(ScriptThreadEventCategory::AttachLayout, || {
script_thread.handle_new_layout(new_layout_info);
})
}
});
}
pub fn find_document(id: PipelineId) -> Option<Root<Document>> {
SCRIPT_THREAD_ROOT.with(|root| root.get().and_then(|script_thread| {
let script_thread = unsafe { &*script_thread };
@ -681,6 +696,8 @@ impl ScriptThread {
content_process_shutdown_chan: state.content_process_shutdown_chan,
promise_job_queue: PromiseJobQueue::new(),
layout_to_constellation_chan: state.layout_to_constellation_chan,
}
}
@ -1179,7 +1196,6 @@ impl ScriptThread {
load_data,
window_size,
pipeline_port,
layout_to_constellation_chan,
content_process_shutdown_chan,
layout_threads,
} = new_layout_info;
@ -1193,7 +1209,7 @@ impl ScriptThread {
is_parent: false,
layout_pair: layout_pair,
pipeline_port: pipeline_port,
constellation_chan: layout_to_constellation_chan,
constellation_chan: self.layout_to_constellation_chan.clone(),
script_chan: self.control_chan.clone(),
image_cache_thread: self.image_cache_thread.clone(),
content_process_shutdown_chan: content_process_shutdown_chan,
@ -1215,7 +1231,11 @@ impl ScriptThread {
let new_load = InProgressLoad::new(new_pipeline_id, frame_id, parent_info,
layout_chan, window_size,
load_data.url.clone());
self.start_page_load(new_load, load_data);
if load_data.url.as_str() == "about:blank" {
self.start_page_load_about_blank(new_load);
} else {
self.start_page_load(new_load, load_data);
}
}
fn handle_loads_complete(&self, pipeline: PipelineId) {
@ -1641,7 +1661,8 @@ impl ScriptThread {
/// Notify the containing document of a child frame that has completed loading.
fn handle_frame_load_event(&self, parent_id: PipelineId, frame_id: FrameId, child_id: PipelineId) {
match self.documents.borrow().find_iframe(parent_id, frame_id) {
let iframe = self.documents.borrow().find_iframe(parent_id, frame_id);
match iframe {
Some(iframe) => iframe.iframe_load_event_steps(child_id),
None => warn!("Message sent to closed pipeline {}.", parent_id),
}
@ -2014,7 +2035,8 @@ impl ScriptThread {
replace: bool) {
match frame_id {
Some(frame_id) => {
if let Some(iframe) = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id) {
let iframe = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id);
if let Some(iframe) = iframe {
iframe.navigate_or_reload_child_browsing_context(Some(load_data), replace);
}
}
@ -2092,6 +2114,23 @@ impl ScriptThread {
self.incomplete_loads.borrow_mut().push(incomplete);
}
/// Synchronously fetch `about:blank`. Stores the `InProgressLoad`
/// argument until a notification is received that the fetch is complete.
fn start_page_load_about_blank(&self, incomplete: InProgressLoad) {
let id = incomplete.pipeline_id;
self.incomplete_loads.borrow_mut().push(incomplete);
let url = ServoUrl::parse("about:blank").unwrap();
let mut context = ParserContext::new(id, url.clone());
let mut meta = Metadata::default(url);
meta.set_content_type(Some(&mime!(Text / Html)));
context.process_response(Ok(FetchMetadata::Unfiltered(meta)));
context.process_response_chunk(vec![]);
context.process_response_eof(Ok(()));
}
fn handle_parsing_complete(&self, id: PipelineId) {
let document = match self.documents.borrow().find_document(id) {
Some(document) => document,

Просмотреть файл

@ -142,6 +142,6 @@ pub struct NewLayoutThreadInfo {
pub constellation_chan: IpcSender<ConstellationMsg>,
pub script_chan: IpcSender<ConstellationControlMsg>,
pub image_cache_thread: ImageCacheThread,
pub content_process_shutdown_chan: IpcSender<()>,
pub content_process_shutdown_chan: Option<IpcSender<()>>,
pub layout_threads: usize,
}

Просмотреть файл

@ -177,10 +177,8 @@ pub struct NewLayoutInfo {
pub window_size: Option<WindowSizeData>,
/// A port on which layout can receive messages from the pipeline.
pub pipeline_port: IpcReceiver<LayoutControlMsg>,
/// A sender for the layout thread to communicate to the constellation.
pub layout_to_constellation_chan: IpcSender<LayoutMsg>,
/// A shutdown channel so that layout can tell the content process to shut down when it's done.
pub content_process_shutdown_chan: IpcSender<()>,
pub content_process_shutdown_chan: Option<IpcSender<()>>,
/// Number of threads to use for layout.
pub layout_threads: usize,
}
@ -450,6 +448,8 @@ pub struct InitialScriptState {
pub control_port: IpcReceiver<ConstellationControlMsg>,
/// A channel on which messages can be sent to the constellation from script.
pub constellation_chan: IpcSender<ScriptMsg>,
/// A sender for the layout thread to communicate to the constellation.
pub layout_to_constellation_chan: IpcSender<LayoutMsg>,
/// A channel to schedule timer events.
pub scheduler_chan: IpcSender<TimerEventRequest>,
/// A channel to the resource manager thread.
@ -492,21 +492,15 @@ pub enum IFrameSandboxState {
IFrameUnsandboxed
}
/// Specifies the information required to load a URL in an iframe.
/// Specifies the information required to load an iframe.
#[derive(Deserialize, Serialize)]
pub struct IFrameLoadInfo {
/// Load data containing the url to load
pub load_data: Option<LoadData>,
/// Pipeline ID of the parent of this iframe
pub parent_pipeline_id: PipelineId,
/// The ID for this iframe.
pub frame_id: FrameId,
/// The old pipeline ID for this iframe, if a page was previously loaded.
pub old_pipeline_id: Option<PipelineId>,
/// The new pipeline ID that the iframe has generated.
pub new_pipeline_id: PipelineId,
/// Sandbox type of this iframe
pub sandbox: IFrameSandboxState,
/// Whether this iframe should be considered private
pub is_private: bool,
/// Whether this iframe is a mozbrowser iframe
@ -516,6 +510,19 @@ pub struct IFrameLoadInfo {
pub replace: bool,
}
/// Specifies the information required to load a URL in an iframe.
#[derive(Deserialize, Serialize)]
pub struct IFrameLoadInfoWithData {
/// The information required to load an iframe.
pub info: IFrameLoadInfo,
/// Load data containing the url to load
pub load_data: Option<LoadData>,
/// The old pipeline ID for this iframe, if a page was previously loaded.
pub old_pipeline_id: Option<PipelineId>,
/// Sandbox type of this iframe
pub sandbox: IFrameSandboxState,
}
// https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API#Events
/// The events fired in a Browser API context (`<iframe mozbrowser>`)
#[derive(Deserialize, Serialize)]

Просмотреть файл

@ -6,6 +6,8 @@ use AnimationState;
use CompositorEvent;
use DocumentState;
use IFrameLoadInfo;
use IFrameLoadInfoWithData;
use LayoutControlMsg;
use LoadData;
use MozBrowserEvent;
use WorkerGlobalScopeInit;
@ -105,7 +107,9 @@ pub enum ScriptMsg {
/// Notifies constellation that an iframe's visibility has been changed.
VisibilityChangeComplete(PipelineId, bool),
/// A load has been requested in an IFrame.
ScriptLoadedURLInIFrame(IFrameLoadInfo),
ScriptLoadedURLInIFrame(IFrameLoadInfoWithData),
/// A load of `about:blank` has been completed in an IFrame.
ScriptLoadedAboutBlankInIFrame(IFrameLoadInfo, IpcSender<LayoutControlMsg>),
/// Requests that the constellation set the contents of the clipboard
SetClipboardContents(String),
/// Mark a new document as active