22
22
using System ;
23
23
using System . Collections . Generic ;
24
24
using System . Collections . ObjectModel ;
25
+ using System . Diagnostics . CodeAnalysis ;
25
26
using System . IO ;
26
27
using System . Threading . Tasks ;
27
28
29
+ #nullable enable
30
+
28
31
namespace OpenQA . Selenium . Chromium
29
32
{
30
33
/// <summary>
@@ -108,9 +111,9 @@ public class ChromiumDriver : WebDriver, ISupportsLogs, IDevTools
108
111
public static readonly string SetPermissionCommand = "setPermission" ;
109
112
110
113
private readonly string optionsCapabilityName ;
111
- private DevToolsSession devToolsSession ;
114
+ private DevToolsSession ? devToolsSession ;
112
115
113
- private static Dictionary < string , CommandInfo > chromiumCustomCommands = new Dictionary < string , CommandInfo > ( )
116
+ private static readonly Dictionary < string , CommandInfo > chromiumCustomCommands = new Dictionary < string , CommandInfo > ( )
114
117
{
115
118
{ GetNetworkConditionsCommand , new HttpCommandInfo ( HttpCommandInfo . GetCommand , "/session/{sessionId}/chromium/network_conditions" ) } ,
116
119
{ SetNetworkConditionsCommand , new HttpCommandInfo ( HttpCommandInfo . PostCommand , "/session/{sessionId}/chromium/network_conditions" ) } ,
@@ -127,19 +130,18 @@ public class ChromiumDriver : WebDriver, ISupportsLogs, IDevTools
127
130
/// <param name="service">The <see cref="ChromiumDriverService"/> to use.</param>
128
131
/// <param name="options">The <see cref="ChromiumOptions"/> to be used with the ChromiumDriver.</param>
129
132
/// <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>
130
135
protected ChromiumDriver ( ChromiumDriverService service , ChromiumOptions options , TimeSpan commandTimeout )
131
136
: base ( GenerateDriverServiceCommandExecutor ( service , options , commandTimeout ) , ConvertOptionsToCapabilities ( options ) )
132
137
{
133
- this . optionsCapabilityName = options . CapabilityName ;
138
+ this . optionsCapabilityName = options . CapabilityName ?? throw new ArgumentException ( "No chromium options capability name specified" , nameof ( options ) ) ;
134
139
}
135
140
136
141
/// <summary>
137
142
/// Gets the dictionary of custom Chromium commands registered with the driver.
138
143
/// </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 ) ;
143
145
144
146
/// <summary>
145
147
/// Uses DriverFinder to set Service attributes if necessary when creating the command executor
@@ -150,6 +152,16 @@ protected static IReadOnlyDictionary<string, CommandInfo> ChromiumCustomCommands
150
152
/// <returns></returns>
151
153
private static ICommandExecutor GenerateDriverServiceCommandExecutor ( DriverService service , DriverOptions options , TimeSpan commandTimeout )
152
154
{
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
+
153
165
if ( service . DriverServicePath == null )
154
166
{
155
167
DriverFinder finder = new DriverFinder ( options ) ;
@@ -177,27 +189,31 @@ private static ICommandExecutor GenerateDriverServiceCommandExecutor(DriverServi
177
189
/// in conjunction with a standalone WebDriver server.</remarks>
178
190
public override IFileDetector FileDetector
179
191
{
180
- get { return base . FileDetector ; }
192
+ get => base . FileDetector ;
181
193
set { }
182
194
}
183
195
184
196
/// <summary>
185
197
/// Gets a value indicating whether a DevTools session is active.
186
198
/// </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 ;
191
201
192
202
/// <summary>
193
203
/// Gets or sets the network condition emulation for Chromium.
194
204
/// </summary>
205
+ /// <exception cref="ArgumentNullException">If the value is set to <see langword="null"/>.</exception>
195
206
public ChromiumNetworkConditions NetworkConditions
196
207
{
197
208
get
198
209
{
199
210
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 ) ;
201
217
}
202
218
203
219
set
@@ -209,6 +225,7 @@ public ChromiumNetworkConditions NetworkConditions
209
225
210
226
Dictionary < string , object > parameters = new Dictionary < string , object > ( ) ;
211
227
parameters [ "network_conditions" ] = value ;
228
+
212
229
this . Execute ( SetNetworkConditionsCommand , parameters ) ;
213
230
}
214
231
}
@@ -217,6 +234,7 @@ public ChromiumNetworkConditions NetworkConditions
217
234
/// Launches a Chromium based application.
218
235
/// </summary>
219
236
/// <param name="id">ID of the chromium app to launch.</param>
237
+ /// <exception cref="ArgumentNullException">If <paramref name="id"/> is <see langword="null"/>.</exception>
220
238
public void LaunchApp ( string id )
221
239
{
222
240
if ( id == null )
@@ -226,6 +244,7 @@ public void LaunchApp(string id)
226
244
227
245
Dictionary < string , object > parameters = new Dictionary < string , object > ( ) ;
228
246
parameters [ "id" ] = id ;
247
+
229
248
this . Execute ( LaunchAppCommand , parameters ) ;
230
249
}
231
250
@@ -234,6 +253,7 @@ public void LaunchApp(string id)
234
253
/// </summary>
235
254
/// <param name="permissionName">Name of item to set the permission on.</param>
236
255
/// <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>
237
257
public void SetPermission ( string permissionName , string permissionValue )
238
258
{
239
259
if ( permissionName == null )
@@ -260,7 +280,8 @@ public void SetPermission(string permissionName, string permissionValue)
260
280
/// <param name="commandName">Name of the command to execute.</param>
261
281
/// <param name="commandParameters">Parameters of the command to execute.</param>
262
282
/// <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 )
264
285
{
265
286
if ( commandName == null )
266
287
{
@@ -296,21 +317,20 @@ public DevToolsSession GetDevToolsSession(DevToolsOptions options)
296
317
throw new WebDriverException ( "Cannot find " + this . optionsCapabilityName + " capability for driver" ) ;
297
318
}
298
319
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 )
301
322
{
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 } ") ;
303
324
}
304
325
305
- if ( ! optionsCapability . ContainsKey ( "debuggerAddress" ) )
326
+ if ( ! optionsCapability . TryGetValue ( "debuggerAddress" , out object ? debuggerAddress ) )
306
327
{
307
328
throw new WebDriverException ( "Did not find debuggerAddress capability in " + this . optionsCapabilityName ) ;
308
329
}
309
330
310
- string debuggerAddress = optionsCapability [ "debuggerAddress" ] . ToString ( ) ;
311
331
try
312
332
{
313
- DevToolsSession session = new DevToolsSession ( debuggerAddress , options ) ;
333
+ DevToolsSession session = new DevToolsSession ( debuggerAddress ? . ToString ( ) , options ) ;
314
334
Task . Run ( async ( ) => await session . StartSession ( ) ) . GetAwaiter ( ) . GetResult ( ) ;
315
335
this . devToolsSession = session ;
316
336
}
@@ -341,7 +361,7 @@ public void CloseDevToolsSession()
341
361
{
342
362
if ( this . devToolsSession != null )
343
363
{
344
- Task . Run ( async ( ) => await this . devToolsSession . StopSession ( true ) ) . GetAwaiter ( ) . GetResult ( ) ;
364
+ Task . Run ( async ( ) => await this . devToolsSession . StopSession ( manualDetach : true ) ) . GetAwaiter ( ) . GetResult ( ) ;
345
365
}
346
366
}
347
367
@@ -361,18 +381,16 @@ public List<Dictionary<string, string>> GetCastSinks()
361
381
{
362
382
List < Dictionary < string , string > > returnValue = new List < Dictionary < string , string > > ( ) ;
363
383
Response response = this . Execute ( GetCastSinksCommand , null ) ;
364
- object [ ] responseValue = response . Value as object [ ] ;
365
- if ( responseValue != null )
384
+ if ( response . Value is object ? [ ] responseValue )
366
385
{
367
- foreach ( object entry in responseValue )
386
+ foreach ( object ? entry in responseValue )
368
387
{
369
- Dictionary < string , object > entryValue = entry as Dictionary < string , object > ;
370
- if ( entryValue != null )
388
+ if ( entry is Dictionary < string , object ? > entryValue )
371
389
{
372
390
Dictionary < string , string > sink = new Dictionary < string , string > ( ) ;
373
- foreach ( KeyValuePair < string , object > pair in entryValue )
391
+ foreach ( KeyValuePair < string , object ? > pair in entryValue )
374
392
{
375
- sink [ pair . Key ] = pair . Value . ToString ( ) ;
393
+ sink [ pair . Key ] = pair . Value ! . ToString ( ) ! ;
376
394
}
377
395
378
396
returnValue . Add ( sink ) ;
@@ -434,10 +452,10 @@ public void StartDesktopMirroring(string deviceName)
434
452
/// Returns the error message if there is any issue in a Cast session.
435
453
/// </summary>
436
454
/// <returns>An error message.</returns>
437
- public String GetCastIssueMessage ( )
455
+ public string ? GetCastIssueMessage ( )
438
456
{
439
457
Response response = this . Execute ( GetCastIssueMessageCommand , null ) ;
440
- return ( string ) response . Value ;
458
+ return ( string ? ) response . Value ;
441
459
}
442
460
443
461
/// <summary>
0 commit comments