aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorConnor Brewster <brewsterc@my.caspercollege.edu>2016-04-25 14:59:48 -0600
committerConnor Brewster <brewsterc@my.caspercollege.edu>2016-05-03 22:09:35 -0600
commitdc85be4be5510f9ef204a35ea7461f645cbc7e39 (patch)
treed8273b417823db1fbe6f5e18a693b77c510359be
parent3f2ceeff5dd1966dafe34381e20ec405ab72ccee (diff)
downloadservo-dc85be4be5510f9ef204a35ea7461f645cbc7e39.tar.gz
servo-dc85be4be5510f9ef204a35ea7461f645cbc7e39.zip
Implement alert dialogs
Fixed conflict Fixed merge issue Finished implementation Disable tinyfiledialogs on Windows addressed comments Use ancestor's SubpageId Move display alert from method to function Add extra test for nested iframes Addressed comments Updated tinyfiledialogs
-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>