1+ use std:: path:: Path ;
2+
3+ use paste:: paste;
4+ use serde:: Serialize ;
5+ use serde_json:: { json, to_value, Value } ;
6+
17use crate :: error:: WebDriverResult ;
2- use crate :: Capabilities ;
38use crate :: CapabilitiesHelper ;
4- use serde:: de:: DeserializeOwned ;
5- use serde:: Serialize ;
6- use serde_json:: { from_value, json, to_value} ;
7- use std:: ops:: { Deref , DerefMut } ;
8- use std:: path:: Path ;
9+ use crate :: { BrowserCapabilitiesHelper , Capabilities } ;
910
1011#[ derive( Debug , Clone , Serialize ) ]
1112#[ serde( transparent) ]
@@ -15,113 +16,161 @@ pub struct ChromeCapabilities {
1516
1617impl Default for ChromeCapabilities {
1718 fn default ( ) -> Self {
18- let mut capabilities = Capabilities :: new ( ) ;
19- capabilities. insert ( "browserName" . to_string ( ) , json ! ( "chrome" ) ) ;
20- ChromeCapabilities {
21- capabilities,
19+ Self :: new ( )
20+ }
21+ }
22+
23+ macro_rules! chrome_arg_wrapper {
24+ ( $( $fname: ident => $opt: literal) ,* ) => {
25+ paste! {
26+ $(
27+ #[ doc = concat!( "Set the " , $opt, " option." ) ]
28+ pub fn [ <set_ $fname>] ( & mut self ) -> WebDriverResult <( ) > {
29+ self . add_arg( $opt)
30+ }
31+
32+ #[ doc = concat!( "Unset the " , $opt, " option." ) ]
33+ pub fn [ <unset_ $fname>] ( & mut self ) -> WebDriverResult <( ) > {
34+ self . remove_arg( $opt)
35+ }
36+
37+ #[ doc = concat!( "Return true if the " , $opt, " option is set." ) ]
38+ pub fn [ <is_ $fname>] ( & mut self ) -> bool {
39+ self . has_arg( $opt)
40+ }
41+ ) *
2242 }
2343 }
2444}
2545
2646impl ChromeCapabilities {
2747 /// Create a new ChromeCapabilities struct.
2848 pub fn new ( ) -> Self {
29- ChromeCapabilities :: default ( )
30- }
31-
32- /// Add the specified Chrome option. This is a helper method for `add_chrome_arg()`.
33- pub fn add_chrome_option < T > ( & mut self , key : & str , value : T ) -> WebDriverResult < ( ) >
34- where
35- T : Serialize ,
36- {
37- self . add_subkey ( "goog:chromeOptions" , key, value)
38- }
39-
40- /// Get the specified Chrome option.
41- pub fn get_chrome_option < T > ( & self , key : & str ) -> T
42- where
43- T : DeserializeOwned + Default ,
44- {
45- self . capabilities
46- . get ( "goog:chromeOptions" )
47- . and_then ( |options| options. get ( key) )
48- . and_then ( |option| from_value ( option. clone ( ) ) . ok ( ) )
49- . unwrap_or_default ( )
49+ let mut capabilities = Capabilities :: new ( ) ;
50+ capabilities. insert ( "browserName" . to_string ( ) , json ! ( "chrome" ) ) ;
51+ ChromeCapabilities {
52+ capabilities,
53+ }
5054 }
5155
5256 /// Get the current list of command-line arguments to `chromedriver` as a vec.
53- pub fn get_args ( & self ) -> Vec < String > {
54- self . get_chrome_option ( "args" )
57+ pub fn args ( & self ) -> Vec < String > {
58+ self . browser_option ( "args" ) . unwrap_or_default ( )
5559 }
5660
5761 /// Get the current list of Chrome extensions as a vec.
62+ ///
5863 /// Each item is a base64-encoded string containing the .CRX extension file contents.
5964 /// Use `add_extension()` to add a new extension file.
60- pub fn get_extensions ( & self ) -> Vec < String > {
61- self . get_chrome_option ( "extensions" )
65+ pub fn extensions ( & self ) -> Vec < String > {
66+ self . browser_option ( "extensions" ) . unwrap_or_default ( )
6267 }
6368
6469 /// Get the path to the chrome binary (if one was previously set).
65- pub fn get_binary ( & self ) -> String {
66- self . get_chrome_option ( "binary" )
70+ pub fn binary ( & self ) -> Option < String > {
71+ self . browser_option ( "binary" )
6772 }
6873
6974 /// Set the path to chrome binary to use.
7075 pub fn set_binary ( & mut self , path : & str ) -> WebDriverResult < ( ) > {
71- self . add_chrome_option ( "binary" , path)
76+ self . insert_browser_option ( "binary" , path)
77+ }
78+
79+ /// Unset the chrome binary path.
80+ pub fn unset_binary ( & mut self ) {
81+ self . remove_browser_option ( "binary" ) ;
7282 }
7383
7484 /// Get the current debugger address (if one was previously set).
75- pub fn get_debugger_address ( & self ) -> String {
76- self . get_chrome_option ( "debuggerAddress" )
85+ pub fn debugger_address ( & self ) -> Option < String > {
86+ self . browser_option ( "debuggerAddress" )
7787 }
7888
7989 /// Set the debugger address.
8090 pub fn set_debugger_address ( & mut self , address : & str ) -> WebDriverResult < ( ) > {
81- self . add_chrome_option ( "debuggerAddress" , address)
91+ self . insert_browser_option ( "debuggerAddress" , address)
92+ }
93+
94+ /// Unset the debugger address.
95+ pub fn unset_debugger_address ( & mut self ) {
96+ self . remove_browser_option ( "debuggerAddress" ) ;
8297 }
8398
84- /// Add the specified command-line argument to `chromedriver`. Eg. "--disable-local-storage"
99+ /// Add the specified command-line argument to `chromedriver`.
100+ ///
101+ /// ## Example
102+ ///
103+ /// ```ignore
104+ /// let mut caps = DesiredCapabilities::chrome();
105+ /// caps.add_chrome_arg("--disable-local-storage")?;
106+ /// ```
107+ ///
85108 /// The full list of switches can be found here:
86109 /// [https://chromium.googlesource.com/chromium/src/+/master/chrome/common/chrome_switches.cc](https://chromium.googlesource.com/chromium/src/+/master/chrome/common/chrome_switches.cc)
87- pub fn add_chrome_arg ( & mut self , arg : & str ) -> WebDriverResult < ( ) > {
88- let mut args = self . get_args ( ) ;
110+ pub fn add_arg ( & mut self , arg : & str ) -> WebDriverResult < ( ) > {
111+ let mut args = self . args ( ) ;
89112 let arg_string = arg. to_string ( ) ;
90113 if !args. contains ( & arg_string) {
91114 args. push ( arg_string) ;
92115 }
93- self . add_chrome_option ( "args" , to_value ( args) ?)
116+ self . insert_browser_option ( "args" , to_value ( args) ?)
94117 }
95118
96119 /// Remove the specified Chrome command-line argument if it had been added previously.
97- pub fn remove_chrome_arg ( & mut self , arg : & str ) -> WebDriverResult < ( ) > {
98- let mut args = self . get_args ( ) ;
120+ pub fn remove_arg ( & mut self , arg : & str ) -> WebDriverResult < ( ) > {
121+ let mut args = self . args ( ) ;
99122 if args. is_empty ( ) {
100123 Ok ( ( ) )
101124 } else {
102125 args. retain ( |v| v != arg) ;
103- self . add_chrome_option ( "args" , to_value ( args) ?)
126+ self . insert_browser_option ( "args" , to_value ( args) ?)
104127 }
105128 }
106129
130+ /// Return true if the specified arg is currently set.
131+ pub fn has_arg ( & self , arg : & str ) -> bool {
132+ self . args ( ) . contains ( & arg. to_string ( ) )
133+ }
134+
135+ /// Add the specified experimental option.
136+ ///
137+ /// ## Example
138+ /// ```no_run
139+ /// use thirtyfour::DesiredCapabilities;
140+ /// let mut caps = DesiredCapabilities::chrome();
141+ /// caps.add_experimental_option("excludeSwitches", vec!["--enable-logging"]).unwrap();
142+ /// ```
143+ pub fn add_experimental_option (
144+ & mut self ,
145+ name : impl Into < String > ,
146+ value : impl Serialize ,
147+ ) -> WebDriverResult < ( ) > {
148+ self . insert_browser_option ( name, value)
149+ }
150+
151+ /// Remove the specified experimental option.
152+ pub fn remove_experimental_option ( & mut self , name : & str ) {
153+ self . remove_browser_option ( name) ;
154+ }
155+
107156 /// Add a base64-encoded extension.
108157 pub fn add_encoded_extension ( & mut self , extension_base64 : & str ) -> WebDriverResult < ( ) > {
109- let mut extensions = self . get_extensions ( ) ;
158+ let mut extensions = self . extensions ( ) ;
110159 let ext_string = extension_base64. to_string ( ) ;
111160 if !extensions. contains ( & ext_string) {
112161 extensions. push ( ext_string) ;
113162 }
114- self . add_chrome_option ( "extensions" , to_value ( extensions) ?)
163+ self . insert_browser_option ( "extensions" , to_value ( extensions) ?)
115164 }
116165
117166 /// Remove the specified base64-encoded extension if it had been added previously.
118167 pub fn remove_encoded_extension ( & mut self , extension_base64 : & str ) -> WebDriverResult < ( ) > {
119- let mut extensions = self . get_extensions ( ) ;
168+ let mut extensions = self . extensions ( ) ;
120169 if extensions. is_empty ( ) {
121170 Ok ( ( ) )
122171 } else {
123172 extensions. retain ( |v| v != extension_base64) ;
124- self . add_chrome_option ( "extensions" , to_value ( extensions) ?)
173+ self . insert_browser_option ( "extensions" , to_value ( extensions) ?)
125174 }
126175 }
127176
@@ -140,77 +189,63 @@ impl ChromeCapabilities {
140189 self . remove_encoded_extension ( & b64_contents)
141190 }
142191
143- /// Set the browser to run headless.
144- pub fn set_headless ( & mut self ) -> WebDriverResult < ( ) > {
145- self . add_chrome_arg ( "--headless" )
146- }
147-
148- /// Unset the headless option.
149- pub fn unset_headless ( & mut self ) -> WebDriverResult < ( ) > {
150- self . remove_chrome_arg ( "--headless" )
151- }
152-
153- /// Set disable web security.
154- pub fn set_disable_web_security ( & mut self ) -> WebDriverResult < ( ) > {
155- self . add_chrome_arg ( "--disable-web-security" )
156- }
157-
158- /// Unset disable web security.
159- pub fn unset_disable_web_security ( & mut self ) -> WebDriverResult < ( ) > {
160- self . remove_chrome_arg ( "--disable-web-security" )
192+ /// Get the list of exclude switches.
193+ pub fn exclude_switches ( & self ) -> Vec < String > {
194+ self . browser_option ( "excludeSwitches" ) . unwrap_or_default ( )
161195 }
162196
163- /// Set ignore certificate errors .
164- pub fn set_ignore_certificate_errors ( & mut self ) -> WebDriverResult < ( ) > {
165- self . add_chrome_arg ( "--ignore-certificate-errors" )
166- }
167-
168- /// Unset ignore certificate errors.
169- pub fn unset_ignore_certificate_errors ( & mut self ) -> WebDriverResult < ( ) > {
170- self . remove_chrome_arg ( "--ignore-certificate-errors" )
197+ /// Add the specified arg to the list of exclude switches .
198+ pub fn add_exclude_switch ( & mut self , arg : & str ) -> WebDriverResult < ( ) > {
199+ let mut args = self . exclude_switches ( ) ;
200+ let arg_string = arg . to_string ( ) ;
201+ if !args . contains ( & arg_string ) {
202+ args . push ( arg_string ) ;
203+ }
204+ self . add_experimental_option ( "excludeSwitches" , to_value ( args ) ? )
171205 }
172206
173- pub fn set_no_sandbox ( & mut self ) -> WebDriverResult < ( ) > {
174- self . add_chrome_arg ( "--no-sandbox" )
207+ /// Remove the specified arg from the list of exclude switches.
208+ pub fn remove_exclude_switch ( & mut self , arg : & str ) -> WebDriverResult < ( ) > {
209+ let mut args = self . exclude_switches ( ) ;
210+ if args. is_empty ( ) {
211+ Ok ( ( ) )
212+ } else {
213+ args. retain ( |v| v != arg) ;
214+ self . add_experimental_option ( "excludeSwitches" , to_value ( args) ?)
215+ }
175216 }
176217
177- pub fn unset_no_sandbox ( & mut self ) -> WebDriverResult < ( ) > {
178- self . remove_chrome_arg ( "--no-sandbox" )
218+ chrome_arg_wrapper ! {
219+ headless => "--headless" ,
220+ disable_web_security => "--disable-web-security" ,
221+ ignore_certificate_errors => "--ignore-certificate-errors" ,
222+ no_sandbox => "--no-sandbox" ,
223+ disable_gpu => "--disable-gpu" ,
224+ disable_dev_shm_usage => "--disable-dev-shm-usage" ,
225+ disable_local_storage => "--disable-local-storage"
179226 }
227+ }
180228
181- pub fn set_disable_gpu ( & mut self ) -> WebDriverResult < ( ) > {
182- self . add_chrome_arg ( "--disable-gpu" )
229+ impl CapabilitiesHelper for ChromeCapabilities {
230+ fn _get ( & self , key : & str ) -> Option < & Value > {
231+ self . capabilities . _get ( key)
183232 }
184233
185- pub fn unset_disable_gpu ( & mut self ) -> WebDriverResult < ( ) > {
186- self . remove_chrome_arg ( "--disable-gpu" )
234+ fn _get_mut ( & mut self , key : & str ) -> Option < & mut Value > {
235+ self . capabilities . _get_mut ( key )
187236 }
188237
189- pub fn set_disable_dev_shm_usage ( & mut self ) -> WebDriverResult < ( ) > {
190- self . add_chrome_arg ( "--disable-dev-shm-usage" )
238+ fn insert_base_capability ( & mut self , key : String , value : Value ) {
239+ self . capabilities . insert_base_capability ( key , value ) ;
191240 }
241+ }
192242
193- pub fn unset_disable_dev_shm_usage ( & mut self ) -> WebDriverResult < ( ) > {
194- self . remove_chrome_arg ( "--disable-dev-shm-usage" )
195- }
243+ impl BrowserCapabilitiesHelper for ChromeCapabilities {
244+ const KEY : & ' static str = "goog:chromeOptions" ;
196245}
197246
198247impl From < ChromeCapabilities > for Capabilities {
199248 fn from ( caps : ChromeCapabilities ) -> Capabilities {
200249 caps. capabilities
201250 }
202251}
203-
204- impl Deref for ChromeCapabilities {
205- type Target = Capabilities ;
206-
207- fn deref ( & self ) -> & Self :: Target {
208- & self . capabilities
209- }
210- }
211-
212- impl DerefMut for ChromeCapabilities {
213- fn deref_mut ( & mut self ) -> & mut Self :: Target {
214- & mut self . capabilities
215- }
216- }
0 commit comments