20
20
using System . Collections . Generic ;
21
21
using System . Globalization ;
22
22
using System . IO ;
23
- using System . Reflection ;
24
23
using System . Text ;
25
24
using System . Xml ;
26
25
using System . Xml . XPath ;
27
26
using Ionic . Zip ;
27
+ using Newtonsoft . Json ;
28
28
using OpenQA . Selenium . Internal ;
29
+ using OpenQA . Selenium . Remote ;
29
30
30
31
namespace OpenQA . Selenium . Firefox
31
32
{
@@ -38,6 +39,11 @@ public class FirefoxProfile
38
39
private const string ExtensionFileName = "webdriver.xpi" ;
39
40
private const string ExtensionResourceId = "WebDriver.FirefoxExt.zip" ;
40
41
private const string UserPreferencesFileName = "user.js" ;
42
+
43
+ private const string WebDriverPortPreferenceName = "webdriver_firefox_port" ;
44
+ private const string EnableNativeEventsPreferenceName = "webdriver_enable_native_events" ;
45
+ private const string AcceptUntrustedCertificatesPreferenceName = "webdriver_accept_untrusted_certs" ;
46
+ private const string AssumeUntrustedCertificateIssuerPreferenceName = "webdriver_assume_untrusted_issuer" ;
41
47
#endregion
42
48
43
49
#region Private members
@@ -47,8 +53,9 @@ public class FirefoxProfile
47
53
private bool enableNativeEvents ;
48
54
private bool loadNoFocusLibrary ;
49
55
private bool acceptUntrustedCerts ;
56
+ private bool assumeUntrustedIssuer ;
50
57
private bool deleteSource ;
51
- private Preferences profileAdditionalPrefs = new Preferences ( ) ;
58
+ private Preferences profilePreferences ;
52
59
private Dictionary < string , FirefoxExtension > extensions = new Dictionary < string , FirefoxExtension > ( ) ;
53
60
#endregion
54
61
@@ -83,7 +90,10 @@ public FirefoxProfile(string profileDirectory, bool deleteSourceOnClean)
83
90
this . profilePort = FirefoxDriver . DefaultPort ;
84
91
this . enableNativeEvents = FirefoxDriver . DefaultEnableNativeEvents ;
85
92
this . acceptUntrustedCerts = FirefoxDriver . AcceptUntrustedCertificates ;
93
+ this . assumeUntrustedIssuer = FirefoxDriver . AssumeUntrustedCertificateIssuer ;
86
94
this . deleteSource = deleteSourceOnClean ;
95
+ this . ReadDefaultPreferences ( ) ;
96
+ this . profilePreferences . AppendPreferences ( this . ReadExistingPreferences ( ) ) ;
87
97
}
88
98
#endregion
89
99
@@ -126,13 +136,39 @@ public bool AlwaysLoadNoFocusLibrary
126
136
}
127
137
128
138
/// <summary>
129
- /// Gets or sets a value indicating whether Firefox should accept untrusted certificates.
139
+ /// Gets or sets a value indicating whether Firefox should accept SSL certificates which have
140
+ /// expired, signed by an unknown authority or are generally untrusted. Set to true
141
+ /// by default.
130
142
/// </summary>
131
143
public bool AcceptUntrustedCertificates
132
144
{
133
145
get { return this . acceptUntrustedCerts ; }
134
146
set { this . acceptUntrustedCerts = value ; }
135
147
}
148
+
149
+ /// <summary>
150
+ /// Gets or sets a value indicating whether Firefox assume untrusted SSL certificates
151
+ /// come from an untrusted issuer or are self-signed. Set to true by default.
152
+ /// </summary>
153
+ /// <remarks>
154
+ /// <para>
155
+ /// Due to limitations within Firefox, it is easy to find out if a certificate has expired
156
+ /// or does not match the host it was served for, but hard to find out if the issuer of the
157
+ /// certificate is untrusted. By default, it is assumed that the certificates were not
158
+ /// issued from a trusted certificate authority.
159
+ /// </para>
160
+ /// <para>
161
+ /// If you receive an "untrusted site" prompt it Firefox when using a certificate that was
162
+ /// issued by valid issuer, but the certificate has expired or is being served served for
163
+ /// a different host (e.g. production certificate served in a testing environment) set this
164
+ /// to false.
165
+ /// </para>
166
+ /// </remarks>
167
+ public bool AssumeUntrustedCertificateIssuer
168
+ {
169
+ get { return this . assumeUntrustedIssuer ; }
170
+ set { this . assumeUntrustedIssuer = value ; }
171
+ }
136
172
#endregion
137
173
138
174
#region Public methods
@@ -173,7 +209,7 @@ public void AddExtension(string extensionToInstall)
173
209
/// <param name="value">A <see cref="System.String"/> value to add to the profile.</param>
174
210
public void SetPreference ( string name , string value )
175
211
{
176
- this . profileAdditionalPrefs . SetPreference ( name , value ) ;
212
+ this . profilePreferences . SetPreference ( name , value ) ;
177
213
}
178
214
179
215
/// <summary>
@@ -183,7 +219,7 @@ public void SetPreference(string name, string value)
183
219
/// <param name="value">A <see cref="System.Int32"/> value to add to the profile.</param>
184
220
public void SetPreference ( string name , int value )
185
221
{
186
- this . profileAdditionalPrefs . SetPreference ( name , value ) ;
222
+ this . profilePreferences . SetPreference ( name , value ) ;
187
223
}
188
224
189
225
/// <summary>
@@ -193,7 +229,7 @@ public void SetPreference(string name, int value)
193
229
/// <param name="value">A <see cref="System.Boolean"/> value to add to the profile.</param>
194
230
public void SetPreference ( string name , bool value )
195
231
{
196
- this . profileAdditionalPrefs . SetPreference ( name , value ) ;
232
+ this . profilePreferences . SetPreference ( name , value ) ;
197
233
}
198
234
199
235
/// <summary>
@@ -313,22 +349,6 @@ internal void AddWebDriverExtension()
313
349
}
314
350
}
315
351
316
- /// <summary>
317
- /// Adds a preference to the profile.
318
- /// </summary>
319
- /// <param name="preferences">The preferences dictionary.</param>
320
- /// <param name="name">The name of the preference.</param>
321
- /// <param name="value">The value of the preference.</param>
322
- private static void AddDefaultPreference ( Dictionary < string , string > preferences , string name , string value )
323
- {
324
- // The user must be able to override the default preferences in the profile,
325
- // so only add them if they don't already exist.
326
- if ( ! preferences . ContainsKey ( name ) )
327
- {
328
- preferences . Add ( name , value ) ;
329
- }
330
- }
331
-
332
352
/// <summary>
333
353
/// Generates a random directory name for the profile.
334
354
/// </summary>
@@ -384,8 +404,6 @@ private void UpdateUserPreferences()
384
404
throw new WebDriverException ( "You must set the port to listen on before updating user.js" ) ;
385
405
}
386
406
387
- Dictionary < string , string > prefs = this . ReadExistingPreferences ( ) ;
388
-
389
407
string userPrefs = Path . Combine ( this . profileDir , UserPreferencesFileName ) ;
390
408
if ( File . Exists ( userPrefs ) )
391
409
{
@@ -399,88 +417,37 @@ private void UpdateUserPreferences()
399
417
}
400
418
}
401
419
402
- this . profileAdditionalPrefs . AppendPreferencesTo ( prefs ) ;
403
-
404
- // Normal settings to facilitate testing
405
- AddDefaultPreference ( prefs , "app.update.auto" , "false" ) ;
406
- AddDefaultPreference ( prefs , "app.update.enabled" , "false" ) ;
407
- AddDefaultPreference ( prefs , "browser.download.manager.showWhenStarting" , "false" ) ;
408
- AddDefaultPreference ( prefs , "browser.EULA.override" , "true" ) ;
409
- AddDefaultPreference ( prefs , "browser.EULA.3.accepted" , "true" ) ;
410
- AddDefaultPreference ( prefs , "browser.link.open_external" , "2" ) ;
411
- AddDefaultPreference ( prefs , "browser.link.open_newwindow" , "2" ) ;
412
- AddDefaultPreference ( prefs , "browser.offline" , "false" ) ;
413
- AddDefaultPreference ( prefs , "browser.safebrowsing.enabled" , "false" ) ;
414
- AddDefaultPreference ( prefs , "browser.safebrowsing.malware.enabled" , "false" ) ;
415
- AddDefaultPreference ( prefs , "browser.search.update" , "false" ) ;
416
- AddDefaultPreference ( prefs , "extensions.blocklist.enabled" , "false" ) ;
417
- AddDefaultPreference ( prefs , "browser.sessionstore.resume_from_crash" , "false" ) ;
418
- AddDefaultPreference ( prefs , "browser.shell.checkDefaultBrowser" , "false" ) ;
419
- AddDefaultPreference ( prefs , "browser.startup.page" , "0" ) ;
420
- AddDefaultPreference ( prefs , "browser.tabs.warnOnClose" , "false" ) ;
421
- AddDefaultPreference ( prefs , "browser.tabs.warnOnOpen" , "false" ) ;
422
- AddDefaultPreference ( prefs , "devtools.errorconsole.enabled" , "true" ) ;
423
- AddDefaultPreference ( prefs , "dom.disable_open_during_load" , "false" ) ;
424
- AddDefaultPreference ( prefs , "dom.max_script_run_time" , "30" ) ;
425
- AddDefaultPreference ( prefs , "extensions.autoDisableScopes" , "10" ) ;
426
- AddDefaultPreference ( prefs , "extensions.logging.enabled" , "true" ) ;
427
- AddDefaultPreference ( prefs , "extensions.update.enabled" , "false" ) ;
428
- AddDefaultPreference ( prefs , "extensions.update.notifyUser" , "false" ) ;
429
- AddDefaultPreference ( prefs , "network.manage-offline-status" , "false" ) ;
430
- AddDefaultPreference ( prefs , "network.http.max-connections-per-server" , "10" ) ;
431
- AddDefaultPreference ( prefs , "network.http.phishy-userpass-length" , "255" ) ;
432
- AddDefaultPreference ( prefs , "offline-apps.allow_by_default" , "true" ) ;
433
- AddDefaultPreference ( prefs , "prompts.tab_modal.enabled" , "false" ) ;
434
- AddDefaultPreference ( prefs , "security.fileuri.origin_policy" , "3" ) ;
435
- AddDefaultPreference ( prefs , "security.fileuri.strict_origin_policy" , "false" ) ;
436
- AddDefaultPreference ( prefs , "security.warn_entering_secure" , "false" ) ;
437
- AddDefaultPreference ( prefs , "security.warn_submit_insecure" , "false" ) ;
438
- AddDefaultPreference ( prefs , "security.warn_entering_secure.show_once" , "false" ) ;
439
- AddDefaultPreference ( prefs , "security.warn_entering_weak" , "false" ) ;
440
- AddDefaultPreference ( prefs , "security.warn_entering_weak.show_once" , "false" ) ;
441
- AddDefaultPreference ( prefs , "security.warn_leaving_secure" , "false" ) ;
442
- AddDefaultPreference ( prefs , "security.warn_leaving_secure.show_once" , "false" ) ;
443
- AddDefaultPreference ( prefs , "security.warn_submit_insecure" , "false" ) ;
444
- AddDefaultPreference ( prefs , "security.warn_viewing_mixed" , "false" ) ;
445
- AddDefaultPreference ( prefs , "security.warn_viewing_mixed.show_once" , "false" ) ;
446
- AddDefaultPreference ( prefs , "signon.rememberSignons" , "false" ) ;
447
- AddDefaultPreference ( prefs , "startup.homepage_welcome_url" , "\" about:blank\" " ) ;
448
- AddDefaultPreference ( prefs , "toolkit.networkmanager.disable" , "true" ) ;
449
- AddDefaultPreference ( prefs , "toolkit.telemetry.enabled" , "false" ) ;
450
- AddDefaultPreference ( prefs , "toolkit.telemetry.prompted" , "2" ) ;
451
- AddDefaultPreference ( prefs , "toolkit.telemetry.rejected" , "true" ) ;
452
-
453
- // Which port should we listen on?
454
- AddDefaultPreference ( prefs , "webdriver_firefox_port" , this . profilePort . ToString ( CultureInfo . InvariantCulture ) ) ;
455
-
456
- // Should we use native events?
457
- AddDefaultPreference ( prefs , "webdriver_enable_native_events" , this . enableNativeEvents . ToString ( ) . ToLowerInvariant ( ) ) ;
458
-
459
- // Should we accept untrusted certificates or not?
460
- AddDefaultPreference ( prefs , "webdriver_accept_untrusted_certs" , this . acceptUntrustedCerts . ToString ( ) . ToLowerInvariant ( ) ) ;
461
-
462
- // Settings to facilitate debugging the driver
463
- // Logs errors in chrome files to the Error Console.
464
- AddDefaultPreference ( prefs , "javascript.options.showInConsole" , "true" ) ; // Logs errors in chrome files to the Error Console.
465
-
466
- // Enables the use of the dump() statement
467
- AddDefaultPreference ( prefs , "browser.dom.window.dump.enabled" , "true" ) ; // Enables the use of the dump() statement
468
-
469
- // Log exceptions from inner frames (i.e. setTimeout)
470
- AddDefaultPreference ( prefs , "dom.report_all_js_exceptions" , "true" ) ;
471
-
472
- // If the user sets the home page, we should also start up there
473
- string userHomePage = string . Empty ;
474
- if ( prefs . TryGetValue ( "browser.startup.homepage" , out userHomePage ) )
420
+ this . profilePreferences . SetPreference ( WebDriverPortPreferenceName , this . profilePort ) ;
421
+ this . profilePreferences . SetPreference ( EnableNativeEventsPreferenceName , this . enableNativeEvents ) ;
422
+ this . profilePreferences . SetPreference ( AcceptUntrustedCertificatesPreferenceName , this . acceptUntrustedCerts ) ;
423
+ this . profilePreferences . SetPreference ( AssumeUntrustedCertificateIssuerPreferenceName , this . assumeUntrustedIssuer ) ;
424
+
425
+ string homePage = this . profilePreferences . GetPreference ( "browser.startup.homepage" ) ;
426
+ if ( ! string . IsNullOrEmpty ( homePage ) )
475
427
{
476
- AddDefaultPreference ( prefs , "startup.homepage_welcome_url" , userHomePage ) ;
477
- if ( userHomePage != "about:blank" )
428
+ this . profilePreferences . SetPreference ( "startup.homepage_welcome_url" , string . Empty ) ;
429
+ if ( homePage != "about:blank" )
478
430
{
479
- AddDefaultPreference ( prefs , "browser.startup.page" , "1" ) ;
431
+ this . profilePreferences . SetPreference ( "browser.startup.page" , 1 ) ;
480
432
}
481
433
}
482
434
483
- this . WriteNewPreferences ( prefs ) ;
435
+ this . profilePreferences . WriteToFile ( userPrefs ) ;
436
+ }
437
+
438
+ private void ReadDefaultPreferences ( )
439
+ {
440
+ using ( Stream defaultPrefsStream = ResourceUtilities . GetResourceStream ( "webdriver.json" , "WebDriver.FirefoxPreferences" ) )
441
+ {
442
+ using ( StreamReader reader = new StreamReader ( defaultPrefsStream ) )
443
+ {
444
+ string defaultPreferences = reader . ReadToEnd ( ) ;
445
+ Dictionary < string , object > deserializedPreferences = JsonConvert . DeserializeObject < Dictionary < string , object > > ( defaultPreferences , new ResponseValueJsonConverter ( ) ) ;
446
+ Dictionary < string , object > immutableDefaultPreferences = deserializedPreferences [ "frozen" ] as Dictionary < string , object > ;
447
+ Dictionary < string , object > editableDefaultPreferences = deserializedPreferences [ "mutable" ] as Dictionary < string , object > ;
448
+ this . profilePreferences = new Preferences ( immutableDefaultPreferences , editableDefaultPreferences ) ;
449
+ }
450
+ }
484
451
}
485
452
486
453
/// <summary>
@@ -522,22 +489,6 @@ private Dictionary<string, string> ReadExistingPreferences()
522
489
return prefs ;
523
490
}
524
491
525
- /// <summary>
526
- /// Writes the specified preferences to the user preferences file.
527
- /// </summary>
528
- /// <param name="preferences">A <see cref="Dictionary{K, V}"/> containing key-value pairs
529
- /// representing the preferences to write.</param>
530
- private void WriteNewPreferences ( Dictionary < string , string > preferences )
531
- {
532
- using ( TextWriter writer = File . CreateText ( Path . Combine ( this . profileDir , UserPreferencesFileName ) ) )
533
- {
534
- foreach ( string prefKey in preferences . Keys )
535
- {
536
- writer . WriteLine ( string . Format ( CultureInfo . InvariantCulture , "user_pref(\" {0}\" , {1});" , prefKey , preferences [ prefKey ] ) ) ;
537
- }
538
- }
539
- }
540
-
541
492
/// <summary>
542
493
/// Sets a preference for a manually specified proxy.
543
494
/// </summary>
0 commit comments