UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

321 lines 51.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BrowserClient = exports.NEW_WINDOW_OPENED_IN_NATIVE_AUTOMATION = void 0; const path_1 = __importDefault(require("path")); const os_1 = __importDefault(require("os")); const chrome_remote_interface_1 = __importDefault(require("chrome-remote-interface")); const debug_1 = __importDefault(require("debug")); const client_functions_1 = require("../../../../utils/client-functions"); const warning_message_1 = __importDefault(require("../../../../../../notifications/warning-message")); const pretty_hrtime_1 = __importDefault(require("pretty-hrtime")); const elapsed_upperbounds_1 = require("../elapsed-upperbounds"); const guard_time_execution_1 = __importDefault(require("../../../../../../utils/guard-time-execution")); const delay_1 = __importDefault(require("../../../../../../utils/delay")); const native_automation_1 = require("../../../../../../native-automation"); const utils_1 = require("./utils"); const DEBUG_SCOPE = (id) => `testcafe:browser:provider:built-in:chrome:browser-client:${id}`; const DOWNLOADS_DIR = path_1.default.join(os_1.default.homedir(), 'Downloads'); const debugLog = (0, debug_1.default)('testcafe:browser:provider:built-in:dedicated:chrome'); class ProtocolApiInfo { constructor(client) { this.client = client; this.inactive = false; } } const SCREENCAST_OPTIONS = { format: 'jpeg', everyNthFrame: 1, }; exports.NEW_WINDOW_OPENED_IN_NATIVE_AUTOMATION = 'new-window-opened-in-native-automation'; class BrowserClient { constructor(runtimeInfo) { this._clients = {}; this._screencastFrameListenerAttached = false; this._runtimeInfo = runtimeInfo; this.debugLogger = (0, debug_1.default)(DEBUG_SCOPE(runtimeInfo.browserId)); runtimeInfo.browserClient = this; this._videoFramesBuffer = []; this._lastFrame = null; } get _port() { return this._runtimeInfo.cdpPort; } get _clientKey() { return this._runtimeInfo.activeWindowId || this._runtimeInfo.browserId; } get _config() { return this._runtimeInfo.config; } _checkDropOfPerformance(method, elapsedTime) { this.debugLogger(`CDP method '${method}' took ${(0, pretty_hrtime_1.default)(elapsedTime)}`); const [elapsedSeconds] = elapsedTime; if (elapsedSeconds > elapsed_upperbounds_1.ELAPSED_TIME_UPPERBOUNDS[method]) { this._runtimeInfo.providerMethods.reportWarning(warning_message_1.default.browserProviderDropOfPerformance, this._runtimeInfo.browserName); } } async _createClient(target, cacheKey = this._clientKey) { const client = await (0, chrome_remote_interface_1.default)({ target, port: this._port }); const { Page, Network, Runtime } = client; this._clients[cacheKey] = new ProtocolApiInfo(client); await (0, guard_time_execution_1.default)(async () => await Page.enable(), elapsedTime => this._checkDropOfPerformance(elapsed_upperbounds_1.CheckedCDPMethod.PageEnable, elapsedTime)); await Network.enable({}); await Runtime.enable(); return client; } async _setupClient(client) { if (this._config.emulation) await this._setEmulation(client); if (this._config.headless) await this._setupDownloads(client); } async _setDeviceMetricsOverride(client, width, height, deviceScaleFactor, mobile) { await (0, guard_time_execution_1.default)(async () => { await client.Emulation.setDeviceMetricsOverride({ width, height, deviceScaleFactor, mobile, // @ts-ignore fitWindow: false, }); }, elapsedTime => this._checkDropOfPerformance(elapsed_upperbounds_1.CheckedCDPMethod.SetDeviceMetricsOverride, elapsedTime)); } async _setUserAgentEmulation(client) { if (this._config.userAgent === void 0) return; await client.Network.setUserAgentOverride({ userAgent: this._config.userAgent }); } async _setTouchEmulation(client) { if (this._config.touch === void 0) return; const touchConfig = { enabled: this._config.touch, configuration: this._config.mobile ? 'mobile' : 'desktop', maxTouchPoints: 1, }; if (client.Emulation.setEmitTouchEventsForMouse) await client.Emulation.setEmitTouchEventsForMouse(touchConfig); if (client.Emulation.setTouchEmulationEnabled) await client.Emulation.setTouchEmulationEnabled(touchConfig); } async _setEmulation(client) { await this._setUserAgentEmulation(client); await this._setTouchEmulation(client); await this.resizeWindow({ width: this._config.width, height: this._config.height, }); } async _setupDownloads(client) { await client.Page.setDownloadBehavior({ behavior: 'allow', downloadPath: DOWNLOADS_DIR, }); } async _evaluateRuntime(client, expression, returnByValue = false) { return client.Runtime.evaluate({ expression, returnByValue }); } async _calculateEmulatedDevicePixelRatio(client) { if (!client) return; const devicePixelRatioQueryResult = await client.Runtime.evaluate({ expression: 'window.devicePixelRatio' }); this._runtimeInfo.originalDevicePixelRatio = devicePixelRatioQueryResult.result.value; this._runtimeInfo.emulatedDevicePixelRatio = this._config.scaleFactor || this._runtimeInfo.originalDevicePixelRatio; } async resizeWindow(newDimensions) { const { browserId, config, viewportSize, providerMethods, emulatedDevicePixelRatio } = this._runtimeInfo; const currentWidth = viewportSize.width; const currentHeight = viewportSize.height; const newWidth = newDimensions.width || currentWidth; const newHeight = newDimensions.height || currentHeight; if (!config.headless) await providerMethods.resizeLocalBrowserWindow(browserId, newWidth, newHeight, currentWidth, currentHeight); viewportSize.width = newWidth; viewportSize.height = newHeight; const client = await this.getActiveClient(); if (client && config.emulation) { await this._setDeviceMetricsOverride(client, viewportSize.width, viewportSize.height, emulatedDevicePixelRatio, config.mobile); await (0, guard_time_execution_1.default)(async () => { await client.Emulation.setVisibleSize({ width: viewportSize.width, height: viewportSize.height }); }, elapsedTime => this._checkDropOfPerformance(elapsed_upperbounds_1.CheckedCDPMethod.SetVisibleSize, elapsedTime)); } } async maximizeWindowNativeAutomation() { const target = await (0, utils_1.getFirstTab)(this._port); const client = await this.getActiveClient(); if (client) { const windowParams = await client.Browser.getWindowForTarget({ targetId: target.id }); await client.Browser.setWindowBounds({ windowId: windowParams.windowId, bounds: { windowState: 'maximized' } }); } } async resizeBounds(newDimensions) { const { viewportSize } = this._runtimeInfo; let nonClientWidth = 0; let nonClientHeight = 0; if (viewportSize.outerWidth && viewportSize.outerHeight) { nonClientWidth = viewportSize.outerWidth - viewportSize.width; nonClientHeight = viewportSize.outerHeight - viewportSize.height; } const target = await (0, utils_1.getFirstTab)(this._port); const client = await this.getActiveClient(); if (client) { const windowParams = await client.Browser.getWindowForTarget({ targetId: target.id }); if (windowParams.bounds.windowState !== 'normal') { await client.Browser.setWindowBounds({ windowId: windowParams.windowId, bounds: { windowState: 'normal', }, }); } await client.Browser.setWindowBounds({ windowId: windowParams.windowId, bounds: { width: newDimensions.width + nonClientWidth, height: newDimensions.height + nonClientHeight, }, }); } } isHeadlessTab() { return !!this._parentTarget && this._config.headless; } async setClientInactive(windowId) { const client = this._clients[windowId]; if (client) client.inactive = true; } async getActiveClient() { try { if (!this._clients[this._clientKey]) { const target = await (0, utils_1.getActiveTab)(this._port, this._runtimeInfo.activeWindowId); await this._createClient(target); } } catch (err) { debugLog(err); return void 0; } const info = this._clients[this._clientKey]; if (info.inactive) return void 0; return info.client; } async initMainWindowCdpClient() { try { const tabs = await (0, utils_1.getTabs)(this._port); this._parentTarget = tabs.find(t => t.url.includes(this._runtimeInfo.browserId)); if (!this._parentTarget) return; const client = await this.getActiveClient(); if (client) { await this._calculateEmulatedDevicePixelRatio(client); await this._setupClient(client); } } catch (e) { return; } } async getScreenshotData(fullPage) { let clip = void 0; const client = await this.getActiveClient(); if (!client) { // NOTE: required for https://github.com/DevExpress/testcafe/issues/6037 await (0, delay_1.default)(0); return Buffer.alloc(0); } if (fullPage) { const metrics = await client.Page.getLayoutMetrics(); const { width, height } = metrics.cssContentSize || metrics.contentSize; clip = { x: 0, y: 0, width, height, scale: 1 }; } const result = await client.Page.captureScreenshot({ clip, captureBeyondViewport: fullPage, }); return Buffer.from(result.data, 'base64'); } async closeTab() { if (this._parentTarget) await chrome_remote_interface_1.default.Close({ id: this._parentTarget.id, port: this._port }); } async updateMobileViewportSize() { const client = await this.getActiveClient(); if (!client) return; const windowDimensionsQueryResult = await this._evaluateRuntime(client, `(${client_functions_1.GET_WINDOW_DIMENSIONS_INFO_SCRIPT})()`, true); const windowDimensions = windowDimensionsQueryResult.result.value; this._runtimeInfo.viewportSize.width = windowDimensions.outerWidth; this._runtimeInfo.viewportSize.height = windowDimensions.outerHeight; } async closeBrowserChildWindow(windowId) { await this.setClientInactive(windowId); // NOTE: delay browser window closing await (0, delay_1.default)(100); } async startCapturingVideo() { const client = await this.getActiveClient(); if (!client) return; if (!this._screencastFrameListenerAttached) { client.Page.on('screencastFrame', (event) => { this._videoFramesBuffer.push({ data: event.data, sessionId: event.sessionId, }); }); this._screencastFrameListenerAttached = true; } await client.Page.startScreencast(SCREENCAST_OPTIONS); } async stopCapturingVideo() { const client = await this.getActiveClient(); if (!client) return; await client.Page.stopScreencast(); this._lastFrame = null; this._videoFramesBuffer = []; } async getVideoFrameData() { const firstFrameFromBuffer = this._videoFramesBuffer.shift(); const currentVideoFrame = firstFrameFromBuffer || this._lastFrame; if (!currentVideoFrame) return null; if (this._videoFramesBuffer.length === 0) this._lastFrame = currentVideoFrame; const client = await this.getActiveClient(); if (!client) return null; if (firstFrameFromBuffer) await client.Page.screencastFrameAck({ sessionId: currentVideoFrame.sessionId }); return Buffer.from(currentVideoFrame.data, 'base64'); } async _onTargetCreatedHandler(targetInfo, options) { const target = await (0, utils_1.getTabById)(this._port, targetInfo.targetId); if (!target) return null; try { const client = await this._createClient(target, targetInfo.targetId); const nativeAutomation = new native_automation_1.NativeAutomationChildWindow(this._runtimeInfo.browserId, target.id, client, options); await nativeAutomation.start(); return target.id; } catch (err) { debugLog(err); return null; } } async createMainWindowNativeAutomation(options) { const target = await (0, utils_1.getFirstTab)(this._port); const client = await this._createClient(target); const nativeAutomation = new native_automation_1.NativeAutomationMainWindow(this._runtimeInfo.browserId, target.id, client, options); nativeAutomation.on(exports.NEW_WINDOW_OPENED_IN_NATIVE_AUTOMATION, async (targetInfo) => this._onTargetCreatedHandler(targetInfo, options)); return nativeAutomation; } } exports.BrowserClient = BrowserClient; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYnJvd3Nlci9wcm92aWRlci9idWlsdC1pbi9kZWRpY2F0ZWQvY2hyb21lL2NkcC1jbGllbnQvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBRUEsZ0RBQXdCO0FBQ3hCLDRDQUFvQjtBQUNwQixzRkFBbUU7QUFDbkUsa0RBQTBCO0FBQzFCLHlFQUF1RjtBQUN2RixzR0FBOEU7QUFROUUsa0VBQXVDO0FBQ3ZDLGdFQUFvRjtBQUNwRix3R0FBOEU7QUFDOUUsMEVBQWtEO0FBTWxELDJFQUk2QztBQUU3QyxtQ0FNbUI7QUFFbkIsTUFBTSxXQUFXLEdBQUcsQ0FBQyxFQUFVLEVBQVUsRUFBRSxDQUFDLDREQUE0RCxFQUFFLEVBQUUsQ0FBQztBQUM3RyxNQUFNLGFBQWEsR0FBRyxjQUFJLENBQUMsSUFBSSxDQUFDLFlBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxXQUFXLENBQUMsQ0FBQztBQUUzRCxNQUFNLFFBQVEsR0FBRyxJQUFBLGVBQUssRUFBQyxxREFBcUQsQ0FBQyxDQUFDO0FBRTlFLE1BQU0sZUFBZTtJQUlqQixZQUFvQixNQUFnQztRQUNoRCxJQUFJLENBQUMsTUFBTSxHQUFLLE1BQU0sQ0FBQztRQUN2QixJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztJQUMxQixDQUFDO0NBQ0o7QUFFRCxNQUFNLGtCQUFrQixHQUFHO0lBQ3ZCLE1BQU0sRUFBUyxNQUFNO0lBQ3JCLGFBQWEsRUFBRSxDQUFDO0NBQ25CLENBQUM7QUFPVyxRQUFBLHNDQUFzQyxHQUFHLHdDQUF3QyxDQUFDO0FBRS9GLE1BQWEsYUFBYTtJQVN0QixZQUFvQixXQUF3QjtRQVJwQyxhQUFRLEdBQWdDLEVBQUUsQ0FBQztRQU0zQyxxQ0FBZ0MsR0FBRyxLQUFLLENBQUM7UUFHN0MsSUFBSSxDQUFDLFlBQVksR0FBRyxXQUFXLENBQUM7UUFDaEMsSUFB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QU0sR0FBYSxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMvRSxNQUFNLGdCQUFnQixHQUFHLElBQUksK0NBQTJCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLEVBQUUsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFFbEgsTUFBTSxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUUvQixPQUFPLE1BQU0sQ0FBQyxFQUFFLENBQUM7U0FDcEI7UUFDRCxPQUFPLEdBQUcsRUFBRTtZQUNSLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUVkLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLGdDQUFnQyxDQUFFLE9BQW9DO1FBQy9FLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBQSxtQkFBVyxFQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QyxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFaEQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLDhDQUEwQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRWpILGdCQUFnQixDQUFDLEVBQUUsQ0FBQyw4Q0FBc0MsRUFBRSxLQUFLLEVBQUMsVUFBVSxFQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFFbkksT0FBTyxnQkFBZ0IsQ0FBQztJQUM1QixDQUFDO0NBQ0o7QUF2WkQsc0NBdVpDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGljdGlvbmFyeSB9IGZyb20gJy4uLy4uLy4uLy4uLy4uLy4uL2NvbmZpZ3VyYXRpb24vaW50ZXJmYWNlcyc7XG5pbXBvcnQgUHJvdG9jb2wgZnJvbSAnZGV2dG9vbHMtcHJvdG9jb2wnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgb3MgZnJvbSAnb3MnO1xuaW1wb3J0IHJlbW90ZUNocm9tZSwgeyBUYXJnZXRJbmZvIH0gZnJvbSAnY2hyb21lLXJlbW90ZS1pbnRlcmZhY2UnO1xuaW1wb3J0IGRlYnVnIGZyb20gJ2RlYnVnJztcbmltcG9ydCB7IEdFVF9XSU5ET1dfRElNRU5TSU9OU19JTkZPX1NDUklQVCB9IGZyb20gJy4uLy4uLy4uLy4uL3V0aWxzL2NsaWVudC1mdW5jdGlvbnMnO1xuaW1wb3J0IFdBUk5JTkdfTUVTU0FHRSBmcm9tICcuLi8uLi8uLi8uLi8uLi8uLi9ub3RpZmljYXRpb25zL3dhcm5pbmctbWVzc2FnZSc7XG5cbmltcG9ydCB7XG4gICAgQ29uZmlnLFxuICAgIFJ1bnRpbWVJbmZvLFxuICAgIFRvdWNoQ29uZmlnT3B0aW9ucyxcbiAgICBTaXplLFxufSBmcm9tICcuLi9pbnRlcmZhY2VzJztcbmltcG9ydCBwcmV0dHlUaW1lIGZyb20gJ3ByZXR0eS1ocnRpbWUnO1xuaW1wb3J0IHsgQ2hlY2tlZENEUE1ldGhvZCwgRUxBUFNFRF9USU1FX1VQUEVSQk9VTkRTIH0gZnJvbSAnLi4vZWxhcHNlZC11cHBlcmJvdW5kcyc7XG5pbXBvcnQgZ3VhcmRUaW1lRXhlY3V0aW9uIGZyb20gJy4uLy4uLy4uLy4uLy4uLy4uL3V0aWxzL2d1YXJkLXRpbWUtZXhlY3V0aW9uJztcbmltcG9ydCBkZWxheSBmcm9tICcuLi8uLi8uLi8uLi8uLi8uLi91dGlscy9kZWxheSc7XG5cbmltcG9ydCBTdGFydFNjcmVlbmNhc3RSZXF1ZXN0ID0gUHJvdG9jb2wuUGFnZS5TdGFydFNjcmVlbmNhc3RSZXF1ZXN0O1xuaW1wb3J0IFNjcmVlbmNhc3RGcmFtZUV2ZW50ID0gUHJvdG9jb2wuUGFnZS5TY3JlZW5jYXN0RnJhbWVFdmVudDtcbmltcG9ydCB7IE5hdGl2ZUF1dG9tYXRpb25Jbml0T3B0aW9ucyB9IGZyb20gJy4uLy4uLy4uLy4uLy4uLy4uL3NoYXJlZC90eXBlcyc7XG5cbmltcG9ydCB7XG4gICAgTmF0aXZlQXV0b21hdGlvbkJhc2UsXG4gICAgTmF0aXZlQXV0b21hdGlvbkNoaWxkV2luZG93LFxuICAgIE5hdGl2ZUF1dG9tYXRpb25NYWluV2luZG93LFxufSBmcm9tICcuLi8uLi8uLi8uLi8uLi8uLi9uYXRpdmUtYXV0b21hdGlvbic7XG5cbmltcG9ydCB7XG4gICAgZ2V0QWN0aXZlVGFiLFxuICAgIGdldEZpcnN0VGFiLFxuICAgIGdldFRhYkJ5SWQsXG4gICAgZ2V0VGFicyxcbn1cbiAgICBmcm9tICcuL3V0aWxzJztcblxuY29uc3QgREVCVUdfU0NPUEUgPSAoaWQ6IHN0cmluZyk6IHN0cmluZyA9PiBgdGVzdGNhZmU6YnJvd3Nlcjpwcm92aWRlcjpidWlsdC1pbjpjaHJvbWU6YnJvd3Nlci1jbGllbnQ6JHtpZH1gO1xuY29uc3QgRE9XTkxPQURTX0RJUiA9IHBhdGguam9pbihvcy5ob21lZGlyKCksICdEb3dubG9hZHMnKTtcblxuY29uc3QgZGVidWdMb2cgPSBkZWJ1ZygndGVzdGNhZmU6YnJvd3Nlcjpwcm92aWRlcjpidWlsdC1pbjpkZWRpY2F0ZWQ6Y2hyb21lJyk7XG5cbmNsYXNzIFByb3RvY29sQXBpSW5mbyB7XG4gICAgcHVibGljIGluYWN0aXZlOiBib29sZWFuO1xuICAgIHB1YmxpYyBjbGllbnQ6IHJlbW90ZUNocm9tZS5Qcm90b2NvbEFwaTtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvciAoY2xpZW50OiByZW1vdGVDaHJvbWUuUHJvdG9jb2xBcGkpIHtcbiAgICAgICAgdGhpcy5jbGllbnQgICA9IGNsaWVudDtcbiAgICAgICAgdGhpcy5pbmFjdGl2ZSA9IGZhbHNlO1xuICAgIH1cbn1cblxuY29uc3QgU0NSRUVOQ0FTVF9PUFRJT05TID0ge1xuICAgIGZvcm1hdDogICAgICAgICdqcGVnJyxcbiAgICBldmVyeU50aEZyYW1lOiAxLFxufTtcblxuaW50ZXJmYWNlIFZpZGVvRnJhbWVEYXRhIHtcbiAgICBkYXRhOiBzdHJpbmc7XG4gICAgc2Vzc2lvbklkOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBORVdfV0lORE9XX09QRU5FRF9JTl9OQVRJVkVfQVVUT01BVElPTiA9ICduZXctd2luZG93LW9wZW5lZC1pbi1uYXRpdmUtYXV0b21hdGlvbic7XG5cbmV4cG9ydCBjbGFzcyBCcm93c2VyQ2xpZW50IHtcbiAgICBwcml2YXRlIF9jbGllbnRzOiBEaWN0aW9uYXJ5PFByb3RvY29sQXBpSW5mbz4gPSB7fTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9ydW50aW1lSW5mbzogUnVudGltZUluZm87XG4gICAgcHJpdmF0ZSBfcGFyZW50VGFyZ2V0PzogcmVtb3RlQ2hyb21lLlRhcmdldEluZm87XG4gICAgcHJpdmF0ZSByZWFkb25seSBkZWJ1Z0xvZ2dlcjogZGVidWcuRGVidWdnZXI7XG4gICAgcHJpdmF0ZSBfdmlkZW9GcmFtZXNCdWZmZXI6IFZpZGVvRnJhbWVEYXRhW107XG4gICAgcHJpdmF0ZSBfbGFzdEZyYW1lOiBWaWRlb0ZyYW1lRGF0YSB8IG51bGw7XG4gICAgcHJpdmF0ZSBfc2NyZWVuY2FzdEZyYW1lTGlzdGVuZXJBdHRhY2hlZCA9IGZhbHNlO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yIChydW50aW1lSW5mbzogUnVudGltZUluZm8pIHtcbiAgICAgICAgdGhpcy5fcnVudGltZUluZm8gPSBydW50aW1lSW5mbztcbiAgICAgICAgdGhpcy5kZWJ1Z0xvZ2dlciAgPSBkZWJ1ZyhERUJVR19TQ09QRShydW50aW1lSW5mby5icm93c2VySWQpKTtcblxuICAgICAgICBydW50aW1lSW5mby5icm93c2VyQ2xpZW50ID0gdGhpcztcblxuICAgICAgICB0aGlzLl92aWRlb0ZyYW1lc0J1ZmZlciA9IFtdO1xuICAgICAgICB0aGlzLl9sYXN0RnJhbWUgICAgICAgICA9IG51bGw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgX3BvcnQgKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ydW50aW1lSW5mby5jZHBQb3J0O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IF9jbGllbnRLZXkgKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ydW50aW1lSW5mby5hY3RpdmVXaW5kb3dJZCB8fCB0aGlzLl9ydW50aW1lSW5mby5icm93c2VySWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgX2NvbmZpZyAoKTogQ29uZmlnIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3J1bnRpbWVJbmZvLmNvbmZpZztcbiAgICB9XG5cbiAgICBwcml2YXRlIF9jaGVja0Ryb3BPZlBlcmZvcm1hbmNlIChtZXRob2Q6IENoZWNrZWRDRFBNZXRob2QsIGVsYXBzZWRUaW1lOiBbbnVtYmVyLCBudW1iZXJdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGVidWdMb2dnZXIoYENEUCBtZXRob2QgJyR7bWV0aG9kfScgdG9vayAke3ByZXR0eVRpbWUoZWxhcHNlZFRpbWUpfWApO1xuXG4gICAgICAgIGNvbnN0IFsgZWxhcHNlZFNlY29uZHMgXSA9IGVsYXBzZWRUaW1lO1xuXG4gICAgICAgIGlmIChlbGFwc2VkU2Vjb25kcyA+IEVMQVBTRURfVElNRV9VUFBFUkJPVU5EU1ttZXRob2RdKSB7XG4gICAgICAgICAgICB0aGlzLl9ydW50aW1lSW5mby5wcm92aWRlck1ldGhvZHMucmVwb3J0V2FybmluZyhcbiAgICAgICAgICAgICAgICBXQVJOSU5HX01FU1NBR0UuYnJvd3NlclByb3ZpZGVyRHJvcE9mUGVyZm9ybWFuY2UsXG4gICAgICAgICAgICAgICAgdGhpcy5fcnVudGltZUluZm8uYnJvd3Nlck5hbWVcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9jcmVhdGVDbGllbnQgKHRhcmdldDogVGFyZ2V0SW5mbywgY2FjaGVLZXk6IHN0cmluZyA9IHRoaXMuX2NsaWVudEtleSk6IFByb21pc2U8cmVtb3RlQ2hyb21lLlByb3RvY29sQXBpPiB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHJlbW90ZUNocm9tZSh7IHRhcmdldCwgcG9ydDogdGhpcy5fcG9ydCB9KTtcblxuICAgICAgICBjb25zdCB7IFBhZ2UsIE5ldHdvcmssIFJ1bnRpbWUgfSA9IGNsaWVudDtcblxuICAgICAgICB0aGlzLl9jbGllbnRzW2NhY2hlS2V5XSA9IG5ldyBQcm90b2NvbEFwaUluZm8oY2xpZW50KTtcblxuICAgICAgICBhd2FpdCBndWFyZFRpbWVFeGVjdXRpb24oXG4gICAgICAgICAgICBhc3luYyAoKSA9PiBhd2FpdCBQYWdlLmVuYWJsZSgpLFxuICAgICAgICAgICAgZWxhcHNlZFRpbWUgPT4gdGhpcy5fY2hlY2tEcm9wT2ZQZXJmb3JtYW5jZShDaGVja2VkQ0RQTWV0aG9kLlBhZ2VFbmFibGUsIGVsYXBzZWRUaW1lKVxuICAgICAgICApO1xuXG4gICAgICAgIGF3YWl0IE5ldHdvcmsuZW5hYmxlKHt9KTtcbiAgICAgICAgYXdhaXQgUnVudGltZS5lbmFibGUoKTtcblxuICAgICAgICByZXR1cm4gY2xpZW50O1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3NldHVwQ2xpZW50IChjbGllbnQ6IHJlbW90ZUNocm9tZS5Qcm90b2NvbEFwaSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAodGhpcy5fY29uZmlnLmVtdWxhdGlvbilcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX3NldEVtdWxhdGlvbihjbGllbnQpO1xuXG4gICAgICAgIGlmICh0aGlzLl9jb25maWcuaGVhZGxlc3MpXG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9zZXR1cERvd25sb2FkcyhjbGllbnQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3NldERldmljZU1ldHJpY3NPdmVycmlkZSAoY2xpZW50OiByZW1vdGVDaHJvbWUuUHJvdG9jb2xBcGksIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyLCBkZXZpY2VTY2FsZUZhY3RvcjogbnVtYmVyLCBtb2JpbGU6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgZ3VhcmRUaW1lRXhlY3V0aW9uKFxuICAgICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGF3YWl0IGNsaWVudC5FbXVsYXRpb24uc2V0RGV2aWNlTWV0cmljc092ZXJyaWRlKHtcbiAgICAgICAgICAgICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIGhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgZGV2aWNlU2NhbGVGYWN0b3IsXG4gICAgICAgICAgICAgICAgICAgIG1vYmlsZSxcbiAgICAgICAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICAgICAgICBmaXRXaW5kb3c6IGZhbHNlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVsYXBzZWRUaW1lID0+IHRoaXMuX2NoZWNrRHJvcE9mUGVyZm9ybWFuY2UoQ2hlY2tlZENEUE1ldGhvZC5TZXREZXZpY2VNZXRyaWNzT3ZlcnJpZGUsIGVsYXBzZWRUaW1lKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3NldFVzZXJBZ2VudEVtdWxhdGlvbiAoY2xpZW50OiByZW1vdGVDaHJvbWUuUHJvdG9jb2xBcGkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy51c2VyQWdlbnQgPT09IHZvaWQgMClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBhd2FpdCBjbGllbnQuTmV0d29yay5zZXRVc2VyQWdlbnRPdmVycmlkZSh7IHVzZXJBZ2VudDogdGhpcy5fY29uZmlnLnVzZXJBZ2VudCB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9zZXRUb3VjaEVtdWxhdGlvbiAoY2xpZW50OiByZW1vdGVDaHJvbWUuUHJvdG9jb2xBcGkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy50b3VjaCA9PT0gdm9pZCAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHRvdWNoQ29uZmlnOiBUb3VjaENvbmZpZ09wdGlvbnMgPSB7XG4gICAgICAgICAgICBlbmFibGVkOiAgICAgICAgdGhpcy5fY29uZmlnLnRvdWNoLFxuICAgICAgICAgICAgY29uZmlndXJhdGlvbjogIHRoaXMuX2NvbmZpZy5tb2JpbGUgPyAnbW9iaWxlJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgIG1heFRvdWNoUG9pbnRzOiAxLFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChjbGllbnQuRW11bGF0aW9uLnNldEVtaXRUb3VjaEV2ZW50c0Zvck1vdXNlKVxuICAgICAgICAgICAgYXdhaXQgY2xpZW50LkVtdWxhdGlvbi5zZXRFbWl0VG91Y2hFdmVudHNGb3JNb3VzZSh0b3VjaENvbmZpZyk7XG5cbiAgICAgICAgaWYgKGNsaWVudC5FbXVsYXRpb24uc2V0VG91Y2hFbXVsYXRpb25FbmFibGVkKVxuICAgICAgICAgICAgYXdhaXQgY2xpZW50LkVtdWxhdGlvbi5zZXRUb3VjaEVtdWxhdGlvbkVuYWJsZWQodG91Y2hDb25maWcpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3NldEVtdWxhdGlvbiAoY2xpZW50OiByZW1vdGVDaHJvbWUuUHJvdG9jb2xBcGkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5fc2V0VXNlckFnZW50RW11bGF0aW9uKGNsaWVudCk7XG4gICAgICAgIGF3YWl0IHRoaXMuX3NldFRvdWNoRW11bGF0aW9uKGNsaWVudCk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5yZXNpemVXaW5kb3coe1xuICAgICAgICAgICAgd2lkdGg6ICB0aGlzLl9jb25maWcud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IHRoaXMuX2NvbmZpZy5oZWlnaHQsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3NldHVwRG93bmxvYWRzIChjbGllbnQ6IHJlbW90ZUNocm9tZS5Qcm90b2NvbEFwaSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCBjbGllbnQuUGFnZS5zZXREb3dubG9hZEJlaGF2aW9yKHtcbiAgICAgICAgICAgIGJlaGF2aW9yOiAgICAgJ2FsbG93JyxcbiAgICAgICAgICAgIGRvd25sb2FkUGF0aDogRE9XTkxPQURTX0RJUixcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfZXZhbHVhdGVSdW50aW1lIChjbGllbnQ6IHJlbW90ZUNocm9tZS5Qcm90b2NvbEFwaSwgZXhwcmVzc2lvbjogc3RyaW5nLCByZXR1cm5CeVZhbHVlID0gZmFsc2UpOiBQcm9taXNlPFByb3RvY29sLlJ1bnRpbWUuRXZhbHVhdGVSZXNwb25zZT4ge1xuICAgICAgICByZXR1cm4gY2xpZW50LlJ1bnRpbWUuZXZhbHVhdGUoeyBleHByZXNzaW9uLCByZXR1cm5CeVZhbHVlIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX2NhbGN1bGF0ZUVtdWxhdGVkRGV2aWNlUGl4ZWxSYXRpbyAoY2xpZW50OiByZW1vdGVDaHJvbWUuUHJvdG9jb2xBcGkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCFjbGllbnQpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgY29uc3QgZGV2aWNlUGl4ZWxSYXRpb1F1ZXJ5UmVzdWx0ID0gYXdhaXQgY2xpZW50LlJ1bnRpbWUuZXZhbHVhdGUoeyBleHByZXNzaW9uOiAnd2luZG93LmRldmljZVBpeGVsUmF0aW8nIH0pO1xuXG4gICAgICAgIHRoaXMuX3J1bnRpbWVJbmZvLm9yaWdpbmFsRGV2aWNlUGl4ZWxSYXRpbyA9IGRldmljZVBpeGVsUmF0aW9RdWVyeVJlc3VsdC5yZXN1bHQudmFsdWU7XG4gICAgICAgIHRoaXMuX3J1bnRpbWVJbmZvLmVtdWxhdGVkRGV2aWNlUGl4ZWxSYXRpbyA9IHRoaXMuX2NvbmZpZy5zY2FsZUZhY3RvciB8fCB0aGlzLl9ydW50aW1lSW5mby5vcmlnaW5hbERldmljZVBpeGVsUmF0aW87XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHJlc2l6ZVdpbmRvdyAobmV3RGltZW5zaW9uczogU2l6ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCB7IGJyb3dzZXJJZCwgY29uZmlnLCB2aWV3cG9ydFNpemUsIHByb3ZpZGVyTWV0aG9kcywgZW11bGF0ZWREZXZpY2VQaXhlbFJhdGlvIH0gPSB0aGlzLl9ydW50aW1lSW5mbztcblxuICAgICAgICBjb25zdCBjdXJyZW50V2lkdGggID0gdmlld3BvcnRTaXplLndpZHRoO1xuICAgICAgICBjb25zdCBjdXJyZW50SGVpZ2h0ID0gdmlld3BvcnRTaXplLmhlaWdodDtcbiAgICAgICAgY29uc3QgbmV3V2lkdGggICAgICA9IG5ld0RpbWVuc2lvbnMud2lkdGggfHwgY3VycmVudFdpZHRoO1xuICAgICAgICBjb25zdCBuZXdIZWlnaHQgICAgID0gbmV3RGltZW5zaW9ucy5oZWlnaHQgfHwgY3VycmVudEhlaWdodDtcblxuICAgICAgICBpZiAoIWNvbmZpZy5oZWFkbGVzcylcbiAgICAgICAgICAgIGF3YWl0IHByb3ZpZGVyTWV0aG9kcy5yZXNpemVMb2NhbEJyb3dzZXJXaW5kb3coYnJvd3NlcklkLCBuZXdXaWR0aCwgbmV3SGVpZ2h0LCBjdXJyZW50V2lkdGgsIGN1cnJlbnRIZWlnaHQpO1xuXG4gICAgICAgIHZpZXdwb3J0U2l6ZS53aWR0aCAgPSBuZXdXaWR0aDtcbiAgICAgICAgdmlld3BvcnRTaXplLmhlaWdodCA9IG5ld0hlaWdodDtcblxuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldEFjdGl2ZUNsaWVudCgpO1xuXG4gICAgICAgIGlmIChjbGllbnQgJiYgY29uZmlnLmVtdWxhdGlvbikge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fc2V0RGV2aWNlTWV0cmljc092ZXJyaWRlKGNsaWVudCwgdmlld3BvcnRTaXplLndpZHRoLCB2aWV3cG9ydFNpemUuaGVpZ2h0LCBlbXVsYXRlZERldmljZVBpeGVsUmF0aW8sIGNvbmZpZy5tb2JpbGUpO1xuXG4gICAgICAgICAgICBhd2FpdCBndWFyZFRpbWVFeGVjdXRpb24oXG4gICAgICAgICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBjbGllbnQuRW11bGF0aW9uLnNldFZpc2libGVTaXplKHsgd2lkdGg6IHZpZXdwb3J0U2l6ZS53aWR0aCwgaGVpZ2h0OiB2aWV3cG9ydFNpemUuaGVpZ2h0IH0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZWxhcHNlZFRpbWUgPT4gdGhpcy5fY2hlY2tEcm9wT2ZQZXJmb3JtYW5jZShDaGVja2VkQ0RQTWV0aG9kLlNldFZpc2libGVTaXplLCBlbGFwc2VkVGltZSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgbWF4aW1pemVXaW5kb3dOYXRpdmVBdXRvbWF0aW9uICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gYXdhaXQgZ2V0Rmlyc3RUYWIodGhpcy5fcG9ydCk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0QWN0aXZlQ2xpZW50KCk7XG5cbiAgICAgICAgaWYgKGNsaWVudCkge1xuICAgICAgICAgICAgY29uc3Qgd2luZG93UGFyYW1zID0gYXdhaXQgY2xpZW50LkJyb3dzZXIuZ2V0V2luZG93Rm9yVGFyZ2V0KHsgdGFyZ2V0SWQ6IHRhcmdldC5pZCB9KTtcblxuICAgICAgICAgICAgYXdhaXQgY2xpZW50LkJyb3dzZXIuc2V0V2luZG93Qm91bmRzKHsgd2luZG93SWQ6IHdpbmRvd1BhcmFtcy53aW5kb3dJZCwgYm91bmRzOiB7IHdpbmRvd1N0YXRlOiAnbWF4aW1pemVkJyB9IH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHJlc2l6ZUJvdW5kcyAobmV3RGltZW5zaW9uczogU2l6ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCB7IHZpZXdwb3J0U2l6ZSB9ID0gdGhpcy5fcnVudGltZUluZm87XG5cbiAgICAgICAgbGV0IG5vbkNsaWVudFdpZHRoICA9IDA7XG4gICAgICAgIGxldCBub25DbGllbnRIZWlnaHQgPSAwO1xuXG4gICAgICAgIGlmICh2aWV3cG9ydFNpemUub3V0ZXJXaWR0aCAmJiB2aWV3cG9ydFNpemUub3V0ZXJIZWlnaHQpIHtcbiAgICAgICAgICAgIG5vbkNsaWVudFdpZHRoICA9IHZpZXdwb3J0U2l6ZS5vdXRlcldpZHRoIC0gdmlld3BvcnRTaXplLndpZHRoO1xuICAgICAgICAgICAgbm9uQ2xpZW50SGVpZ2h0ID0gdmlld3BvcnRTaXplLm91dGVySGVpZ2h0IC0gdmlld3BvcnRTaXplLmhlaWdodDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGF3YWl0IGdldEZpcnN0VGFiKHRoaXMuX3BvcnQpO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldEFjdGl2ZUNsaWVudCgpO1xuXG4gICAgICAgIGlmIChjbGllbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHdpbmRvd1BhcmFtcyA9IGF3YWl0IGNsaWVudC5Ccm93c2VyLmdldFdpbmRvd0ZvclRhcmdldCh7IHRhcmdldElkOiB0YXJnZXQuaWQgfSk7XG5cbiAgICAgICAgICAgIGlmICh3aW5kb3dQYXJhbXMuYm91bmRzLndpbmRvd1N0YXRlICE9PSAnbm9ybWFsJykge1xuICAgICAgICAgICAgICAgIGF3YWl0IGNsaWVudC5Ccm93c2VyLnNldFdpbmRvd0JvdW5kcyh7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvd0lkOiB3aW5kb3dQYXJhbXMud2luZG93SWQsXG4gICAgICAgICAgICAgICAgICAgIGJvdW5kczogICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3dTdGF0ZTogJ25vcm1hbCcsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGF3YWl0IGNsaWVudC5Ccm93c2VyLnNldFdpbmRvd0JvdW5kcyh7XG4gICAgICAgICAgICAgICAgd2luZG93SWQ6IHdpbmRvd1BhcmFtcy53aW5kb3dJZCxcbiAgICAgICAgICAgICAgICBib3VuZHM6ICAge1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogIG5ld0RpbWVuc2lvbnMud2lkdGggKyBub25DbGllbnRXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBuZXdEaW1lbnNpb25zLmhlaWdodCArIG5vbkNsaWVudEhlaWdodCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgaXNIZWFkbGVzc1RhYiAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX3BhcmVudFRhcmdldCAmJiB0aGlzLl9jb25maWcuaGVhZGxlc3M7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldENsaWVudEluYWN0aXZlICh3aW5kb3dJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuX2NsaWVudHNbd2luZG93SWRdO1xuXG4gICAgICAgIGlmIChjbGllbnQpXG4gICAgICAgICAgICBjbGllbnQuaW5hY3RpdmUgPSB0cnVlO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRBY3RpdmVDbGllbnQgKCk6IFByb21pc2U8cmVtb3RlQ2hyb21lLlByb3RvY29sQXBpIHwgdm9pZD4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9jbGllbnRzW3RoaXMuX2NsaWVudEtleV0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXQgPSBhd2FpdCBnZXRBY3RpdmVUYWIodGhpcy5fcG9ydCwgdGhpcy5fcnVudGltZUluZm8uYWN0aXZlV2luZG93SWQpO1xuXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5fY3JlYXRlQ2xpZW50KHRhcmdldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgZGVidWdMb2coZXJyKTtcblxuICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGluZm8gPSB0aGlzLl9jbGllbnRzW3RoaXMuX2NsaWVudEtleV07XG5cbiAgICAgICAgaWYgKGluZm8uaW5hY3RpdmUpXG4gICAgICAgICAgICByZXR1cm4gdm9pZCAwO1xuXG4gICAgICAgIHJldHVybiBpbmZvLmNsaWVudDtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgaW5pdE1haW5XaW5kb3dDZHBDbGllbnQgKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgdGFicyA9IGF3YWl0IGdldFRhYnModGhpcy5fcG9ydCk7XG5cbiAgICAgICAgICAgIHRoaXMuX3BhcmVudFRhcmdldCA9IHRhYnMuZmluZCh0ID0+IHQudXJsLmluY2x1ZGVzKHRoaXMuX3J1bnRpbWVJbmZvLmJyb3dzZXJJZCkpO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuX3BhcmVudFRhcmdldClcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0QWN0aXZlQ2xpZW50KCk7XG5cbiAgICAgICAgICAgIGlmIChjbGllbnQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9jYWxjdWxhdGVFbXVsYXRlZERldmljZVBpeGVsUmF0aW8oY2xpZW50KTtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9zZXR1cENsaWVudChjbGllbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0U2NyZWVuc2hvdERhdGEgKGZ1bGxQYWdlPzogYm9vbGVhbik6IFByb21pc2U8QnVmZmVyPiB7XG4gICAgICAgIGxldCBjbGlwOiBQcm90b2NvbC5QYWdlLlZpZXdwb3J0IHwgdW5kZWZpbmVkID0gdm9pZCAwO1xuXG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0QWN0aXZlQ2xpZW50KCk7XG5cbiAgICAgICAgaWYgKCFjbGllbnQpIHtcbiAgICAgICAgICAgIC8vIE5PVEU6IHJlcXVpcmVkIGZvciBodHRwczovL2dpdGh1Yi5jb20vRGV2RXhwcmVzcy90ZXN0Y2FmZS9pc3N1ZXMvNjAzN1xuICAgICAgICAgICAgYXdhaXQgZGVsYXkoMCk7XG5cbiAgICAgICAgICAgIHJldHVybiBCdWZmZXIuYWxsb2MoMCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZnVsbFBhZ2UpIHtcbiAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgICAgICAgICAgID0gYXdhaXQgY2xpZW50LlBhZ2UuZ2V0TGF5b3V0TWV0cmljcygpO1xuICAgICAgICAgICAgY29uc3QgeyB3aWR0aCwgaGVpZ2h0IH0gPSBtZXRyaWNzLmNzc0NvbnRlbnRTaXplIHx8IG1ldHJpY3MuY29udGVudFNpemU7XG5cbiAgICAgICAgICAgIGNsaXAgPSB7IHg6IDAsIHk6IDAsIHdpZHRoLCBoZWlnaHQsIHNjYWxlOiAxIH07XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjbGllbnQuUGFnZS5jYXB0dXJlU2NyZWVuc2hvdCh7XG4gICAgICAgICAgICBjbGlwLFxuICAgICAgICAgICAgY2FwdHVyZUJleW9uZFZpZXdwb3J0OiBmdWxsUGFnZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHJlc3VsdC5kYXRhLCAnYmFzZTY0Jyk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGNsb3NlVGFiICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKHRoaXMuX3BhcmVudFRhcmdldClcbiAgICAgICAgICAgIGF3YWl0IHJlbW90ZUNocm9tZS5DbG9zZSh7IGlkOiB0aGlzLl9wYXJlbnRUYXJnZXQuaWQsIHBvcnQ6IHRoaXMuX3BvcnQgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHVwZGF0ZU1vYmlsZVZpZXdwb3J0U2l6ZSAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0QWN0aXZlQ2xpZW50KCk7XG5cbiAgICAgICAgaWYgKCFjbGllbnQpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgY29uc3Qgd2luZG93RGltZW5zaW9uc1F1ZXJ5UmVzdWx0ID0gYXdhaXQgdGhpcy5fZXZhbHVhdGVSdW50aW1lKGNsaWVudCwgYCgke0dFVF9XSU5ET1dfRElNRU5TSU9OU19JTkZPX1NDUklQVH0pKClgLCB0cnVlKTtcblxuICAgICAgICBjb25zdCB3aW5kb3dEaW1lbnNpb25zID0gd2luZG93RGltZW5zaW9uc1F1ZXJ5UmVzdWx0LnJlc3VsdC52YWx1ZTtcblxuICAgICAgICB0aGlzLl9ydW50aW1lSW5mby52aWV3cG9ydFNpemUud2lkdGggID0gd2luZG93RGltZW5zaW9ucy5vdXRlcldpZHRoO1xuICAgICAgICB0aGlzLl9ydW50aW1lSW5mby52aWV3cG9ydFNpemUuaGVpZ2h0ID0gd2luZG93RGltZW5zaW9ucy5vdXRlckhlaWdodDtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgY2xvc2VCcm93c2VyQ2hpbGRXaW5kb3cgKHdpbmRvd0lkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zZXRDbGllbnRJbmFjdGl2ZSh3aW5kb3dJZCk7XG5cbiAgICAgICAgLy8gTk9URTogZGVsYXkgYnJvd3NlciB3aW5kb3cgY2xvc2luZ1xuICAgICAgICBhd2FpdCBkZWxheSgxMDApO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzdGFydENhcHR1cmluZ1ZpZGVvICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRBY3RpdmVDbGllbnQoKTtcblxuICAgICAgICBpZiAoIWNsaWVudClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBpZiAoIXRoaXMuX3NjcmVlbmNhc3RGcmFtZUxpc3RlbmVyQXR0YWNoZWQpIHtcbiAgICAgICAgICAgIGNsaWVudC5QYWdlLm9uKCdzY3JlZW5jYXN0RnJhbWUnLCAoZXZlbnQ6IFNjcmVlbmNhc3RGcmFtZUV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlkZW9GcmFtZXNCdWZmZXIucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGRhdGE6ICAgICAgZXZlbnQuZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiBldmVudC5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGhpcy5fc2NyZWVuY2FzdEZyYW1lTGlzdGVuZXJBdHRhY2hlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCBjbGllbnQuUGFnZS5zdGFydFNjcmVlbmNhc3QoU0NSRUVOQ0FTVF9PUFRJT05TIGFzIFN0YXJ0U2NyZWVuY2FzdFJlcXVlc3QpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzdG9wQ2FwdHVyaW5nVmlkZW8gKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldEFjdGl2ZUNsaWVudCgpO1xuXG4gICAgICAgIGlmICghY2xpZW50KVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGF3YWl0IGNsaWVudC5QYWdlLnN0b3BTY3JlZW5jYXN0KCk7XG5cbiAgICAgICAgdGhpcy5fbGFzdEZyYW1lICAgICAgICAgPSBudWxsO1xuICAgICAgICB0aGlzLl92aWRlb0ZyYW1lc0J1ZmZlciA9IFtdO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRWaWRlb0ZyYW1lRGF0YSAoKTogUHJvbWlzZTxCdWZmZXIgfCBudWxsPiB7XG4gICAgICAgIGNvbnN0IGZpcnN0RnJhbWVGcm9tQnVmZmVyID0gdGhpcy5fdmlkZW9GcmFtZXNCdWZmZXIuc2hpZnQoKTtcbiAgICAgICAgY29uc3QgY3VycmVudFZpZGVvRnJhbWUgICAgPSBmaXJzdEZyYW1lRnJvbUJ1ZmZlciB8fCB0aGlzLl9sYXN0RnJhbWU7XG5cbiAgICAgICAgaWYgKCFjdXJyZW50VmlkZW9GcmFtZSlcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICAgIGlmICh0aGlzLl92aWRlb0ZyYW1lc0J1ZmZlci5sZW5ndGggPT09IDApXG4gICAgICAgICAgICB0aGlzLl9sYXN0RnJhbWUgPSBjdXJyZW50VmlkZW9GcmFtZTtcblxuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldEFjdGl2ZUNsaWVudCgpO1xuXG4gICAgICAgIGlmICghY2xpZW50KVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG5cbiAgICAgICAgaWYgKGZpcnN0RnJhbWVGcm9tQnVmZmVyKVxuICAgICAgICAgICAgYXdhaXQgY2xpZW50LlBhZ2Uuc2NyZWVuY2FzdEZyYW1lQWNrKHsgc2Vzc2lvbklkOiBjdXJyZW50VmlkZW9GcmFtZS5zZXNzaW9uSWQgfSk7XG5cbiAgICAgICAgcmV0dXJuIE