# 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 |
115 | var fs = require('fs'),
116 | util = require('util');
117 |
118 | var 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 | */
130 | var 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 | */
146 | var 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} */
168 | ServiceBuilder.prototype.port_ = 0;
169 |
170 |
171 | /** @private {(string|!Array.<string|number|!Stream|null|undefined>)} */
172 | ServiceBuilder.prototype.stdio_ = 'ignore';
173 |
174 |
175 | /** @private {Object.<string, string>} */
176 | ServiceBuilder.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 | */
185 | ServiceBuilder.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 | */
202 | ServiceBuilder.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 | */
214 | ServiceBuilder.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 | */
224 | ServiceBuilder.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 | */
236 | ServiceBuilder.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 | */
248 | ServiceBuilder.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 | */
261 | ServiceBuilder.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 | */
273 | ServiceBuilder.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 | */
286 | ServiceBuilder.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} */
303 | var 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 | */
311 | function 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 | */
327 | function getDefaultService() {
328 | if (!defaultService) {
329 | defaultService = new ServiceBuilder().build();
330 | }
331 | return defaultService;
332 | }
333 |
334 |
335 | /**
336 | * @type {string}
337 | * @const
338 | */
339 | var OPTIONS_CAPABILITY_KEY = 'chromeOptions';
340 |
341 |
342 | /**
343 | * Class for managing ChromeDriver specific options.
344 | * @constructor
345 | * @extends {webdriver.Serializable}
346 | */
347 | var 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 | };
362 | util.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 | */
371 | Options.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 | */
413 | Options.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 | */
430 | Options.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 | */
448 | Options.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 | */
465 | Options.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 | */
479 | Options.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 | */
491 | Options.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 | */
502 | Options.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 | */
532 | Options.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 | */
544 | Options.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 | */
558 | Options.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 | */
572 | Options.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 | */
584 | Options.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 | */
596 | Options.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 | */
610 | Options.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 | */
624 | Options.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 | */
636 | Options.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 | */
648 | Options.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 | */
690 | Options.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 | */
701 | Options.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 | */
713 | Options.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 | */
736 | Options.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 | */
766 | function 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 | */
783 | var 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 | };
797 | util.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 | */
805 | Driver.prototype.setFileDetector = function() {
806 | };
807 |
808 |
809 | // PUBLIC API
810 |
811 |
812 | exports.Driver = Driver;
813 | exports.Options = Options;
814 | exports.ServiceBuilder = ServiceBuilder;
815 | exports.createDriver = createDriver;
816 | exports.getDefaultService = getDefaultService;
817 | exports.setDefaultService = setDefaultService;