chrome.js

1// Copyright 2013 Selenium committers
2// Copyright 2013 Software Freedom Conservancy
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16/**
17 * @fileoverview Defines a {@linkplain Driver WebDriver} client for the Chrome
18 * web browser. Before using this module, you must download the latest
19 * [ChromeDriver release] and ensure it can be found on your system [PATH].
20 *
21 * There are three primary classes exported by this module:
22 *
23 * 1. {@linkplain ServiceBuilder}: configures the
24 * {@link selenium-webdriver/remote.DriverService remote.DriverService}
25 * that manages the [ChromeDriver] child process.
26 *
27 * 2. {@linkplain Options}: defines configuration options for each new Chrome
28 * session, such as which {@linkplain Options#setProxy proxy} to use,
29 * what {@linkplain Options#addExtensions extensions} to install, or
30 * what {@linkplain Options#addArguments command-line switches} to use when
31 * starting the browser.
32 *
33 * 3. {@linkplain Driver}: the WebDriver client; each new instance will control
34 * a unique browser session with a clean user profile (unless otherwise
35 * configured through the {@link Options} class).
36 *
37 * __Customizing the ChromeDriver Server__ <a id="custom-server"></a>
38 *
39 * By default, every Chrome session will use a single driver service, which is
40 * started the first time a {@link Driver} instance is created and terminated
41 * when this process exits. The default service will inherit its environment
42 * from the current process and direct all output to /dev/null. You may obtain
43 * a handle to this default service using
44 * {@link #getDefaultService getDefaultService()} and change its configuration
45 * with {@link #setDefaultService setDefaultService()}.
46 *
47 * You may also create a {@link Driver} with its own driver service. This is
48 * useful if you need to capture the server's log output for a specific session:
49 *
50 * var chrome = require('selenium-webdriver/chrome');
51 *
52 * var service = new chrome.ServiceBuilder()
53 * .loggingTo('/my/log/file.txt')
54 * .enableVerboseLogging()
55 * .build();
56 *
57 * var options = new chrome.Options();
58 * // configure browser options ...
59 *
60 * var driver = new chrome.Driver(options, service);
61 *
62 * Users should only instantiate the {@link Driver} class directly when they
63 * need a custom driver service configuration (as shown above). For normal
64 * operation, users should start Chrome using the
65 * {@link selenium-webdriver.Builder}.
66 *
67 * __Working with Android__ <a id="android"></a>
68 *
69 * The [ChromeDriver][android] supports running tests on the Chrome browser as
70 * well as [WebView apps][webview] starting in Android 4.4 (KitKat). In order to
71 * work with Android, you must first start the adb
72 *
73 * adb start-server
74 *
75 * By default, adb will start on port 5037. You may change this port, but this
76 * will require configuring a [custom server](#custom-server) that will connect
77 * to adb on the {@linkplain ServiceBuilder#setAdbPort correct port}:
78 *
79 * var service = new chrome.ServiceBuilder()
80 * .setAdbPort(1234)
81 * build();
82 * // etc.
83 *
84 * The ChromeDriver may be configured to launch Chrome on Android using
85 * {@link Options#androidChrome()}:
86 *
87 * var driver = new Builder()
88 * .forBrowser('chrome')
89 * .setChromeOptions(new chrome.Options().androidChrome())
90 * .build();
91 *
92 * Alternatively, you can configure the ChromeDriver to launch an app with a
93 * Chrome-WebView by setting the {@linkplain Options#androidActivity
94 * androidActivity} option:
95 *
96 * var driver = new Builder()
97 * .forBrowser('chrome')
98 * .setChromeOptions(new chrome.Options()
99 * .androidPackage('com.example')
100 * .androidActivity('com.example.Activity'))
101 * .build();
102 *
103 * Refer to the ChromeDriver site] for more information on using the
104 * [ChromeDriver with Android][android].
105 *
106 * [ChromeDriver]: https://sites.google.com/a/chromium.org/chromedriver/
107 * [ChromeDriver release]: http://chromedriver.storage.googleapis.com/index.html
108 * [PATH]: http://en.wikipedia.org/wiki/PATH_%28variable%29
109 * [android]: https://sites.google.com/a/chromium.org/chromedriver/getting-started/getting-started---android
110 * [webview]: https://developer.chrome.com/multidevice/webview/overview
111 */
112
113'use strict';
114
115var fs = require('fs'),
116 util = require('util');
117
118var webdriver = require('./index'),
119 executors = require('./executors'),
120 io = require('./io'),
121 portprober = require('./net/portprober'),
122 remote = require('./remote');
123
124
125/**
126 * Name of the ChromeDriver executable.
127 * @type {string}
128 * @const
129 */
130var CHROMEDRIVER_EXE =
131 process.platform === 'win32' ? 'chromedriver.exe' : 'chromedriver';
132
133
134/**
135 * Creates {@link selenium-webdriver/remote.DriverService} instances that manage
136 * a [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/)
137 * server in a child process.
138 *
139 * @param {string=} opt_exe Path to the server executable to use. If omitted,
140 * the builder will attempt to locate the chromedriver on the current
141 * PATH.
142 * @throws {Error} If provided executable does not exist, or the chromedriver
143 * cannot be found on the PATH.
144 * @constructor
145 */
146var ServiceBuilder = function(opt_exe) {
147 /** @private {string} */
148 this.exe_ = opt_exe || io.findInPath(CHROMEDRIVER_EXE, true);
149 if (!this.exe_) {
150 throw Error(
151 'The ChromeDriver could not be found on the current PATH. Please ' +
152 'download the latest version of the ChromeDriver from ' +
153 'http://chromedriver.storage.googleapis.com/index.html and ensure ' +
154 'it can be found on your PATH.');
155 }
156
157 if (!fs.existsSync(this.exe_)) {
158 throw Error('File does not exist: ' + this.exe_);
159 }
160
161 /** @private {!Array.<string>} */
162 this.args_ = [];
163 this.stdio_ = 'ignore';
164};
165
166
167/** @private {number} */
168ServiceBuilder.prototype.port_ = 0;
169
170
171/** @private {(string|!Array.<string|number|!Stream|null|undefined>)} */
172ServiceBuilder.prototype.stdio_ = 'ignore';
173
174
175/** @private {Object.<string, string>} */
176ServiceBuilder.prototype.env_ = null;
177
178
179/**
180 * Sets the port to start the ChromeDriver on.
181 * @param {number} port The port to use, or 0 for any free port.
182 * @return {!ServiceBuilder} A self reference.
183 * @throws {Error} If the port is invalid.
184 */
185ServiceBuilder.prototype.usingPort = function(port) {
186 if (port < 0) {
187 throw Error('port must be >= 0: ' + port);
188 }
189 this.port_ = port;
190 return this;
191};
192
193
194/**
195 * Sets which port adb is listening to. _The ChromeDriver will connect to adb
196 * if an {@linkplain Options#androidPackage Android session} is requested, but
197 * adb **must** be started beforehand._
198 *
199 * @param {number} port Which port adb is running on.
200 * @return {!ServiceBuilder} A self reference.
201 */
202ServiceBuilder.prototype.setAdbPort = function(port) {
203 this.args_.push('--adb-port=' + port);
204 return this;
205};
206
207
208/**
209 * Sets the path of the log file the driver should log to. If a log file is
210 * not specified, the driver will log to stderr.
211 * @param {string} path Path of the log file to use.
212 * @return {!ServiceBuilder} A self reference.
213 */
214ServiceBuilder.prototype.loggingTo = function(path) {
215 this.args_.push('--log-path=' + path);
216 return this;
217};
218
219
220/**
221 * Enables verbose logging.
222 * @return {!ServiceBuilder} A self reference.
223 */
224ServiceBuilder.prototype.enableVerboseLogging = function() {
225 this.args_.push('--verbose');
226 return this;
227};
228
229
230/**
231 * Sets the number of threads the driver should use to manage HTTP requests.
232 * By default, the driver will use 4 threads.
233 * @param {number} n The number of threads to use.
234 * @return {!ServiceBuilder} A self reference.
235 */
236ServiceBuilder.prototype.setNumHttpThreads = function(n) {
237 this.args_.push('--http-threads=' + n);
238 return this;
239};
240
241
242/**
243 * Sets the base path for WebDriver REST commands (e.g. "/wd/hub").
244 * By default, the driver will accept commands relative to "/".
245 * @param {string} path The base path to use.
246 * @return {!ServiceBuilder} A self reference.
247 */
248ServiceBuilder.prototype.setUrlBasePath = function(path) {
249 this.args_.push('--url-base=' + path);
250 return this;
251};
252
253
254/**
255 * Defines the stdio configuration for the driver service. See
256 * {@code child_process.spawn} for more information.
257 * @param {(string|!Array.<string|number|!Stream|null|undefined>)} config The
258 * configuration to use.
259 * @return {!ServiceBuilder} A self reference.
260 */
261ServiceBuilder.prototype.setStdio = function(config) {
262 this.stdio_ = config;
263 return this;
264};
265
266
267/**
268 * Defines the environment to start the server under. This settings will be
269 * inherited by every browser session started by the server.
270 * @param {!Object.<string, string>} env The environment to use.
271 * @return {!ServiceBuilder} A self reference.
272 */
273ServiceBuilder.prototype.withEnvironment = function(env) {
274 this.env_ = env;
275 return this;
276};
277
278
279/**
280 * Creates a new DriverService using this instance's current configuration.
281 * @return {remote.DriverService} A new driver service using this instance's
282 * current configuration.
283 * @throws {Error} If the driver exectuable was not specified and a default
284 * could not be found on the current PATH.
285 */
286ServiceBuilder.prototype.build = function() {
287 var port = this.port_ || portprober.findFreePort();
288 var args = this.args_.concat(); // Defensive copy.
289
290 return new remote.DriverService(this.exe_, {
291 loopback: true,
292 port: port,
293 args: webdriver.promise.when(port, function(port) {
294 return args.concat('--port=' + port);
295 }),
296 env: this.env_,
297 stdio: this.stdio_
298 });
299};
300
301
302/** @type {remote.DriverService} */
303var defaultService = null;
304
305
306/**
307 * Sets the default service to use for new ChromeDriver instances.
308 * @param {!remote.DriverService} service The service to use.
309 * @throws {Error} If the default service is currently running.
310 */
311function setDefaultService(service) {
312 if (defaultService && defaultService.isRunning()) {
313 throw Error(
314 'The previously configured ChromeDriver service is still running. ' +
315 'You must shut it down before you may adjust its configuration.');
316 }
317 defaultService = service;
318}
319
320
321/**
322 * Returns the default ChromeDriver service. If such a service has not been
323 * configured, one will be constructed using the default configuration for
324 * a ChromeDriver executable found on the system PATH.
325 * @return {!remote.DriverService} The default ChromeDriver service.
326 */
327function getDefaultService() {
328 if (!defaultService) {
329 defaultService = new ServiceBuilder().build();
330 }
331 return defaultService;
332}
333
334
335/**
336 * @type {string}
337 * @const
338 */
339var OPTIONS_CAPABILITY_KEY = 'chromeOptions';
340
341
342/**
343 * Class for managing ChromeDriver specific options.
344 * @constructor
345 * @extends {webdriver.Serializable}
346 */
347var Options = function() {
348 webdriver.Serializable.call(this);
349
350 /** @private {!Object} */
351 this.options_ = {};
352
353 /** @private {!Array.<(string|!Buffer)>} */
354 this.extensions_ = [];
355
356 /** @private {?webdriver.logging.Preferences} */
357 this.logPrefs_ = null;
358
359 /** @private {?webdriver.ProxyConfig} */
360 this.proxy_ = null;
361};
362util.inherits(Options, webdriver.Serializable);
363
364
365/**
366 * Extracts the ChromeDriver specific options from the given capabilities
367 * object.
368 * @param {!webdriver.Capabilities} capabilities The capabilities object.
369 * @return {!Options} The ChromeDriver options.
370 */
371Options.fromCapabilities = function(capabilities) {
372 var options = new Options();
373
374 var o = capabilities.get(OPTIONS_CAPABILITY_KEY);
375 if (o instanceof Options) {
376 options = o;
377 } else if (o) {
378 options.
379 addArguments(o.args || []).
380 addExtensions(o.extensions || []).
381 detachDriver(o.detach).
382 excludeSwitches(o.excludeSwitches || []).
383 setChromeBinaryPath(o.binary).
384 setChromeLogFile(o.logPath).
385 setChromeMinidumpPath(o.minidumpPath).
386 setLocalState(o.localState).
387 setMobileEmulation(o.mobileEmulation).
388 setUserPreferences(o.prefs).
389 setPerfLoggingPrefs(o.perfLoggingPrefs);
390 }
391
392 if (capabilities.has(webdriver.Capability.PROXY)) {
393 options.setProxy(capabilities.get(webdriver.Capability.PROXY));
394 }
395
396 if (capabilities.has(webdriver.Capability.LOGGING_PREFS)) {
397 options.setLoggingPrefs(
398 capabilities.get(webdriver.Capability.LOGGING_PREFS));
399 }
400
401 return options;
402};
403
404
405/**
406 * Add additional command line arguments to use when launching the Chrome
407 * browser. Each argument may be specified with or without the "--" prefix
408 * (e.g. "--foo" and "foo"). Arguments with an associated value should be
409 * delimited by an "=": "foo=bar".
410 * @param {...(string|!Array.<string>)} var_args The arguments to add.
411 * @return {!Options} A self reference.
412 */
413Options.prototype.addArguments = function(var_args) {
414 var args = this.options_.args || [];
415 args = args.concat.apply(args, arguments);
416 if (args.length) {
417 this.options_.args = args;
418 }
419 return this;
420};
421
422
423/**
424 * List of Chrome command line switches to exclude that ChromeDriver by default
425 * passes when starting Chrome. Do not prefix switches with "--".
426 *
427 * @param {...(string|!Array<string>)} var_args The switches to exclude.
428 * @return {!Options} A self reference.
429 */
430Options.prototype.excludeSwitches = function(var_args) {
431 var switches = this.options_.excludeSwitches || [];
432 switches = switches.concat.apply(switches, arguments);
433 if (switches.length) {
434 this.options_.excludeSwitches = switches;
435 }
436 return this;
437};
438
439
440/**
441 * Add additional extensions to install when launching Chrome. Each extension
442 * should be specified as the path to the packed CRX file, or a Buffer for an
443 * extension.
444 * @param {...(string|!Buffer|!Array.<(string|!Buffer)>)} var_args The
445 * extensions to add.
446 * @return {!Options} A self reference.
447 */
448Options.prototype.addExtensions = function(var_args) {
449 this.extensions_ = this.extensions_.concat.apply(this.extensions_, arguments);
450 return this;
451};
452
453
454/**
455 * Sets the path to the Chrome binary to use. On Mac OS X, this path should
456 * reference the actual Chrome executable, not just the application binary
457 * (e.g. "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome").
458 *
459 * The binary path be absolute or relative to the chromedriver server
460 * executable, but it must exist on the machine that will launch Chrome.
461 *
462 * @param {string} path The path to the Chrome binary to use.
463 * @return {!Options} A self reference.
464 */
465Options.prototype.setChromeBinaryPath = function(path) {
466 this.options_.binary = path;
467 return this;
468};
469
470
471/**
472 * Sets whether to leave the started Chrome browser running if the controlling
473 * ChromeDriver service is killed before {@link webdriver.WebDriver#quit()} is
474 * called.
475 * @param {boolean} detach Whether to leave the browser running if the
476 * chromedriver service is killed before the session.
477 * @return {!Options} A self reference.
478 */
479Options.prototype.detachDriver = function(detach) {
480 this.options_.detach = detach;
481 return this;
482};
483
484
485/**
486 * Sets the user preferences for Chrome's user profile. See the "Preferences"
487 * file in Chrome's user data directory for examples.
488 * @param {!Object} prefs Dictionary of user preferences to use.
489 * @return {!Options} A self reference.
490 */
491Options.prototype.setUserPreferences = function(prefs) {
492 this.options_.prefs = prefs;
493 return this;
494};
495
496
497/**
498 * Sets the logging preferences for the new session.
499 * @param {!webdriver.logging.Preferences} prefs The logging preferences.
500 * @return {!Options} A self reference.
501 */
502Options.prototype.setLoggingPrefs = function(prefs) {
503 this.logPrefs_ = prefs;
504 return this;
505};
506
507
508/**
509 * Sets the performance logging preferences. Options include:
510 *
511 * - `enableNetwork`: Whether or not to collect events from Network domain.
512 * - `enablePage`: Whether or not to collect events from Page domain.
513 * - `enableTimeline`: Whether or not to collect events from Timeline domain.
514 * Note: when tracing is enabled, Timeline domain is implicitly disabled,
515 * unless `enableTimeline` is explicitly set to true.
516 * - `tracingCategories`: A comma-separated string of Chrome tracing categories
517 * for which trace events should be collected. An unspecified or empty
518 * string disables tracing.
519 * - `bufferUsageReportingInterval`: The requested number of milliseconds
520 * between DevTools trace buffer usage events. For example, if 1000, then
521 * once per second, DevTools will report how full the trace buffer is. If a
522 * report indicates the buffer usage is 100%, a warning will be issued.
523 *
524 * @param {{enableNetwork: boolean,
525 * enablePage: boolean,
526 * enableTimeline: boolean,
527 * tracingCategories: string,
528 * bufferUsageReportingInterval: number}} prefs The performance
529 * logging preferences.
530 * @return {!Options} A self reference.
531 */
532Options.prototype.setPerfLoggingPrefs = function(prefs) {
533 this.options_.perfLoggingPrefs = prefs;
534 return this;
535};
536
537
538/**
539 * Sets preferences for the "Local State" file in Chrome's user data
540 * directory.
541 * @param {!Object} state Dictionary of local state preferences.
542 * @return {!Options} A self reference.
543 */
544Options.prototype.setLocalState = function(state) {
545 this.options_.localState = state;
546 return this;
547};
548
549
550/**
551 * Sets the name of the activity hosting a Chrome-based Android WebView. This
552 * option must be set to connect to an [Android WebView](
553 * https://sites.google.com/a/chromium.org/chromedriver/getting-started/getting-started---android)
554 *
555 * @param {string} name The activity name.
556 * @return {!Options} A self reference.
557 */
558Options.prototype.androidActivity = function(name) {
559 this.options_.androidActivity = name;
560 return this;
561};
562
563
564/**
565 * Sets the device serial number to connect to via ADB. If not specified, the
566 * ChromeDriver will select an unused device at random. An error will be
567 * returned if all devices already have active sessions.
568 *
569 * @param {string} serial The device serial number to connect to.
570 * @return {!Options} A self reference.
571 */
572Options.prototype.androidDeviceSerial = function(serial) {
573 this.options_.androidDeviceSerial = serial;
574 return this;
575};
576
577
578/**
579 * Configures the ChromeDriver to launch Chrome on Android via adb. This
580 * function is shorthand for
581 * {@link #androidPackage options.androidPackage('com.android.chrome')}.
582 * @return {!Options} A self reference.
583 */
584Options.prototype.androidChrome = function() {
585 return this.androidPackage('com.android.chrome');
586};
587
588
589/**
590 * Sets the package name of the Chrome or WebView app.
591 *
592 * @param {?string} pkg The package to connect to, or `null` to disable Android
593 * and switch back to using desktop Chrome.
594 * @return {!Options} A self reference.
595 */
596Options.prototype.androidPackage = function(pkg) {
597 this.options_.androidPackage = pkg;
598 return this;
599};
600
601
602/**
603 * Sets the process name of the Activity hosting the WebView (as given by `ps`).
604 * If not specified, the process name is assumed to be the same as
605 * {@link #androidPackage}.
606 *
607 * @param {string} processName The main activity name.
608 * @return {!Options} A self reference.
609 */
610Options.prototype.androidProcess = function(processName) {
611 this.options_.androidProcess = pkg;
612 return this;
613};
614
615
616/**
617 * Sets whether to connect to an already-running instead of the specified
618 * {@linkplain #androidProcess app} instead of launching the app with a clean
619 * data directory.
620 *
621 * @param {boolean} useRunning Whether to connect to a running instance.
622 * @return {!Options} A self reference.
623 */
624Options.prototype.androidUseRunningApp = function(useRunning) {
625 this.options_.androidUseRunningApp = useRunning;
626 return this;
627};
628
629
630/**
631 * Sets the path to Chrome's log file. This path should exist on the machine
632 * that will launch Chrome.
633 * @param {string} path Path to the log file to use.
634 * @return {!Options} A self reference.
635 */
636Options.prototype.setChromeLogFile = function(path) {
637 this.options_.logPath = path;
638 return this;
639};
640
641
642/**
643 * Sets the directory to store Chrome minidumps in. This option is only
644 * supported when ChromeDriver is running on Linux.
645 * @param {string} path The directory path.
646 * @return {!Options} A self reference.
647 */
648Options.prototype.setChromeMinidumpPath = function(path) {
649 this.options_.minidumpPath = path;
650 return this;
651};
652
653
654/**
655 * Configures Chrome to emulate a mobile device. For more information, refer to
656 * the ChromeDriver project page on [mobile emulation][em]. Configuration
657 * options include:
658 *
659 * - `deviceName`: The name of a pre-configured [emulated device][devem]
660 * - `width`: screen width, in pixels
661 * - `height`: screen height, in pixels
662 * - `pixelRatio`: screen pixel ratio
663 *
664 * __Example 1: Using a Pre-configured Device__
665 *
666 * var options = new chrome.Options().setMobileEmulation(
667 * {deviceName: 'Google Nexus 5'});
668 *
669 * var driver = new chrome.Driver(options);
670 *
671 * __Example 2: Using Custom Screen Configuration__
672 *
673 * var options = new chrome.Options().setMobileEmulation({
674 * width: 360,
675 * height: 640,
676 * pixelRatio: 3.0
677 * });
678 *
679 * var driver = new chrome.Driver(options);
680 *
681 *
682 * [em]: https://sites.google.com/a/chromium.org/chromedriver/mobile-emulation
683 * [devem]: https://developer.chrome.com/devtools/docs/device-mode
684 *
685 * @param {?({deviceName: string}|
686 * {width: number, height: number, pixelRatio: number})} config The
687 * mobile emulation configuration, or `null` to disable emulation.
688 * @return {!Options} A self reference.
689 */
690Options.prototype.setMobileEmulation = function(config) {
691 this.options_.mobileEmulation = config;
692 return this;
693};
694
695
696/**
697 * Sets the proxy settings for the new session.
698 * @param {webdriver.ProxyConfig} proxy The proxy configuration to use.
699 * @return {!Options} A self reference.
700 */
701Options.prototype.setProxy = function(proxy) {
702 this.proxy_ = proxy;
703 return this;
704};
705
706
707/**
708 * Converts this options instance to a {@link webdriver.Capabilities} object.
709 * @param {webdriver.Capabilities=} opt_capabilities The capabilities to merge
710 * these options into, if any.
711 * @return {!webdriver.Capabilities} The capabilities.
712 */
713Options.prototype.toCapabilities = function(opt_capabilities) {
714 var capabilities = opt_capabilities || webdriver.Capabilities.chrome();
715 capabilities.
716 set(webdriver.Capability.PROXY, this.proxy_).
717 set(webdriver.Capability.LOGGING_PREFS, this.logPrefs_).
718 set(OPTIONS_CAPABILITY_KEY, this);
719 return capabilities;
720};
721
722
723/**
724 * Converts this instance to its JSON wire protocol representation. Note this
725 * function is an implementation not intended for general use.
726 * @return {{args: !Array.<string>,
727 * binary: (string|undefined),
728 * detach: boolean,
729 * extensions: !Array.<(string|!webdriver.promise.Promise.<string>)>,
730 * localState: (Object|undefined),
731 * logPath: (string|undefined),
732 * prefs: (Object|undefined)}} The JSON wire protocol representation
733 * of this instance.
734 * @override
735 */
736Options.prototype.serialize = function() {
737 var json = {};
738 for (var key in this.options_) {
739 if (this.options_[key] != null) {
740 json[key] = this.options_[key];
741 }
742 }
743 if (this.extensions_.length) {
744 json.extensions = this.extensions_.map(function(extension) {
745 if (Buffer.isBuffer(extension)) {
746 return extension.toString('base64');
747 }
748 return webdriver.promise.checkedNodeCall(
749 fs.readFile, extension, 'base64');
750 });
751 }
752 return json;
753};
754
755
756/**
757 * Creates a new ChromeDriver session.
758 * @param {(webdriver.Capabilities|Options)=} opt_options The session options.
759 * @param {remote.DriverService=} opt_service The session to use; will use
760 * the {@linkplain #getDefaultService default service} by default.
761 * @param {webdriver.promise.ControlFlow=} opt_flow The control flow to use, or
762 * {@code null} to use the currently active flow.
763 * @return {!webdriver.WebDriver} A new WebDriver instance.
764 * @deprecated Use {@link Driver new Driver()}.
765 */
766function createDriver(opt_options, opt_service, opt_flow) {
767 return new Driver(opt_options, opt_service, opt_flow);
768}
769
770
771/**
772 * Creates a new WebDriver client for Chrome.
773 *
774 * @param {(webdriver.Capabilities|Options)=} opt_config The configuration
775 * options.
776 * @param {remote.DriverService=} opt_service The session to use; will use
777 * the {@linkplain #getDefaultService default service} by default.
778 * @param {webdriver.promise.ControlFlow=} opt_flow The control flow to use, or
779 * {@code null} to use the currently active flow.
780 * @constructor
781 * @extends {webdriver.WebDriver}
782 */
783var Driver = function(opt_config, opt_service, opt_flow) {
784 var service = opt_service || getDefaultService();
785 var executor = executors.createExecutor(service.start());
786
787 var capabilities =
788 opt_config instanceof Options ? opt_config.toCapabilities() :
789 (opt_config || webdriver.Capabilities.chrome());
790
791 var driver = webdriver.WebDriver.createSession(
792 executor, capabilities, opt_flow);
793
794 webdriver.WebDriver.call(
795 this, driver.getSession(), executor, driver.controlFlow());
796};
797util.inherits(Driver, webdriver.WebDriver);
798
799
800/**
801 * This function is a no-op as file detectors are not supported by this
802 * implementation.
803 * @override
804 */
805Driver.prototype.setFileDetector = function() {
806};
807
808
809// PUBLIC API
810
811
812exports.Driver = Driver;
813exports.Options = Options;
814exports.ServiceBuilder = ServiceBuilder;
815exports.createDriver = createDriver;
816exports.getDefaultService = getDefaultService;
817exports.setDefaultService = setDefaultService;