1use std::borrow::ToOwned;
10use std::sync::Arc;
11use std::thread;
12
13use backtrace::Backtrace;
14use base::id::WebViewId;
15use constellation_traits::{
16 EmbedderToConstellationMessage, LogEntry, ScriptToConstellationChan,
17 ScriptToConstellationMessage,
18};
19use crossbeam_channel::Sender;
20use log::{Level, LevelFilter, Log, Metadata, Record};
21use parking_lot::ReentrantMutex;
22
23pub struct FromScriptLogger {
26 pub script_to_constellation_chan: Arc<ReentrantMutex<ScriptToConstellationChan>>,
28}
29
30impl FromScriptLogger {
32 pub fn new(script_to_constellation_chan: ScriptToConstellationChan) -> FromScriptLogger {
34 FromScriptLogger {
35 script_to_constellation_chan: Arc::new(ReentrantMutex::new(
36 script_to_constellation_chan,
37 )),
38 }
39 }
40
41 pub fn filter(&self) -> LevelFilter {
43 LevelFilter::Warn
44 }
45}
46
47impl Log for FromScriptLogger {
48 fn enabled(&self, metadata: &Metadata) -> bool {
49 metadata.level() <= Level::Warn
50 }
51
52 fn log(&self, record: &Record) {
53 if let Some(entry) = log_entry(record) {
54 let thread_name = thread::current().name().map(ToOwned::to_owned);
55 let msg = ScriptToConstellationMessage::LogEntry(thread_name, entry);
56 let chan = self.script_to_constellation_chan.lock();
57 let _ = chan.send(msg);
58 }
59 }
60
61 fn flush(&self) {}
62}
63
64#[derive(Clone)]
66pub struct FromEmbedderLogger {
67 pub constellation_chan: Arc<ReentrantMutex<Sender<EmbedderToConstellationMessage>>>,
69}
70
71impl FromEmbedderLogger {
72 pub fn new(constellation_chan: Sender<EmbedderToConstellationMessage>) -> FromEmbedderLogger {
74 FromEmbedderLogger {
75 constellation_chan: Arc::new(ReentrantMutex::new(constellation_chan)),
76 }
77 }
78
79 pub fn filter(&self) -> LevelFilter {
81 LevelFilter::Warn
82 }
83}
84
85impl Log for FromEmbedderLogger {
86 fn enabled(&self, metadata: &Metadata) -> bool {
87 metadata.level() <= Level::Warn
88 }
89
90 fn log(&self, record: &Record) {
91 if let Some(entry) = log_entry(record) {
92 let webview_id = WebViewId::installed();
93 let thread_name = thread::current().name().map(ToOwned::to_owned);
94 let msg = EmbedderToConstellationMessage::LogEntry(webview_id, thread_name, entry);
95 let chan = self.constellation_chan.lock();
96 let _ = chan.send(msg);
97 }
98 }
99
100 fn flush(&self) {}
101}
102
103fn log_entry(record: &Record) -> Option<LogEntry> {
108 match record.level() {
109 Level::Error if thread::panicking() => Some(LogEntry::Panic(
110 format!("{}", record.args()),
111 format!("{:?}", Backtrace::new()),
112 )),
113 Level::Error => Some(LogEntry::Error(format!("{}", record.args()))),
114 Level::Warn => Some(LogEntry::Warn(format!("{}", record.args()))),
115 _ => None,
116 }
117}