1use cbf::{browser::BrowserHandle, data::ids::BrowsingContextId, error::Error};
8
9use crate::{
10 backend::ChromiumBackend,
11 command::ChromeCommand,
12 data::{
13 find::{ChromeFindInPageOptions, ChromeStopFindAction},
14 ids::TabId,
15 },
16};
17
18pub trait ChromiumBrowserHandleExt {
24 fn activate_extension_action(
26 &self,
27 browsing_context_id: BrowsingContextId,
28 extension_id: impl Into<String>,
29 ) -> Result<(), Error>;
30
31 fn find_in_page(
33 &self,
34 browsing_context_id: BrowsingContextId,
35 request_id: u64,
36 options: ChromeFindInPageOptions,
37 ) -> Result<(), Error>;
38
39 fn find_next(
41 &self,
42 browsing_context_id: BrowsingContextId,
43 request_id: u64,
44 query: impl Into<String>,
45 match_case: bool,
46 ) -> Result<(), Error>;
47
48 fn find_previous(
50 &self,
51 browsing_context_id: BrowsingContextId,
52 request_id: u64,
53 query: impl Into<String>,
54 match_case: bool,
55 ) -> Result<(), Error>;
56
57 fn stop_finding(
59 &self,
60 browsing_context_id: BrowsingContextId,
61 action: ChromeStopFindAction,
62 ) -> Result<(), Error>;
63}
64
65impl ChromiumBrowserHandleExt for BrowserHandle<ChromiumBackend> {
66 fn activate_extension_action(
67 &self,
68 browsing_context_id: BrowsingContextId,
69 extension_id: impl Into<String>,
70 ) -> Result<(), Error> {
71 self.send_raw(ChromeCommand::ActivateExtensionAction {
72 browsing_context_id: TabId::from(browsing_context_id),
73 extension_id: extension_id.into(),
74 })
75 }
76
77 fn find_in_page(
78 &self,
79 browsing_context_id: BrowsingContextId,
80 request_id: u64,
81 options: ChromeFindInPageOptions,
82 ) -> Result<(), Error> {
83 self.send_raw(ChromeCommand::FindInPage {
84 browsing_context_id: TabId::from(browsing_context_id),
85 request_id,
86 options,
87 })
88 }
89
90 fn find_next(
91 &self,
92 browsing_context_id: BrowsingContextId,
93 request_id: u64,
94 query: impl Into<String>,
95 match_case: bool,
96 ) -> Result<(), Error> {
97 self.find_in_page(
98 browsing_context_id,
99 request_id,
100 ChromeFindInPageOptions {
101 query: query.into(),
102 forward: true,
103 match_case,
104 new_session: false,
105 find_match: true,
106 },
107 )
108 }
109
110 fn find_previous(
111 &self,
112 browsing_context_id: BrowsingContextId,
113 request_id: u64,
114 query: impl Into<String>,
115 match_case: bool,
116 ) -> Result<(), Error> {
117 self.find_in_page(
118 browsing_context_id,
119 request_id,
120 ChromeFindInPageOptions {
121 query: query.into(),
122 forward: false,
123 match_case,
124 new_session: false,
125 find_match: true,
126 },
127 )
128 }
129
130 fn stop_finding(
131 &self,
132 browsing_context_id: BrowsingContextId,
133 action: ChromeStopFindAction,
134 ) -> Result<(), Error> {
135 self.send_raw(ChromeCommand::StopFinding {
136 browsing_context_id: TabId::from(browsing_context_id),
137 action,
138 })
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145 use async_channel::unbounded;
146 use cbf::browser::{CommandEnvelope, CommandSender};
147
148 fn build_sender() -> CommandSender<ChromiumBackend> {
149 let (tx, _rx) = unbounded::<CommandEnvelope<ChromiumBackend>>();
150 CommandSender::from_raw_sender(tx)
151 }
152
153 #[test]
154 fn find_options_default_to_forward_new_session() {
155 let options = ChromeFindInPageOptions::new("needle");
156 assert_eq!(options.query, "needle");
157 assert!(options.forward);
158 assert!(!options.match_case);
159 assert!(options.new_session);
160 assert!(options.find_match);
161 }
162
163 #[test]
164 fn stop_find_action_maps_to_expected_ffi_value() {
165 assert_eq!(
166 ChromeStopFindAction::ClearSelection.to_ffi(),
167 cbf_chrome_sys::ffi::CbfStopFindAction_kCbfStopFindActionClearSelection as u8
168 );
169 assert_eq!(
170 ChromeStopFindAction::KeepSelection.to_ffi(),
171 cbf_chrome_sys::ffi::CbfStopFindAction_kCbfStopFindActionKeepSelection as u8
172 );
173 assert_eq!(
174 ChromeStopFindAction::ActivateSelection.to_ffi(),
175 cbf_chrome_sys::ffi::CbfStopFindAction_kCbfStopFindActionActivateSelection as u8
176 );
177 }
178
179 #[test]
180 fn command_sender_can_be_constructed_for_find_helpers() {
181 let _sender = build_sender();
182 }
183}