servo/
clipboard_delegate.rs1use ipc_channel::ipc::IpcSender;
6
7use crate::WebView;
8
9pub struct StringRequest {
10 pub(crate) result_sender: IpcSender<Result<String, String>>,
11 response_sent: bool,
12}
13
14impl StringRequest {
15 pub fn success(mut self, string: String) {
16 let _ = self.result_sender.send(Ok(string));
17 self.response_sent = true;
18 }
19
20 pub fn failure(mut self, message: String) {
21 let _ = self.result_sender.send(Err(message));
22 self.response_sent = true;
23 }
24}
25
26impl From<IpcSender<Result<String, String>>> for StringRequest {
27 fn from(result_sender: IpcSender<Result<String, String>>) -> Self {
28 Self {
29 result_sender,
30 response_sent: false,
31 }
32 }
33}
34
35impl Drop for StringRequest {
36 fn drop(&mut self) {
37 if !self.response_sent {
38 let _ = self
39 .result_sender
40 .send(Err("No response sent to request.".into()));
41 }
42 }
43}
44
45pub trait ClipboardDelegate {
50 fn clear(&self, _webview: WebView) {}
52
53 fn get_text(&self, _webview: WebView, _request: StringRequest) {}
57
58 fn set_text(&self, _webview: WebView, _new_contents: String) {}
60}
61
62pub(crate) struct DefaultClipboardDelegate;
63
64impl ClipboardDelegate for DefaultClipboardDelegate {
65 fn clear(&self, _webview: WebView) {
66 clipboard::clear();
67 }
68
69 fn get_text(&self, _webview: WebView, request: StringRequest) {
70 clipboard::get_text(request);
71 }
72
73 fn set_text(&self, _webview: WebView, new_contents: String) {
74 clipboard::set_text(new_contents);
75 }
76}
77
78#[cfg(all(
79 feature = "clipboard",
80 not(any(target_os = "android", target_env = "ohos"))
81))]
82mod clipboard {
83 use std::sync::OnceLock;
84
85 use arboard::Clipboard;
86 use parking_lot::Mutex;
87
88 use super::StringRequest;
89
90 static SHARED_CLIPBOARD: OnceLock<Option<Mutex<Clipboard>>> = OnceLock::new();
95
96 fn with_shared_clipboard(callback: impl FnOnce(&mut Clipboard)) {
97 if let Some(clipboard_mutex) =
98 SHARED_CLIPBOARD.get_or_init(|| Clipboard::new().ok().map(Mutex::new))
99 {
100 callback(&mut clipboard_mutex.lock())
101 }
102 }
103
104 pub(super) fn clear() {
105 with_shared_clipboard(|clipboard| {
106 let _ = clipboard.clear();
107 });
108 }
109
110 pub(super) fn get_text(request: StringRequest) {
111 with_shared_clipboard(move |clipboard| match clipboard.get_text() {
112 Ok(text) => request.success(text),
113 Err(error) => request.failure(format!("{error:?}")),
114 });
115 }
116
117 pub(super) fn set_text(new_contents: String) {
118 with_shared_clipboard(move |clipboard| {
119 let _ = clipboard.set_text(new_contents);
120 });
121 }
122}
123
124#[cfg(any(not(feature = "clipboard"), target_os = "android", target_env = "ohos"))]
125mod clipboard {
126 use super::StringRequest;
127
128 pub(super) fn clear() {}
129 pub(super) fn get_text(_: StringRequest) {}
130 pub(super) fn set_text(_: String) {}
131}