diff options
Diffstat (limited to 'components/script')
21 files changed, 554 insertions, 67 deletions
diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs index 7282e23c322..4d5df6c74e5 100644 --- a/components/script/document_loader.rs +++ b/components/script/document_loader.rs @@ -8,8 +8,8 @@ use dom::bindings::js::JS; use dom::document::Document; use msg::constellation_msg::PipelineId; -use net_traits::AsyncResponseTarget; use net_traits::{PendingAsyncLoad, CoreResourceThread, LoadContext}; +use net_traits::{RequestSource, AsyncResponseTarget}; use std::sync::Arc; use std::thread; use url::Url; @@ -130,20 +130,27 @@ impl DocumentLoader { /// Create a new pending network request, which can be initiated at some point in /// the future. - pub fn prepare_async_load(&mut self, load: LoadType, referrer: &Document) -> PendingAsyncLoad { + pub fn prepare_async_load(&mut self, + load: LoadType, + referrer: &Document) -> PendingAsyncLoad { let context = load.to_load_context(); let url = load.url().clone(); self.add_blocking_load(load); + let client_chan = referrer.window().custom_message_chan(); PendingAsyncLoad::new(context, (*self.resource_thread).clone(), url, self.pipeline, referrer.get_referrer_policy(), - Some(referrer.url().clone())) + Some(referrer.url().clone()), + RequestSource::Window(client_chan)) } /// Create and initiate a new network request. - pub fn load_async(&mut self, load: LoadType, listener: AsyncResponseTarget, referrer: &Document) { + pub fn load_async(&mut self, + load: LoadType, + listener: AsyncResponseTarget, + referrer: &Document) { let pending = self.prepare_async_load(load, referrer); pending.load_async(listener) } diff --git a/components/script/dom/beforeunloadevent.rs b/components/script/dom/beforeunloadevent.rs new file mode 100644 index 00000000000..9257cbcafcb --- /dev/null +++ b/components/script/dom/beforeunloadevent.rs @@ -0,0 +1,67 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::BeforeUnloadEventBinding; +use dom::bindings::codegen::Bindings::BeforeUnloadEventBinding::BeforeUnloadEventMethods; +use dom::bindings::codegen::Bindings::EventBinding::EventMethods; +use dom::bindings::global::GlobalRef; +use dom::bindings::inheritance::Castable; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::event::{Event, EventBubbles, EventCancelable}; +use string_cache::Atom; +use util::str::DOMString; + +// https://html.spec.whatwg.org/multipage/#beforeunloadevent +#[dom_struct] +pub struct BeforeUnloadEvent { + event: Event, + return_value: DOMRefCell<DOMString>, +} + +impl BeforeUnloadEvent { + fn new_inherited() -> BeforeUnloadEvent { + BeforeUnloadEvent { + event: Event::new_inherited(), + return_value: DOMRefCell::new(DOMString::new()), + } + } + + pub fn new_uninitialized(global: GlobalRef) -> Root<BeforeUnloadEvent> { + reflect_dom_object(box BeforeUnloadEvent::new_inherited(), + global, + BeforeUnloadEventBinding::Wrap) + } + + pub fn new(global: GlobalRef, + type_: Atom, + bubbles: EventBubbles, + cancelable: EventCancelable) -> Root<BeforeUnloadEvent> { + let ev = BeforeUnloadEvent::new_uninitialized(global); + { + let event = ev.upcast::<Event>(); + event.init_event(type_, bool::from(bubbles), + bool::from(cancelable)); + } + ev + } +} + +impl BeforeUnloadEventMethods for BeforeUnloadEvent { + // https://html.spec.whatwg.org/multipage/#dom-beforeunloadevent-returnvalue + fn ReturnValue(&self) -> DOMString { + self.return_value.borrow().clone() + } + + // https://html.spec.whatwg.org/multipage/#dom-beforeunloadevent-returnvalue + fn SetReturnValue(&self, value: DOMString) { + *self.return_value.borrow_mut() = value; + } + + // https://dom.spec.whatwg.org/#dom-event-istrusted + fn IsTrusted(&self) -> bool { + self.event.IsTrusted() + } +} diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs index 61b948dbf35..ff36817b660 100644 --- a/components/script/dom/bindings/global.rs +++ b/components/script/dom/bindings/global.rs @@ -18,8 +18,8 @@ use ipc_channel::ipc::IpcSender; use js::jsapi::{CurrentGlobalOrNull, GetGlobalForObjectCrossCompartment}; use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue}; use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL}; -use msg::constellation_msg::{PanicMsg, PipelineId}; -use net_traits::CoreResourceThread; +use msg::constellation_msg::{PipelineId, PanicMsg}; +use net_traits::{CoreResourceThread, RequestSource}; use profile_traits::{mem, time}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort}; use script_thread::{MainThreadScriptChan, ScriptThread}; @@ -65,6 +65,14 @@ impl<'a> GlobalRef<'a> { } } + /// gets the custom message channel associated with global object + pub fn request_source(&self) -> RequestSource { + match *self { + GlobalRef::Window(ref window) => RequestSource::Window(window.custom_message_chan()), + GlobalRef::Worker(ref worker) => RequestSource::Worker(worker.custom_message_chan()), + } + } + /// Get the `PipelineId` for this global scope. pub fn pipeline(&self) -> PipelineId { match *self { diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index bd5cd63fcfb..120565b00fa 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -16,7 +16,8 @@ use dom::bindings::refcounted::LiveDOMReferences; use dom::bindings::reflector::Reflectable; use dom::bindings::structuredclone::StructuredCloneData; use dom::messageevent::MessageEvent; -use dom::worker::{SimpleWorkerErrorHandler, SharedRt, TrustedWorkerAddress, WorkerMessageHandler}; +use dom::worker::{SimpleWorkerErrorHandler, SharedRt, TrustedWorkerAddress}; +use dom::worker::{WorkerScriptLoadOrigin, WorkerMessageHandler}; use dom::workerglobalscope::WorkerGlobalScope; use dom::workerglobalscope::WorkerGlobalScopeInit; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; @@ -26,7 +27,7 @@ use js::jsapi::{JSAutoCompartment, JSContext, RootedValue}; use js::jsval::UndefinedValue; use js::rust::Runtime; use msg::constellation_msg::PipelineId; -use net_traits::{LoadContext, load_whole_resource}; +use net_traits::{LoadContext, load_whole_resource, CustomResponse}; use rand::random; use script_runtime::ScriptThreadEventCategory::WorkerEvent; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_reports, new_rt_and_cx}; @@ -133,6 +134,7 @@ enum MixedMessage { FromWorker((TrustedWorkerAddress, WorkerScriptMsg)), FromScheduler((TrustedWorkerAddress, TimerEvent)), FromDevtools(DevtoolScriptControlMsg), + FromNetwork(IpcSender<Option<CustomResponse>>), } // https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope @@ -215,18 +217,18 @@ impl DedicatedWorkerGlobalScope { worker: TrustedWorkerAddress, parent_sender: Box<ScriptChan + Send>, own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>, - receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>) { + receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>, + worker_load_origin: WorkerScriptLoadOrigin) { let serialized_worker_url = worker_url.to_string(); let name = format!("WebWorker for {}", serialized_worker_url); let panic_chan = init.panic_chan.clone(); spawn_named_with_send_on_panic(name, SCRIPT | IN_WORKER, move || { let roots = RootCollection::new(); let _stack_roots_tls = StackRootTLS::new(&roots); - let (url, source) = match load_whole_resource(LoadContext::Script, &init.core_resource_thread, worker_url, - None) { + &worker_load_origin) { Err(_) => { println!("error loading script {}", serialized_worker_url); parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent, @@ -316,17 +318,20 @@ impl DedicatedWorkerGlobalScope { let worker_port = &self.receiver; let timer_event_port = &self.timer_event_port; let devtools_port = scope.from_devtools_receiver(); + let msg_port = scope.custom_message_port(); let sel = Select::new(); let mut worker_handle = sel.handle(worker_port); let mut timer_event_handle = sel.handle(timer_event_port); let mut devtools_handle = sel.handle(devtools_port); + let mut msg_port_handle = sel.handle(msg_port); unsafe { worker_handle.add(); timer_event_handle.add(); if scope.from_devtools_sender().is_some() { devtools_handle.add(); } + msg_port_handle.add(); } let ret = sel.wait(); if ret == worker_handle.id() { @@ -335,6 +340,8 @@ impl DedicatedWorkerGlobalScope { Ok(MixedMessage::FromScheduler(try!(timer_event_port.recv()))) } else if ret == devtools_handle.id() { Ok(MixedMessage::FromDevtools(try!(devtools_port.recv()))) + } else if ret == msg_port_handle.id() { + Ok(MixedMessage::FromNetwork(try!(msg_port.recv()))) } else { panic!("unexpected select result!") } @@ -397,6 +404,10 @@ impl DedicatedWorkerGlobalScope { let _ar = AutoWorkerReset::new(self, linked_worker); self.handle_script_event(msg); }, + MixedMessage::FromNetwork(network_sender) => { + // We send None as of now + let _ = network_sender.send(None); + } } } } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index ddf23297282..10645b761d7 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -1354,7 +1354,7 @@ impl Document { pub fn load_async(&self, load: LoadType, listener: AsyncResponseTarget) { let mut loader = self.loader.borrow_mut(); - loader.load_async(load, listener, self) + loader.load_async(load, listener, self); } pub fn finish_load(&self, load: LoadType) { @@ -2795,6 +2795,9 @@ impl DocumentMethods for Document { // Step 5 elements } + + // https://html.spec.whatwg.org/multipage/#documentandelementeventhandlers + document_and_element_event_handlers!(); } fn update_with_current_time_ms(marker: &Cell<u64>) { diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs index 3b20120628d..c8eecc8e65d 100644 --- a/components/script/dom/eventtarget.rs +++ b/components/script/dom/eventtarget.rs @@ -2,11 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::beforeunloadevent::BeforeUnloadEvent; use dom::bindings::callback::{CallbackContainer, ExceptionHandling, CallbackFunction}; use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::BeforeUnloadEventBinding::BeforeUnloadEventMethods; use dom::bindings::codegen::Bindings::ErrorEventBinding::ErrorEventMethods; use dom::bindings::codegen::Bindings::EventBinding::EventMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; +use dom::bindings::codegen::Bindings::EventHandlerBinding::OnBeforeUnloadEventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull; use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener; use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; @@ -45,6 +48,7 @@ use util::str::DOMString; pub enum CommonEventHandler { EventHandler(Rc<EventHandlerNonNull>), ErrorEventHandler(Rc<OnErrorEventHandlerNonNull>), + BeforeUnloadEventHandler(Rc<OnBeforeUnloadEventHandlerNonNull>), } impl CommonEventHandler { @@ -52,6 +56,7 @@ impl CommonEventHandler { match *self { CommonEventHandler::EventHandler(ref handler) => &handler.parent, CommonEventHandler::ErrorEventHandler(ref handler) => &handler.parent, + CommonEventHandler::BeforeUnloadEventHandler(ref handler) => &handler.parent, } } } @@ -173,6 +178,27 @@ impl CompiledEventListener { None, None, None, None, exception_handle); } + CommonEventHandler::BeforeUnloadEventHandler(ref handler) => { + if let Some(event) = event.downcast::<BeforeUnloadEvent>() { + let rv = event.ReturnValue(); + + if let Ok(value) = handler.Call_(object, + event.upcast::<Event>(), + exception_handle) { + match value { + Some(value) => { + if rv.is_empty() { + event.SetReturnValue(value); + } + } + None => { + event.upcast::<Event>().PreventDefault(); + } + } + } + } + } + CommonEventHandler::EventHandler(ref handler) => { if let Ok(value) = handler.Call_(object, event, exception_handle) { let global = object.global(); @@ -183,7 +209,6 @@ impl CompiledEventListener { //Step 4 let should_cancel = match event.type_() { atom!("mouseover") => value.is_boolean() && value.to_boolean() == true, - atom!("beforeunload") => value.is_null(), _ => value.is_boolean() && value.to_boolean() == false }; if should_cancel { @@ -412,7 +437,12 @@ impl EventTarget { if is_error { Some(CommonEventHandler::ErrorEventHandler(OnErrorEventHandlerNonNull::new(funobj))) } else { - Some(CommonEventHandler::EventHandler(EventHandlerNonNull::new(funobj))) + if ty == &atom!("beforeunload") { + Some(CommonEventHandler::BeforeUnloadEventHandler( + OnBeforeUnloadEventHandlerNonNull::new(funobj))) + } else { + Some(CommonEventHandler::EventHandler(EventHandlerNonNull::new(funobj))) + } } } @@ -436,6 +466,16 @@ impl EventTarget { self.set_inline_event_listener(Atom::from(ty), event_listener); } + pub fn set_beforeunload_event_handler<T: CallbackContainer>(&self, ty: &str, + listener: Option<Rc<T>>) { + let event_listener = listener.map(|listener| + InlineEventListener::Compiled( + CommonEventHandler::BeforeUnloadEventHandler( + OnBeforeUnloadEventHandlerNonNull::new(listener.callback()))) + ); + self.set_inline_event_listener(Atom::from(ty), event_listener); + } + pub fn get_event_handler_common<T: CallbackContainer>(&self, ty: &str) -> Option<Rc<T>> { let listener = self.get_inline_event_listener(&Atom::from(ty)); listener.map(|listener| CallbackContainer::new(listener.parent().callback())) diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs index 2fd18a00c08..536e3759fb3 100644 --- a/components/script/dom/htmlbodyelement.rs +++ b/components/script/dom/htmlbodyelement.rs @@ -4,7 +4,7 @@ use cssparser::RGBA; use dom::attr::{Attr, AttrValue}; -use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; +use dom::bindings::codegen::Bindings::EventHandlerBinding::{EventHandlerNonNull, OnBeforeUnloadEventHandlerNonNull}; use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::{self, HTMLBodyElementMethods}; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::inheritance::Castable; @@ -16,7 +16,6 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use script_traits::ScriptMsg as ConstellationMsg; -use std::rc::Rc; use string_cache::Atom; use time; use url::Url; @@ -70,31 +69,14 @@ impl HTMLBodyElementMethods for HTMLBodyElement { // https://html.spec.whatwg.org/multipage/#dom-body-text make_legacy_color_setter!(SetText, "text"); - // https://html.spec.whatwg.org/multipage/#the-body-element - fn GetOnunload(&self) -> Option<Rc<EventHandlerNonNull>> { - window_from_node(self).GetOnunload() - } - - // https://html.spec.whatwg.org/multipage/#the-body-element - fn SetOnunload(&self, listener: Option<Rc<EventHandlerNonNull>>) { - window_from_node(self).SetOnunload(listener) - } - - // https://html.spec.whatwg.org/multipage/#the-body-element - fn GetOnstorage(&self) -> Option<Rc<EventHandlerNonNull>> { - window_from_node(self).GetOnstorage() - } - - // https://html.spec.whatwg.org/multipage/#the-body-element - fn SetOnstorage(&self, listener: Option<Rc<EventHandlerNonNull>>) { - window_from_node(self).SetOnstorage(listener) - } - // https://html.spec.whatwg.org/multipage/#dom-body-background make_getter!(Background, "background"); // https://html.spec.whatwg.org/multipage/#dom-body-background make_url_setter!(SetBackground, "background"); + + // https://html.spec.whatwg.org/multipage/#windoweventhandlers + window_event_handlers!(ForwardToWindow); } pub trait HTMLBodyElementLayoutHelpers { diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index 3ad8f977869..7e310db8903 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -137,6 +137,9 @@ impl HTMLElementMethods for HTMLElement { // https://html.spec.whatwg.org/multipage/#globaleventhandlers global_event_handlers!(NoOnload); + // https://html.spec.whatwg.org/multipage/#documentandelementeventhandlers + document_and_element_event_handlers!(); + // https://html.spec.whatwg.org/multipage/#dom-dataset fn Dataset(&self) -> Root<DOMStringMap> { self.dataset.or_init(|| DOMStringMap::new(self)) @@ -196,6 +199,42 @@ impl HTMLElementMethods for HTMLElement { } } + // https://html.spec.whatwg.org/multipage/#handler-onfocus + fn GetOnfocus(&self) -> Option<Rc<EventHandlerNonNull>> { + if self.is_body_or_frameset() { + window_from_node(self).GetOnfocus() + } else { + self.upcast::<EventTarget>().get_event_handler_common("focus") + } + } + + // https://html.spec.whatwg.org/multipage/#handler-onfocus + fn SetOnfocus(&self, listener: Option<Rc<EventHandlerNonNull>>) { + if self.is_body_or_frameset() { + window_from_node(self).SetOnfocus(listener) + } else { + self.upcast::<EventTarget>().set_event_handler_common("focus", listener) + } + } + + // https://html.spec.whatwg.org/multipage/#handler-onscroll + fn GetOnscroll(&self) -> Option<Rc<EventHandlerNonNull>> { + if self.is_body_or_frameset() { + window_from_node(self).GetOnscroll() + } else { + self.upcast::<EventTarget>().get_event_handler_common("scroll") + } + } + + // https://html.spec.whatwg.org/multipage/#handler-onscroll + fn SetOnscroll(&self, listener: Option<Rc<EventHandlerNonNull>>) { + if self.is_body_or_frameset() { + window_from_node(self).SetOnscroll(listener) + } else { + self.upcast::<EventTarget>().set_event_handler_common("scroll", listener) + } + } + // https://html.spec.whatwg.org/multipage/#dom-click fn Click(&self) { if !self.upcast::<Element>().disabled_state() { diff --git a/components/script/dom/htmlframesetelement.rs b/components/script/dom/htmlframesetelement.rs index 92170a0baf4..df73bc893e9 100644 --- a/components/script/dom/htmlframesetelement.rs +++ b/components/script/dom/htmlframesetelement.rs @@ -2,11 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::codegen::Bindings::EventHandlerBinding::{EventHandlerNonNull, OnBeforeUnloadEventHandlerNonNull}; use dom::bindings::codegen::Bindings::HTMLFrameSetElementBinding; +use dom::bindings::codegen::Bindings::HTMLFrameSetElementBinding::HTMLFrameSetElementMethods; +use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::js::Root; use dom::document::Document; use dom::htmlelement::HTMLElement; -use dom::node::Node; +use dom::node::{Node, window_from_node}; use string_cache::Atom; use util::str::DOMString; @@ -33,3 +36,8 @@ impl HTMLFrameSetElement { Node::reflect_node(box element, document, HTMLFrameSetElementBinding::Wrap) } } + +impl HTMLFrameSetElementMethods for HTMLFrameSetElement { + // https://html.spec.whatwg.org/multipage/#windoweventhandlers + window_event_handlers!(ForwardToWindow); +} diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs index cf93b72f985..78238dc09fd 100644 --- a/components/script/dom/macros.rs +++ b/components/script/dom/macros.rs @@ -321,6 +321,18 @@ macro_rules! define_event_handler( ) ); +macro_rules! define_window_owned_event_handler( + ($handler: ident, $event_type: ident, $getter: ident, $setter: ident) => ( + fn $getter(&self) -> Option<::std::rc::Rc<$handler>> { + window_from_node(self).$getter() + } + + fn $setter(&self, listener: Option<::std::rc::Rc<$handler>>) { + window_from_node(self).$setter(listener) + } + ) +); + macro_rules! event_handler( ($event_type: ident, $getter: ident, $setter: ident) => ( define_event_handler!(EventHandlerNonNull, $event_type, $getter, $setter, @@ -335,42 +347,158 @@ macro_rules! error_event_handler( ) ); +macro_rules! beforeunload_event_handler( + ($event_type: ident, $getter: ident, $setter: ident) => ( + define_event_handler!(OnBeforeUnloadEventHandlerNonNull, $event_type, + $getter, $setter, set_beforeunload_event_handler); + ) +); + +macro_rules! window_owned_event_handler( + ($event_type: ident, $getter: ident, $setter: ident) => ( + define_window_owned_event_handler!(EventHandlerNonNull, + $event_type, $getter, $setter); + ) +); + +macro_rules! window_owned_beforeunload_event_handler( + ($event_type: ident, $getter: ident, $setter: ident) => ( + define_window_owned_event_handler!(OnBeforeUnloadEventHandlerNonNull, + $event_type, $getter, $setter); + ) +); + // https://html.spec.whatwg.org/multipage/#globaleventhandlers // see webidls/EventHandler.webidl // As more methods get added, just update them here. macro_rules! global_event_handlers( () => ( event_handler!(blur, GetOnblur, SetOnblur); + event_handler!(focus, GetOnfocus, SetOnfocus); event_handler!(load, GetOnload, SetOnload); event_handler!(resize, GetOnresize, SetOnresize); + event_handler!(scroll, GetOnscroll, SetOnscroll); global_event_handlers!(NoOnload); ); (NoOnload) => ( event_handler!(abort, GetOnabort, SetOnabort); + event_handler!(cancel, GetOncancel, SetOncancel); event_handler!(canplay, GetOncanplay, SetOncanplay); event_handler!(canplaythrough, GetOncanplaythrough, SetOncanplaythrough); event_handler!(change, GetOnchange, SetOnchange); event_handler!(click, GetOnclick, SetOnclick); + event_handler!(close, GetOnclose, SetOnclose); + event_handler!(contextmenu, GetOncontextmenu, SetOncontextmenu); + event_handler!(cuechange, GetOncuechange, SetOncuechange); event_handler!(dblclick, GetOndblclick, SetOndblclick); + event_handler!(drag, GetOndrag, SetOndrag); + event_handler!(dragend, GetOndragend, SetOndragend); + event_handler!(dragenter, GetOndragenter, SetOndragenter); + event_handler!(dragexit, GetOndragexit, SetOndragexit); + event_handler!(dragleave, GetOndragleave, SetOndragleave); + event_handler!(dragover, GetOndragover, SetOndragover); + event_handler!(dragstart, GetOndragstart, SetOndragstart); + event_handler!(drop, GetOndrop, SetOndrop); + event_handler!(durationchange, GetOndurationchange, SetOndurationchange); event_handler!(emptied, GetOnemptied, SetOnemptied); + event_handler!(ended, GetOnended, SetOnended); error_event_handler!(error, GetOnerror, SetOnerror); event_handler!(input, GetOninput, SetOninput); + event_handler!(invalid, GetOninvalid, SetOninvalid); event_handler!(keydown, GetOnkeydown, SetOnkeydown); event_handler!(keypress, GetOnkeypress, SetOnkeypress); event_handler!(keyup, GetOnkeyup, SetOnkeyup); event_handler!(loadeddata, GetOnloadeddata, SetOnloadeddata); event_handler!(loadedmetata, GetOnloadedmetadata, SetOnloadedmetadata); + event_handler!(loadstart, GetOnloadstart, SetOnloadstart); + event_handler!(mousedown, GetOnmousedown, SetOnmousedown); + event_handler!(mouseenter, GetOnmouseenter, SetOnmouseenter); + event_handler!(mouseleave, GetOnmouseleave, SetOnmouseleave); + event_handler!(mousemove, GetOnmousemove, SetOnmousemove); + event_handler!(mouseout, GetOnmouseout, SetOnmouseout); event_handler!(mouseover, GetOnmouseover, SetOnmouseover); + event_handler!(mouseup, GetOnmouseup, SetOnmouseup); + event_handler!(wheel, GetOnwheel, SetOnwheel); event_handler!(pause, GetOnpause, SetOnpause); event_handler!(play, GetOnplay, SetOnplay); event_handler!(playing, GetOnplaying, SetOnplaying); event_handler!(progress, GetOnprogress, SetOnprogress); + event_handler!(ratechange, GetOnratechange, SetOnratechange); event_handler!(reset, GetOnreset, SetOnreset); + event_handler!(seeked, GetOnseeked, SetOnseeked); + event_handler!(seeking, GetOnseeking, SetOnseeking); + event_handler!(select, GetOnselect, SetOnselect); + event_handler!(show, GetOnshow, SetOnshow); + event_handler!(stalled, GetOnstalled, SetOnstalled); event_handler!(submit, GetOnsubmit, SetOnsubmit); event_handler!(suspend, GetOnsuspend, SetOnsuspend); event_handler!(timeupdate, GetOntimeupdate, SetOntimeupdate); event_handler!(toggle, GetOntoggle, SetOntoggle); + event_handler!(volumechange, GetOnvolumechange, SetOnvolumechange); event_handler!(waiting, GetOnwaiting, SetOnwaiting); ) ); + +// https://html.spec.whatwg.org/multipage/#windoweventhandlers +// see webidls/EventHandler.webidl +// As more methods get added, just update them here. +macro_rules! window_event_handlers( + () => ( + event_handler!(afterprint, GetOnafterprint, SetOnafterprint); + event_handler!(beforeprint, GetOnbeforeprint, SetOnbeforeprint); + beforeunload_event_handler!(beforeunload, GetOnbeforeunload, + SetOnbeforeunload); + event_handler!(hashchange, GetOnhashchange, SetOnhashchange); + event_handler!(languagechange, GetOnlanguagechange, + SetOnlanguagechange); + event_handler!(message, GetOnmessage, SetOnmessage); + event_handler!(offline, GetOnoffline, SetOnoffline); + event_handler!(online, GetOnonline, SetOnonline); + event_handler!(pagehide, GetOnpagehide, SetOnpagehide); + event_handler!(pageshow, GetOnpageshow, SetOnpageshow); + event_handler!(popstate, GetOnpopstate, SetOnpopstate); + event_handler!(rejectionhandled, GetOnrejectionhandled, + SetOnrejectionhandled); + event_handler!(storage, GetOnstorage, SetOnstorage); + event_handler!(unhandledrejection, GetOnunhandledrejection, + SetOnunhandledrejection); + event_handler!(unload, GetOnunload, SetOnunload); + ); + (ForwardToWindow) => ( + window_owned_event_handler!(afterprint, GetOnafterprint, + SetOnafterprint); + window_owned_event_handler!(beforeprint, GetOnbeforeprint, + SetOnbeforeprint); + window_owned_beforeunload_event_handler!(beforeunload, + GetOnbeforeunload, + SetOnbeforeunload); + window_owned_event_handler!(hashchange, GetOnhashchange, + SetOnhashchange); + window_owned_event_handler!(languagechange, GetOnlanguagechange, + SetOnlanguagechange); + window_owned_event_handler!(message, GetOnmessage, SetOnmessage); + window_owned_event_handler!(offline, GetOnoffline, SetOnoffline); + window_owned_event_handler!(online, GetOnonline, SetOnonline); + window_owned_event_handler!(pagehide, GetOnpagehide, SetOnpagehide); + window_owned_event_handler!(pageshow, GetOnpageshow, SetOnpageshow); + window_owned_event_handler!(popstate, GetOnpopstate, SetOnpopstate); + window_owned_event_handler!(rejectionhandled, GetOnrejectionhandled, + SetOnrejectionhandled); + window_owned_event_handler!(storage, GetOnstorage, SetOnstorage); + window_owned_event_handler!(unhandledrejection, GetOnunhandledrejection, + SetOnunhandledrejection); + window_owned_event_handler!(unload, GetOnunload, SetOnunload); + ); +); + +// https://html.spec.whatwg.org/multipage/#documentandelementeventhandlers +// see webidls/EventHandler.webidl +// As more methods get added, just update them here. +macro_rules! document_and_element_event_handlers( + () => ( + event_handler!(cut, GetOncut, SetOncut); + event_handler!(copy, GetOncopy, SetOncopy); + event_handler!(paste, GetOnpaste, SetOnpaste); + ) +); diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index cfa41a1ae19..a5d8e7a707a 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -157,18 +157,18 @@ //! Inheritance and casting //! ======================= //! -//! For all DOM interfaces `Foo` in an inheritance chain, a -//! `dom::bindings::inheritance::FooCast` provides methods to cast -//! to other types in the inheritance chain. For example: +//! All DOM interfaces part of an inheritance chain (i.e. interfaces +//! that derive others or are derived from) implement the trait `Castable` +//! which provides both downcast and upcasts. //! //! ```ignore -//! # use script::dom::bindings::inheritance::{NodeCast, HTMLElementCast}; +//! # use script::dom::bindings::inheritance::Castable; //! # use script::dom::element::Element; //! # use script::dom::node::Node; //! # use script::dom::htmlelement::HTMLElement; //! fn f(element: &Element) { //! let base = element.upcast::<Node>(); -//! let derived = element.downcast::<HTMLElement>(); +//! let derived = element.downcast::<HTMLElement>().unwrap(); //! } //! ``` //! @@ -211,6 +211,7 @@ pub mod types { pub mod activation; pub mod attr; +pub mod beforeunloadevent; mod create; #[allow(unsafe_code)] #[deny(missing_docs, non_snake_case)] diff --git a/components/script/dom/webidls/BeforeUnloadEvent.webidl b/components/script/dom/webidls/BeforeUnloadEvent.webidl new file mode 100644 index 00000000000..5e4a099725a --- /dev/null +++ b/components/script/dom/webidls/BeforeUnloadEvent.webidl @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * For more information on this interface please see + * https://html.spec.whatwg.org/multipage/#beforeunloadevent + */ + +interface BeforeUnloadEvent : Event { + attribute DOMString returnValue; +}; diff --git a/components/script/dom/webidls/Document.webidl b/components/script/dom/webidls/Document.webidl index b211fe7be58..b73d563bac7 100644 --- a/components/script/dom/webidls/Document.webidl +++ b/components/script/dom/webidls/Document.webidl @@ -138,6 +138,7 @@ partial /*sealed*/ interface Document { // also has obsolete members }; Document implements GlobalEventHandlers; +Document implements DocumentAndElementEventHandlers; // https://html.spec.whatwg.org/multipage/#Document-partial partial interface Document { diff --git a/components/script/dom/webidls/EventHandler.webidl b/components/script/dom/webidls/EventHandler.webidl index fa42b757cab..957fc0bd4dd 100644 --- a/components/script/dom/webidls/EventHandler.webidl +++ b/components/script/dom/webidls/EventHandler.webidl @@ -20,42 +20,99 @@ callback OnErrorEventHandlerNonNull = any ((Event or DOMString) event, optional optional any error); typedef OnErrorEventHandlerNonNull? OnErrorEventHandler; +[TreatNonObjectAsNull] +callback OnBeforeUnloadEventHandlerNonNull = DOMString? (Event event); +typedef OnBeforeUnloadEventHandlerNonNull? OnBeforeUnloadEventHandler; + // https://html.spec.whatwg.org/multipage/#globaleventhandlers [NoInterfaceObject] interface GlobalEventHandlers { attribute EventHandler onabort; attribute EventHandler onblur; + attribute EventHandler oncancel; attribute EventHandler oncanplay; attribute EventHandler oncanplaythrough; attribute EventHandler onchange; attribute EventHandler onclick; + attribute EventHandler onclose; + attribute EventHandler oncontextmenu; + attribute EventHandler oncuechange; attribute EventHandler ondblclick; + attribute EventHandler ondrag; + attribute EventHandler ondragend; + attribute EventHandler ondragenter; + attribute EventHandler ondragexit; + attribute EventHandler ondragleave; + attribute EventHandler ondragover; + attribute EventHandler ondragstart; + attribute EventHandler ondrop; + attribute EventHandler ondurationchange; attribute EventHandler onemptied; + attribute EventHandler onended; attribute OnErrorEventHandler onerror; + attribute EventHandler onfocus; attribute EventHandler oninput; + attribute EventHandler oninvalid; attribute EventHandler onkeydown; attribute EventHandler onkeypress; attribute EventHandler onkeyup; attribute EventHandler onload; attribute EventHandler onloadeddata; attribute EventHandler onloadedmetadata; + attribute EventHandler onloadstart; + attribute EventHandler onmousedown; + [LenientThis] attribute EventHandler onmouseenter; + [LenientThis] attribute EventHandler onmouseleave; + attribute EventHandler onmousemove; + attribute EventHandler onmouseout; attribute EventHandler onmouseover; + attribute EventHandler onmouseup; + attribute EventHandler onwheel; attribute EventHandler onpause; attribute EventHandler onplay; attribute EventHandler onplaying; attribute EventHandler onprogress; + attribute EventHandler onratechange; attribute EventHandler onreset; attribute EventHandler onresize; + attribute EventHandler onscroll; + attribute EventHandler onseeked; + attribute EventHandler onseeking; + attribute EventHandler onselect; + attribute EventHandler onshow; + attribute EventHandler onstalled; attribute EventHandler onsubmit; attribute EventHandler onsuspend; attribute EventHandler ontimeupdate; attribute EventHandler ontoggle; + attribute EventHandler onvolumechange; attribute EventHandler onwaiting; }; // https://html.spec.whatwg.org/multipage/#windoweventhandlers [NoInterfaceObject] interface WindowEventHandlers { - attribute EventHandler onunload; + attribute EventHandler onafterprint; + attribute EventHandler onbeforeprint; + attribute OnBeforeUnloadEventHandler onbeforeunload; + attribute EventHandler onhashchange; + attribute EventHandler onlanguagechange; + attribute EventHandler onmessage; + attribute EventHandler onoffline; + attribute EventHandler ononline; + attribute EventHandler onpagehide; + attribute EventHandler onpageshow; + attribute EventHandler onpopstate; + attribute EventHandler onrejectionhandled; attribute EventHandler onstorage; + attribute EventHandler onunhandledrejection; + attribute EventHandler onunload; +}; + +// https://html.spec.whatwg.org/multipage/#documentandelementeventhandlers +[NoInterfaceObject] +interface DocumentAndElementEventHandlers { + attribute EventHandler oncopy; + attribute EventHandler oncut; + attribute EventHandler onpaste; }; diff --git a/components/script/dom/webidls/HTMLElement.webidl b/components/script/dom/webidls/HTMLElement.webidl index 9778985dd40..19222109d63 100644 --- a/components/script/dom/webidls/HTMLElement.webidl +++ b/components/script/dom/webidls/HTMLElement.webidl @@ -54,5 +54,6 @@ partial interface HTMLElement { }; HTMLElement implements GlobalEventHandlers; +HTMLElement implements DocumentAndElementEventHandlers; HTMLElement implements ElementContentEditable; HTMLElement implements ElementCSSInlineStyle; diff --git a/components/script/dom/webidls/HTMLFrameSetElement.webidl b/components/script/dom/webidls/HTMLFrameSetElement.webidl index f35de93e545..5addd41d253 100644 --- a/components/script/dom/webidls/HTMLFrameSetElement.webidl +++ b/components/script/dom/webidls/HTMLFrameSetElement.webidl @@ -7,4 +7,5 @@ interface HTMLFrameSetElement : HTMLElement { // attribute DOMString cols; // attribute DOMString rows; }; -//HTMLFrameSetElement implements WindowEventHandlers; + +HTMLFrameSetElement implements WindowEventHandlers; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 7eab91db3a4..8fdb7049715 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -7,7 +7,9 @@ use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarker use dom::bindings::callback::ExceptionHandling; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState}; -use dom::bindings::codegen::Bindings::EventHandlerBinding::{EventHandlerNonNull, OnErrorEventHandlerNonNull}; +use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; +use dom::bindings::codegen::Bindings::EventHandlerBinding::OnBeforeUnloadEventHandlerNonNull; +use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull; use dom::bindings::codegen::Bindings::FunctionBinding::Function; use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions}; use dom::bindings::codegen::Bindings::WindowBinding::{self, FrameRequestCallback, WindowMethods}; @@ -45,10 +47,10 @@ use libc; use msg::constellation_msg::{LoadData, PanicMsg, PipelineId, SubpageId}; use msg::constellation_msg::{WindowSizeData, WindowSizeType}; use msg::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; -use net_traits::ResourceThreads; use net_traits::bluetooth_thread::BluetoothMethodMsg; use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread}; use net_traits::storage_thread::StorageType; +use net_traits::{ResourceThreads, CustomResponseSender}; use num_traits::ToPrimitive; use profile_traits::mem; use profile_traits::time::{ProfilerCategory, TimerMetadata, TimerMetadataFrameType}; @@ -148,6 +150,8 @@ pub struct Window { image_cache_thread: ImageCacheThread, #[ignore_heap_size_of = "channels are hard"] image_cache_chan: ImageCacheChan, + #[ignore_heap_size_of = "channels are hard"] + custom_message_chan: IpcSender<CustomResponseSender>, #[ignore_heap_size_of = "TODO(#6911) newtypes containing unmeasurable types are hard"] compositor: IpcSender<ScriptToCompositorMsg>, browsing_context: MutNullableHeap<JS<BrowsingContext>>, @@ -303,6 +307,10 @@ impl Window { self.image_cache_chan.clone() } + pub fn custom_message_chan(&self) -> IpcSender<CustomResponseSender> { + self.custom_message_chan.clone() + } + pub fn get_next_worker_id(&self) -> WorkerId { let worker_id = self.next_worker_id.get(); let WorkerId(id_num) = worker_id; @@ -585,11 +593,8 @@ impl WindowMethods for Window { // https://html.spec.whatwg.org/multipage/#globaleventhandlers global_event_handlers!(); - // https://html.spec.whatwg.org/multipage/#handler-window-onunload - event_handler!(unload, GetOnunload, SetOnunload); - - // https://html.spec.whatwg.org/multipage/#handler-window-onstorage - event_handler!(storage, GetOnstorage, SetOnstorage); + // https://html.spec.whatwg.org/multipage/#windoweventhandlers + window_event_handlers!(); // https://developer.mozilla.org/en-US/docs/Web/API/Window/screen fn Screen(&self) -> Root<Screen> { @@ -1443,6 +1448,7 @@ impl Window { history_task_source: HistoryTraversalTaskSource, file_task_source: FileReadingTaskSource, image_cache_chan: ImageCacheChan, + custom_message_chan: IpcSender<CustomResponseSender>, compositor: IpcSender<ScriptToCompositorMsg>, image_cache_thread: ImageCacheThread, resource_threads: ResourceThreads, @@ -1480,6 +1486,7 @@ impl Window { history_traversal_task_source: history_task_source, file_reading_task_source: file_task_source, image_cache_chan: image_cache_chan, + custom_message_chan: custom_message_chan, console: Default::default(), crypto: Default::default(), compositor: compositor, diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 661d397460f..f7900a0d0f0 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -24,10 +24,13 @@ use js::jsapi::{HandleValue, JSContext, JSRuntime, RootedValue}; use js::jsapi::{JSAutoCompartment, JS_RequestInterruptCallback}; use js::jsval::UndefinedValue; use js::rust::Runtime; +use msg::constellation_msg::{PipelineId, ReferrerPolicy}; +use net_traits::{RequestSource, LoadOrigin}; use script_thread::Runnable; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{Sender, channel}; use std::sync::{Arc, Mutex}; +use url::Url; use util::str::DOMString; pub type TrustedWorkerAddress = Trusted<Worker>; @@ -45,6 +48,29 @@ pub struct Worker { runtime: Arc<Mutex<Option<SharedRt>>> } +#[derive(Clone)] +pub struct WorkerScriptLoadOrigin { + referrer_url: Option<Url>, + referrer_policy: Option<ReferrerPolicy>, + request_source: RequestSource, + pipeline_id: Option<PipelineId> +} + +impl LoadOrigin for WorkerScriptLoadOrigin { + fn referrer_url(&self) -> Option<Url> { + self.referrer_url.clone() + } + fn referrer_policy(&self) -> Option<ReferrerPolicy> { + self.referrer_policy.clone() + } + fn request_source(&self) -> RequestSource { + self.request_source.clone() + } + fn pipeline_id(&self) -> Option<PipelineId> { + self.pipeline_id.clone() + } +} + impl Worker { fn new_inherited(sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>, closing: Arc<AtomicBool>) -> Worker { @@ -82,6 +108,13 @@ impl Worker { let worker_ref = Trusted::new(worker.r()); let worker_id = global.get_next_worker_id(); + let worker_load_origin = WorkerScriptLoadOrigin { + referrer_url: None, + referrer_policy: None, + request_source: global.request_source(), + pipeline_id: Some(global.pipeline()) + }; + let (devtools_sender, devtools_receiver) = ipc::channel().unwrap(); let optional_sender = match global.devtools_chan() { Some(ref chan) => { @@ -114,7 +147,7 @@ impl Worker { DedicatedWorkerGlobalScope::run_worker_scope( init, worker_url, global.pipeline(), devtools_receiver, worker.runtime.clone(), worker_ref, - global.script_chan(), sender, receiver); + global.script_chan(), sender, receiver, worker_load_origin); Ok(worker) } diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index ef9afd34cf7..a8b5d9a48c3 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -17,12 +17,13 @@ use dom::eventtarget::EventTarget; use dom::window::{base64_atob, base64_btoa}; use dom::workerlocation::WorkerLocation; use dom::workernavigator::WorkerNavigator; -use ipc_channel::ipc::IpcSender; +use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::router::ROUTER; use js::jsapi::{HandleValue, JSContext, JSRuntime, RootedValue}; use js::jsval::UndefinedValue; use js::rust::Runtime; -use msg::constellation_msg::{PanicMsg, PipelineId}; -use net_traits::{LoadContext, CoreResourceThread, load_whole_resource}; +use msg::constellation_msg::{PipelineId, ReferrerPolicy, PanicMsg}; +use net_traits::{LoadContext, CoreResourceThread, load_whole_resource, RequestSource, LoadOrigin, CustomResponseSender}; use profile_traits::{mem, time}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort}; use script_traits::ScriptMsg as ConstellationMsg; @@ -101,6 +102,12 @@ pub struct WorkerGlobalScope { #[ignore_heap_size_of = "Defined in ipc-channel"] panic_chan: IpcSender<PanicMsg>, + + #[ignore_heap_size_of = "Defined in ipc-channel"] + custom_msg_chan: IpcSender<CustomResponseSender>, + + #[ignore_heap_size_of = "Defined in std"] + custom_msg_port: Receiver<CustomResponseSender>, } impl WorkerGlobalScope { @@ -110,7 +117,8 @@ impl WorkerGlobalScope { from_devtools_receiver: Receiver<DevtoolScriptControlMsg>, timer_event_chan: IpcSender<TimerEvent>) -> WorkerGlobalScope { - + let (msg_chan, msg_port) = ipc::channel().unwrap(); + let custom_msg_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(msg_port); WorkerGlobalScope { eventtarget: EventTarget::new_inherited(), next_worker_id: Cell::new(WorkerId(0)), @@ -133,6 +141,8 @@ impl WorkerGlobalScope { constellation_chan: init.constellation_chan, scheduler_chan: init.scheduler_chan, panic_chan: init.panic_chan, + custom_msg_chan: msg_chan, + custom_msg_port: custom_msg_port } } @@ -182,6 +192,14 @@ impl WorkerGlobalScope { self.runtime.cx() } + pub fn custom_message_chan(&self) -> IpcSender<CustomResponseSender> { + self.custom_msg_chan.clone() + } + + pub fn custom_message_port(&self) -> &Receiver<CustomResponseSender> { + &self.custom_msg_port + } + pub fn is_closing(&self) -> bool { self.closing.load(Ordering::SeqCst) } @@ -210,6 +228,21 @@ impl WorkerGlobalScope { } } +impl LoadOrigin for WorkerGlobalScope { + fn referrer_url(&self) -> Option<Url> { + None + } + fn referrer_policy(&self) -> Option<ReferrerPolicy> { + None + } + fn request_source(&self) -> RequestSource { + RequestSource::None + } + fn pipeline_id(&self) -> Option<PipelineId> { + Some(self.pipeline()) + } +} + impl WorkerGlobalScopeMethods for WorkerGlobalScope { // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-self fn Self_(&self) -> Root<WorkerGlobalScope> { @@ -236,7 +269,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope { let mut rval = RootedValue::new(self.runtime.cx(), UndefinedValue()); for url in urls { - let (url, source) = match load_whole_resource(LoadContext::Script, &self.core_resource_thread, url, None) { + let (url, source) = match load_whole_resource(LoadContext::Script, &self.core_resource_thread, url, self) { Err(_) => return Err(Error::Network), Ok((metadata, bytes)) => { (metadata.final_url, String::from_utf8(bytes).unwrap()) diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index b72d5995b20..567db277b8f 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -44,9 +44,10 @@ use ipc_channel::router::ROUTER; use js::jsapi::JS_ClearPendingException; use js::jsapi::{JSContext, JS_ParseJSON, RootedValue}; use js::jsval::{JSVal, NullValue, UndefinedValue}; +use msg::constellation_msg::{PipelineId, ReferrerPolicy}; use net_traits::CoreResourceMsg::Load; -use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError}; -use net_traits::{LoadConsumer, LoadContext, LoadData, ResourceCORSData, CoreResourceThread}; +use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError, RequestSource}; +use net_traits::{LoadConsumer, LoadContext, LoadData, ResourceCORSData, CoreResourceThread, LoadOrigin}; use network_listener::{NetworkListener, PreInvoke}; use parse::html::{ParseContext, parse_html}; use parse::xml::{self, parse_xml}; @@ -295,6 +296,26 @@ impl XMLHttpRequest { } } +impl LoadOrigin for XMLHttpRequest { + fn referrer_url(&self) -> Option<Url> { + None + } + fn referrer_policy(&self) -> Option<ReferrerPolicy> { + None + } + fn request_source(&self) -> RequestSource { + if self.sync.get() { + RequestSource::None + } else { + self.global().r().request_source() + } + } + fn pipeline_id(&self) -> Option<PipelineId> { + let global = self.global(); + Some(global.r().pipeline()) + } +} + impl XMLHttpRequestMethods for XMLHttpRequest { // https://xhr.spec.whatwg.org/#handler-xhr-onreadystatechange event_handler!(readystatechange, GetOnreadystatechange, SetOnreadystatechange); @@ -572,14 +593,11 @@ impl XMLHttpRequestMethods for XMLHttpRequest { // Step 5 let global = self.global(); - let pipeline_id = global.r().pipeline(); //TODO - set referrer_policy/referrer_url in load_data let mut load_data = LoadData::new(LoadContext::Browsing, self.request_url.borrow().clone().unwrap(), - Some(pipeline_id), - None, - None); + self); if load_data.url.origin().ne(&global.r().get_url().origin()) { load_data.credentials_flag = self.WithCredentials(); } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 8f43e1b1bfc..f7bb765651d 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -65,8 +65,8 @@ use msg::webdriver_msg::WebDriverScriptCommand; use net_traits::LoadData as NetLoadData; use net_traits::bluetooth_thread::BluetoothMethodMsg; use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread}; -use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadContext, Metadata}; -use net_traits::{ResourceThreads, IpcSend}; +use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadContext, Metadata, ResourceThreads}; +use net_traits::{RequestSource, CustomResponse, CustomResponseSender, IpcSend}; use network_listener::NetworkListener; use parse::ParserRoot; use parse::html::{ParseContext, parse_html}; @@ -205,6 +205,7 @@ enum MixedMessage { FromDevtools(DevtoolScriptControlMsg), FromImageCache(ImageCacheResult), FromScheduler(TimerEvent), + FromNetwork(IpcSender<Option<CustomResponse>>), } /// Messages used to control the script event loop @@ -321,6 +322,12 @@ pub struct ScriptThread { /// events in the event queue. chan: MainThreadScriptChan, + /// A handle to network event messages + custom_message_chan: IpcSender<CustomResponseSender>, + + /// The port which receives a sender from the network + custom_message_port: Receiver<CustomResponseSender>, + dom_manipulation_task_source: DOMManipulationTaskSource, user_interaction_task_source: UserInteractionTaskSource, @@ -536,6 +543,9 @@ impl ScriptThread { let (ipc_devtools_sender, ipc_devtools_receiver) = ipc::channel().unwrap(); let devtools_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_devtools_receiver); + let (ipc_custom_resp_chan, ipc_custom_resp_port) = ipc::channel().unwrap(); + let custom_msg_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_custom_resp_port); + // Ask the router to proxy IPC messages from the image cache thread to us. let (ipc_image_cache_channel, ipc_image_cache_port) = ipc::channel().unwrap(); let image_cache_port = @@ -558,6 +568,9 @@ impl ScriptThread { bluetooth_thread: state.bluetooth_thread, port: port, + custom_message_chan: ipc_custom_resp_chan, + custom_message_port: custom_msg_port, + chan: MainThreadScriptChan(chan.clone()), dom_manipulation_task_source: DOMManipulationTaskSource(chan.clone()), user_interaction_task_source: UserInteractionTaskSource(chan.clone()), @@ -619,7 +632,8 @@ impl ScriptThread { /// Handle incoming control messages. fn handle_msgs(&self) -> bool { - use self::MixedMessage::{FromScript, FromConstellation, FromScheduler, FromDevtools, FromImageCache}; + use self::MixedMessage::{FromConstellation, FromDevtools, FromImageCache}; + use self::MixedMessage::{FromScheduler, FromScript, FromNetwork}; // Handle pending resize events. // Gather them first to avoid a double mut borrow on self. @@ -653,6 +667,7 @@ impl ScriptThread { let mut timer_event_port = sel.handle(&self.timer_event_port); let mut devtools_port = sel.handle(&self.devtools_port); let mut image_cache_port = sel.handle(&self.image_cache_port); + let mut custom_message_port = sel.handle(&self.custom_message_port); unsafe { script_port.add(); control_port.add(); @@ -661,6 +676,7 @@ impl ScriptThread { devtools_port.add(); } image_cache_port.add(); + custom_message_port.add(); } let ret = sel.wait(); if ret == script_port.id() { @@ -673,6 +689,8 @@ impl ScriptThread { FromDevtools(self.devtools_port.recv().unwrap()) } else if ret == image_cache_port.id() { FromImageCache(self.image_cache_port.recv().unwrap()) + } else if ret == custom_message_port.id() { + FromNetwork(self.custom_message_port.recv().unwrap()) } else { panic!("unexpected select result") } @@ -735,7 +753,10 @@ impl ScriptThread { Err(_) => match self.timer_event_port.try_recv() { Err(_) => match self.devtools_port.try_recv() { Err(_) => match self.image_cache_port.try_recv() { - Err(_) => break, + Err(_) => match self.custom_message_port.try_recv() { + Err(_) => break, + Ok(ev) => event = FromNetwork(ev) + }, Ok(ev) => event = FromImageCache(ev), }, Ok(ev) => event = FromDevtools(ev), @@ -761,6 +782,7 @@ impl ScriptThread { }, FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg), FromScript(inner_msg) => self.handle_msg_from_script(inner_msg), + FromNetwork(inner_msg) => self.handle_msg_from_network(inner_msg), FromScheduler(inner_msg) => self.handle_timer_event(inner_msg), FromDevtools(inner_msg) => self.handle_msg_from_devtools(inner_msg), FromImageCache(inner_msg) => self.handle_msg_from_image_cache(inner_msg), @@ -820,6 +842,7 @@ impl ScriptThread { } }, MixedMessage::FromScheduler(_) => ScriptThreadEventCategory::TimerEvent, + MixedMessage::FromNetwork(_) => ScriptThreadEventCategory::NetworkEvent } } @@ -989,6 +1012,12 @@ impl ScriptThread { msg.responder.unwrap().respond(msg.image_response); } + fn handle_msg_from_network(&self, msg: IpcSender<Option<CustomResponse>>) { + // We may detect controlling service workers here + // We send None as default + let _ = msg.send(None); + } + fn handle_webdriver_msg(&self, pipeline_id: PipelineId, msg: WebDriverScriptCommand) { let context = self.root_browsing_context(); match msg { @@ -1437,6 +1466,7 @@ impl ScriptThread { HistoryTraversalTaskSource(history_sender.clone()), FileReadingTaskSource(file_sender.clone()), self.image_cache_channel.clone(), + self.custom_message_chan.clone(), self.compositor.borrow_mut().clone(), self.image_cache_thread.clone(), self.resource_threads.clone(), @@ -1905,6 +1935,7 @@ impl ScriptThread { credentials_flag: true, referrer_policy: load_data.referrer_policy, referrer_url: load_data.referrer_url, + source: RequestSource::Window(self.custom_message_chan.clone()) }, LoadConsumer::Listener(response_target), None)).unwrap(); self.incomplete_loads.borrow_mut().push(incomplete); |