diff --git a/components/embedder_traits/lib.rs b/components/embedder_traits/lib.rs index 340eb674054..9122a76f0ef 100644 --- a/components/embedder_traits/lib.rs +++ b/components/embedder_traits/lib.rs @@ -84,6 +84,8 @@ pub enum EmbedderMsg { Alert(String, IpcSender<()>), /// Wether or not to follow a link AllowNavigation(ServoUrl, IpcSender), + /// Wether or not to unload a document + AllowUnload(IpcSender), /// Sends an unconsumed key event back to the embedder. KeyEvent(Option, Key, KeyState, KeyModifiers), /// Changes the cursor. @@ -122,6 +124,7 @@ impl Debug for EmbedderMsg { EmbedderMsg::MoveTo(..) => write!(f, "MoveTo"), EmbedderMsg::ResizeTo(..) => write!(f, "ResizeTo"), EmbedderMsg::Alert(..) => write!(f, "Alert"), + EmbedderMsg::AllowUnload(..) => write!(f, "AllowUnload"), EmbedderMsg::AllowNavigation(..) => write!(f, "AllowNavigation"), EmbedderMsg::KeyEvent(..) => write!(f, "KeyEvent"), EmbedderMsg::SetCursor(..) => write!(f, "SetCursor"), diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 58c9df6d1bf..dc9eae886bb 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -10,8 +10,10 @@ use dom::attr::Attr; use dom::beforeunloadevent::BeforeUnloadEvent; use dom::bindings::callback::ExceptionHandling; use dom::bindings::cell::DomRefCell; +use dom::bindings::codegen::Bindings::BeforeUnloadEventBinding::BeforeUnloadEventBinding::BeforeUnloadEventMethods; use dom::bindings::codegen::Bindings::DocumentBinding; use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState, ElementCreationOptions}; +use dom::bindings::codegen::Bindings::EventBinding::EventBinding::EventMethods; use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementBinding::HTMLIFrameElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter; @@ -95,7 +97,7 @@ use fetch::FetchCanceller; use html5ever::{LocalName, Namespace, QualName}; use hyper::header::{Header, SetCookie}; use hyper_serde::Serde; -use ipc_channel::ipc::IpcSender; +use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::{JSContext, JSObject, JSRuntime}; use js::jsapi::JS_GetRuntime; use metrics::{InteractiveFlag, InteractiveMetrics, InteractiveWindow, ProfilerMetadataFactory, ProgressiveWebMetric}; @@ -108,7 +110,7 @@ use net_traits::pub_domains::is_pub_domain; use net_traits::request::RequestInit; use net_traits::response::HttpsState; use num_traits::ToPrimitive; -use profile_traits::ipc; +use profile_traits::ipc as profile_ipc; use profile_traits::time::{TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType}; use ref_slice::ref_slice; use script_layout_interface::message::{Msg, NodesFromPointQueryType, QueryMsg, ReflowGoal}; @@ -1665,7 +1667,15 @@ impl Document { // Step 7 self.salvageable.set(!has_listeners); let mut can_unload = true; - // TODO: Step 8 send a message to embedder to prompt user. + // TODO: Step 8, also check sandboxing modals flag. + let default_prevented = event.DefaultPrevented(); + let return_value_not_empty = !event.downcast::().unwrap().ReturnValue().is_empty(); + if default_prevented || return_value_not_empty { + let (chan, port) = ipc::channel().expect("Failed to create IPC channel!"); + let msg = EmbedderMsg::AllowUnload(chan); + self.send_to_embedder(msg); + can_unload = port.recv().unwrap(); + } // Step 9 if !recursive_flag { for iframe in self.iter_iframes() { @@ -3638,7 +3648,7 @@ impl DocumentMethods for Document { } let url = self.url(); - let (tx, rx) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); + let (tx, rx) = profile_ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let _ = self.window .upcast::() .resource_threads() diff --git a/ports/servo/browser.rs b/ports/servo/browser.rs index f874baa346c..996ad276a8d 100644 --- a/ports/servo/browser.rs +++ b/ports/servo/browser.rs @@ -266,6 +266,13 @@ impl Browser { self.event_queue.push(WindowEvent::SendError(browser_id, reason)); } } + EmbedderMsg::AllowUnload(sender) => { + // Always allow unload for now. + if let Err(e) = sender.send(true) { + let reason = format!("Failed to send AllowUnload response: {}", e); + self.event_queue.push(WindowEvent::SendError(browser_id, reason)); + } + } EmbedderMsg::AllowNavigation(_url, response_chan) => { if let Err(e) = response_chan.send(true) { warn!("Failed to send allow_navigation() response: {}", e);