From db2e4f30a7665e7c23176736acc4d6b4a4f6b193 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 17 Sep 2023 10:53:04 +0800 Subject: [PATCH 1/2] Privacy mode, msgbox, add details Signed-off-by: fufesou --- libs/hbb_common/protos/message.proto | 2 + src/client/io_loop.rs | 57 +++++++++++++++++++++++----- src/common.rs | 12 +++++- src/ipc.rs | 3 +- src/platform/linux.rs | 4 +- src/platform/macos.rs | 4 +- src/platform/windows.rs | 10 ++++- src/server/connection.rs | 41 ++++++++++++-------- src/server/video_service.rs | 20 ++++++---- 9 files changed, 112 insertions(+), 41 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 47de31e45..9cf464547 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -624,6 +624,8 @@ message BackNotification { PrivacyModeState privacy_mode_state = 1; BlockInputState block_input_state = 2; } + // Supplementary message, for "PrvOnFailed" and "PrvOffFailed" + string details = 3; } message ElevationRequestWithLogon { diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index ddf4b64ac..254f72583 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -1485,6 +1485,7 @@ impl Remote { Some(back_notification::Union::BlockInputState(state)) => { self.handle_back_msg_block_input( state.enum_value_or(back_notification::BlockInputState::BlkStateUnknown), + notification.details, ) .await; } @@ -1492,6 +1493,7 @@ impl Remote { if !self .handle_back_msg_privacy_mode( state.enum_value_or(back_notification::PrivacyModeState::PrvStateUnknown), + notification.details, ) .await { @@ -1508,22 +1510,42 @@ impl Remote { self.handler.update_block_input_state(on); } - async fn handle_back_msg_block_input(&mut self, state: back_notification::BlockInputState) { + async fn handle_back_msg_block_input( + &mut self, + state: back_notification::BlockInputState, + details: String, + ) { match state { back_notification::BlockInputState::BlkOnSucceeded => { self.update_block_input_state(true); } back_notification::BlockInputState::BlkOnFailed => { - self.handler - .msgbox("custom-error", "Block user input", "Failed", ""); + self.handler.msgbox( + "custom-error", + "Block user input", + if details.is_empty() { + "Failed" + } else { + &details + }, + "", + ); self.update_block_input_state(false); } back_notification::BlockInputState::BlkOffSucceeded => { self.update_block_input_state(false); } back_notification::BlockInputState::BlkOffFailed => { - self.handler - .msgbox("custom-error", "Unblock user input", "Failed", ""); + self.handler.msgbox( + "custom-error", + "Unblock user input", + if details.is_empty() { + "Failed" + } else { + &details + }, + "", + ); } _ => {} } @@ -1541,6 +1563,7 @@ impl Remote { async fn handle_back_msg_privacy_mode( &mut self, state: back_notification::PrivacyModeState, + details: String, ) -> bool { match state { back_notification::PrivacyModeState::PrvOnByOther => { @@ -1573,8 +1596,16 @@ impl Remote { self.update_privacy_mode(false); } back_notification::PrivacyModeState::PrvOnFailed => { - self.handler - .msgbox("custom-error", "Privacy mode", "Failed", ""); + self.handler.msgbox( + "custom-error", + "Privacy mode", + if details.is_empty() { + "Failed" + } else { + &details + }, + "", + ); self.update_privacy_mode(false); } back_notification::PrivacyModeState::PrvOffSucceeded => { @@ -1588,8 +1619,16 @@ impl Remote { self.update_privacy_mode(false); } back_notification::PrivacyModeState::PrvOffFailed => { - self.handler - .msgbox("custom-error", "Privacy mode", "Failed to turn off", ""); + self.handler.msgbox( + "custom-error", + "Privacy mode", + if details.is_empty() { + "Failed to turn off" + } else { + &details + }, + "", + ); } back_notification::PrivacyModeState::PrvOffUnknown => { self.handler diff --git a/src/common.rs b/src/common.rs index 8477c9e62..35c062139 100644 --- a/src/common.rs +++ b/src/common.rs @@ -940,9 +940,12 @@ pub async fn post_request_sync(url: String, body: String, header: &str) -> Resul } #[inline] -pub fn make_privacy_mode_msg(state: back_notification::PrivacyModeState) -> Message { +pub fn make_privacy_mode_msg_with_details(state: back_notification::PrivacyModeState, details: String) -> Message { let mut misc = Misc::new(); - let mut back_notification = BackNotification::new(); + let mut back_notification = BackNotification { + details, + ..Default::default() + }; back_notification.set_privacy_mode_state(state); misc.set_back_notification(back_notification); let mut msg_out = Message::new(); @@ -950,6 +953,11 @@ pub fn make_privacy_mode_msg(state: back_notification::PrivacyModeState) -> Mess msg_out } +#[inline] +pub fn make_privacy_mode_msg(state: back_notification::PrivacyModeState) -> Message { + make_privacy_mode_msg_with_details(state, "".to_owned()) +} + pub fn is_keyboard_mode_supported(keyboard_mode: &KeyboardMode, version_number: i64) -> bool { match keyboard_mode { KeyboardMode::Legacy => true, diff --git a/src/ipc.rs b/src/ipc.rs index db41b8649..77440d6dd 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -31,11 +31,10 @@ use hbb_common::{ use crate::rendezvous_mediator::RendezvousMediator; // State with timestamp, because std::time::Instant cannot be serialized -#[derive(Debug, Serialize, Deserialize, Copy, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] #[serde(tag = "t", content = "c")] pub enum PrivacyModeState { OffSucceeded, - OffFailed, OffByPeer, OffUnknown, } diff --git a/src/platform/linux.rs b/src/platform/linux.rs index fb48a9307..f78f1f87c 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -627,8 +627,8 @@ pub fn toggle_blank_screen(_v: bool) { // https://unix.stackexchange.com/questions/17170/disable-keyboard-mouse-input-on-unix-under-x } -pub fn block_input(_v: bool) -> bool { - true +pub fn block_input(_v: bool) -> (bool, String) { + (true, "".to_owned()) } pub fn is_installed() -> bool { diff --git a/src/platform/macos.rs b/src/platform/macos.rs index 78e52faf4..0731ae87a 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -572,8 +572,8 @@ pub fn toggle_blank_screen(_v: bool) { // https://unix.stackexchange.com/questions/17115/disable-keyboard-mouse-temporarily } -pub fn block_input(_v: bool) -> bool { - true +pub fn block_input(_v: bool) -> (bool, String) { + (true, "".to_owned()) } pub fn is_installed() -> bool { diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 41ac9e5ea..e4b3c431d 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1269,9 +1269,15 @@ pub fn toggle_blank_screen(v: bool) { } } -pub fn block_input(v: bool) -> bool { +pub fn block_input(v: bool) -> (bool, String) { let v = if v { TRUE } else { FALSE }; - unsafe { BlockInput(v) == TRUE } + unsafe { + if BlockInput(v) == TRUE { + (true, "".to_owned()) + } else { + (false, format!("Error code: {}", GetLastError())) + } + } } pub fn add_recent_document(path: &str) { diff --git a/src/server/connection.rs b/src/server/connection.rs index 517e7d4e3..bfda275c1 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -471,11 +471,6 @@ impl Connection { back_notification::PrivacyModeState::PrvOffSucceeded, ) } - ipc::PrivacyModeState::OffFailed => { - crate::common::make_privacy_mode_msg( - back_notification::PrivacyModeState::PrvOffFailed, - ) - } ipc::PrivacyModeState::OffByPeer => { video_service::set_privacy_mode_conn_id(0); crate::common::make_privacy_mode_msg( @@ -704,29 +699,34 @@ impl Connection { handle_pointer(&msg, id); } MessageInput::BlockOn => { - if crate::platform::block_input(true) { + let (ok, msg) = crate::platform::block_input(true); + if ok { block_input_mode = true; } else { Self::send_block_input_error( &tx, back_notification::BlockInputState::BlkOnFailed, + msg, ); } } MessageInput::BlockOff => { - if crate::platform::block_input(false) { + let (ok, msg) = crate::platform::block_input(false); + if ok { block_input_mode = false; } else { Self::send_block_input_error( &tx, back_notification::BlockInputState::BlkOffFailed, + msg, ); } } #[cfg(all(feature = "flutter", feature = "plugin_framework"))] #[cfg(not(any(target_os = "android", target_os = "ios")))] MessageInput::BlockOnPlugin(_peer) => { - if crate::platform::block_input(true) { + let (ok, _msg) = crate::platform::block_input(true); + if ok { block_input_mode = true; } let _r = PLUGIN_BLOCK_INPUT_TX_RX @@ -738,7 +738,8 @@ impl Connection { #[cfg(all(feature = "flutter", feature = "plugin_framework"))] #[cfg(not(any(target_os = "android", target_os = "ios")))] MessageInput::BlockOffPlugin(_peer) => { - if crate::platform::block_input(false) { + let (ok, _msg) = crate::platform::block_input(false); + if ok { block_input_mode = false; } let _r = PLUGIN_BLOCK_INPUT_TX_RX @@ -1209,7 +1210,11 @@ impl Connection { } #[inline] - pub fn send_block_input_error(s: &Sender, state: back_notification::BlockInputState) { + pub fn send_block_input_error( + s: &Sender, + state: back_notification::BlockInputState, + details: String, + ) { let mut misc = Misc::new(); let mut back_notification = BackNotification::new(); back_notification.set_block_input_state(state); @@ -2221,13 +2226,16 @@ impl Connection { match q { BoolOption::Yes => { let msg_out = if !video_service::is_privacy_mode_supported() { - crate::common::make_privacy_mode_msg( + crate::common::make_privacy_mode_msg_with_details( back_notification::PrivacyModeState::PrvNotSupported, + "Unsupported. 1 Multi-screen is not supported. 2 Please confirm the license is activated.".to_string(), ) } else { match privacy_mode::turn_on_privacy(self.inner.id) { Ok(true) => { - if video_service::test_create_capturer(self.inner.id, 5_000) { + let err_msg = + video_service::test_create_capturer(self.inner.id, 5_000); + if err_msg.is_empty() { video_service::set_privacy_mode_conn_id(self.inner.id); crate::common::make_privacy_mode_msg( back_notification::PrivacyModeState::PrvOnSucceeded, @@ -2238,8 +2246,9 @@ impl Connection { ); video_service::set_privacy_mode_conn_id(0); let _ = privacy_mode::turn_off_privacy(self.inner.id); - crate::common::make_privacy_mode_msg( + crate::common::make_privacy_mode_msg_with_details( back_notification::PrivacyModeState::PrvOnFailed, + err_msg, ) } } @@ -2261,8 +2270,9 @@ impl Connection { } BoolOption::No => { let msg_out = if !video_service::is_privacy_mode_supported() { - crate::common::make_privacy_mode_msg( + crate::common::make_privacy_mode_msg_with_details( back_notification::PrivacyModeState::PrvNotSupported, + "Unsupported. 1 Multi-screen is not supported. 2 Please confirm the license is activated.".to_string(), ) } else { video_service::set_privacy_mode_conn_id(0); @@ -2597,8 +2607,9 @@ mod privacy_mode { ), Err(e) => { log::error!("Failed to turn off privacy mode {}", e); - crate::common::make_privacy_mode_msg( + crate::common::make_privacy_mode_msg_with_details( back_notification::PrivacyModeState::PrvOffFailed, + e.to_string(), ) } } diff --git a/src/server/video_service.rs b/src/server/video_service.rs index e8f6f30c2..07db5e3be 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -317,17 +317,23 @@ fn create_capturer( } // This function works on privacy mode. Windows only for now. -pub fn test_create_capturer(privacy_mode_id: i32, timeout_millis: u64) -> bool { +pub fn test_create_capturer(privacy_mode_id: i32, timeout_millis: u64) -> String { let test_begin = Instant::now(); - while test_begin.elapsed().as_millis() < timeout_millis as _ { - if let Ok((_, current, display)) = get_current_display() { - if let Ok(_) = create_capturer(privacy_mode_id, display, true, current, false) { - return true; + loop { + let err = match get_current_display() { + Ok((_, current, display)) => { + match create_capturer(privacy_mode_id, display, true, current, false) { + Ok(_) => return "".to_owned(), + Err(e) => e, + } } + Err(e) => e, + }; + if test_begin.elapsed().as_millis() >= timeout_millis as _ { + return err.to_string(); } std::thread::sleep(Duration::from_millis(300)); } - false } #[cfg(windows)] @@ -1025,7 +1031,7 @@ fn try_get_displays() -> ResultType> { // displays = Display::all()?; // } // } - Ok( Display::all()?) + Ok(Display::all()?) } pub(super) fn get_current_display_2(mut all: Vec) -> ResultType<(usize, usize, Display)> { From df19ccf99886a461ffb3a3a3a9389d85be40245b Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 17 Sep 2023 11:07:06 +0800 Subject: [PATCH 2/2] Set details for block input back notification Signed-off-by: fufesou --- src/server/connection.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/server/connection.rs b/src/server/connection.rs index bfda275c1..9c2928e94 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1216,7 +1216,10 @@ impl Connection { details: String, ) { let mut misc = Misc::new(); - let mut back_notification = BackNotification::new(); + let mut back_notification = BackNotification { + details, + ..Default::default() + }; back_notification.set_block_input_state(state); misc.set_back_notification(back_notification); let mut msg_out = Message::new();