aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/compositing/constellation.rs83
-rw-r--r--components/script/Cargo.toml3
-rw-r--r--components/script/dom/window.rs25
-rw-r--r--components/script/lib.rs2
-rw-r--r--components/script_traits/script_msg.rs2
-rw-r--r--components/servo/Cargo.lock3
-rw-r--r--ports/cef/Cargo.lock3
-rw-r--r--ports/gonk/Cargo.lock3
-rw-r--r--tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event.html12
-rw-r--r--tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event_nested_iframe.html5
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>