mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Implement dissimilar-origin postMessage.
This commit is contained in:
parent
f5c67fda04
commit
f9c5d0c117
12 changed files with 191 additions and 13 deletions
|
@ -29,6 +29,7 @@ use js::jsapi::{MutableHandle, MutableHandleObject, MutableHandleValue};
|
|||
use js::jsapi::{ObjectOpResult, PropertyDescriptor};
|
||||
use js::jsval::{UndefinedValue, PrivateValue};
|
||||
use js::rust::get_object_class;
|
||||
use msg::constellation_msg::FrameId;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
|
@ -45,6 +46,11 @@ pub struct BrowsingContext {
|
|||
/// changes Window.
|
||||
reflector: Reflector,
|
||||
|
||||
/// The frame id of the browsing context.
|
||||
/// In the case that this is a nested browsing context, this is the frame id
|
||||
/// of the container.
|
||||
frame_id: FrameId,
|
||||
|
||||
/// 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,
|
||||
|
@ -60,9 +66,14 @@ pub struct BrowsingContext {
|
|||
}
|
||||
|
||||
impl BrowsingContext {
|
||||
pub fn new_inherited(currently_active: PipelineId, frame_element: Option<&Element>) -> BrowsingContext {
|
||||
pub fn new_inherited(frame_id: FrameId,
|
||||
currently_active: PipelineId,
|
||||
frame_element: Option<&Element>)
|
||||
-> BrowsingContext
|
||||
{
|
||||
BrowsingContext {
|
||||
reflector: Reflector::new(),
|
||||
frame_id: frame_id,
|
||||
currently_active: Cell::new(Some(currently_active)),
|
||||
discarded: Cell::new(false),
|
||||
frame_element: frame_element.map(JS::from_ref),
|
||||
|
@ -70,7 +81,7 @@ impl BrowsingContext {
|
|||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn new(window: &Window, frame_element: Option<&Element>) -> Root<BrowsingContext> {
|
||||
pub fn new(window: &Window, frame_id: FrameId, frame_element: Option<&Element>) -> Root<BrowsingContext> {
|
||||
unsafe {
|
||||
let WindowProxyHandler(handler) = window.windowproxy_handler();
|
||||
assert!(!handler.is_null());
|
||||
|
@ -87,7 +98,7 @@ impl BrowsingContext {
|
|||
|
||||
// Create a new browsing context.
|
||||
let currently_active = window.global().pipeline_id();
|
||||
let mut browsing_context = box BrowsingContext::new_inherited(currently_active, frame_element);
|
||||
let mut browsing_context = box BrowsingContext::new_inherited(frame_id, currently_active, frame_element);
|
||||
|
||||
// The window proxy owns the browsing context.
|
||||
// When we finalize the window proxy, it drops the browsing context it owns.
|
||||
|
@ -111,6 +122,10 @@ impl BrowsingContext {
|
|||
self.discarded.get()
|
||||
}
|
||||
|
||||
pub fn frame_id(&self) -> FrameId {
|
||||
self.frame_id
|
||||
}
|
||||
|
||||
pub fn frame_element(&self) -> Option<&Element> {
|
||||
self.frame_element.r()
|
||||
}
|
||||
|
|
|
@ -4,9 +4,12 @@
|
|||
|
||||
use dom::bindings::codegen::Bindings::DissimilarOriginWindowBinding;
|
||||
use dom::bindings::codegen::Bindings::DissimilarOriginWindowBinding::DissimilarOriginWindowMethods;
|
||||
use dom::bindings::error::{Error, ErrorResult};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::js::{JS, MutNullableJS, Root};
|
||||
use dom::bindings::reflector::DomObject;
|
||||
use dom::bindings::str::DOMString;
|
||||
use dom::bindings::structuredclone::StructuredCloneData;
|
||||
use dom::browsingcontext::BrowsingContext;
|
||||
use dom::dissimilaroriginlocation::DissimilarOriginLocation;
|
||||
use dom::globalscope::GlobalScope;
|
||||
|
@ -15,6 +18,9 @@ use ipc_channel::ipc;
|
|||
use js::jsapi::{JSContext, HandleValue};
|
||||
use js::jsval::{JSVal, UndefinedValue};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use script_traits::ScriptMsg as ConstellationMsg;
|
||||
use servo_url::ImmutableOrigin;
|
||||
use servo_url::ServoUrl;
|
||||
|
||||
/// Represents a dissimilar-origin `Window` that exists in another script thread.
|
||||
///
|
||||
|
@ -107,8 +113,27 @@ impl DissimilarOriginWindowMethods for DissimilarOriginWindow {
|
|||
|
||||
#[allow(unsafe_code)]
|
||||
// https://html.spec.whatwg.org/multipage/#dom-window-postmessage
|
||||
unsafe fn PostMessage(&self, _: *mut JSContext, _: HandleValue, _: DOMString) {
|
||||
// TODO: Implement x-origin postMessage
|
||||
unsafe fn PostMessage(&self, cx: *mut JSContext, message: HandleValue, origin: DOMString) -> ErrorResult {
|
||||
// Step 3-5.
|
||||
let origin = match &origin[..] {
|
||||
"*" => None,
|
||||
"/" => {
|
||||
// TODO: Should be the origin of the incumbent settings object.
|
||||
None
|
||||
},
|
||||
url => match ServoUrl::parse(&url) {
|
||||
Ok(url) => Some(url.origin()),
|
||||
Err(_) => return Err(Error::Syntax),
|
||||
}
|
||||
};
|
||||
|
||||
// Step 1-2, 6-8.
|
||||
// TODO(#12717): Should implement the `transfer` argument.
|
||||
let data = try!(StructuredCloneData::write(cx, message));
|
||||
|
||||
// Step 9.
|
||||
self.post_message(origin, data);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
@ -139,3 +164,10 @@ impl DissimilarOriginWindowMethods for DissimilarOriginWindow {
|
|||
self.location.or_init(|| DissimilarOriginLocation::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl DissimilarOriginWindow {
|
||||
pub fn post_message(&self, origin: Option<ImmutableOrigin>, data: StructuredCloneData) {
|
||||
let msg = ConstellationMsg::PostMessage(self.browsing_context.frame_id(), origin, data.move_to_arraybuffer());
|
||||
let _ = self.upcast::<GlobalScope>().constellation_chan().send(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ interface DissimilarOriginWindow : GlobalScope {
|
|||
|
||||
void close();
|
||||
readonly attribute boolean closed;
|
||||
void postMessage(any message, DOMString targetOrigin);
|
||||
[Throws] void postMessage(any message, DOMString targetOrigin);
|
||||
attribute any opener;
|
||||
void blur();
|
||||
void focus();
|
||||
|
|
|
@ -718,10 +718,7 @@ impl WindowMethods for Window {
|
|||
let data = try!(StructuredCloneData::write(cx, message));
|
||||
|
||||
// Step 9.
|
||||
let runnable = PostMessageHandler::new(self, origin, data);
|
||||
let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::DomEvent, box runnable);
|
||||
// TODO(#12718): Use the "posted message task source".
|
||||
let _ = self.script_chan.send(msg);
|
||||
self.post_message(origin, data);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1910,3 +1907,12 @@ impl Runnable for PostMessageHandler {
|
|||
message.handle());
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn post_message(&self, origin: Option<ImmutableOrigin>, data: StructuredCloneData) {
|
||||
let runnable = PostMessageHandler::new(self, origin, data);
|
||||
let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::DomEvent, box runnable);
|
||||
// TODO(#12718): Use the "posted message task source".
|
||||
let _ = self.script_chan.send(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ use dom::bindings::js::{RootCollectionPtr, RootedReference};
|
|||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::reflector::DomObject;
|
||||
use dom::bindings::str::DOMString;
|
||||
use dom::bindings::structuredclone::StructuredCloneData;
|
||||
use dom::bindings::trace::JSTraceable;
|
||||
use dom::bindings::utils::WRAP_CALLBACKS;
|
||||
use dom::browsingcontext::BrowsingContext;
|
||||
|
@ -93,7 +94,7 @@ use script_traits::WebVREventMsg;
|
|||
use script_traits::webdriver_msg::WebDriverScriptCommand;
|
||||
use serviceworkerjob::{Job, JobQueue, AsyncJobHandler};
|
||||
use servo_config::opts;
|
||||
use servo_url::{MutableOrigin, ServoUrl};
|
||||
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
||||
use std::cell::Cell;
|
||||
use std::collections::{hash_map, HashMap, HashSet};
|
||||
use std::default::Default;
|
||||
|
@ -1018,6 +1019,8 @@ impl ScriptThread {
|
|||
self.handle_visibility_change_msg(pipeline_id, visible),
|
||||
ConstellationControlMsg::NotifyVisibilityChange(parent_pipeline_id, frame_id, visible) =>
|
||||
self.handle_visibility_change_complete_msg(parent_pipeline_id, frame_id, visible),
|
||||
ConstellationControlMsg::PostMessage(pipeline_id, origin, data) =>
|
||||
self.handle_post_message_msg(pipeline_id, origin, data),
|
||||
ConstellationControlMsg::MozBrowserEvent(parent_pipeline_id,
|
||||
frame_id,
|
||||
event) =>
|
||||
|
@ -1396,6 +1399,13 @@ impl ScriptThread {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_post_message_msg(&self, pipeline_id: PipelineId, origin: Option<ImmutableOrigin>, data: Vec<u8>) {
|
||||
match { self.documents.borrow().find_window(pipeline_id) } {
|
||||
None => return warn!("postMessage after pipeline {} closed.", pipeline_id),
|
||||
Some(window) => window.post_message(origin, StructuredCloneData::Vector(data)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles a mozbrowser event, for example see:
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
|
||||
fn handle_mozbrowser_event_msg(&self,
|
||||
|
@ -1705,7 +1715,7 @@ impl ScriptThread {
|
|||
|
||||
match self.browsing_contexts.borrow_mut().entry(incomplete.frame_id) {
|
||||
hash_map::Entry::Vacant(entry) => {
|
||||
let browsing_context = BrowsingContext::new(&window, frame_element);
|
||||
let browsing_context = BrowsingContext::new(&window, incomplete.frame_id, frame_element);
|
||||
entry.insert(JS::from_ref(&*browsing_context));
|
||||
window.init_browsing_context(&browsing_context);
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue