Skip to content

Commit

Permalink
refactor(clipboard): use arboard instead of tao closes #8177 (#8394)
Browse files Browse the repository at this point in the history
* refactor(clipboard): use arboard instead of tao closes #8177

* update api lock

* add change file
  • Loading branch information
lucasfernog authored Dec 14, 2023
1 parent 1c582a9 commit 0d0501c
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 94 deletions.
5 changes: 5 additions & 0 deletions .changes/arboard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri-runtime-wry": patch:bug
---

Use `arboard` instead of `tao` clipboard implementation to prevent a crash.
3 changes: 2 additions & 1 deletion core/tauri-runtime-wry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ uuid = { version = "1", features = [ "v4" ] }
rand = "0.8"
raw-window-handle = "0.5"
tracing = { version = "0.1", optional = true }
arboard = { version = "3", optional = true }

[target."cfg(windows)".dependencies]
webview2-com = "0.19.1"
Expand Down Expand Up @@ -47,6 +48,6 @@ macos-private-api = [
]
objc-exception = [ "wry/objc-exception" ]
global-shortcut = [ "tauri-runtime/global-shortcut" ]
clipboard = [ "tauri-runtime/clipboard" ]
clipboard = [ "tauri-runtime/clipboard", "arboard" ]
linux-headers = [ "wry/linux-headers", "webkit2gtk/v2_36" ]
tracing = [ "dep:tracing", "wry/tracing" ]
63 changes: 20 additions & 43 deletions core/tauri-runtime-wry/src/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,59 +4,36 @@

//! Clipboard implementation.
use crate::{getter, Context, Message};

