mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Added a TopLevelBrowsingContextId type.
This commit is contained in:
parent
b428a94326
commit
42577365b7
15 changed files with 407 additions and 234 deletions
|
@ -58,7 +58,7 @@ use js::glue::{CallObjectTracer, CallValueTracer};
|
|||
use js::jsapi::{GCTraceKindToAscii, Heap, JSObject, JSTracer, TraceKind};
|
||||
use js::jsval::JSVal;
|
||||
use js::rust::Runtime;
|
||||
use msg::constellation_msg::{BrowsingContextId, FrameType, PipelineId};
|
||||
use msg::constellation_msg::{BrowsingContextId, FrameType, PipelineId, TopLevelBrowsingContextId};
|
||||
use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads};
|
||||
use net_traits::filemanager_thread::RelativePos;
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
|
@ -336,7 +336,8 @@ unsafe_no_jsmanaged_fields!(TrustedPromise);
|
|||
unsafe_no_jsmanaged_fields!(PropertyDeclarationBlock);
|
||||
// These three are interdependent, if you plan to put jsmanaged data
|
||||
// in one of these make sure it is propagated properly to containing structs
|
||||
unsafe_no_jsmanaged_fields!(DocumentActivity, BrowsingContextId, FrameType, WindowSizeData, WindowSizeType, PipelineId);
|
||||
unsafe_no_jsmanaged_fields!(DocumentActivity, WindowSizeData, WindowSizeType);
|
||||
unsafe_no_jsmanaged_fields!(BrowsingContextId, FrameType, PipelineId, TopLevelBrowsingContextId);
|
||||
unsafe_no_jsmanaged_fields!(TimerEventId, TimerSource);
|
||||
unsafe_no_jsmanaged_fields!(TimelineMarkerType);
|
||||
unsafe_no_jsmanaged_fields!(WorkerId);
|
||||
|
|
|
@ -27,7 +27,7 @@ use js::jsapi::{HandleValue, JS_SetInterruptCallback};
|
|||
use js::jsapi::{JSAutoCompartment, JSContext};
|
||||
use js::jsval::UndefinedValue;
|
||||
use js::rust::Runtime;
|
||||
use msg::constellation_msg::BrowsingContextId;
|
||||
use msg::constellation_msg::TopLevelBrowsingContextId;
|
||||
use net_traits::{IpcSend, load_whole_resource};
|
||||
use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType};
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
|
||||
|
@ -159,13 +159,13 @@ impl DedicatedWorkerGlobalScope {
|
|||
closing: Arc<AtomicBool>) {
|
||||
let serialized_worker_url = worker_url.to_string();
|
||||
let name = format!("WebWorker for {}", serialized_worker_url);
|
||||
let top_level_browsing_context_id = BrowsingContextId::installed();
|
||||
let top_level_browsing_context_id = TopLevelBrowsingContextId::installed();
|
||||
|
||||
thread::Builder::new().name(name).spawn(move || {
|
||||
thread_state::initialize(thread_state::SCRIPT | thread_state::IN_WORKER);
|
||||
|
||||
if let Some(top_level_browsing_context_id) = top_level_browsing_context_id {
|
||||
BrowsingContextId::install(top_level_browsing_context_id);
|
||||
TopLevelBrowsingContextId::install(top_level_browsing_context_id);
|
||||
}
|
||||
|
||||
let roots = RootCollection::new();
|
||||
|
|
|
@ -100,7 +100,7 @@ use ipc_channel::ipc::{self, IpcSender};
|
|||
use js::jsapi::{JSContext, JSObject, JSRuntime};
|
||||
use js::jsapi::JS_GetRuntime;
|
||||
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
|
||||
use msg::constellation_msg::{BrowsingContextId, Key, KeyModifiers, KeyState};
|
||||
use msg::constellation_msg::{BrowsingContextId, Key, KeyModifiers, KeyState, TopLevelBrowsingContextId};
|
||||
use net_traits::{FetchResponseMsg, IpcSend, ReferrerPolicy};
|
||||
use net_traits::CookieSource::NonHTTP;
|
||||
use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl};
|
||||
|
@ -1899,7 +1899,21 @@ impl Document {
|
|||
/// Find an iframe element in the document.
|
||||
pub fn find_iframe(&self, browsing_context_id: BrowsingContextId) -> Option<Root<HTMLIFrameElement>> {
|
||||
self.iter_iframes()
|
||||
.find(|node| node.browsing_context_id() == browsing_context_id)
|
||||
.find(|node| node.browsing_context_id() == Some(browsing_context_id))
|
||||
}
|
||||
|
||||
/// Find a mozbrowser iframe element in the document.
|
||||
pub fn find_mozbrowser_iframe(&self,
|
||||
top_level_browsing_context_id: TopLevelBrowsingContextId)
|
||||
-> Option<Root<HTMLIFrameElement>>
|
||||
{
|
||||
match self.find_iframe(BrowsingContextId::from(top_level_browsing_context_id)) {
|
||||
None => None,
|
||||
Some(iframe) => {
|
||||
assert!(iframe.Mozbrowser());
|
||||
Some(iframe)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_dom_loading(&self) -> u64 {
|
||||
|
|
|
@ -40,7 +40,7 @@ use html5ever::{LocalName, Prefix};
|
|||
use ipc_channel::ipc;
|
||||
use js::jsapi::{JSAutoCompartment, JSContext, MutableHandleValue};
|
||||
use js::jsval::{NullValue, UndefinedValue};
|
||||
use msg::constellation_msg::{FrameType, BrowsingContextId, PipelineId, TraversalDirection};
|
||||
use msg::constellation_msg::{FrameType, BrowsingContextId, PipelineId, TopLevelBrowsingContextId, TraversalDirection};
|
||||
use net_traits::response::HttpsState;
|
||||
use script_layout_interface::message::ReflowQueryType;
|
||||
use script_thread::{ScriptThread, Runnable};
|
||||
|
@ -84,7 +84,8 @@ enum ProcessingMode {
|
|||
#[dom_struct]
|
||||
pub struct HTMLIFrameElement {
|
||||
htmlelement: HTMLElement,
|
||||
browsing_context_id: BrowsingContextId,
|
||||
top_level_browsing_context_id: Cell<Option<TopLevelBrowsingContextId>>,
|
||||
browsing_context_id: Cell<Option<BrowsingContextId>>,
|
||||
pipeline_id: Cell<Option<PipelineId>>,
|
||||
pending_pipeline_id: Cell<Option<PipelineId>>,
|
||||
sandbox: MutNullableJS<DOMTokenList>,
|
||||
|
@ -112,13 +113,6 @@ impl HTMLIFrameElement {
|
|||
}).unwrap_or_else(|| ServoUrl::parse("about:blank").unwrap())
|
||||
}
|
||||
|
||||
pub fn generate_new_pipeline_id(&self) -> (Option<PipelineId>, PipelineId) {
|
||||
let old_pipeline_id = self.pipeline_id.get();
|
||||
let new_pipeline_id = PipelineId::new();
|
||||
debug!("Frame {} created pipeline {}.", self.browsing_context_id, new_pipeline_id);
|
||||
(old_pipeline_id, new_pipeline_id)
|
||||
}
|
||||
|
||||
pub fn navigate_or_reload_child_browsing_context(&self,
|
||||
load_data: Option<LoadData>,
|
||||
nav_type: NavigationType,
|
||||
|
@ -129,6 +123,16 @@ impl HTMLIFrameElement {
|
|||
IFrameUnsandboxed
|
||||
};
|
||||
|
||||
let browsing_context_id = match self.browsing_context_id() {
|
||||
None => return warn!("Navigating unattached iframe."),
|
||||
Some(id) => id,
|
||||
};
|
||||
|
||||
let top_level_browsing_context_id = match self.top_level_browsing_context_id() {
|
||||
None => return warn!("Navigating unattached iframe."),
|
||||
Some(id) => id,
|
||||
};
|
||||
|
||||
let document = document_from_node(self);
|
||||
|
||||
let mut load_blocker = self.load_blocker.borrow_mut();
|
||||
|
@ -144,7 +148,8 @@ impl HTMLIFrameElement {
|
|||
}
|
||||
|
||||
let window = window_from_node(self);
|
||||
let (old_pipeline_id, new_pipeline_id) = self.generate_new_pipeline_id();
|
||||
let old_pipeline_id = self.pipeline_id();
|
||||
let new_pipeline_id = PipelineId::new();
|
||||
self.pending_pipeline_id.set(Some(new_pipeline_id));
|
||||
let private_iframe = self.privatebrowsing();
|
||||
let frame_type = if self.Mozbrowser() { FrameType::MozBrowserIFrame } else { FrameType::IFrame };
|
||||
|
@ -152,7 +157,8 @@ impl HTMLIFrameElement {
|
|||
let global_scope = window.upcast::<GlobalScope>();
|
||||
let load_info = IFrameLoadInfo {
|
||||
parent_pipeline_id: global_scope.pipeline_id(),
|
||||
browsing_context_id: self.browsing_context_id,
|
||||
browsing_context_id: browsing_context_id,
|
||||
top_level_browsing_context_id: top_level_browsing_context_id,
|
||||
new_pipeline_id: new_pipeline_id,
|
||||
is_private: private_iframe,
|
||||
frame_type: frame_type,
|
||||
|
@ -171,7 +177,8 @@ impl HTMLIFrameElement {
|
|||
let new_layout_info = NewLayoutInfo {
|
||||
parent_info: Some((global_scope.pipeline_id(), frame_type)),
|
||||
new_pipeline_id: new_pipeline_id,
|
||||
browsing_context_id: self.browsing_context_id,
|
||||
browsing_context_id: browsing_context_id,
|
||||
top_level_browsing_context_id: top_level_browsing_context_id,
|
||||
load_data: load_data.unwrap(),
|
||||
pipeline_port: pipeline_receiver,
|
||||
content_process_shutdown_chan: None,
|
||||
|
@ -246,11 +253,29 @@ impl HTMLIFrameElement {
|
|||
// 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 pipeline_id = Some(window_from_node(self).upcast::<GlobalScope>().pipeline_id());
|
||||
let window = window_from_node(self);
|
||||
let pipeline_id = Some(window.upcast::<GlobalScope>().pipeline_id());
|
||||
let load_data = LoadData::new(url, pipeline_id, document.get_referrer_policy(), Some(document.url().clone()));
|
||||
let (browsing_context_id, top_level_browsing_context_id) = if self.Mozbrowser() {
|
||||
let top_level_browsing_context_id = TopLevelBrowsingContextId::new();
|
||||
(BrowsingContextId::from(top_level_browsing_context_id), top_level_browsing_context_id)
|
||||
} else {
|
||||
(BrowsingContextId::new(), window.window_proxy().top_level_browsing_context_id())
|
||||
};
|
||||
self.pipeline_id.set(None);
|
||||
self.pending_pipeline_id.set(None);
|
||||
self.top_level_browsing_context_id.set(Some(top_level_browsing_context_id));
|
||||
self.browsing_context_id.set(Some(browsing_context_id));
|
||||
self.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::InitialAboutBlank, false);
|
||||
}
|
||||
|
||||
fn destroy_nested_browsing_context(&self) {
|
||||
self.pipeline_id.set(None);
|
||||
self.pending_pipeline_id.set(None);
|
||||
self.top_level_browsing_context_id.set(None);
|
||||
self.browsing_context_id.set(None);
|
||||
}
|
||||
|
||||
pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId, reason: UpdatePipelineIdReason) {
|
||||
if self.pending_pipeline_id.get() != Some(new_pipeline_id) && reason == UpdatePipelineIdReason::Navigation {
|
||||
return;
|
||||
|
@ -277,7 +302,8 @@ impl HTMLIFrameElement {
|
|||
document: &Document) -> HTMLIFrameElement {
|
||||
HTMLIFrameElement {
|
||||
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
|
||||
browsing_context_id: BrowsingContextId::new(),
|
||||
browsing_context_id: Cell::new(None),
|
||||
top_level_browsing_context_id: Cell::new(None),
|
||||
pipeline_id: Cell::new(None),
|
||||
pending_pipeline_id: Cell::new(None),
|
||||
sandbox: Default::default(),
|
||||
|
@ -302,8 +328,13 @@ impl HTMLIFrameElement {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn browsing_context_id(&self) -> BrowsingContextId {
|
||||
self.browsing_context_id
|
||||
pub fn browsing_context_id(&self) -> Option<BrowsingContextId> {
|
||||
self.browsing_context_id.get()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn top_level_browsing_context_id(&self) -> Option<TopLevelBrowsingContextId> {
|
||||
self.top_level_browsing_context_id.get()
|
||||
}
|
||||
|
||||
pub fn change_visibility_status(&self, visibility: bool) {
|
||||
|
@ -364,7 +395,7 @@ impl HTMLIFrameElement {
|
|||
|
||||
pub trait HTMLIFrameElementLayoutMethods {
|
||||
fn pipeline_id(&self) -> Option<PipelineId>;
|
||||
fn browsing_context_id(&self) -> BrowsingContextId;
|
||||
fn browsing_context_id(&self) -> Option<BrowsingContextId>;
|
||||
fn get_width(&self) -> LengthOrPercentageOrAuto;
|
||||
fn get_height(&self) -> LengthOrPercentageOrAuto;
|
||||
}
|
||||
|
@ -380,9 +411,9 @@ impl HTMLIFrameElementLayoutMethods for LayoutJS<HTMLIFrameElement> {
|
|||
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
fn browsing_context_id(&self) -> BrowsingContextId {
|
||||
fn browsing_context_id(&self) -> Option<BrowsingContextId> {
|
||||
unsafe {
|
||||
(*self.unsafe_get()).browsing_context_id
|
||||
(*self.unsafe_get()).browsing_context_id.get()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,7 +572,8 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-iframe-contentwindow
|
||||
fn GetContentWindow(&self) -> Option<Root<WindowProxy>> {
|
||||
self.pipeline_id.get().and_then(|_| ScriptThread::find_window_proxy(self.browsing_context_id))
|
||||
self.browsing_context_id.get()
|
||||
.and_then(|browsing_context_id| ScriptThread::find_window_proxy(browsing_context_id))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-iframe-contentdocument
|
||||
|
@ -711,7 +743,7 @@ impl VirtualMethods for HTMLIFrameElement {
|
|||
// 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.browsing_context_id);
|
||||
debug!("iframe src set while in browsing context.");
|
||||
self.process_the_iframe_attributes(ProcessingMode::NotFirstTime);
|
||||
}
|
||||
},
|
||||
|
@ -740,7 +772,7 @@ impl VirtualMethods for HTMLIFrameElement {
|
|||
// to the newly-created browsing context, and then process the
|
||||
// iframe attributes for the "first time"."
|
||||
if self.upcast::<Node>().is_in_doc_with_browsing_context() {
|
||||
debug!("iframe {} bound to browsing context.", self.browsing_context_id);
|
||||
debug!("iframe bound to browsing context.");
|
||||
debug_assert!(tree_in_doc, "is_in_doc_with_bc, but not tree_in_doc");
|
||||
self.create_nested_browsing_context();
|
||||
self.process_the_iframe_attributes(ProcessingMode::FirstTime);
|
||||
|
@ -754,13 +786,18 @@ impl VirtualMethods for HTMLIFrameElement {
|
|||
LoadBlocker::terminate(&mut blocker);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded
|
||||
debug!("Unbinding frame {}.", self.browsing_context_id);
|
||||
let window = window_from_node(self);
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
|
||||
// Ask the constellation to remove the iframe, and tell us the
|
||||
// pipeline ids of the closed pipelines.
|
||||
let msg = ConstellationMsg::RemoveIFrame(self.browsing_context_id, sender);
|
||||
let browsing_context_id = match self.browsing_context_id() {
|
||||
None => return warn!("Unbinding already unbound iframe."),
|
||||
Some(id) => id,
|
||||
};
|
||||
debug!("Unbinding frame {}.", browsing_context_id);
|
||||
|
||||
let msg = ConstellationMsg::RemoveIFrame(browsing_context_id, sender);
|
||||
window.upcast::<GlobalScope>().constellation_chan().send(msg).unwrap();
|
||||
let exited_pipeline_ids = receiver.recv().unwrap();
|
||||
|
||||
|
@ -769,9 +806,11 @@ impl VirtualMethods for HTMLIFrameElement {
|
|||
// when the `PipelineExit` message arrives.
|
||||
for exited_pipeline_id in exited_pipeline_ids {
|
||||
if let Some(exited_document) = ScriptThread::find_document(exited_pipeline_id) {
|
||||
debug!("Discarding browsing context for pipeline {}", exited_pipeline_id);
|
||||
exited_document.window().window_proxy().discard_browsing_context();
|
||||
for exited_iframe in exited_document.iter_iframes() {
|
||||
exited_iframe.pipeline_id.set(None);
|
||||
debug!("Discarding nested browsing context");
|
||||
exited_iframe.destroy_nested_browsing_context();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -781,8 +820,7 @@ impl VirtualMethods for HTMLIFrameElement {
|
|||
// the load doesn't think that it's a navigation, but instead
|
||||
// a new iframe. Without this, the constellation gets very
|
||||
// confused.
|
||||
self.pipeline_id.set(None);
|
||||
self.pending_pipeline_id.set(None);
|
||||
self.destroy_nested_browsing_context();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1136,7 +1136,7 @@ impl LayoutNodeHelpers for LayoutJS<Node> {
|
|||
fn iframe_browsing_context_id(&self) -> BrowsingContextId {
|
||||
let iframe_element = self.downcast::<HTMLIFrameElement>()
|
||||
.expect("not an iframe element!");
|
||||
iframe_element.browsing_context_id()
|
||||
iframe_element.browsing_context_id().unwrap()
|
||||
}
|
||||
|
||||
fn iframe_pipeline_id(&self) -> PipelineId {
|
||||
|
|
|
@ -30,6 +30,7 @@ use js::jsval::{UndefinedValue, PrivateValue};
|
|||
use js::rust::get_object_class;
|
||||
use msg::constellation_msg::BrowsingContextId;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use msg::constellation_msg::TopLevelBrowsingContextId;
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
|
||||
|
@ -50,6 +51,10 @@ pub struct WindowProxy {
|
|||
/// of the container.
|
||||
browsing_context_id: BrowsingContextId,
|
||||
|
||||
/// The frame id of the top-level ancestor browsing context.
|
||||
/// In the case that this is a top-level window, this is our id.
|
||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||
|
||||
/// The pipeline id of the currently active document.
|
||||
/// May be None, when the currently active document is in another script thread.
|
||||
/// We do not try to keep the pipeline id for documents in other threads,
|
||||
|
@ -69,6 +74,7 @@ pub struct WindowProxy {
|
|||
|
||||
impl WindowProxy {
|
||||
pub fn new_inherited(browsing_context_id: BrowsingContextId,
|
||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||
currently_active: Option<PipelineId>,
|
||||
frame_element: Option<&Element>,
|
||||
parent: Option<&WindowProxy>)
|
||||
|
@ -77,6 +83,7 @@ impl WindowProxy {
|
|||
WindowProxy {
|
||||
reflector: Reflector::new(),
|
||||
browsing_context_id: browsing_context_id,
|
||||
top_level_browsing_context_id: top_level_browsing_context_id,
|
||||
currently_active: Cell::new(currently_active),
|
||||
discarded: Cell::new(false),
|
||||
frame_element: frame_element.map(JS::from_ref),
|
||||
|
@ -87,6 +94,7 @@ impl WindowProxy {
|
|||
#[allow(unsafe_code)]
|
||||
pub fn new(window: &Window,
|
||||
browsing_context_id: BrowsingContextId,
|
||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||
frame_element: Option<&Element>,
|
||||
parent: Option<&WindowProxy>)
|
||||
-> Root<WindowProxy>
|
||||
|
@ -107,7 +115,11 @@ impl WindowProxy {
|
|||
|
||||
// Create a new browsing context.
|
||||
let current = Some(window.global().pipeline_id());
|
||||
let mut window_proxy = box WindowProxy::new_inherited(browsing_context_id, current, frame_element, parent);
|
||||
let mut window_proxy = box WindowProxy::new_inherited(browsing_context_id,
|
||||
top_level_browsing_context_id,
|
||||
current,
|
||||
frame_element,
|
||||
parent);
|
||||
|
||||
// The window proxy owns the browsing context.
|
||||
// When we finalize the window proxy, it drops the browsing context it owns.
|
||||
|
@ -126,6 +138,7 @@ impl WindowProxy {
|
|||
#[allow(unsafe_code)]
|
||||
pub fn new_dissimilar_origin(global_to_clone_from: &GlobalScope,
|
||||
browsing_context_id: BrowsingContextId,
|
||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||
parent: Option<&WindowProxy>)
|
||||
-> Root<WindowProxy>
|
||||
{
|
||||
|
@ -136,7 +149,11 @@ impl WindowProxy {
|
|||
let cx = global_to_clone_from.get_cx();
|
||||
|
||||
// Create a new browsing context.
|
||||
let mut window_proxy = box WindowProxy::new_inherited(browsing_context_id, None, None, parent);
|
||||
let mut window_proxy = box WindowProxy::new_inherited(browsing_context_id,
|
||||
top_level_browsing_context_id,
|
||||
None,
|
||||
None,
|
||||
parent);
|
||||
|
||||
// Create a new dissimilar-origin window.
|
||||
let window = DissimilarOriginWindow::new(global_to_clone_from, &*window_proxy);
|
||||
|
@ -175,6 +192,10 @@ impl WindowProxy {
|
|||
self.browsing_context_id
|
||||
}
|
||||
|
||||
pub fn top_level_browsing_context_id(&self) -> TopLevelBrowsingContextId {
|
||||
self.top_level_browsing_context_id
|
||||
}
|
||||
|
||||
pub fn frame_element(&self) -> Option<&Element> {
|
||||
self.frame_element.r()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue