Skip to content

Commit dc85be4

Browse files
committed
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
1 parent 3f2ceef commit dc85be4

File tree

10 files changed

+122
-19
lines changed

10 files changed

+122
-19
lines changed

components/compositing/constellation.rs

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,10 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
797797
debug!("constellation got SetDocumentState message");
798798
self.document_states.insert(pipeline_id, state);
799799
}
800+
Request::Script(FromScriptMsg::Alert(pipeline_id, message, sender)) => {
801+
debug!("constellation got Alert message");
802+
self.handle_alert(pipeline_id, message, sender);
803+
}
800804

801805

802806
// Messages from layout thread
@@ -1069,6 +1073,44 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
10691073
}
10701074
}
10711075

1076+
fn handle_alert(&mut self, pipeline_id: PipelineId, message: String, sender: IpcSender<bool>) {
1077+
let display_alert_dialog = if prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false) {
1078+
let parent_pipeline_info = self.pipelines.get(&pipeline_id).and_then(|source| source.parent_info);
1079+
if let Some(_) = parent_pipeline_info {
1080+
let root_pipeline_id = self.root_frame_id
1081+
.and_then(|root_frame_id| self.frames.get(&root_frame_id))
1082+
.map(|root_frame| root_frame.current);
1083+
1084+
let ancestor_info = self.get_root_pipeline_and_containing_parent(&pipeline_id);
1085+
if let Some(ancestor_info) = ancestor_info {
1086+
if root_pipeline_id == Some(ancestor_info.0) {
1087+
match root_pipeline_id.and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) {
1088+
Some(root_pipeline) => {
1089+
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsershowmodalprompt
1090+
let event = MozBrowserEvent::ShowModalPrompt("alert".to_owned(), "Alert".to_owned(),
1091+
String::from(message), "".to_owned());
1092+
root_pipeline.trigger_mozbrowser_event(ancestor_info.1, event);
1093+
}
1094+
None => return warn!("Alert sent to Pipeline {:?} after closure.", root_pipeline_id),
1095+
}
1096+
} else {
1097+
warn!("A non-current frame is trying to show an alert.")
1098+
}
1099+
}
1100+
false
1101+
} else {
1102+
true
1103+
}
1104+
} else {
1105+
true
1106+
};
1107+
1108+
let result = sender.send(display_alert_dialog);
1109+
if let Err(e) = result {
1110+
self.handle_send_error(pipeline_id, e);
1111+
}
1112+
}
1113+
10721114
fn handle_load_url_msg(&mut self, source_id: PipelineId, load_data: LoadData) {
10731115
self.load_url(source_id, load_data);
10741116
}
@@ -1945,6 +1987,29 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
19451987
}
19461988
}
19471989

1990+
/// For a given pipeline, determine the iframe in the root pipeline that transitively contains
1991+
/// it. There could be arbitrary levels of nested iframes in between them.
1992+
fn get_root_pipeline_and_containing_parent(&self, pipeline_id: &PipelineId) -> Option<(PipelineId, SubpageId)> {
1993+
if let Some(pipeline) = self.pipelines.get(pipeline_id) {
1994+
if let Some(mut ancestor_info) = pipeline.parent_info {
1995+
if let Some(mut ancestor) = self.pipelines.get(&ancestor_info.0) {
1996+
while let Some(next_info) = ancestor.parent_info {
1997+
ancestor_info = next_info;
1998+
ancestor = match self.pipelines.get(&ancestor_info.0) {
1999+
Some(ancestor) => ancestor,
2000+
None => {
2001+
warn!("Get parent pipeline before root via closed pipeline {:?}.", ancestor_info.0);
2002+
return None;
2003+
},
2004+
};
2005+
}
2006+
return Some(ancestor_info);
2007+
}
2008+
}
2009+
}
2010+
None
2011+
}
2012+
19482013
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserlocationchange
19492014
// Note that this is a no-op if the pipeline is not an immediate child iframe of the root
19502015
fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) {
@@ -1976,19 +2041,15 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
19762041
fn trigger_mozbrowsererror(&self, pipeline_id: PipelineId, reason: String, backtrace: String) {
19772042
if !prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false) { return; }
19782043

1979-
if let Some(pipeline) = self.pipelines.get(&pipeline_id) {
1980-
if let Some(mut ancestor_info) = pipeline.parent_info {
1981-
if let Some(mut ancestor) = self.pipelines.get(&ancestor_info.0) {
1982-
while let Some(next_info) = ancestor.parent_info {
1983-
ancestor_info = next_info;
1984-
ancestor = match self.pipelines.get(&ancestor_info.0) {
1985-
Some(ancestor) => ancestor,
1986-
None => return warn!("Mozbrowsererror via closed pipeline {:?}.", ancestor_info.0),
1987-
};
1988-
}
2044+
let ancestor_info = self.get_root_pipeline_and_containing_parent(&pipeline_id);
2045+
2046+
if let Some(ancestor_info) = ancestor_info {
2047+
match self.pipelines.get(&ancestor_info.0) {
2048+
Some(ancestor) => {
19892049
let event = MozBrowserEvent::Error(MozBrowserErrorType::Fatal, Some(reason), Some(backtrace));
19902050
ancestor.trigger_mozbrowser_event(ancestor_info.1, event);
1991-
}
2051+
},
2052+
None => return warn!("Mozbrowsererror via closed pipeline {:?}.", ancestor_info.0),
19922053
}
19932054
}
19942055
}

components/script/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ path = "lib.rs"
1313
[features]
1414
debugmozjs = ['js/debugmozjs']
1515

16+
[target.'cfg(any(target_os = "macos", target_os = "linux"))'.dependencies]
17+
tinyfiledialogs = {git = "https://github.com/jdm/tinyfiledialogs"}
18+
1619
[dependencies]
1720
plugins = {path = "../plugins"}
1821
util = {path = "../util"}

components/script/dom/window.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ use script_thread::SendableMainThreadScriptChan;
5959
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper};
6060
use script_traits::{ConstellationControlMsg, UntrustedNodeAddress};
6161
use script_traits::{DocumentState, MsDuration, ScriptToCompositorMsg, TimerEvent, TimerEventId};
62-
use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSource};
62+
use script_traits::{ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSource};
6363
use std::ascii::AsciiExt;
6464
use std::borrow::ToOwned;
6565
use std::cell::Cell;
@@ -85,6 +85,8 @@ use task_source::networking::NetworkingTaskSource;
8585
use task_source::user_interaction::UserInteractionTaskSource;
8686
use time;
8787
use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback};
88+
#[cfg(any(target_os = "macos", target_os = "linux"))]
89+
use tinyfiledialogs::{self, MessageBoxIcon};
8890
use url::Url;
8991
use util::geometry::{self, MAX_RECT};
9092
use util::str::{DOMString, HTML_SPACE_CHARACTERS};
@@ -343,6 +345,16 @@ impl Window {
343345
}
344346
}
345347

