diff options
-rw-r--r-- | components/compositing/constellation.rs | 83 | ||||
-rw-r--r-- | components/script/Cargo.toml | 3 | ||||
-rw-r--r-- | components/script/dom/window.rs | 25 | ||||
-rw-r--r-- | components/script/lib.rs | 2 | ||||
-rw-r--r-- | components/script_traits/script_msg.rs | 2 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 3 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 3 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 3 | ||||
-rw-r--r-- | tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event.html | 12 | ||||
-rw-r--r-- | tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event_nested_iframe.html | 5 |
10 files changed, 122 insertions, 19 deletions
diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 0b235257d1a..cfa4269258d 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -797,6 +797,10 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> debug!("constellation got SetDocumentState message"); self.document_states.insert(pipeline_id, state); } + Request::Script(FromScriptMsg::Alert(pipeline_id, message, sender)) => { + debug!("constellation got Alert message"); + self.handle_alert(pipeline_id, message, sender); + } // Messages from layout thread @@ -1069,6 +1073,44 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> } } + fn handle_alert(&mut self, pipeline_id: PipelineId, message: String, sender: IpcSender<bool>) { + let display_alert_dialog = if prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false) { + let parent_pipeline_info = self.pipelines.get(&pipeline_id).and_then(|source| source.parent_info); + if let Some(_) = parent_pipeline_info { + let root_pipeline_id = self.root_frame_id + .and_then(|root_frame_id| self.frames.get(&root_frame_id)) + .map(|root_frame| root_frame.current); + + let ancestor_info = self.get_root_pipeline_and_containing_parent(&pipeline_id); + if let Some(ancestor_info) = ancestor_info { + if root_pipeline_id == Some(ancestor_info.0) { + match root_pipeline_id.and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) { + Some(root_pipeline) => { + // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsershowmodalprompt + let event = MozBrowserEvent::ShowModalPrompt("alert".to_owned(), "Alert".to_owned(), + String::from(message), "".to_owned()); + root_pipeline.trigger_mozbrowser_event(ancestor_info.1, event); + } + None => return warn!("Alert sent to Pipeline {:?} after closure.", root_pipeline_id), + } + } else { + warn!("A non-current frame is trying to show an alert.") + } + } + false + } else { + true + } + } else { + true + }; + + let result = sender.send(display_alert_dialog); + if let Err(e) = result { + self.handle_send_error(pipeline_id, e); + } + } + fn handle_load_url_msg(&mut self, source_id: PipelineId, load_data: LoadData) { self.load_url(source_id, load_data); } @@ -1945,6 +1987,29 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> } } + /// For a given pipeline, determine the iframe in the root pipeline that transitively contains + /// it. There could be arbitrary levels of nested iframes in between them. + fn get_root_pipeline_and_containing_parent(&self, pipeline_id: &PipelineId) -> Option<(PipelineId, SubpageId)> { + if let Some(pipeline) = self.pipelines.get(pipeline_id) { + if let Some(mut ancestor_info) = pipeline.parent_info { + if let Some(mut ancestor) = self.pipelines.get(&ancestor_info.0) { + while let Some(next_info) = ancestor.parent_info { + ancestor_info = next_info; + ancestor = match self.pipelines.get(&ancestor_info.0) { + Some(ancestor) => ancestor, + None => { + warn!("Get parent pipeline before root via closed pipeline {:?}.", ancestor_info.0); + return None; + }, + }; + } + return Some(ancestor_info); + } + } + } + None + } + // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserlocationchange // Note that this is a no-op if the pipeline is not an immediate child iframe of the root fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) { @@ -1976,19 +2041,15 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> fn trigger_mozbrowsererror(&self, pipeline_id: PipelineId, reason: String, backtrace: String) { if !prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false) { return; } - if let Some(pipeline) = self.pipelines.get(&pipeline_id) { - if let Some(mut ancestor_info) = pipeline.parent_info { - if let Some(mut ancestor) = self.pipelines.get(&ancestor_info.0) { - while let Some(next_info) = ancestor.parent_info { - ancestor_info = next_info; - ancestor = match self.pipelines.get(&ancestor_info.0) { - Some(ancestor) => ancestor, - None => return warn!("Mozbrowsererror via closed pipeline {:?}.", ancestor_info.0), - }; - } + let ancestor_info = self.get_root_pipeline_and_containing_parent(&pipeline_id); + + if let Some(ancestor_info) = ancestor_info { + match self.pipelines.get(&ancestor_info.0) { + Some(ancestor) => { let event = MozBrowserEvent::Error(MozBrowserErrorType::Fatal, Some(reason), Some(backtrace)); ancestor.trigger_mozbrowser_event(ancestor_info.1, event); - } + }, + None => return warn!("Mozbrowsererror via closed pipeline {:?}.", ancestor_info.0), } } } diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index d032bc81921..1e3326ae356 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -13,6 +13,9 @@ path = "lib.rs" [features] debugmozjs = ['js/debugmozjs'] +[target.'cfg(any(target_os = "macos", target_os = "linux"))'.dependencies] +tinyfiledialogs = {git = "https://github.com/jdm/tinyfiledialogs"} + [dependencies] plugins = {path = "../plugins"} util = {path = "../util"} diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 94b6d2c7fb3..2f017c3b107 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -59,7 +59,7 @@ use script_thread::SendableMainThreadScriptChan; use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper}; use script_traits::{ConstellationControlMsg, UntrustedNodeAddress}; use script_traits::{DocumentState, MsDuration, ScriptToCompositorMsg, TimerEvent, TimerEventId}; -use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSource}; +use script_traits::{ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSource}; use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::Cell; @@ -85,6 +85,8 @@ use task_source::networking::NetworkingTaskSource; use task_source::user_interaction::UserInteractionTaskSource; use time; use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback}; +#[cfg(any(target_os = "macos", target_os = "linux"))] +use tinyfiledialogs::{self, MessageBoxIcon}; use url::Url; use util::geometry::{self, MAX_RECT}; use util::str::{DOMString, HTML_SPACE_CHARACTERS}; @@ -343,6 +345,16 @@ impl Window { } } +#[cfg(any(target_os = "macos", target_os = "linux"))] +fn display_alert_dialog(message: &str) { + tinyfiledialogs::message_box_ok("Alert!", message, MessageBoxIcon::Warning); +} + +#[cfg(not(any(target_os = "macos", target_os = "linux")))] +fn display_alert_dialog(_message: &str) { + // tinyfiledialogs not supported on Windows +} + // https://html.spec.whatwg.org/multipage/#atob pub fn base64_btoa(input: DOMString) -> Fallible<DOMString> { // "The btoa() method must throw an InvalidCharacterError exception if @@ -425,10 +437,13 @@ impl WindowMethods for Window { stdout.flush().unwrap(); stderr.flush().unwrap(); - // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsershowmodalprompt - let event = MozBrowserEvent::ShowModalPrompt("alert".to_owned(), "Alert".to_owned(), - String::from(s), "".to_owned()); - self.Document().trigger_mozbrowser_event(event); + let (sender, receiver) = ipc::channel().unwrap(); + self.constellation_chan().0.send(ConstellationMsg::Alert(self.pipeline(), s.to_string(), sender)).unwrap(); + + let should_display_alert_dialog = receiver.recv().unwrap(); + if should_display_alert_dialog { + display_alert_dialog(&s); + } } // https://html.spec.whatwg.org/multipage/#dom-window-close diff --git a/components/script/lib.rs b/components/script/lib.rs index 05700431c3d..4feaae05845 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -73,6 +73,8 @@ extern crate smallvec; #[macro_use] extern crate style; extern crate time; +#[cfg(any(target_os = "macos", target_os = "linux"))] +extern crate tinyfiledialogs; extern crate unicase; extern crate url; #[macro_use] diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index 14aa50b6a83..aee49bac43f 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -81,4 +81,6 @@ pub enum ScriptMsg { SetDocumentState(PipelineId, DocumentState), /// Update the pipeline Url, which can change after redirections. SetFinalUrl(PipelineId, Url), + /// Check if an alert dialog box should be presented + Alert(PipelineId, String, IpcSender<bool>), } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index adba235f7f4..eb16f14d9a7 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1837,6 +1837,7 @@ dependencies = [ "string_cache 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", @@ -2210,7 +2211,7 @@ dependencies = [ [[package]] name = "tinyfiledialogs" version = "0.1.0" -source = "git+https://github.com/jdm/tinyfiledialogs#2d2285985db1168da4d516000f24842aba46fd94" +source = "git+https://github.com/jdm/tinyfiledialogs#686abf781f30b360a4c265964fd3744e2f61cf2d" dependencies = [ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 0c52ffcddee..4448c5e5a88 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -1706,6 +1706,7 @@ dependencies = [ "string_cache 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", @@ -2086,7 +2087,7 @@ dependencies = [ [[package]] name = "tinyfiledialogs" version = "0.1.0" -source = "git+https://github.com/jdm/tinyfiledialogs#2d2285985db1168da4d516000f24842aba46fd94" +source = "git+https://github.com/jdm/tinyfiledialogs#686abf781f30b360a4c265964fd3744e2f61cf2d" dependencies = [ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index c535617e7ee..2c4366e76d8 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -1689,6 +1689,7 @@ dependencies = [ "string_cache 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", @@ -2067,7 +2068,7 @@ dependencies = [ [[package]] name = "tinyfiledialogs" version = "0.1.0" -source = "git+https://github.com/jdm/tinyfiledialogs#2d2285985db1168da4d516000f24842aba46fd94" +source = "git+https://github.com/jdm/tinyfiledialogs#686abf781f30b360a4c265964fd3744e2f61cf2d" dependencies = [ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event.html b/tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event.html index 731e508f876..20c7faad07a 100644 --- a/tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event.html +++ b/tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event.html @@ -16,4 +16,16 @@ })); document.body.appendChild(iframe); }); + + async_test(function(t) { + var iframe = document.createElement("iframe"); + iframe.mozbrowser = "true"; + iframe.src = "mozbrowsershowmodalprompt_event_nested_iframe.html"; + iframe.addEventListener("mozbrowsershowmodalprompt", t.step_func(e => { + assert_equals(e.detail.promptType, "alert"); + assert_equals(e.detail.message, "my alert message"); + t.done(); + })); + document.body.appendChild(iframe); + }, "mozbrowsershowmodalprompt event from nested iframes triggering an alert"); </script> diff --git a/tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event_nested_iframe.html b/tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event_nested_iframe.html new file mode 100644 index 00000000000..9d9efd7f922 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event_nested_iframe.html @@ -0,0 +1,5 @@ +<html> + <body> + <iframe src="mozbrowsershowmodalprompt_event_iframe.html" /> + </body> +</html> |