Skip to content

Commit f96df28

Browse files
committed
[js] Do not hold command handle in the firefox.Binary class
This allows a single firefox.Binary instance to configure and launch multiple Firefox processes. Fixes #1116
1 parent 55715c9 commit f96df28

File tree

4 files changed

+67
-51
lines changed

4 files changed

+67
-51
lines changed

javascript/node/selenium-webdriver/CHANGES.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
## v2.48.0-dev
22

3+
* FIXED: a single `firefox.Binary` instance may be used to configure and
4+
launch multiple FirefoxDriver sessions.
5+
6+
var binary = new firefox.Binary();
7+
var options = new firefox.Options().setBinary(binary);
8+
var builder = new Builder().setFirefoxOptions(options);
9+
10+
var driver1 = builder.build();
11+
var driver2 = builder.build();
12+
313
* FIXED: zip files created for transfer to a remote WebDriver server are no
414
longer compressed. If the zip contained a file that was already compressed,
515
the server would return an "invalid code lengths set" error.

javascript/node/selenium-webdriver/firefox/binary.js

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ function installNoFocusLibs(profileDir) {
133133

134134

135135
/**
136-
* Manages a Firefox subprocess configured for use with WebDriver.
136+
* Provides a mechanism to configure and launch Firefox in a subprocess for
137+
* use with WebDriver.
137138
*
138139
* @param {string=} opt_exe Path to the Firefox binary to use. If not
139140
* specified, will attempt to locate Firefox on the current system.
@@ -157,9 +158,6 @@ var Binary = function(opt_exe) {
157158
this.env_['MOZ_CRASHREPORTER_DISABLE'] = '1';
158159
this.env_['MOZ_NO_REMOTE'] = '1';
159160
this.env_['NO_EM_RESTART'] = '1';
160-
161-
/** @private {promise.Promise.<!exec.Command>} */
162-
this.command_ = null;
163161
};
164162
util.inherits(Binary, Serializable);
165163

@@ -181,11 +179,11 @@ Binary.prototype.addArguments = function(var_args) {
181179

182180

183181
/**
184-
* Launches Firefox and eturns a promise that will be fulfilled when the process
185-
* terminates.
182+
* Launches Firefox and returns a promise that will be fulfilled when the
183+
* process terminates.
186184
* @param {string} profile Path to the profile directory to use.
187-
* @return {!promise.Promise.<!exec.Result>} A promise for the process result.
188-
* @throws {Error} If this instance has already been started.
185+
* @return {!promise.Promise.<!exec.Command>} A promise for the handle to the
186+
* started subprocess.
189187
*/
190188
Binary.prototype.launch = function(profile) {
191189
if (this.command_) {
@@ -200,7 +198,7 @@ Binary.prototype.launch = function(profile) {
200198

201199
var args = ['-foreground'].concat(this.args_);
202200

203-
this.command_ = promise.when(this.exe_ || findFirefox(), function(firefox) {
201+
return promise.when(this.exe_ || findFirefox(), function(firefox) {
204202
if (process.platform === 'win32' || process.platform === 'darwin') {
205203
return exec(firefox, {args: args, env: env});
206204
}
@@ -210,26 +208,6 @@ Binary.prototype.launch = function(profile) {
210208
return exec(firefox, {args: args, env: env});
211209
});
212210
});
213-
214-
return this.command_.then(function() {
215-
// Don't return the actual command handle, just a promise to signal it has
216-
// been started.
217-
});
218-
};
219-
220-
221-
/**
222-
* Kills the managed Firefox process.
223-
* @return {!promise.Promise} A promise for when the process has terminated.
224-
*/
225-
Binary.prototype.kill = function() {
226-
if (!this.command_) {
227-
return promise.defer(); // Not running.
228-
}
229-
return this.command_.then(function(command) {
230-
command.kill();
231-
return command.result();
232-
});
233211
};
234212

235213

javascript/node/selenium-webdriver/firefox/index.js

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -239,39 +239,40 @@ var Driver = function(opt_config, opt_flow) {
239239
/** @private {?string} */
240240
this.profilePath_ = null;
241241

242-
/** @private {!Binary} */
243-
this.binary_ = binary;
244-
245242
var self = this;
246-
var serverUrl = portprober.findFreePort().then(function(port) {
247-
var prepareProfile;
243+
var freePort = portprober.findFreePort();
244+
245+
/** @private */
246+
this.command_ = freePort.then(function(port) {
248247
if (typeof profile === 'string') {
249-
prepareProfile = decodeProfile(profile).then(function(dir) {
248+
return decodeProfile(profile).then(function(dir) {
250249
var profile = new Profile(dir);
251250
profile.setPreference('webdriver_firefox_port', port);
252251
return profile.writeToDisk();
253252
});
254253
} else {
255254
profile.setPreference('webdriver_firefox_port', port);
256-
prepareProfile = profile.writeToDisk();
255+
return profile.writeToDisk();
257256
}
257+
}).then(function(profileDir) {
258+
self.profilePath_ = profileDir;
259+
return binary.launch(profileDir);
260+
});
258261

259-
return prepareProfile.then(function(dir) {
260-
self.profilePath_ = dir;
261-
return binary.launch(dir);
262-
}).then(function() {
263-
var serverUrl = url.format({
264-
protocol: 'http',
265-
hostname: net.getLoopbackAddress(),
266-
port: port,
267-
pathname: '/hub'
268-
});
262+
var serverUrl = this.command_
263+
.then(function() { return freePort; })
264+
.then(function(port) {
265+
var serverUrl = url.format({
266+
protocol: 'http',
267+
hostname: net.getLoopbackAddress(),
268+
port: port,
269+
pathname: '/hub'
270+
});
269271

270-
return httpUtil.waitForServer(serverUrl, 45 * 1000).then(function() {
271-
return serverUrl;
272+
return httpUtil.waitForServer(serverUrl, 45 * 1000).then(function() {
273+
return serverUrl;
274+
});
272275
});
273-
});
274-
});
275276

276277
var executor = executors.createExecutor(serverUrl);
277278
var driver = webdriver.WebDriver.createSession(executor, caps, opt_flow);
@@ -296,7 +297,10 @@ Driver.prototype.quit = function() {
296297
var self = this;
297298
return Driver.super_.prototype.quit.call(this)
298299
.thenFinally(function() {
299-
return self.binary_.kill();
300+
return self.command_.then(function(command) {
301+
command.kill();
302+
return command.result();
303+
});
300304
})
301305
.thenFinally(function() {
302306
if (self.profilePath_) {

javascript/node/selenium-webdriver/test/firefox/firefox_test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,5 +155,29 @@ test.suite(function(env) {
155155
});
156156
});
157157
});
158+
159+
describe('binary management', function() {
160+
var driver1, driver2;
161+
162+
test.ignore(env.isRemote).
163+
it('can start multiple sessions with single binary instance', function() {
164+
var options = new firefox.Options().setBinary(new firefox.Binary);
165+
env.builder().setFirefoxOptions(options);
166+
driver1 = env.builder().build();
167+
driver2 = env.builder().build();
168+
// Ok if this doesn't fail.
169+
});
170+
171+
test.afterEach(function() {
172+
if (driver1) {
173+
driver1.quit();
174+
}
175+
176+
if (driver2) {
177+
driver2.quit();
178+
}
179+
});
180+
});
181+
158182
});
159183
}, {browsers: ['firefox']});

0 commit comments

Comments
 (0)