appium-chromium-driver
Version:
Appium driver for Chromium-based browsers that work with Chromedriver
210 lines • 8.53 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChromiumDriver = void 0;
const driver_1 = require("appium/driver");
const appium_chromedriver_1 = require("appium-chromedriver");
const chrome_1 = require("./chrome");
const desired_caps_1 = require("./desired-caps");
const msedge = __importStar(require("./msedge/index"));
const node_path_1 = __importDefault(require("node:path"));
const STANDARD_CAPS_LOWER = new Set([...driver_1.STANDARD_CAPS].map((cap) => cap.toLowerCase()));
const CHROME_VENDOR_PREFIX = 'goog:';
const EDGE_VENDOR_PREFIX = 'ms:';
class ChromiumDriver extends driver_1.BaseDriver {
desiredCapConstraints = desired_caps_1.desiredCapConstraints;
proxyReqRes = null;
proxyCommand;
doesSupportBidi = true;
_proxyActive = false;
_cd = null;
_bidiProxyUrl = null;
constructor(opts = {}) {
super(opts);
}
get bidiProxyUrl() {
return this._bidiProxyUrl;
}
get cd() {
if (!this._cd) {
throw new Error('Chromedriver not started');
}
return this._cd;
}
proxyActive() {
return this._proxyActive;
}
canProxy() {
return true;
}
validateDesiredCaps(caps) {
return super.validateDesiredCaps(this.excludeBrowserPrefixCaps(caps));
}
async createSession(jsonwpDesiredCapabilities, jsonwpRequiredCaps, w3cCapabilities, driverData) {
const [sessionId] = await super.createSession(jsonwpDesiredCapabilities, jsonwpRequiredCaps, w3cCapabilities, driverData);
const returnedCaps = await this.startChromedriverSession();
if (returnedCaps.webSocketUrl) {
this._bidiProxyUrl = String(returnedCaps.webSocketUrl);
}
return [sessionId, returnedCaps];
}
async startChromedriverSession() {
const isAutodownloadEnabled = this.opts.autodownloadEnabled ?? true;
const browserVersionInfo = await this.getBrowserInfo();
const cdOpts = {
port: this.opts.chromedriverPort?.toString(),
useSystemExecutable: this.opts.useSystemExecutable,
executable: await this.getExecutable(browserVersionInfo, isAutodownloadEnabled),
executableDir: this.getExecutableDir(),
verbose: this.opts.verbose,
logPath: this.opts.logPath,
disableBuildCheck: this.opts.disableBuildCheck,
details: browserVersionInfo,
isAutodownloadEnabled,
};
if (this.basePath) {
cdOpts.reqBasePath = this.basePath;
}
this._cd = new appium_chromedriver_1.Chromedriver(cdOpts);
const cdStartRes = (await this._cd.start(this.getSessionCaps()));
this._proxyActive = true;
this.proxyReqRes = this._cd.proxyReq.bind(this._cd);
this.proxyCommand = this._cd.sendCommand.bind(this._cd);
return cdStartRes;
}
async deleteSession(sessionId) {
try {
await super.deleteSession(sessionId);
}
finally {
this._proxyActive = false;
this._bidiProxyUrl = null;
this.proxyReqRes = null;
this.proxyCommand = undefined;
if (this._cd) {
try {
await this._cd.stop();
}
catch (err) {
this.log.warn(`Failed to stop Chromedriver: ${err.message}`);
}
this._cd = null;
}
}
}
/**
* Exclude browser-specific capabilities (e.g. `goog:chromeOptions` and `ms:edgeOptions`)
* from the capabilities to skip validation error for unrecognized capabilities.
* @param caps
* @returns
*/
excludeBrowserPrefixCaps(caps) {
const browserCapKeys = Object.keys(caps).filter((key) => key.startsWith(CHROME_VENDOR_PREFIX) || key.startsWith(EDGE_VENDOR_PREFIX));
return Object.keys(caps).reduce((acc, capName) => {
if (!browserCapKeys.includes(capName)) {
acc[capName] = caps[capName];
}
return acc;
}, {});
}
async getBrowserInfo() {
const opts = this.opts;
const browserBinary = opts['goog:chromeOptions']?.binary ??
opts['ms:edgeOptions']?.binary;
try {
const bv = await this.getBrowserDriverStrategy().discoverBrowserVersion(browserBinary);
this.log.info(`Detected browser version: ${bv}`);
return { info: { Browser: bv } };
}
catch (err) {
this.log.warn(`Failed to get browser version from binary: ${err.message}`);
}
}
/**
* FIXME: Please use this driver's local storage instead of the node_modules path
* to avoid potential read-only issue.
* Please update the `appium driver run chromium install-chromedriver` command behavior
* also to reflect the change.
* This change is a breaking change.
*/
getDefaultChromeDriverDir() {
const pkgJson = require.resolve('appium-chromedriver/package.json');
const packageDir = node_path_1.default.dirname(pkgJson);
return node_path_1.default.join(packageDir, 'chromedriver');
}
async getExecutable(browserVersionInfo, isAutodownloadEnabled = true) {
if (this.opts.executable) {
return this.opts.executable;
}
return await this.getBrowserDriverStrategy().resolveExecutable(browserVersionInfo, isAutodownloadEnabled);
}
getExecutableDir() {
if (this.opts.executableDir) {
return this.opts.executableDir;
}
return this.getBrowserDriverStrategy().getDefaultExecutableDir();
}
getBrowserDriverStrategy() {
if (msedge.isMsEdge(this.opts.browserName)) {
return {
discoverBrowserVersion: async (browserBinary) => await msedge.discoverMsEdgeBrowserVersion(browserBinary),
resolveExecutable: async (browserVersionInfo, isAutodownloadEnabled) => await msedge.determineDriverExecutable(this.opts, browserVersionInfo, isAutodownloadEnabled),
getDefaultExecutableDir: () => msedge.getDefaultDriverDir(),
};
}
return {
discoverBrowserVersion: async (browserBinary) => await (0, chrome_1.detectChromeBrowserVersion)(browserBinary),
resolveExecutable: async () => undefined,
getDefaultExecutableDir: () => this.getDefaultChromeDriverDir(),
};
}
getSessionCaps() {
const opts = this.opts;
return Object.keys(opts).reduce((acc, capName) => {
if (STANDARD_CAPS_LOWER.has(capName.toLowerCase()) ||
capName.startsWith(CHROME_VENDOR_PREFIX) ||
capName.startsWith(EDGE_VENDOR_PREFIX)) {
acc[capName] = opts[capName];
}
return acc;
}, {});
}
}
exports.ChromiumDriver = ChromiumDriver;
exports.default = ChromiumDriver;
//# sourceMappingURL=driver.js.map