mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Add creator URL, creator base URL and creator origin in browsing context
This commit is contained in:
parent
1c78728ff1
commit
ab672577e8
5 changed files with 135 additions and 20 deletions
|
@ -575,10 +575,19 @@ impl Document {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#fallback-base-url
|
// https://html.spec.whatwg.org/multipage/#fallback-base-url
|
||||||
pub fn fallback_base_url(&self) -> ServoUrl {
|
pub fn fallback_base_url(&self) -> ServoUrl {
|
||||||
// Step 1: iframe srcdoc (#4767).
|
let document_url = self.url();
|
||||||
// Step 2: about:blank with a creator browsing context.
|
if let Some(browsing_context) = self.browsing_context() {
|
||||||
// Step 3.
|
// Step 1: If document is an iframe srcdoc document, then return the
|
||||||
self.url()
|
// document base URL of document's browsing context's container document.
|
||||||
|
|
||||||
|
// Step 2: If document's URL is about:blank, and document's browsing
|
||||||
|
// context's creator base URL is non-null, then return that creator base URL.
|
||||||
|
if document_url.as_str() == "about:blank" && browsing_context.has_creator_base_url() {
|
||||||
|
return browsing_context.creator_base_url().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Step 3: Return document's URL.
|
||||||
|
document_url
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#document-base-url
|
// https://html.spec.whatwg.org/multipage/#document-base-url
|
||||||
|
|
|
@ -52,7 +52,7 @@ use script_traits::{
|
||||||
AuxiliaryBrowsingContextLoadInfo, HistoryEntryReplacement, LoadData, LoadOrigin,
|
AuxiliaryBrowsingContextLoadInfo, HistoryEntryReplacement, LoadData, LoadOrigin,
|
||||||
};
|
};
|
||||||
use script_traits::{NewLayoutInfo, ScriptMsg};
|
use script_traits::{NewLayoutInfo, ScriptMsg};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use style::attr::parse_integer;
|
use style::attr::parse_integer;
|
||||||
|
@ -108,6 +108,15 @@ pub struct WindowProxy {
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#delaying-load-events-mode
|
/// https://html.spec.whatwg.org/multipage/#delaying-load-events-mode
|
||||||
delaying_load_events_mode: Cell<bool>,
|
delaying_load_events_mode: Cell<bool>,
|
||||||
|
|
||||||
|
/// The creator browsing context's base url.
|
||||||
|
creator_base_url: Option<ServoUrl>,
|
||||||
|
|
||||||
|
/// The creator browsing context's url.
|
||||||
|
creator_url: Option<ServoUrl>,
|
||||||
|
|
||||||
|
/// The creator browsing context's origin.
|
||||||
|
creator_origin: Option<ImmutableOrigin>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowProxy {
|
impl WindowProxy {
|
||||||
|
@ -118,6 +127,7 @@ impl WindowProxy {
|
||||||
frame_element: Option<&Element>,
|
frame_element: Option<&Element>,
|
||||||
parent: Option<&WindowProxy>,
|
parent: Option<&WindowProxy>,
|
||||||
opener: Option<BrowsingContextId>,
|
opener: Option<BrowsingContextId>,
|
||||||
|
creator: CreatorBrowsingContextInfo,
|
||||||
) -> WindowProxy {
|
) -> WindowProxy {
|
||||||
let name = frame_element.map_or(DOMString::new(), |e| {
|
let name = frame_element.map_or(DOMString::new(), |e| {
|
||||||
e.get_string_attribute(&local_name!("name"))
|
e.get_string_attribute(&local_name!("name"))
|
||||||
|
@ -135,6 +145,9 @@ impl WindowProxy {
|
||||||
parent: parent.map(Dom::from_ref),
|
parent: parent.map(Dom::from_ref),
|
||||||
delaying_load_events_mode: Cell::new(false),
|
delaying_load_events_mode: Cell::new(false),
|
||||||
opener,
|
opener,
|
||||||
|
creator_base_url: creator.base_url,
|
||||||
|
creator_url: creator.url,
|
||||||
|
creator_origin: creator.origin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +159,7 @@ impl WindowProxy {
|
||||||
frame_element: Option<&Element>,
|
frame_element: Option<&Element>,
|
||||||
parent: Option<&WindowProxy>,
|
parent: Option<&WindowProxy>,
|
||||||
opener: Option<BrowsingContextId>,
|
opener: Option<BrowsingContextId>,
|
||||||
|
creator: CreatorBrowsingContextInfo,
|
||||||
) -> DomRoot<WindowProxy> {
|
) -> DomRoot<WindowProxy> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let WindowProxyHandler(handler) = window.windowproxy_handler();
|
let WindowProxyHandler(handler) = window.windowproxy_handler();
|
||||||
|
@ -173,6 +187,7 @@ impl WindowProxy {
|
||||||
frame_element,
|
frame_element,
|
||||||
parent,
|
parent,
|
||||||
opener,
|
opener,
|
||||||
|
creator,
|
||||||
));
|
));
|
||||||
|
|
||||||
// The window proxy owns the browsing context.
|
// The window proxy owns the browsing context.
|
||||||
|
@ -204,6 +219,7 @@ impl WindowProxy {
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
parent: Option<&WindowProxy>,
|
parent: Option<&WindowProxy>,
|
||||||
opener: Option<BrowsingContextId>,
|
opener: Option<BrowsingContextId>,
|
||||||
|
creator: CreatorBrowsingContextInfo,
|
||||||
) -> DomRoot<WindowProxy> {
|
) -> DomRoot<WindowProxy> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let handler = CreateWrapperProxyHandler(&XORIGIN_PROXY_HANDLER);
|
let handler = CreateWrapperProxyHandler(&XORIGIN_PROXY_HANDLER);
|
||||||
|
@ -219,6 +235,7 @@ impl WindowProxy {
|
||||||
None,
|
None,
|
||||||
parent,
|
parent,
|
||||||
opener,
|
opener,
|
||||||
|
creator,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Create a new dissimilar-origin window.
|
// Create a new dissimilar-origin window.
|
||||||
|
@ -368,6 +385,33 @@ impl WindowProxy {
|
||||||
self.is_closing.get()
|
self.is_closing.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/browsers.html#creator-base-url
|
||||||
|
pub fn creator_base_url(&self) -> Option<ServoUrl> {
|
||||||
|
self.creator_base_url.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_creator_base_url(&self) -> bool {
|
||||||
|
self.creator_base_url.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/browsers.html#creator-url
|
||||||
|
pub fn creator_url(&self) -> Option<ServoUrl> {
|
||||||
|
self.creator_url.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_creator_url(&self) -> bool {
|
||||||
|
self.creator_base_url.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/browsers.html#creator-origin
|
||||||
|
pub fn creator_origin(&self) -> Option<ImmutableOrigin> {
|
||||||
|
self.creator_origin.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_creator_origin(&self) -> bool {
|
||||||
|
self.creator_origin.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-opener
|
// https://html.spec.whatwg.org/multipage/#dom-opener
|
||||||
pub fn opener(&self, cx: *mut JSContext, in_realm_proof: InRealm) -> JSVal {
|
pub fn opener(&self, cx: *mut JSContext, in_realm_proof: InRealm) -> JSVal {
|
||||||
|
@ -378,6 +422,7 @@ impl WindowProxy {
|
||||||
Some(opener_browsing_context_id) => opener_browsing_context_id,
|
Some(opener_browsing_context_id) => opener_browsing_context_id,
|
||||||
None => return NullValue(),
|
None => return NullValue(),
|
||||||
};
|
};
|
||||||
|
let parent_browsing_context = self.parent.as_deref();
|
||||||
let opener_proxy = match ScriptThread::find_window_proxy(opener_id) {
|
let opener_proxy = match ScriptThread::find_window_proxy(opener_id) {
|
||||||
Some(window_proxy) => window_proxy,
|
Some(window_proxy) => window_proxy,
|
||||||
None => {
|
None => {
|
||||||
|
@ -389,12 +434,15 @@ impl WindowProxy {
|
||||||
Some(opener_top_id) => {
|
Some(opener_top_id) => {
|
||||||
let global_to_clone_from =
|
let global_to_clone_from =
|
||||||
unsafe { GlobalScope::from_context(cx, in_realm_proof) };
|
unsafe { GlobalScope::from_context(cx, in_realm_proof) };
|
||||||
|
let creator =
|
||||||
|
CreatorBrowsingContextInfo::from(parent_browsing_context, None);
|
||||||
WindowProxy::new_dissimilar_origin(
|
WindowProxy::new_dissimilar_origin(
|
||||||
&*global_to_clone_from,
|
&*global_to_clone_from,
|
||||||
opener_id,
|
opener_id,
|
||||||
opener_top_id,
|
opener_top_id,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
creator,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
None => return NullValue(),
|
None => return NullValue(),
|
||||||
|
@ -655,6 +703,56 @@ impl WindowProxy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A browsing context can have a creator browsing context, the browsing context that
|
||||||
|
/// was responsible for its creation. If a browsing context has a parent browsing context,
|
||||||
|
/// then that is its creator browsing context. Otherwise, if the browsing context has an
|
||||||
|
/// opener browsing context, then that is its creator browsing context. Otherwise, the
|
||||||
|
/// browsing context has no creator browsing context.
|
||||||
|
///
|
||||||
|
/// If a browsing context A has a creator browsing context, then the Document that was the
|
||||||
|
/// active document of that creator browsing context at the time A was created is the creator
|
||||||
|
/// Document.
|
||||||
|
///
|
||||||
|
/// See: https://html.spec.whatwg.org/multipage/browsers.html#creating-browsing-contexts
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct CreatorBrowsingContextInfo {
|
||||||
|
/// Creator document URL.
|
||||||
|
url: Option<ServoUrl>,
|
||||||
|
|
||||||
|
/// Creator document base URL.
|
||||||
|
base_url: Option<ServoUrl>,
|
||||||
|
|
||||||
|
/// Creator document origin.
|
||||||
|
origin: Option<ImmutableOrigin>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CreatorBrowsingContextInfo {
|
||||||
|
pub fn from(
|
||||||
|
parent: Option<&WindowProxy>,
|
||||||
|
opener: Option<&WindowProxy>,
|
||||||
|
) -> CreatorBrowsingContextInfo {
|
||||||
|
let creator = if parent.is_some() {
|
||||||
|
parent.unwrap().document()
|
||||||
|
} else if opener.is_some() {
|
||||||
|
opener.unwrap().document()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let base_url = creator.as_deref().map(|document| document.base_url());
|
||||||
|
let url = creator.as_deref().map(|document| document.url());
|
||||||
|
let origin = creator
|
||||||
|
.as_deref()
|
||||||
|
.map(|document| document.origin().immutable().clone());
|
||||||
|
|
||||||
|
CreatorBrowsingContextInfo {
|
||||||
|
base_url,
|
||||||
|
url,
|
||||||
|
origin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#concept-window-open-features-tokenize
|
// https://html.spec.whatwg.org/multipage/#concept-window-open-features-tokenize
|
||||||
fn tokenize_open_features(features: DOMString) -> IndexMap<String, String> {
|
fn tokenize_open_features(features: DOMString) -> IndexMap<String, String> {
|
||||||
let is_feature_sep = |c: char| c.is_ascii_whitespace() || ['=', ','].contains(&c);
|
let is_feature_sep = |c: char| c.is_ascii_whitespace() || ['=', ','].contains(&c);
|
||||||
|
|
|
@ -68,7 +68,7 @@ use crate::dom::servoparser::{ParserContext, ServoParser};
|
||||||
use crate::dom::transitionevent::TransitionEvent;
|
use crate::dom::transitionevent::TransitionEvent;
|
||||||
use crate::dom::uievent::UIEvent;
|
use crate::dom::uievent::UIEvent;
|
||||||
use crate::dom::window::{ReflowReason, Window};
|
use crate::dom::window::{ReflowReason, Window};
|
||||||
use crate::dom::windowproxy::WindowProxy;
|
use crate::dom::windowproxy::{CreatorBrowsingContextInfo, WindowProxy};
|
||||||
use crate::dom::worker::TrustedWorkerAddress;
|
use crate::dom::worker::TrustedWorkerAddress;
|
||||||
use crate::dom::worklet::WorkletThreadPool;
|
use crate::dom::worklet::WorkletThreadPool;
|
||||||
use crate::dom::workletglobalscope::WorkletGlobalScopeInit;
|
use crate::dom::workletglobalscope::WorkletGlobalScopeInit;
|
||||||
|
@ -3162,7 +3162,7 @@ impl ScriptThread {
|
||||||
return Some(DomRoot::from_ref(window_proxy));
|
return Some(DomRoot::from_ref(window_proxy));
|
||||||
}
|
}
|
||||||
|
|
||||||
let parent = parent_pipeline_id.and_then(|parent_id| {
|
let parent_browsing_context = parent_pipeline_id.and_then(|parent_id| {
|
||||||
self.remote_window_proxy(
|
self.remote_window_proxy(
|
||||||
global_to_clone,
|
global_to_clone,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
|
@ -3170,12 +3170,21 @@ impl ScriptThread {
|
||||||
opener,
|
opener,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let opener_browsing_context = opener.and_then(|id| ScriptThread::find_window_proxy(id));
|
||||||
|
|
||||||
|
let creator = CreatorBrowsingContextInfo::from(
|
||||||
|
parent_browsing_context.as_deref(),
|
||||||
|
opener_browsing_context.as_deref(),
|
||||||
|
);
|
||||||
|
|
||||||
let window_proxy = WindowProxy::new_dissimilar_origin(
|
let window_proxy = WindowProxy::new_dissimilar_origin(
|
||||||
global_to_clone,
|
global_to_clone,
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
parent.as_deref(),
|
parent_browsing_context.as_deref(),
|
||||||
opener,
|
opener,
|
||||||
|
creator,
|
||||||
);
|
);
|
||||||
self.window_proxies
|
self.window_proxies
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -3207,7 +3216,7 @@ impl ScriptThread {
|
||||||
.borrow()
|
.borrow()
|
||||||
.find_iframe(parent_id, browsing_context_id)
|
.find_iframe(parent_id, browsing_context_id)
|
||||||
});
|
});
|
||||||
let parent = match (parent_info, iframe.as_ref()) {
|
let parent_browsing_context = match (parent_info, iframe.as_ref()) {
|
||||||
(_, Some(iframe)) => Some(window_from_node(&**iframe).window_proxy()),
|
(_, Some(iframe)) => Some(window_from_node(&**iframe).window_proxy()),
|
||||||
(Some(parent_id), _) => self.remote_window_proxy(
|
(Some(parent_id), _) => self.remote_window_proxy(
|
||||||
window.upcast(),
|
window.upcast(),
|
||||||
|
@ -3217,13 +3226,22 @@ impl ScriptThread {
|
||||||
),
|
),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let opener_browsing_context = opener.and_then(|id| ScriptThread::find_window_proxy(id));
|
||||||
|
|
||||||
|
let creator = CreatorBrowsingContextInfo::from(
|
||||||
|
parent_browsing_context.as_deref(),
|
||||||
|
opener_browsing_context.as_deref(),
|
||||||
|
);
|
||||||
|
|
||||||
let window_proxy = WindowProxy::new(
|
let window_proxy = WindowProxy::new(
|
||||||
&window,
|
&window,
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
iframe.as_deref().map(Castable::upcast),
|
iframe.as_deref().map(Castable::upcast),
|
||||||
parent.as_deref(),
|
parent_browsing_context.as_deref(),
|
||||||
opener,
|
opener,
|
||||||
|
creator,
|
||||||
);
|
);
|
||||||
self.window_proxies
|
self.window_proxies
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[open-url-about-blank-window.htm]
|
|
||||||
type: testharness
|
|
||||||
[XMLHttpRequest: open() resolving URLs (about:blank iframe)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[open-url-javascript-window-2.htm]
|
|
||||||
type: testharness
|
|
||||||
[XMLHttpRequest: open() - resolving URLs (javascript: <iframe>; 2)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue