diff options
author | Alan Jeffrey <ajeffrey@mozilla.com> | 2017-05-15 16:09:49 -0500 |
---|---|---|
committer | Alan Jeffrey <ajeffrey@mozilla.com> | 2017-05-22 09:27:07 -0500 |
commit | 42577365b7924d0af64033d852447ff61579da3a (patch) | |
tree | 107d4646c361a97a1e72e7ccf13fa9370ebea06b /components/script/dom | |
parent | b428a94326322c88da4c32e56ee753ceeffca7d1 (diff) | |
download | servo-42577365b7924d0af64033d852447ff61579da3a.tar.gz servo-42577365b7924d0af64033d852447ff61579da3a.zip |
Added a TopLevelBrowsingContextId type.
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 5 | ||||
-rw-r--r-- | components/script/dom/dedicatedworkerglobalscope.rs | 6 | ||||
-rw-r--r-- | components/script/dom/document.rs | 18 | ||||
-rw-r--r-- | components/script/dom/htmliframeelement.rs | 92 | ||||
-rw-r--r-- | components/script/dom/node.rs | 2 | ||||
-rw-r--r-- | components/script/dom/windowproxy.rs | 25 |
6 files changed, 111 insertions, 37 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 3b96d954dcb..dca1b0e2ea5 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -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); diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 6b73df12dfc..f4de73747c4 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -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(); diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 3bca1dcee9e..378dee975fa 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -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 { diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 8334b4cb421..00755213c75 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -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(); } } diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index ff3e5d64787..cc817587eda 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -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 { diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs index e022e69a810..2578bb3b46c 100644 --- a/components/script/dom/windowproxy.rs +++ b/components/script/dom/windowproxy.rs @@ -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() } |