@@ -35,7 +35,7 @@ namespace OpenQA.Selenium.Firefox
35
35
/// </summary>
36
36
/// <remarks>The <see cref="FirefoxBinary"/> class is responsible for instantiating the
37
37
/// Firefox process, and the operating system environment in which it runs.</remarks>
38
- public class FirefoxBinary
38
+ public class FirefoxBinary : IDisposable
39
39
{
40
40
#region Constants
41
41
private const string NoFocusLibraryName = "x_ignore_nofocus.so" ;
@@ -46,6 +46,7 @@ public class FirefoxBinary
46
46
private Executable executable ;
47
47
private Process process ;
48
48
private TimeSpan timeout = TimeSpan . FromSeconds ( 45 ) ;
49
+ private bool isDisposed = false ;
49
50
#endregion
50
51
51
52
#region Constructors
@@ -140,28 +141,28 @@ public void StartProfile(FirefoxProfile profile, params string[] commandLineArgu
140
141
commandLineArgs . Append ( " " ) . Append ( commandLineArg ) ;
141
142
}
142
143
143
- Process builder = new Process ( ) ;
144
- builder . StartInfo . FileName = this . BinaryExecutable . ExecutablePath ;
145
- builder . StartInfo . Arguments = commandLineArgs . ToString ( ) ;
146
- builder . StartInfo . UseShellExecute = false ;
144
+ this . process = new Process ( ) ;
145
+ this . process . StartInfo . FileName = this . BinaryExecutable . ExecutablePath ;
146
+ this . process . StartInfo . Arguments = commandLineArgs . ToString ( ) ;
147
+ this . process . StartInfo . UseShellExecute = false ;
147
148
148
149
foreach ( string environmentVar in this . extraEnv . Keys )
149
150
{
150
- if ( builder . StartInfo . EnvironmentVariables . ContainsKey ( environmentVar ) )
151
+ if ( this . process . StartInfo . EnvironmentVariables . ContainsKey ( environmentVar ) )
151
152
{
152
- builder . StartInfo . EnvironmentVariables [ environmentVar ] = this . extraEnv [ environmentVar ] ;
153
+ this . process . StartInfo . EnvironmentVariables [ environmentVar ] = this . extraEnv [ environmentVar ] ;
153
154
}
154
155
else
155
156
{
156
- builder . StartInfo . EnvironmentVariables . Add ( environmentVar , this . extraEnv [ environmentVar ] ) ;
157
+ this . process . StartInfo . EnvironmentVariables . Add ( environmentVar , this . extraEnv [ environmentVar ] ) ;
157
158
}
158
159
}
159
160
160
- this . BinaryExecutable . SetLibraryPath ( builder ) ;
161
+ this . BinaryExecutable . SetLibraryPath ( this . process ) ;
161
162
162
- this . StartFirefoxProcess ( builder ) ;
163
+ this . StartFirefoxProcess ( ) ;
163
164
164
- this . CopeWithTheStrangenessOfTheMac ( builder ) ;
165
+ this . CopeWithTheStrangenessOfTheMac ( ) ;
165
166
}
166
167
167
168
/// <summary>
@@ -186,21 +187,6 @@ public void SetEnvironmentProperty(string propertyName, string value)
186
187
}
187
188
}
188
189
189
- /// <summary>
190
- /// Creates a named profile for Firefox.
191
- /// </summary>
192
- /// <param name="profileName">The name of the profile to create.</param>
193
- [ SecurityPermission ( SecurityAction . Demand ) ]
194
- public void CreateProfile ( string profileName )
195
- {
196
- Process builder = new Process ( ) ;
197
- builder . StartInfo . FileName = this . executable . ExecutablePath ;
198
- builder . StartInfo . Arguments = "--verbose -CreateProfile " + profileName ;
199
- builder . StartInfo . EnvironmentVariables . Add ( "MOZ_NO_REMOTE" , "1" ) ;
200
-
201
- this . StartFirefoxProcess ( builder ) ;
202
- }
203
-
204
190
/// <summary>
205
191
/// Waits for the process to complete execution.
206
192
/// </summary>
@@ -211,30 +197,12 @@ public void WaitForProcessExit()
211
197
}
212
198
213
199
/// <summary>
214
- /// Stops the execution of this <see cref="FirefoxBinary"/>, terminating the process if necessary .
200
+ /// Releases all resources used by the <see cref="FirefoxBinary"/>.
215
201
/// </summary>
216
- [ SecurityPermission ( SecurityAction . Demand ) ]
217
- public void Quit ( )
202
+ public void Dispose ( )
218
203
{
219
- // Suicide watch: First, a second to see if the process will die on
220
- // it's own (we will likely have asked the process to kill itself just
221
- // before calling this method).
222
- if ( this . process != null )
223
- {
224
- if ( ! this . process . HasExited )
225
- {
226
- System . Threading . Thread . Sleep ( 1000 ) ;
227
- }
228
-
229
- // Murder option: The process is still alive, so kill it.
230
- if ( ! this . process . HasExited )
231
- {
232
- this . process . Kill ( ) ;
233
- }
234
-
235
- this . process . Dispose ( ) ;
236
- this . process = null ;
237
- }
204
+ this . Dispose ( true ) ;
205
+ GC . SuppressFinalize ( this ) ;
238
206
}
239
207
240
208
/// <summary>
@@ -249,17 +217,48 @@ public override string ToString()
249
217
/// <summary>
250
218
/// Starts the Firefox process.
251
219
/// </summary>
252
- /// <param name="builder">A <see cref="Process"/> object used to start Firefox.</param>
253
220
[ SecurityPermission ( SecurityAction . Demand ) ]
254
- protected void StartFirefoxProcess ( Process builder )
221
+ protected void StartFirefoxProcess ( )
222
+ {
223
+ this . process . Start ( ) ;
224
+ }
225
+
226
+ /// <summary>
227
+ /// Releases the unmanaged resources used by the <see cref="FirefoxBinary"/> and optionally
228
+ /// releases the managed resources.
229
+ /// </summary>
230
+ /// <param name="disposing"><see langword="true"/> to release managed and resources;
231
+ /// <see langword="false"/> to only release unmanaged resources.</param>
232
+ [ SecurityPermission ( SecurityAction . Demand ) ]
233
+ protected virtual void Dispose ( bool disposing )
255
234
{
256
- if ( builder == null )
235
+ if ( ! this . isDisposed )
257
236
{
258
- throw new ArgumentNullException ( "builder" , "builder cannot be null" ) ;
259
- }
237
+ if ( disposing )
238
+ {
239
+ // Suicide watch: First, a second to see if the process will die on
240
+ // it's own (we will likely have asked the process to kill itself just
241
+ // before calling this method).
242
+ if ( this . process != null )
243
+ {
244
+ if ( ! this . process . HasExited )
245
+ {
246
+ System . Threading . Thread . Sleep ( 1000 ) ;
247
+ }
260
248
261
- this . process = builder ;
262
- this . process . Start ( ) ;
249
+ // Murder option: The process is still alive, so kill it.
250
+ if ( ! this . process . HasExited )
251
+ {
252
+ this . process . Kill ( ) ;
253
+ }
254
+
255
+ this . process . Dispose ( ) ;
256
+ this . process = null ;
257
+ }
258
+ }
259
+
260
+ this . isDisposed = true ;
261
+ }
263
262
}
264
263
265
264
private static void Sleep ( int timeInMilliseconds )
@@ -343,7 +342,7 @@ private void ModifyLinkLibraryPath(FirefoxProfile profile)
343
342
}
344
343
345
344
[ SecurityPermission ( SecurityAction . Demand ) ]
346
- private void CopeWithTheStrangenessOfTheMac ( Process builder )
345
+ private void CopeWithTheStrangenessOfTheMac ( )
347
346
{
348
347
if ( Platform . CurrentPlatform . IsPlatformType ( PlatformType . Mac ) )
349
348
{
@@ -363,7 +362,7 @@ private void CopeWithTheStrangenessOfTheMac(Process builder)
363
362
// TODO(simon): This is utterly bogus. We should do something far smarter
364
363
System . Threading . Thread . Sleep ( 10000 ) ;
365
364
366
- this . StartFirefoxProcess ( builder ) ;
365
+ this . StartFirefoxProcess ( ) ;
367
366
}
368
367
catch ( ThreadStateException )
369
368
{
@@ -382,7 +381,7 @@ private void CopeWithTheStrangenessOfTheMac(Process builder)
382
381
383
382
StringBuilder message = new StringBuilder ( "Unable to start firefox cleanly.\n " ) ;
384
383
message . Append ( "Exit value: " ) . Append ( this . process . ExitCode . ToString ( CultureInfo . InvariantCulture ) ) . Append ( "\n " ) ;
385
- message . Append ( "Ran from: " ) . Append ( builder . StartInfo . FileName ) . Append ( "\n " ) ;
384
+ message . Append ( "Ran from: " ) . Append ( this . process . StartInfo . FileName ) . Append ( "\n " ) ;
386
385
throw new WebDriverException ( message . ToString ( ) ) ;
387
386
}
388
387
catch ( ThreadStateException )
0 commit comments