use std::sync::{
mpsc::{channel, Sender},
Arc, Mutex,
use std::{
fmt,
sync::{Arc, Mutex},
};

use tauri_runtime::{ClipboardManager, Result, UserEvent};
pub use wry::application::clipboard::Clipboard;
pub use arboard::Clipboard;
use tauri_runtime::{ClipboardManager, Result};

#[derive(Debug, Clone)]
pub enum ClipboardMessage {
WriteText(String, Sender<()>),
ReadText(Sender<Option<String>>),
#[derive(Clone)]
pub struct ClipboardManagerWrapper {
pub clipboard: Arc<Mutex<Clipboard>>,
}

#[derive(Debug, Clone)]
pub struct ClipboardManagerWrapper<T: UserEvent> {
pub context: Context<T>,
impl fmt::Debug for ClipboardManagerWrapper {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ClipboardManagerWrapper").finish()
}
}

// SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`.
#[allow(clippy::non_send_fields_in_send_ty)]
unsafe impl<T: UserEvent> Sync for ClipboardManagerWrapper<T> {}

impl<T: UserEvent> ClipboardManager for ClipboardManagerWrapper<T> {
impl ClipboardManager for ClipboardManagerWrapper {
fn read_text(&self) -> Result<Option<String>> {
let (tx, rx) = channel();
getter!(self, rx, Message::Clipboard(ClipboardMessage::ReadText(tx)))
Ok(self.clipboard.lock().unwrap().get_text().ok())
}

fn write_text<V: Into<String>>(&mut self, text: V) -> Result<()> {
let (tx, rx) = channel();
getter!(
self,
rx,
Message::Clipboard(ClipboardMessage::WriteText(text.into(), tx))
)?;
Ok(())
}
}

pub fn handle_clipboard_message(
message: ClipboardMessage,
clipboard_manager: &Arc<Mutex<Clipboard>>,
) {
match message {
ClipboardMessage::WriteText(text, tx) => {
clipboard_manager.lock().unwrap().write_text(text);
tx.send(()).unwrap();
}
ClipboardMessage::ReadText(tx) => tx
.send(clipboard_manager.lock().unwrap().read_text())
.unwrap(),
self
.clipboard
.lock()
.unwrap()
.set_text(text.into())
.map_err(|e| crate::Error::Clipboard(Box::new(e)))
}
}
50 changes: 4 additions & 46 deletions core/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,6 @@ pub(crate) fn send_user_message<T: UserEvent>(
webview_id_map: context.webview_id_map.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager: context.main_thread.global_shortcut_manager.clone(),
#[cfg(feature = "clipboard")]
clipboard_manager: context.main_thread.clipboard_manager.clone(),
windows: context.main_thread.windows.clone(),
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: context.main_thread.system_tray_manager.clone(),
Expand Down Expand Up @@ -276,8 +274,6 @@ pub struct DispatcherMainThreadContext<T: UserEvent> {
pub web_context: WebContextStore,
#[cfg(all(desktop, feature = "global-shortcut"))]
pub global_shortcut_manager: Rc<Mutex<WryShortcutManager>>,
#[cfg(feature = "clipboard")]
pub clipboard_manager: Arc<Mutex<Clipboard>>,
pub windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: SystemTrayManager,
Expand Down Expand Up @@ -1213,8 +1209,6 @@ pub enum Message<T: 'static> {
),
#[cfg(all(desktop, feature = "global-shortcut"))]
GlobalShortcut(GlobalShortcutMessage),
#[cfg(feature = "clipboard")]
Clipboard(ClipboardMessage),
UserEvent(T),
}

Expand All @@ -1226,8 +1220,6 @@ impl<T: UserEvent> Clone for Message<T> {
Self::Tray(i, m) => Self::Tray(*i, m.clone()),
#[cfg(all(desktop, feature = "global-shortcut"))]
Self::GlobalShortcut(m) => Self::GlobalShortcut(m.clone()),
#[cfg(feature = "clipboard")]
Self::Clipboard(m) => Self::Clipboard(m.clone()),
Self::UserEvent(t) => Self::UserEvent(t.clone()),
_ => unimplemented!(),
}
Expand Down Expand Up @@ -1829,7 +1821,7 @@ pub struct Wry<T: UserEvent> {
global_shortcut_manager_handle: GlobalShortcutManagerHandle<T>,

#[cfg(feature = "clipboard")]
clipboard_manager_handle: ClipboardManagerWrapper<T>,
clipboard_manager_handle: ClipboardManagerWrapper,

event_loop: EventLoop<Message<T>>,
}
Expand Down Expand Up @@ -1860,11 +1852,7 @@ impl<T: UserEvent> fmt::Debug for Wry<T> {
);

#[cfg(feature = "clipboard")]
d.field(
"clipboard_manager",
&self.context.main_thread.clipboard_manager,
)
.field("clipboard_manager_handle", &self.clipboard_manager_handle);
d.field("clipboard_manager_handle", &self.clipboard_manager_handle);

d.finish()
}
Expand Down Expand Up @@ -1985,9 +1973,6 @@ impl<T: UserEvent> Wry<T> {
#[cfg(all(desktop, feature = "global-shortcut"))]
let global_shortcut_manager = Rc::new(Mutex::new(WryShortcutManager::new(&event_loop)));

#[cfg(feature = "clipboard")]
let clipboard_manager = Arc::new(Mutex::new(Clipboard::new()));

let windows = Rc::new(RefCell::new(HashMap::default()));
let webview_id_map = WebviewIdStore::default();

Expand All @@ -2003,8 +1988,6 @@ impl<T: UserEvent> Wry<T> {
web_context,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager,
#[cfg(feature = "clipboard")]
clipboard_manager,
windows,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager,
Expand All @@ -2023,7 +2006,7 @@ impl<T: UserEvent> Wry<T> {
#[cfg(feature = "clipboard")]
#[allow(clippy::redundant_clone)]
let clipboard_manager_handle = ClipboardManagerWrapper {
context: context.clone(),
clipboard: Arc::new(Mutex::new(Clipboard::new().unwrap())),
};

Ok(Self {
Expand Down Expand Up @@ -2056,7 +2039,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
type GlobalShortcutManager = GlobalShortcutManagerHandle<T>;

#[cfg(feature = "clipboard")]
type ClipboardManager = ClipboardManagerWrapper<T>;
type ClipboardManager = ClipboardManagerWrapper;

#[cfg(all(desktop, feature = "system-tray"))]
type TrayHandler = SystemTrayHandle<T>;
Expand Down Expand Up @@ -2221,8 +2204,6 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
#[cfg(all(desktop, feature = "global-shortcut"))]
let global_shortcut_manager_handle = self.global_shortcut_manager_handle.clone();

#[cfg(feature = "clipboard")]
let clipboard_manager = self.context.main_thread.clipboard_manager.clone();
let mut iteration = RunIteration::default();

let proxy = self.event_loop.create_proxy();
Expand All @@ -2249,8 +2230,6 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
global_shortcut_manager: global_shortcut_manager.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager_handle: &global_shortcut_manager_handle,
#[cfg(feature = "clipboard")]
clipboard_manager: clipboard_manager.clone(),
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: system_tray_manager.clone(),
#[cfg(feature = "tracing")]
Expand All @@ -2275,8 +2254,6 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
global_shortcut_manager: global_shortcut_manager.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager_handle: &global_shortcut_manager_handle,
#[cfg(feature = "clipboard")]
clipboard_manager: clipboard_manager.clone(),
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: system_tray_manager.clone(),
#[cfg(feature = "tracing")]
Expand Down Expand Up @@ -2306,9 +2283,6 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
#[cfg(all(desktop, feature = "global-shortcut"))]
let global_shortcut_manager_handle = self.global_shortcut_manager_handle.clone();

#[cfg(feature = "clipboard")]
let clipboard_manager = self.context.main_thread.clipboard_manager.clone();

let proxy = self.event_loop.create_proxy();

self.event_loop.run(move |event, event_loop, control_flow| {
Expand All @@ -2326,8 +2300,6 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
global_shortcut_manager: global_shortcut_manager.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager_handle: &global_shortcut_manager_handle,
#[cfg(feature = "clipboard")]
clipboard_manager: clipboard_manager.clone(),
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: system_tray_manager.clone(),
#[cfg(feature = "tracing")]
Expand All @@ -2351,8 +2323,6 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
global_shortcut_manager: global_shortcut_manager.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager_handle: &global_shortcut_manager_handle,
#[cfg(feature = "clipboard")]
clipboard_manager: clipboard_manager.clone(),
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: system_tray_manager.clone(),
#[cfg(feature = "tracing")]
Expand All @@ -2372,8 +2342,6 @@ pub struct EventLoopIterationContext<'a, T: UserEvent> {
pub global_shortcut_manager: Rc<Mutex<WryShortcutManager>>,
#[cfg(all(desktop, feature = "global-shortcut"))]
pub global_shortcut_manager_handle: &'a GlobalShortcutManagerHandle<T>,
#[cfg(feature = "clipboard")]
pub clipboard_manager: Arc<Mutex<Clipboard>>,
#[cfg(all(desktop, feature = "system-tray"))]
pub system_tray_manager: SystemTrayManager,
#[cfg(feature = "tracing")]
Expand All @@ -2385,8 +2353,6 @@ struct UserMessageContext {
webview_id_map: WebviewIdStore,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager: Rc<Mutex<WryShortcutManager>>,
#[cfg(feature = "clipboard")]
clipboard_manager: Arc<Mutex<Clipboard>>,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: SystemTrayManager,
}
Expand All @@ -2401,8 +2367,6 @@ fn handle_user_message<T: UserEvent>(
webview_id_map,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager,
#[cfg(feature = "clipboard")]
clipboard_manager,
windows,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager,
Expand Down Expand Up @@ -2805,8 +2769,6 @@ fn handle_user_message<T: UserEvent>(
Message::GlobalShortcut(message) => {
handle_global_shortcut_message(message, &global_shortcut_manager)
}
#[cfg(feature = "clipboard")]
Message::Clipboard(message) => handle_clipboard_message(message, &clipboard_manager),
Message::UserEvent(_) => (),
}

Expand All @@ -2831,8 +2793,6 @@ fn handle_event_loop<T: UserEvent>(
global_shortcut_manager,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager_handle,
#[cfg(feature = "clipboard")]
clipboard_manager,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager,
#[cfg(feature = "tracing")]
Expand Down Expand Up @@ -3079,8 +3039,6 @@ fn handle_event_loop<T: UserEvent>(
webview_id_map,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager,
#[cfg(feature = "clipboard")]
clipboard_manager,
windows,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager,
Expand Down
3 changes: 3 additions & 0 deletions core/tauri-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ pub enum Error {
#[cfg(all(desktop, feature = "global-shortcut"))]
#[error(transparent)]
GlobalShortcut(Box<dyn std::error::Error + Send + Sync>),
#[cfg(all(desktop, feature = "clipboard"))]
#[error(transparent)]
Clipboard(Box<dyn std::error::Error + Send + Sync>),
#[error("Invalid header name: {0}")]
InvalidHeaderName(#[from] InvalidHeaderName),
#[error("Invalid header value: {0}")]
Expand Down
Loading

0 comments on commit 0d0501c

Please sign in to comment.