зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #10840 - Implement alert dialogs (from cbrewster:window_alert); r=jdm
fix #10812 Implements alert dialogs using tinyfiledialogs r? @jdm Source-Repo: https://github.com/servo/servo Source-Revision: b4f573db1a4a054f7f991ac19c299a5a10aabad8
This commit is contained in:
Родитель
4b585c7691
Коммит
45d5d547d3
|
@ -805,6 +805,10 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
||||||
debug!("constellation got SetDocumentState message");
|
debug!("constellation got SetDocumentState message");
|
||||||
self.document_states.insert(pipeline_id, state);
|
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
|
// Messages from layout thread
|
||||||
|
@ -1080,6 +1084,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) {
|
fn handle_load_url_msg(&mut self, source_id: PipelineId, load_data: LoadData) {
|
||||||
self.load_url(source_id, load_data);
|
self.load_url(source_id, load_data);
|
||||||
}
|
}
|
||||||
|
@ -1956,6 +1998,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
|
// 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
|
// 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) {
|
fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) {
|
||||||
|
@ -1987,19 +2052,15 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
||||||
fn trigger_mozbrowsererror(&self, pipeline_id: PipelineId, reason: String, backtrace: String) {
|
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 !prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false) { return; }
|
||||||
|
|
||||||
if let Some(pipeline) = self.pipelines.get(&pipeline_id) {
|
let ancestor_info = self.get_root_pipeline_and_containing_parent(&pipeline_id);
|
||||||
if let Some(mut ancestor_info) = pipeline.parent_info {
|
|
||||||
if let Some(mut ancestor) = self.pipelines.get(&ancestor_info.0) {
|
if let Some(ancestor_info) = ancestor_info {
|
||||||
while let Some(next_info) = ancestor.parent_info {
|
match self.pipelines.get(&ancestor_info.0) {
|
||||||
ancestor_info = next_info;
|
Some(ancestor) => {
|
||||||
ancestor = match self.pipelines.get(&ancestor_info.0) {
|
|
||||||
Some(ancestor) => ancestor,
|
|
||||||
None => return warn!("Mozbrowsererror via closed pipeline {:?}.", ancestor_info.0),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
let event = MozBrowserEvent::Error(MozBrowserErrorType::Fatal, Some(reason), Some(backtrace));
|
let event = MozBrowserEvent::Error(MozBrowserErrorType::Fatal, Some(reason), Some(backtrace));
|
||||||
ancestor.trigger_mozbrowser_event(ancestor_info.1, event);
|
ancestor.trigger_mozbrowser_event(ancestor_info.1, event);
|
||||||
}
|
},
|
||||||
|
None => return warn!("Mozbrowsererror via closed pipeline {:?}.", ancestor_info.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,9 @@ path = "lib.rs"
|
||||||
[features]
|
[features]
|
||||||
debugmozjs = ['js/debugmozjs']
|
debugmozjs = ['js/debugmozjs']
|
||||||
|
|
||||||
|
[target.'cfg(any(target_os = "macos", target_os = "linux"))'.dependencies]
|
||||||
|
tinyfiledialogs = {git = "https://github.com/jdm/tinyfiledialogs"}
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
plugins = {path = "../plugins"}
|
plugins = {path = "../plugins"}
|
||||||
util = {path = "../util"}
|
util = {path = "../util"}
|
||||||
|
|
|
@ -60,7 +60,7 @@ use script_thread::SendableMainThreadScriptChan;
|
||||||
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper};
|
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper};
|
||||||
use script_traits::{ConstellationControlMsg, UntrustedNodeAddress};
|
use script_traits::{ConstellationControlMsg, UntrustedNodeAddress};
|
||||||
use script_traits::{DocumentState, MsDuration, ScriptToCompositorMsg, TimerEvent, TimerEventId};
|
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::ascii::AsciiExt;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -86,6 +86,8 @@ use task_source::networking::NetworkingTaskSource;
|
||||||
use task_source::user_interaction::UserInteractionTaskSource;
|
use task_source::user_interaction::UserInteractionTaskSource;
|
||||||
use time;
|
use time;
|
||||||
use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback};
|
use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback};
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
||||||
|
use tinyfiledialogs::{self, MessageBoxIcon};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::geometry::{self, MAX_RECT};
|
use util::geometry::{self, MAX_RECT};
|
||||||
use util::str::{DOMString, HTML_SPACE_CHARACTERS};
|
use util::str::{DOMString, HTML_SPACE_CHARACTERS};
|
||||||
|
@ -352,6 +354,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
|
// https://html.spec.whatwg.org/multipage/#atob
|
||||||
pub fn base64_btoa(input: DOMString) -> Fallible<DOMString> {
|
pub fn base64_btoa(input: DOMString) -> Fallible<DOMString> {
|
||||||
// "The btoa() method must throw an InvalidCharacterError exception if
|
// "The btoa() method must throw an InvalidCharacterError exception if
|
||||||
|
@ -434,10 +446,13 @@ impl WindowMethods for Window {
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
stderr.flush().unwrap();
|
stderr.flush().unwrap();
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsershowmodalprompt
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
let event = MozBrowserEvent::ShowModalPrompt("alert".to_owned(), "Alert".to_owned(),
|
self.constellation_chan().0.send(ConstellationMsg::Alert(self.pipeline(), s.to_string(), sender)).unwrap();
|
||||||
String::from(s), "".to_owned());
|
|
||||||
self.Document().trigger_mozbrowser_event(event);
|
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
|
// https://html.spec.whatwg.org/multipage/#dom-window-close
|
||||||
|
|
|
@ -73,6 +73,8 @@ extern crate smallvec;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate style;
|
extern crate style;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
||||||
|
extern crate tinyfiledialogs;
|
||||||
extern crate unicase;
|
extern crate unicase;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -81,4 +81,6 @@ pub enum ScriptMsg {
|
||||||
SetDocumentState(PipelineId, DocumentState),
|
SetDocumentState(PipelineId, DocumentState),
|
||||||
/// Update the pipeline Url, which can change after redirections.
|
/// Update the pipeline Url, which can change after redirections.
|
||||||
SetFinalUrl(PipelineId, Url),
|
SetFinalUrl(PipelineId, Url),
|
||||||
|
/// Check if an alert dialog box should be presented
|
||||||
|
Alert(PipelineId, String, IpcSender<bool>),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1865,6 +1865,7 @@ dependencies = [
|
||||||
"string_cache 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"string_cache 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"style 0.0.1",
|
"style 0.0.1",
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"util 0.0.1",
|
"util 0.0.1",
|
||||||
|
@ -2238,7 +2239,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyfiledialogs"
|
name = "tinyfiledialogs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/jdm/tinyfiledialogs#2d2285985db1168da4d516000f24842aba46fd94"
|
source = "git+https://github.com/jdm/tinyfiledialogs#686abf781f30b360a4c265964fd3744e2f61cf2d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
|
@ -1734,6 +1734,7 @@ dependencies = [
|
||||||
"string_cache 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"string_cache 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"style 0.0.1",
|
"style 0.0.1",
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"util 0.0.1",
|
"util 0.0.1",
|
||||||
|
@ -2114,7 +2115,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyfiledialogs"
|
name = "tinyfiledialogs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/jdm/tinyfiledialogs#2d2285985db1168da4d516000f24842aba46fd94"
|
source = "git+https://github.com/jdm/tinyfiledialogs#686abf781f30b360a4c265964fd3744e2f61cf2d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
|
@ -1717,6 +1717,7 @@ dependencies = [
|
||||||
"string_cache 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"string_cache 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"style 0.0.1",
|
"style 0.0.1",
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"util 0.0.1",
|
"util 0.0.1",
|
||||||
|
@ -2095,7 +2096,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyfiledialogs"
|
name = "tinyfiledialogs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/jdm/tinyfiledialogs#2d2285985db1168da4d516000f24842aba46fd94"
|
source = "git+https://github.com/jdm/tinyfiledialogs#686abf781f30b360a4c265964fd3744e2f61cf2d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче