Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/toolkit/crashreporter/client/app/src/ui/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 12 kB image not shown  

Quelle  mod.rs

  Sprache: Rust
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


//! The UI model, UI implementations, and functions using them.
//!
//! UIs must implement:
//! * a `fn run_loop(&self, app: model::Application)` method which should display the UI and block while
//!   handling events until the application terminates,
//! * a `fn invoke(&self, f: model::InvokeFn)` method which invokes the given function
//!   asynchronously (without blocking) on the UI loop thread.

use crate::std::sync::Arc;
use crate::{
    async_task::AsyncTask, config::Config, data, logic::ReportCrash, settings::Settings, std,
    thread_bound::ThreadBound,
};
use model::{ui, Application};
use ui_impl::UI;

mod model;

#[cfg(all(not(test), any(target_os = "linux", target_os = "windows")))]
mod icon {
    // Must be DWORD-aligned for Win32 CreateIconFromResource.
    #[repr(align(4))]
    struct Aligned<Bytes: ?Sized>(Bytes);
    static PNG_DATA_ALIGNMENT: &'static Aligned<[u8]> =
        &Aligned(*include_bytes!("crashreporter.png"));
    pub static PNG_DATA: &'static [u8] = &PNG_DATA_ALIGNMENT.0;
}

#[cfg(test)]
pub mod test {
    pub mod model {
        pub use crate::ui::model::*;
    }
}

cfg_if::cfg_if! {
    if #[cfg(test)] {
        #[path = "test.rs"]
        pub mod ui_impl;
    } else if #[cfg(target_os = "linux")] {
        #[path = "gtk.rs"]
        mod ui_impl;
    } else if #[cfg(target_os = "windows")] {
        #[path = "windows/mod.rs"]
        mod ui_impl;
    } else if #[cfg(target_os = "macos")] {
        #[path = "macos/mod.rs"]
        mod ui_impl;
    } else {
        mod ui_impl {
            #[derive(Default)]
            pub struct UI;

            impl UI {
                pub fn run_loop(&self, _app: super::model::Application) {
                    unimplemented!();
                }

                pub fn invoke(&self, _f: super::model::InvokeFn) {
                    unimplemented!();
                }
            }
        }
    }
}

/// Display an error dialog with the given message.
#[cfg_attr(mock, allow(unused))]
pub fn error_dialog<M: std::fmt::Debug>(config: Arc<Config>, message: M) {
    let close = data::Event::default();
    // Config may not have localized strings
    let string_or = |name, fallback: &str| {
        if config.strings.is_none() {
            fallback.into()
        } else {
            config.string(name)
        }
    };

    let window = ui! {
        Window title(string_or("crashreporter-branded-title""Firefox Crash Reporter")) hsize(600) vsize(400)
            close_when(&close) halign(Alignment::Fill) valign(Alignment::Fill) {
            VBox margin(10) spacing(10) halign(Alignment::Fill) valign(Alignment::Fill) {
                Label text(string_or(
                        "crashreporter-error",
                        "The application had a problem and crashed. \
                        Unfortunately, the crash reporter is unable to submit a report for the crash."
                )),
                Label text(string_or("crashreporter-error-details-header""Details:")),
                Scroll halign(Alignment::Fill) valign(Alignment::Fill) {
                    TextBox content(format!("{message:?}")) halign(Alignment::Fill) valign(Alignment::Fill)
                },
                HBox valign(Alignment::End) halign(Alignment::End) spacing(10) affirmative_order(true)
                {
                    Button["restart"] hsize(160) visible(config.restart_command.is_some())
                        on_click(cc! { (config, close) move || {
                            config.restart_process();
                            close.fire(&());
                        }})
                    {
                        Label text(string_or("crashreporter-button-restart""Restart"))
                    },
                    Button["quit"] hsize(160) on_click(move || close.fire(&()))
                    {
                        Label text(string_or("crashreporter-button-quit""Quit"))
                    }
                }
            }
        }
    };

    UI::default().run_loop(Application {
        windows: vec![window],
        rtl: config.is_rtl(),
    });
}

#[derive(Default, Debug, PartialEq, Eq)]
pub enum SubmitState {
    #[default]
    Initial,
    WaitingHardwareTests,
    InProgress,
    Success,
    Failure,
}

/// The UI for the main crash reporter windows.
pub struct ReportCrashUI {
    state: Arc<ThreadBound<ReportCrashUIState>>,
    ui: Arc<UI>,
    config: Arc<Config>,
    logic: AsyncTask<ReportCrash>,
}

/// The state of the creash UI.
pub struct ReportCrashUIState {
    pub send_report: data::Synchronized<bool>,
    pub include_address: data::Synchronized<bool>,
    pub test_hardware: data::Synchronized<bool>,
    pub show_details: data::Synchronized<bool>,
    pub details: data::Synchronized<String>,
    pub comment: data::OnDemand<String>,
    pub submit_state: data::Synchronized<SubmitState>,
    pub close_window: data::Event<()>,
}

impl ReportCrashUI {
    pub fn new(
        initial_settings: &Settings,
        config: Arc<Config>,
        logic: AsyncTask<ReportCrash>,
    ) -> Self {
        let send_report = data::Synchronized::new(initial_settings.submit_report);
        let include_address = data::Synchronized::new(initial_settings.include_url);
        let test_hardware = data::Synchronized::new(initial_settings.test_hardware);

        ReportCrashUI {
            state: Arc::new(ThreadBound::new(ReportCrashUIState {
                send_report,
                include_address,
                test_hardware,
                show_details: Default::default(),
                details: Default::default(),
                comment: Default::default(),
                submit_state: Default::default(),
                close_window: Default::default(),
            })),
            ui: Default::default(),
            config,
            logic,
        }
    }

    pub fn async_task(&self) -> AsyncTask<ReportCrashUIState> {
        let state = self.state.clone();
        let ui = Arc::downgrade(&self.ui);
        AsyncTask::new(move |f| {
            let Some(ui) = ui.upgrade() else { return };
            ui.invoke(Box::new(cc! { (state) move || {
                f(state.borrow());
            }}));
        })
    }

    pub fn run(&self) {
        let ReportCrashUI {
            state,
            ui,
            config,
            logic,
        } = self;
        let ReportCrashUIState {
            send_report,
            include_address,
            show_details,
            test_hardware,
            details,
            comment,
            submit_state,
            close_window,
        } = state.borrow();

        send_report.on_change(cc! { (logic) move |v| {
            let v = *v;
            logic.push(move |s| s.settings.borrow_mut().submit_report = v);
        }});
        include_address.on_change(cc! { (logic) move |v| {
            let v = *v;
            logic.push(move |s| s.settings.borrow_mut().include_url = v);
        }});
        test_hardware.on_change(cc! { (logic) move |v| {
            let v = *v;
            logic.push(move |s| s.settings.borrow_mut().test_hardware = v);
        }});

        let input_enabled = submit_state.mapped(|s| s == &SubmitState::Initial);
        let send_report_and_input_enabled =
            data::Synchronized::join(send_report, &input_enabled, |s, e| *s && *e);

        let submit_status_text = submit_state.mapped(cc! { (config) move |s| {
            config.string(match s {
                SubmitState::Initial => "crashreporter-submit-status",
                SubmitState::WaitingHardwareTests => "crashreporter-submit-waiting-hardware-tests",
                SubmitState::InProgress => "crashreporter-submit-in-progress",
                SubmitState::Success => "crashreporter-submit-success",
                SubmitState::Failure => "crashreporter-submit-failure",
            })
        }});

        let progress_visible = submit_state.mapped(|s| s == &SubmitState::InProgress);
        let hardware_test_checkbox_visible = data::Synchronized::new(self.config.run_memtest);

        let details_window = ui! {
            Window["crash-details-window"] title(config.string("crashreporter-view-report-title"))
                visible(show_details) modal(true) hsize(600) vsize(400)
                halign(Alignment::Fill) valign(Alignment::Fill)
            {
                VBox margin(10) spacing(10) halign(Alignment::Fill) valign(Alignment::Fill) {
                    Scroll halign(Alignment::Fill) valign(Alignment::Fill) {
                        TextBox["details-text"] content(details) halign(Alignment::Fill) valign(Alignment::Fill)
                    },
                    Button["close-details"] halign(Alignment::End) on_click(cc! { (show_details) move || *show_details.borrow_mut() = false }) {
                        Label text(config.string("crashreporter-button-ok"))
                    }
                }
            }
        };

        let main_window = ui! {
            Window title(config.string("crashreporter-branded-title")) hsize(600) vsize(400)
                halign(Alignment::Fill) valign(Alignment::Fill) close_when(close_window)
                child_window(details_window)
            {
                VBox margin(10) spacing(10) halign(Alignment::Fill) valign(Alignment::Fill) {
                    Label text(config.string("crashreporter-apology")) bold(true),
                    Label text(config.string("crashreporter-crashed-and-restore")),
                    Label text(config.string("crashreporter-plea")),
                    Checkbox["test-hardware"] checked(test_hardware)
                        label(config.string("crashreporter-checkbox-test-hardware"))
                        enabled(&input_enabled) visible(&hardware_test_checkbox_visible),
                    Checkbox["send"] checked(send_report) label(config.string("crashreporter-checkbox-send-report"))
                        enabled(&input_enabled),
                    VBox margin_start(20) spacing(5) halign(Alignment::Fill) valign(Alignment::Fill) {
                        Button["details"] enabled(&send_report_and_input_enabled) on_click(cc! { (config, details, show_details, logic) move || {
                                // Immediately display the window to feel responsive, even if forming
                                // the details string takes a little while (it really shouldn't
                                // though).
                                *details.borrow_mut() = config.string("crashreporter-loading-details");
                                logic.push(|s| s.update_details());
                                *show_details.borrow_mut() = true;
                            }})
                        {
                            Label text(config.string("crashreporter-button-details"))
                        },
                        Scroll halign(Alignment::Fill) valign(Alignment::Fill) {
                            TextBox["comment"] placeholder(config.string("crashreporter-comment-prompt"))
                                content(comment)
                                editable(true)
                                enabled(&send_report_and_input_enabled)
                                halign(Alignment::Fill) valign(Alignment::Fill)
                        },
                        Checkbox["include-url"] checked(include_address)
                            label(config.string("crashreporter-checkbox-include-url")) enabled(&send_report_and_input_enabled),
                        Label text(&submit_status_text) margin_top(20),
                        Progress halign(Alignment::Fill) visible(&progress_visible),
                    },
                    HBox valign(Alignment::End) halign(Alignment::End) spacing(10) affirmative_order(true)
                    {
                        Button["restart"] visible(config.restart_command.is_some())
                            on_click(cc! { (logic) move || logic.push_async(|s| Box::pin(s.restart())) })
                            enabled(&input_enabled) hsize(160)
                        {
                            Label text(config.string("crashreporter-button-restart"))
                        },
                        Button["quit"] on_click(cc! { (logic) move || logic.push_async(|s| Box::pin(s.quit())) })
                            enabled(&input_enabled) hsize(160)
                        {
                            Label text(config.string("crashreporter-button-quit"))
                        }
                    }
                }
            }
        };

        ui.run_loop(Application {
            windows: vec![main_window],
            rtl: config.is_rtl(),
        });
    }
}

Messung V0.5 in Prozent
C=96 H=99 G=97

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.