2222using  System ; 
2323using  System . Collections . Generic ; 
2424using  System . Collections . ObjectModel ; 
25+ using  System . Diagnostics . CodeAnalysis ; 
2526using  System . IO ; 
2627using  System . Threading . Tasks ; 
2728
29+ #nullable enable
30+ 
2831namespace  OpenQA . Selenium . Chromium 
2932{ 
3033    /// <summary> 
@@ -108,9 +111,9 @@ public class ChromiumDriver : WebDriver, ISupportsLogs, IDevTools
108111        public  static   readonly  string  SetPermissionCommand  =  "setPermission" ; 
109112
110113        private  readonly  string  optionsCapabilityName ; 
111-         private  DevToolsSession  devToolsSession ; 
114+         private  DevToolsSession ?  devToolsSession ; 
112115
113-         private  static   Dictionary < string ,  CommandInfo >  chromiumCustomCommands  =  new  Dictionary < string ,  CommandInfo > ( ) 
116+         private  static   readonly   Dictionary < string ,  CommandInfo >  chromiumCustomCommands  =  new  Dictionary < string ,  CommandInfo > ( ) 
114117        { 
115118            {  GetNetworkConditionsCommand ,  new  HttpCommandInfo ( HttpCommandInfo . GetCommand ,  "/session/{sessionId}/chromium/network_conditions" )  } , 
116119            {  SetNetworkConditionsCommand ,  new  HttpCommandInfo ( HttpCommandInfo . PostCommand ,  "/session/{sessionId}/chromium/network_conditions" )  } , 
@@ -127,19 +130,18 @@ public class ChromiumDriver : WebDriver, ISupportsLogs, IDevTools
127130        /// <param name="service">The <see cref="ChromiumDriverService"/> to use.</param> 
128131        /// <param name="options">The <see cref="ChromiumOptions"/> to be used with the ChromiumDriver.</param> 
129132        /// <param name="commandTimeout">The maximum amount of time to wait for each command.</param> 
133+         /// <exception cref="ArgumentNullException">If <paramref name="service"/> or <paramref name="options"/> are <see langword="null"/>.</exception> 
134+         /// <exception cref="ArgumentException">If the Chromium options capability name is <see langword="null"/>.</exception> 
130135        protected  ChromiumDriver ( ChromiumDriverService  service ,  ChromiumOptions  options ,  TimeSpan  commandTimeout ) 
131136            :  base ( GenerateDriverServiceCommandExecutor ( service ,  options ,  commandTimeout ) ,  ConvertOptionsToCapabilities ( options ) ) 
132137        { 
133-             this . optionsCapabilityName  =  options . CapabilityName ; 
138+             this . optionsCapabilityName  =  options . CapabilityName   ??   throw   new   ArgumentException ( "No chromium options capability name specified" ,   nameof ( options ) ) ; 
134139        } 
135140
136141        /// <summary> 
137142        /// Gets the dictionary of custom Chromium commands registered with the driver. 
138143        /// </summary> 
139-         protected  static   IReadOnlyDictionary < string ,  CommandInfo >  ChromiumCustomCommands 
140-         { 
141-             get  {  return  new  ReadOnlyDictionary < string ,  CommandInfo > ( chromiumCustomCommands ) ;  } 
142-         } 
144+         protected  static   IReadOnlyDictionary < string ,  CommandInfo >  ChromiumCustomCommands  =>  new  ReadOnlyDictionary < string ,  CommandInfo > ( chromiumCustomCommands ) ; 
143145
144146        /// <summary> 
145147        /// Uses DriverFinder to set Service attributes if necessary when creating the command executor 
@@ -150,6 +152,16 @@ protected static IReadOnlyDictionary<string, CommandInfo> ChromiumCustomCommands
150152        /// <returns></returns> 
151153        private  static   ICommandExecutor  GenerateDriverServiceCommandExecutor ( DriverService  service ,  DriverOptions  options ,  TimeSpan  commandTimeout ) 
152154        { 
155+             if  ( service  is  null ) 
156+             { 
157+                 throw  new  ArgumentNullException ( nameof ( service ) ) ; 
158+             } 
159+ 
160+             if  ( options  is  null ) 
161+             { 
162+                 throw  new  ArgumentNullException ( nameof ( options ) ) ; 
163+             } 
164+ 
153165            if  ( service . DriverServicePath  ==  null ) 
154166            { 
155167                DriverFinder  finder  =  new  DriverFinder ( options ) ; 
@@ -177,27 +189,31 @@ private static ICommandExecutor GenerateDriverServiceCommandExecutor(DriverServi
177189        /// in conjunction with a standalone WebDriver server.</remarks> 
178190        public  override  IFileDetector  FileDetector 
179191        { 
180-             get  {   return   base . FileDetector ;   } 
192+             get  =>   base . FileDetector ; 
181193            set  {  } 
182194        } 
183195
184196        /// <summary> 
185197        /// Gets a value indicating whether a DevTools session is active. 
186198        /// </summary> 
187-         public  bool  HasActiveDevToolsSession 
188-         { 
189-             get  {  return  this . devToolsSession  !=  null ;  } 
190-         } 
199+         [ MemberNotNullWhen ( true ,  nameof ( devToolsSession ) ) ] 
200+         public  bool  HasActiveDevToolsSession  =>  this . devToolsSession  !=  null ; 
191201
192202        /// <summary> 
193203        /// Gets or sets the network condition emulation for Chromium. 
194204        /// </summary> 
205+         /// <exception cref="ArgumentNullException">If the value is set to <see langword="null"/>.</exception> 
195206        public  ChromiumNetworkConditions  NetworkConditions 
196207        { 
197208            get 
198209            { 
199210                Response  response  =  this . Execute ( GetNetworkConditionsCommand ,  null ) ; 
200-                 return  ChromiumNetworkConditions . FromDictionary ( response . Value  as  Dictionary < string ,  object > ) ; 
211+                 if  ( response . Value  is  not Dictionary < string ,  object ? >  responseDictionary ) 
212+                 { 
213+                     throw  new  WebDriverException ( $ "GetNetworkConditions command returned successfully, but data was not an object: { response . Value } ") ; 
214+                 } 
215+ 
216+                 return  ChromiumNetworkConditions . FromDictionary ( responseDictionary ) ; 
201217            } 
202218
203219            set 
@@ -209,6 +225,7 @@ public ChromiumNetworkConditions NetworkConditions
209225
210226                Dictionary < string ,  object >  parameters  =  new  Dictionary < string ,  object > ( ) ; 
211227                parameters [ "network_conditions" ]  =  value ; 
228+ 
212229                this . Execute ( SetNetworkConditionsCommand ,  parameters ) ; 
213230            } 
214231        } 
@@ -217,6 +234,7 @@ public ChromiumNetworkConditions NetworkConditions
217234        /// Launches a Chromium based application. 
218235        /// </summary> 
219236        /// <param name="id">ID of the chromium app to launch.</param> 
237+         /// <exception cref="ArgumentNullException">If <paramref name="id"/> is <see langword="null"/>.</exception> 
220238        public  void  LaunchApp ( string  id ) 
221239        { 
222240            if  ( id  ==  null ) 
@@ -226,6 +244,7 @@ public void LaunchApp(string id)
226244
227245            Dictionary < string ,  object >  parameters  =  new  Dictionary < string ,  object > ( ) ; 
228246            parameters [ "id" ]  =  id ; 
247+ 
229248            this . Execute ( LaunchAppCommand ,  parameters ) ; 
230249        } 
231250
@@ -234,6 +253,7 @@ public void LaunchApp(string id)
234253        /// </summary> 
235254        /// <param name="permissionName">Name of item to set the permission on.</param> 
236255        /// <param name="permissionValue">Value to set the permission to.</param> 
256+         /// <exception cref="ArgumentNullException">If <paramref name="permissionName"/> or <paramref name="permissionValue"/> are <see langword="null"/>.</exception> 
237257        public  void  SetPermission ( string  permissionName ,  string  permissionValue ) 
238258        { 
239259            if  ( permissionName  ==  null ) 
@@ -260,7 +280,8 @@ public void SetPermission(string permissionName, string permissionValue)
260280        /// <param name="commandName">Name of the command to execute.</param> 
261281        /// <param name="commandParameters">Parameters of the command to execute.</param> 
262282        /// <returns>An object representing the result of the command, if applicable.</returns> 
263-         public  object  ExecuteCdpCommand ( string  commandName ,  Dictionary < string ,  object >  commandParameters ) 
283+         /// <exception cref="ArgumentNullException">If <paramref name="commandName"/> is <see langword="null"/>.</exception> 
284+         public  object ?  ExecuteCdpCommand ( string  commandName ,  Dictionary < string ,  object >  commandParameters ) 
264285        { 
265286            if  ( commandName  ==  null ) 
266287            { 
@@ -296,21 +317,20 @@ public DevToolsSession GetDevToolsSession(DevToolsOptions options)
296317                    throw  new  WebDriverException ( "Cannot find "  +  this . optionsCapabilityName  +  " capability for driver" ) ; 
297318                } 
298319
299-                 Dictionary < string ,   object >   optionsCapability  =  this . Capabilities . GetCapability ( this . optionsCapabilityName )   as   Dictionary < string ,   object > ; 
300-                 if  ( optionsCapability   ==   null ) 
320+                 object ?   optionsCapabilityObject  =  this . Capabilities . GetCapability ( this . optionsCapabilityName ) ; 
321+                 if  ( optionsCapabilityObject   is  not  Dictionary < string ,   object ? >   optionsCapability ) 
301322                { 
302-                     throw  new  WebDriverException ( "Found "    +   this . optionsCapabilityName   +   "  capability, but is not an object") ; 
323+                     throw  new  WebDriverException ( $ "Found { this . optionsCapabilityName }   capability, but is not an object:  { optionsCapabilityObject } ") ; 
303324                } 
304325
305-                 if  ( ! optionsCapability . ContainsKey ( "debuggerAddress" ) ) 
326+                 if  ( ! optionsCapability . TryGetValue ( "debuggerAddress" ,   out   object ?   debuggerAddress ) ) 
306327                { 
307328                    throw  new  WebDriverException ( "Did not find debuggerAddress capability in "  +  this . optionsCapabilityName ) ; 
308329                } 
309330
310-                 string  debuggerAddress  =  optionsCapability [ "debuggerAddress" ] . ToString ( ) ; 
311331                try 
312332                { 
313-                     DevToolsSession  session  =  new  DevToolsSession ( debuggerAddress ,  options ) ; 
333+                     DevToolsSession  session  =  new  DevToolsSession ( debuggerAddress ? . ToString ( ) ,  options ) ; 
314334                    Task . Run ( async  ( )  =>  await  session . StartSession ( ) ) . GetAwaiter ( ) . GetResult ( ) ; 
315335                    this . devToolsSession  =  session ; 
316336                } 
@@ -341,7 +361,7 @@ public void CloseDevToolsSession()
341361        { 
342362            if  ( this . devToolsSession  !=  null ) 
343363            { 
344-                 Task . Run ( async  ( )  =>  await  this . devToolsSession . StopSession ( true ) ) . GetAwaiter ( ) . GetResult ( ) ; 
364+                 Task . Run ( async  ( )  =>  await  this . devToolsSession . StopSession ( manualDetach :   true ) ) . GetAwaiter ( ) . GetResult ( ) ; 
345365            } 
346366        } 
347367
@@ -361,18 +381,16 @@ public List<Dictionary<string, string>> GetCastSinks()
361381        { 
362382            List < Dictionary < string ,  string > >  returnValue  =  new  List < Dictionary < string ,  string > > ( ) ; 
363383            Response  response  =  this . Execute ( GetCastSinksCommand ,  null ) ; 
364-             object [ ]  responseValue  =  response . Value  as  object [ ] ; 
365-             if  ( responseValue  !=  null ) 
384+             if  ( response . Value  is  object ? [ ]  responseValue ) 
366385            { 
367-                 foreach  ( object  entry  in  responseValue ) 
386+                 foreach  ( object ?  entry  in  responseValue ) 
368387                { 
369-                     Dictionary < string ,  object >  entryValue  =  entry  as  Dictionary < string ,  object > ; 
370-                     if  ( entryValue  !=  null ) 
388+                     if  ( entry  is  Dictionary < string ,  object ? >  entryValue ) 
371389                    { 
372390                        Dictionary < string ,  string >  sink  =  new  Dictionary < string ,  string > ( ) ; 
373-                         foreach  ( KeyValuePair < string ,  object >  pair  in  entryValue ) 
391+                         foreach  ( KeyValuePair < string ,  object ? >  pair  in  entryValue ) 
374392                        { 
375-                             sink [ pair . Key ]  =  pair . Value . ToString ( ) ; 
393+                             sink [ pair . Key ]  =  pair . Value ! . ToString ( ) ! ; 
376394                        } 
377395
378396                        returnValue . Add ( sink ) ; 
@@ -434,10 +452,10 @@ public void StartDesktopMirroring(string deviceName)
434452        /// Returns the error message if there is any issue in a Cast session. 
435453        /// </summary> 
436454        /// <returns>An error message.</returns> 
437-         public  String  GetCastIssueMessage ( ) 
455+         public  string ?  GetCastIssueMessage ( ) 
438456        { 
439457            Response  response  =  this . Execute ( GetCastIssueMessageCommand ,  null ) ; 
440-             return  ( string ) response . Value ; 
458+             return  ( string ? ) response . Value ; 
441459        } 
442460
443461        /// <summary> 
0 commit comments