348+
#[cfg(any(target_os = "macos", target_os = "linux"))]
349+
fn display_alert_dialog(message: &str) {
350+
tinyfiledialogs::message_box_ok("Alert!", message, MessageBoxIcon::Warning);
351+
}
352+
353+
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
354+
fn display_alert_dialog(_message: &str) {
355+
// tinyfiledialogs not supported on Windows
356+
}
357+
346358
// https://html.spec.whatwg.org/multipage/#atob
347359
pub fn base64_btoa(input: DOMString) -> Fallible<DOMString> {
348360
// "The btoa() method must throw an InvalidCharacterError exception if
@@ -425,10 +437,13 @@ impl WindowMethods for Window {
425437
stdout.flush().unwrap();
426438
stderr.flush().unwrap();
427439

428-
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsershowmodalprompt
429-
let event = MozBrowserEvent::ShowModalPrompt("alert".to_owned(), "Alert".to_owned(),
430-
String::from(s), "".to_owned());
431-
self.Document().trigger_mozbrowser_event(event);
440+
let (sender, receiver) = ipc::channel().unwrap();
441+
self.constellation_chan().0.send(ConstellationMsg::Alert(self.pipeline(), s.to_string(), sender)).unwrap();
442+
443+
let should_display_alert_dialog = receiver.recv().unwrap();
444+
if should_display_alert_dialog {
445+
display_alert_dialog(&s);
446+
}
432447
}
433448

434449
// https://html.spec.whatwg.org/multipage/#dom-window-close

components/script/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ extern crate smallvec;
7373
#[macro_use]
7474
extern crate style;
7575
extern crate time;
76+
#[cfg(any(target_os = "macos", target_os = "linux"))]
77+
extern crate tinyfiledialogs;
7678
extern crate unicase;
7779
extern crate url;
7880
#[macro_use]

components/script_traits/script_msg.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,6 @@ pub enum ScriptMsg {
8181
SetDocumentState(PipelineId, DocumentState),
8282
/// Update the pipeline Url, which can change after redirections.
8383
SetFinalUrl(PipelineId, Url),
84+
/// Check if an alert dialog box should be presented
85+
Alert(PipelineId, String, IpcSender<bool>),
8486
}

components/servo/Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ports/cef/Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ports/gonk/Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/wpt/mozilla/tests/mozilla/mozbrowser/mozbrowsershowmodalprompt_event.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,16 @@
1616
}));
1717
document.body.appendChild(iframe);
1818
});
19+
20+
async_test(function(t) {
21+
var iframe = document.createElement("iframe");
22+
iframe.mozbrowser = "true";
23+
iframe.src = "mozbrowsershowmodalprompt_event_nested_iframe.html";
24+
iframe.addEventListener("mozbrowsershowmodalprompt", t.step_func(e => {
25+
assert_equals(e.detail.promptType, "alert");
26+
assert_equals(e.detail.message, "my alert message");
27+
t.done();
28+
}));
29+
document.body.appendChild(iframe);
30+
}, "mozbrowsershowmodalprompt event from nested iframes triggering an alert");
1931
</script>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<html>
2+
<body>
3+
<iframe src="mozbrowsershowmodalprompt_event_iframe.html" />
4+
</body>
5+
</html>

0 commit comments

Comments
 (0)