# phantomjs.js

    1// Copyright 2013 Selenium committers2// Copyright 2013 Software Freedom Conservancy3//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 at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing, software11// 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 and14// limitations under the License.1516'use strict';1718var fs = require('fs'),19    util = require('util');2021var webdriver = require('./index'),22    LogLevel = webdriver.logging.LevelName,23    executors = require('./executors'),24    io = require('./io'),25    portprober = require('./net/portprober'),26    remote = require('./remote');272829/**30 * Name of the PhantomJS executable.31 * @type {string}32 * @const33 */34var PHANTOMJS_EXE =35    process.platform === 'win32' ? 'phantomjs.exe' : 'phantomjs';363738/**39 * Capability that designates the location of the PhantomJS executable to use.40 * @type {string}41 * @const42 */43var BINARY_PATH_CAPABILITY = 'phantomjs.binary.path';444546/**47 * Capability that designates the CLI arguments to pass to PhantomJS.48 * @type {string}49 * @const50 */51var CLI_ARGS_CAPABILITY = 'phantomjs.cli.args';525354/**55 * Default log file to use if one is not specified through CLI args.56 * @type {string}57 * @const58 */59var DEFAULT_LOG_FILE = 'phantomjsdriver.log';606162/**63 * Finds the PhantomJS executable.64 * @param {string=} opt_exe Path to the executable to use.65 * @return {string} The located executable.66 * @throws {Error} If the executable cannot be found on the PATH, or if the67 *     provided executable path does not exist.68 */69function findExecutable(opt_exe) {70  var exe = opt_exe || io.findInPath(PHANTOMJS_EXE, true);71  if (!exe) {72    throw Error(73        'The PhantomJS executable could not be found on the current PATH. ' +74        'Please download the latest version from ' +75        'http://phantomjs.org/download.html and ensure it can be found on ' +76        'your PATH. For more information, see ' +77        'https://github.com/ariya/phantomjs/wiki');78  }79  if (!fs.existsSync(exe)) {80    throw Error('File does not exist: ' + exe);81  }82  return exe;83}848586/**87 * Maps WebDriver logging level name to those recognised by PhantomJS.88 * @type {!Object.<webdriver.logging.LevelName, string>}89 * @const90 */91var WEBDRIVER_TO_PHANTOMJS_LEVEL = (function() {92  var map = {};93  map[LogLevel.ALL] = map[LogLevel.DEBUG] = 'DEBUG';94  map[LogLevel.INFO] = 'INFO';95  map[LogLevel.WARNING] = 'WARN';96  map[LogLevel.SEVERE] = map[LogLevel.OFF] = 'ERROR';97  return map;98})();99100101/**102 * Creates a new PhantomJS WebDriver client.103 * @param {webdriver.Capabilities=} opt_capabilities The desired capabilities.104 * @return {!webdriver.WebDriver} A new WebDriver instance.105 */106function createDriver(opt_capabilities) {107  var capabilities = opt_capabilities || webdriver.Capabilities.phantomjs();108  var exe = findExecutable(capabilities.get(BINARY_PATH_CAPABILITY));109  var args = ['--webdriver-logfile=' + DEFAULT_LOG_FILE];110111  var logPrefs = capabilities.get(webdriver.Capability.LOGGING_PREFS);112  if (logPrefs && logPrefs[webdriver.logging.Type.DRIVER]) {113    var level = WEBDRIVER_TO_PHANTOMJS_LEVEL[114        logPrefs[webdriver.logging.Type.DRIVER]];115    if (level) {116      args.push('--webdriver-loglevel=' + level);117    }118  }119120  var proxy = capabilities.get(webdriver.Capability.PROXY);121  if (proxy) {122    switch (proxy.proxyType) {123      case 'manual':124        if (proxy.httpProxy) {125          args.push(126              '--proxy-type=http',127              '--proxy=http://' + proxy.httpProxy);128        }129        break;130      case 'pac':131        throw Error('PhantomJS does not support Proxy PAC files');132      case 'system':133        args.push('--proxy-type=system');134        break;135      case 'direct':136        args.push('--proxy-type=none');137        break;138    }139  }140  args = args.concat(capabilities.get(CLI_ARGS_CAPABILITY) || []);141142  var port = portprober.findFreePort();143  var service = new remote.DriverService(exe, {144    port: port,145    args: webdriver.promise.when(port, function(port) {146      args.push('--webdriver=' + port);147      return args;148    })149  });150151  var executor = executors.createExecutor(service.start());152  var driver = webdriver.WebDriver.createSession(executor, capabilities);153  var boundQuit = driver.quit.bind(driver);154  driver.quit = function() {155    return boundQuit().thenFinally(service.kill.bind(service));156  };157  return driver;158}159160161// PUBLIC API162163164exports.createDriver = createDriver;