UNPKG

@nota/nativescript-webview-ext

Version:

Extended WebView for NativeScript which adds 'x-local' scheme for local-files. events between WebView and native-layer, javascript execution, injecting CSS and JS-files.

528 lines 74.7 kB
"use strict"; function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; } Object.defineProperty(exports, "__esModule", { value: true }); var fs = require("tns-core-modules/file-system"); var webview_ext_common_1 = require("./webview-ext-common"); __export(require("./webview-ext-common")); var extToMimeType = new Map([ ["html", "text/html"], ["htm", "text/html"], ["xhtml", "text/html"], ["xhtm", "text/html"], ["css", "text/css"], ["gif", "image/gif"], ["jpeg", "image/jpeg"], ["jpg", "image/jpeg"], ["js", "text/javascript"], ["otf", "application/vnd.ms-opentype"], ["png", "image/png"], ["svg", "image/svg+xml"], ["ttf", "application/x-font-ttf"], ]); var extToBinaryEncoding = new Set(["gif", "jpeg", "jpg", "otf", "png", "ttf"]); var cacheModeMap; var WebViewExtClient; var WebViewBridgeInterface; function initializeWebViewClient() { if (WebViewExtClient) { return; } cacheModeMap = new Map([ ["cache_first", android.webkit.WebSettings.LOAD_CACHE_ELSE_NETWORK], ["cache_only", android.webkit.WebSettings.LOAD_CACHE_ONLY], ["default", android.webkit.WebSettings.LOAD_DEFAULT], ["no_cache", android.webkit.WebSettings.LOAD_NO_CACHE], ]); var WebViewExtClientImpl = (function (_super) { __extends(WebViewExtClientImpl, _super); function WebViewExtClientImpl(owner) { var _this = _super.call(this) || this; _this.owner = owner; return global.__native(_this); } WebViewExtClientImpl.prototype.shouldOverrideUrlLoading = function (view, request) { var owner = this.owner; if (!owner) { console.warn("WebViewExtClientImpl.shouldOverrideUrlLoading(...) - no owner"); return true; } var url = request; var httpMethod = "GET"; var isRedirect = false; var hasGesture = false; var isForMainFrame = false; var requestHeaders = null; if (typeof request === "object") { httpMethod = request.getMethod(); isRedirect = request.isRedirect(); hasGesture = request.hasGesture(); isForMainFrame = request.isForMainFrame(); requestHeaders = request.getRequestHeaders(); url = request.getUrl().toString(); } owner.writeTrace("WebViewClientClass.shouldOverrideUrlLoading(\"" + url + "\") - method:" + httpMethod + " isRedirect:" + isRedirect + " hasGesture:" + hasGesture + " isForMainFrame:" + isForMainFrame + " headers:" + requestHeaders); if (url.startsWith(owner.interceptScheme)) { owner.writeTrace("WebViewClientClass.shouldOverrideUrlLoading(\"" + url + "\") - \"" + owner.interceptScheme + "\" - cancel"); return true; } var shouldOverrideUrlLoading = owner._onShouldOverrideUrlLoading(url, httpMethod); if (shouldOverrideUrlLoading === true) { owner.writeTrace("WebViewClientClass.shouldOverrideUrlLoading(\"" + url + "\") - cancel loading url"); return true; } return false; }; WebViewExtClientImpl.prototype.shouldInterceptRequest = function (view, request) { var owner = this.owner; if (!owner) { console.warn("WebViewExtClientImpl.shouldInterceptRequest(...) - no owner"); return _super.prototype.shouldInterceptRequest.call(this, view, request); } var url = request; if (typeof request === "object") { url = request.getUrl().toString(); } if (typeof url !== "string") { owner.writeTrace("WebViewClientClass.shouldInterceptRequest(\"" + url + "\") - is not a string"); return _super.prototype.shouldInterceptRequest.call(this, view, request); } if (!url.startsWith(owner.interceptScheme)) { return _super.prototype.shouldInterceptRequest.call(this, view, request); } var filepath = owner.getRegisteredLocalResource(url); if (!filepath) { owner.writeTrace("WebViewClientClass.shouldInterceptRequest(\"" + url + "\") - no matching file"); return _super.prototype.shouldInterceptRequest.call(this, view, request); } if (!fs.File.exists(filepath)) { owner.writeTrace("WebViewClientClass.shouldInterceptRequest(\"" + url + "\") - file: \"" + filepath + "\" doesn't exists"); return _super.prototype.shouldInterceptRequest.call(this, view, request); } var tnsFile = fs.File.fromPath(filepath); var javaFile = new java.io.File(tnsFile.path); var stream = new java.io.FileInputStream(javaFile); var ext = tnsFile.extension.substr(1).toLowerCase(); var mimeType = extToMimeType.get(ext) || "application/octet-stream"; var encoding = extToBinaryEncoding.has(ext) || mimeType === "application/octet-stream" ? "binary" : "UTF-8"; owner.writeTrace("WebViewClientClass.shouldInterceptRequest(\"" + url + "\") - file: \"" + filepath + "\" mimeType:" + mimeType + " encoding:" + encoding); var response = new android.webkit.WebResourceResponse(mimeType, encoding, stream); if (webview_ext_common_1.androidSDK < 21) { return response; } var r = response; if (!r.getResponseHeaders) { return response; } var responseHeaders = r.getResponseHeaders() || new java.util.HashMap(); responseHeaders.put("Access-Control-Allow-Origin", "*"); r.setResponseHeaders(responseHeaders); return response; }; WebViewExtClientImpl.prototype.onPageStarted = function (view, url, favicon) { _super.prototype.onPageStarted.call(this, view, url, favicon); var owner = this.owner; if (!owner) { console.warn("WebViewExtClientImpl.onPageStarted(...) - no owner"); return; } owner.writeTrace("WebViewClientClass.onPageStarted(\"" + url + "\", \"" + favicon + "\")"); owner._onLoadStarted(url); }; WebViewExtClientImpl.prototype.onPageFinished = function (view, url) { _super.prototype.onPageFinished.call(this, view, url); var owner = this.owner; if (!owner) { console.warn("WebViewExtClientImpl.onPageFinished(...) - no owner"); return; } owner.writeTrace("WebViewClientClass.onPageFinished(\"" + url + "\")"); owner._onLoadFinished(url).catch(function () { return void 0; }); }; WebViewExtClientImpl.prototype.onReceivedError = function () { if (arguments.length === 4) { var _a = Array.from(arguments), view = _a[0], errorCode = _a[1], description = _a[2], failingUrl = _a[3]; this.onReceivedErrorBeforeAPI23(view, errorCode, description, failingUrl); } else { var _b = Array.from(arguments), view = _b[0], request = _b[1], error = _b[2]; this.onReceivedErrorAPI23(view, request, error); } }; WebViewExtClientImpl.prototype.onReceivedErrorAPI23 = function (view, request, error) { _super.prototype.onReceivedError.call(this, view, request, error); var owner = this.owner; if (!owner) { console.warn("WebViewExtClientImpl.onReceivedErrorAPI23(...) - no owner"); return; } var url = error.getUrl && error.getUrl(); if (!url && typeof request === "object") { url = request.getUrl().toString(); } owner.writeTrace("WebViewClientClass.onReceivedErrorAPI23(" + error.getErrorCode() + ", " + error.getDescription() + ", " + url + ")"); owner._onLoadFinished(url, error.getDescription() + "(" + error.getErrorCode() + ")").catch(function () { return void 0; }); }; WebViewExtClientImpl.prototype.onReceivedErrorBeforeAPI23 = function (view, errorCode, description, failingUrl) { _super.prototype.onReceivedError.call(this, view, errorCode, description, failingUrl); var owner = this.owner; if (!owner) { console.warn("WebViewExtClientImpl.onReceivedErrorBeforeAPI23(...) - no owner"); return; } owner.writeTrace("WebViewClientClass.onReceivedErrorBeforeAPI23(" + errorCode + ", \"" + description + "\", \"" + failingUrl + "\")"); owner._onLoadFinished(failingUrl, description + "(" + errorCode + ")").catch(function () { return void 0; }); }; return WebViewExtClientImpl; }(android.webkit.WebViewClient)); WebViewExtClient = WebViewExtClientImpl; var WebViewBridgeInterfaceImpl = (function (_super) { __extends(WebViewBridgeInterfaceImpl, _super); function WebViewBridgeInterfaceImpl(owner) { var _this = _super.call(this) || this; _this.owner = owner; return global.__native(_this); } WebViewBridgeInterfaceImpl.prototype.emitEventToNativeScript = function (eventName, data) { var owner = this.owner; if (!owner) { console.warn("WebViewExtClientImpl.onReceivedErrorBeforeAPI23(...) - no owner"); return; } try { owner.onWebViewEvent(eventName, JSON.parse(data)); return; } catch (_a) { } owner.onWebViewEvent(eventName, data); }; return WebViewBridgeInterfaceImpl; }(dk.nota.webviewinterface.WebViewBridgeInterface)); WebViewBridgeInterface = WebViewBridgeInterfaceImpl; } var instanceNo = 0; var WebViewExt = (function (_super) { __extends(WebViewExt, _super); function WebViewExt() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.localResourceMap = new Map(); _this.instance = ++instanceNo; return _this; } Object.defineProperty(WebViewExt.prototype, "isUIWebView", { get: function () { return false; }, enumerable: true, configurable: true }); Object.defineProperty(WebViewExt.prototype, "isWKWebView", { get: function () { return false; }, enumerable: true, configurable: true }); WebViewExt.prototype.createNativeView = function () { var nativeView = new android.webkit.WebView(this._context); var settings = nativeView.getSettings(); settings.setJavaScriptEnabled(true); settings.setBuiltInZoomControls(true); settings.setAllowUniversalAccessFromFileURLs(true); return nativeView; }; WebViewExt.prototype.initNativeView = function () { _super.prototype.initNativeView.call(this); initializeWebViewClient(); var nativeView = this.nativeViewProtected; if (!nativeView) { return; } var client = new WebViewExtClient(this); nativeView.setWebViewClient(client); nativeView.client = client; var bridgeInterface = new WebViewBridgeInterface(this); nativeView.addJavascriptInterface(bridgeInterface, "androidWebViewBridge"); nativeView.bridgeInterface = bridgeInterface; }; WebViewExt.prototype.disposeNativeView = function () { var nativeView = this.nativeViewProtected; if (nativeView) { nativeView.client.owner = null; nativeView.bridgeInterface.owner = null; nativeView.destroy(); } _super.prototype.disposeNativeView.call(this); }; WebViewExt.prototype._loadUrl = function (src) { var nativeView = this.nativeViewProtected; if (!nativeView) { return; } this.writeTrace("WebViewExt<android>._loadUrl(\"" + src + "\")"); nativeView.loadUrl(src); }; WebViewExt.prototype._loadData = function (src) { var nativeView = this.nativeViewProtected; if (!nativeView) { return; } var baseUrl = "file:///" + fs.knownFolders.currentApp().path + "/"; this.writeTrace("WebViewExt<android>._loadData(\"" + src + "\") -> baseUrl: \"" + baseUrl + "\""); nativeView.loadDataWithBaseURL(baseUrl, src, "text/html", "utf-8", null); }; Object.defineProperty(WebViewExt.prototype, "canGoBack", { get: function () { var nativeView = this.nativeViewProtected; if (nativeView) { return nativeView.canGoBack(); } return false; }, enumerable: true, configurable: true }); WebViewExt.prototype.stopLoading = function () { var nativeView = this.nativeViewProtected; if (nativeView) { nativeView.stopLoading(); } }; Object.defineProperty(WebViewExt.prototype, "canGoForward", { get: function () { var nativeView = this.nativeViewProtected; if (nativeView) { return nativeView.canGoForward(); } return false; }, enumerable: true, configurable: true }); WebViewExt.prototype.goBack = function () { var nativeView = this.nativeViewProtected; if (nativeView) { return nativeView.goBack(); } }; WebViewExt.prototype.goForward = function () { var nativeView = this.nativeViewProtected; if (nativeView) { return nativeView.goForward(); } }; WebViewExt.prototype.reload = function () { var nativeView = this.nativeViewProtected; if (nativeView) { return nativeView.reload(); } }; WebViewExt.prototype.registerLocalResource = function (resourceName, path) { resourceName = this.fixLocalResourceName(resourceName); var filepath = this.resolveLocalResourceFilePath(path); if (!filepath) { this.writeTrace("WebViewExt<android>.registerLocalResource(\"" + resourceName + "\", \"" + path + "\") -> file doesn't exist", webview_ext_common_1.traceMessageType.error); return; } this.writeTrace("WebViewExt<android>.registerLocalResource(\"" + resourceName + "\", \"" + path + "\") -> file: \"" + filepath + "\""); this.localResourceMap.set(resourceName, filepath); }; WebViewExt.prototype.unregisterLocalResource = function (resourceName) { this.writeTrace("WebViewExt<android>.unregisterLocalResource(\"" + resourceName + "\")"); resourceName = this.fixLocalResourceName(resourceName); this.localResourceMap.delete(resourceName); }; WebViewExt.prototype.getRegisteredLocalResource = function (resourceName) { resourceName = this.fixLocalResourceName(resourceName); var result = this.localResourceMap.get(resourceName); this.writeTrace("WebViewExt<android>.getRegisteredLocalResource(\"" + resourceName + "\") => \"" + result + "\""); return result; }; WebViewExt.prototype.ensureFetchSupport = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: this.writeTrace("WebViewExt<android>.ensureFetchSupport() - Override 'Fetch API' to support x-local."); return [4, this.executeJavaScript("\n try {\n window.fetch = null;\n } catch (err) {\n console.error(\"null'ing Native Fetch API failed:\", err);\n }\n ")]; case 1: _a.sent(); return [4, this.loadFetchPolyfill()]; case 2: _a.sent(); return [2]; } }); }); }; WebViewExt.prototype.executeJavaScript = function (scriptCode) { return __awaiter(this, void 0, void 0, function () { var result; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: if (webview_ext_common_1.androidSDK < 19) { this.writeTrace("WebViewExt<android>.executeJavaScript() -> SDK:" + webview_ext_common_1.androidSDK + " not supported", webview_ext_common_1.traceMessageType.error); return [2, Promise.reject(new webview_ext_common_1.UnsupportSDKError(19))]; } return [4, new Promise(function (resolve, reject) { if (!_this.nativeViewProtected) { _this.writeTrace("WebViewExt<android>.executeJavaScript() -> no nativeview?", webview_ext_common_1.traceMessageType.error); reject(new Error("Native Android not inited, cannot call executeJavaScript")); return; } _this.nativeViewProtected.evaluateJavascript(scriptCode, new android.webkit.ValueCallback({ onReceiveValue: function (result) { resolve(result); }, })); })]; case 1: result = _a.sent(); return [4, this.parseWebViewJavascriptResult(result)]; case 2: return [2, _a.sent()]; } }); }); }; WebViewExt.prototype.getTitle = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2, this.nativeViewProtected && this.nativeViewProtected.getTitle()]; }); }); }; WebViewExt.prototype.zoomIn = function () { if (!this.nativeViewProtected) { return false; } return this.nativeViewProtected.zoomIn(); }; WebViewExt.prototype.zoomOut = function () { if (!this.nativeViewProtected) { return false; } return this.nativeViewProtected.zoomOut(); }; WebViewExt.prototype.zoomBy = function (zoomFactor) { if (webview_ext_common_1.androidSDK < 21) { this.writeTrace("WebViewExt<android>.zoomBy - not supported on this SDK"); return; } if (!this.nativeViewProtected) { return; } if (zoomFactor >= 0.01 && zoomFactor <= 100) { return this.nativeViewProtected.zoomBy(zoomFactor); } throw new Error("ZoomBy only accepts values between 0.01 and 100 both inclusive"); }; WebViewExt.prototype[webview_ext_common_1.debugModeProperty.getDefault] = function () { return false; }; WebViewExt.prototype[webview_ext_common_1.debugModeProperty.setNative] = function (enabled) { android.webkit.WebView.setWebContentsDebuggingEnabled(!!enabled); }; WebViewExt.prototype[webview_ext_common_1.builtInZoomControlsProperty.getDefault] = function () { if (!this.nativeViewProtected) { return false; } var settings = this.nativeViewProtected.getSettings(); return settings.getBuiltInZoomControls(); }; WebViewExt.prototype[webview_ext_common_1.builtInZoomControlsProperty.setNative] = function (enabled) { if (!this.nativeViewProtected) { return; } var settings = this.nativeViewProtected.getSettings(); settings.setBuiltInZoomControls(!!enabled); }; WebViewExt.prototype[webview_ext_common_1.displayZoomControlsProperty.getDefault] = function () { if (!this.nativeViewProtected) { return false; } var settings = this.nativeViewProtected.getSettings(); return settings.getDisplayZoomControls(); }; WebViewExt.prototype[webview_ext_common_1.displayZoomControlsProperty.setNative] = function (enabled) { if (!this.nativeViewProtected) { return; } var settings = this.nativeViewProtected.getSettings(); settings.setDisplayZoomControls(!!enabled); }; WebViewExt.prototype[webview_ext_common_1.cacheModeProperty.getDefault] = function () { if (!this.nativeViewProtected) { return null; } var settings = this.nativeViewProtected.getSettings(); var cacheModeInt = settings.getCacheMode(); for (var _i = 0, _a = Array.from(cacheModeMap); _i < _a.length; _i++) { var _b = _a[_i], key = _b[0], value = _b[1]; if (value === cacheModeInt) { return key; } } return null; }; WebViewExt.prototype[webview_ext_common_1.cacheModeProperty.setNative] = function (cacheMode) { if (!this.nativeViewProtected) { return; } var settings = this.nativeViewProtected.getSettings(); for (var _i = 0, _a = Array.from(cacheModeMap); _i < _a.length; _i++) { var _b = _a[_i], key = _b[0], nativeValue = _b[1]; if (key === cacheMode) { settings.setCacheMode(nativeValue); return; } } }; WebViewExt.prototype[webview_ext_common_1.databaseStorageProperty.getDefault] = function () { if (!this.nativeViewProtected) { return false; } var settings = this.nativeViewProtected.getSettings(); return settings.getDatabaseEnabled(); }; WebViewExt.prototype[webview_ext_common_1.databaseStorageProperty.setNative] = function (enabled) { if (!this.nativeViewProtected) { return; } var settings = this.nativeViewProtected.getSettings(); settings.setDatabaseEnabled(!!enabled); }; WebViewExt.prototype[webview_ext_common_1.domStorageProperty.getDefault] = function () { if (!this.nativeViewProtected) { return false; } var settings = this.nativeViewProtected.getSettings(); return settings.getDomStorageEnabled(); }; WebViewExt.prototype[webview_ext_common_1.domStorageProperty.setNative] = function (enabled) { if (!this.nativeViewProtected) { return; } var settings = this.nativeViewProtected.getSettings(); settings.setDomStorageEnabled(!!enabled); }; WebViewExt.prototype[webview_ext_common_1.supportZoomProperty.getDefault] = function () { if (!this.nativeViewProtected) { return false; } var settings = this.nativeViewProtected.getSettings(); return settings.supportZoom(); }; WebViewExt.prototype[webview_ext_common_1.supportZoomProperty.setNative] = function (enabled) { if (!this.nativeViewProtected) { return; } var settings = this.nativeViewProtected.getSettings(); settings.setSupportZoom(!!enabled); }; return WebViewExt; }(webview_ext_common_1.WebViewExtBase)); exports.WebViewExt = WebViewExt; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vidmlldy1leHQuYW5kcm9pZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIndlYnZpZXctZXh0LmFuZHJvaWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFFQSxpREFBbUQ7QUFDbkQsMkRBWThCO0FBRTlCLDBDQUFxQztBQUVyQyxJQUFNLGFBQWEsR0FBRyxJQUFJLEdBQUcsQ0FBaUI7SUFDMUMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDO0lBQ3JCLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQztJQUNwQixDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUM7SUFDdEIsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDO0lBQ3JCLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQztJQUNuQixDQUFDLEtBQUssRUFBRSxXQUFXLENBQUM7SUFDcEIsQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDO0lBQ3RCLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQztJQUNyQixDQUFDLElBQUksRUFBRSxpQkFBaUIsQ0FBQztJQUN6QixDQUFDLEtBQUssRUFBRSw2QkFBNkIsQ0FBQztJQUN0QyxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUM7SUFDcEIsQ0FBQyxLQUFLLEVBQUUsZUFBZSxDQUFDO0lBQ3hCLENBQUMsS0FBSyxFQUFFLHdCQUF3QixDQUFDO0NBQ3BDLENBQUMsQ0FBQztBQUVILElBQU0sbUJBQW1CLEdBQUcsSUFBSSxHQUFHLENBQVMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFLekYsSUFBSSxZQUFvQyxDQUFDO0FBc0J6QyxJQUFJLGdCQUFpRSxDQUFDO0FBQ3RFLElBQUksc0JBQWtHLENBQUM7QUFFdkcsU0FBUyx1QkFBdUI7SUFDNUIsSUFBSSxnQkFBZ0IsRUFBRTtRQUNsQixPQUFPO0tBQ1Y7SUFFRCxZQUFZLEdBQUcsSUFBSSxHQUFHLENBQW9CO1FBQ3RD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LENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRCxxQkFBQyx3Q0FBbUIsQ0FBQyxVQUFVLENBQUMsR0FBaEM7UUFDSSxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFO1lBQzNCLE9BQU8sS0FBSyxDQUFDO1NBQ2hCO1FBRUQsSUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3hELE9BQU8sUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFFRCxxQkFBQyx3Q0FBbUIsQ0FBQyxTQUFTLENBQUMsR0FBL0IsVUFBZ0MsT0FBZ0I7UUFDNUMsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRTtZQUMzQixPQUFPO1NBQ1Y7UUFFRCxJQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDeEQsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUNMLGlCQUFDO0FBQUQsQ0FBQyxBQXhXRCxDQUFnQyxtQ0FBYyxHQXdXN0M7QUF4V1ksZ0NBQVUiLCJzb3VyY2VzQ29udGVudCI6WyIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9wbGF0Zm9ybXMvYW5kcm9pZC93ZWJ2aWV3aW50ZXJmYWNlLmQudHNcIiAvPlxuXG5pbXBvcnQgKiBhcyBmcyBmcm9tIFwidG5zLWNvcmUtbW9kdWxlcy9maWxlLXN5c3RlbVwiO1xuaW1wb3J0IHtcbiAgICBhbmRyb2lkU0RLLFxuICAgIGJ1aWx0SW5ab29tQ29udHJvbHNQcm9wZXJ0eSxcbiAgICBjYWNoZU1vZGVQcm9wZXJ0eSxcbiAgICBkYXRhYmFzZVN0b3JhZ2VQcm9wZXJ0eSxcbiAgICBkZWJ1Z01vZGVQcm9wZXJ0eSxcbiAgICBkaXNwbGF5Wm9vbUNvbnRyb2xzUHJvcGVydHksXG4gICAgZG9tU3RvcmFnZVByb3BlcnR5LFxuICAgIHN1cHBvcnRab29tUHJvcGVydHksXG4gICAgdHJhY2VNZXNzYWdlVHlwZSxcbiAgICBVbnN1cHBvcnRTREtFcnJvcixcbiAgICBXZWJWaWV3RXh0QmFzZSxcbn0gZnJvbSBcIi4vd2Vidmlldy1leHQtY29tbW9uXCI7XG5cbmV4cG9ydCAqIGZyb20gXCIuL3dlYnZpZXctZXh0LWNvbW1vblwiO1xuXG5jb25zdCBleHRUb01pbWVUeXBlID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oW1xuICAgIFtcImh0bWxcIiwgXCJ0ZXh0L2h0bWxcIl0sXG4gICAgW1wiaHRtXCIsIFwidGV4dC9odG1sXCJdLFxuICAgIFtcInhodG1sXCIsIFwidGV4dC9odG1sXCJdLFxuICAgIFtcInhodG1cIiwgXCJ0ZXh0L2h0bWxcIl0sXG4gICAgW1wiY3NzXCIsIFwidGV4dC9jc3NcIl0sXG4gICAgW1wiZ2lmXCIsIFwiaW1hZ2UvZ2lmXCJdLFxuICAgIFtcImpwZWdcIiwgXCJpbWFnZS9qcGVnXCJdLFxuICAgIFtcImpwZ1wiLCBcImltYWdlL2pwZWdcIl0sXG4gICAgW1wianNcIiwgXCJ0ZXh0L2phdmFzY3JpcHRcIl0sXG4gICAgW1wib3RmXCIsIFwiYXBwbGljYXRpb24vdm5kLm1zLW9wZW50eXBlXCJdLFxuICAgIFtcInBuZ1wiLCBcImltYWdlL3BuZ1wiXSxcbiAgICBbXCJzdmdcIiwgXCJpbWFnZS9zdmcreG1sXCJdLFxuICAgIFtcInR0ZlwiLCBcImFwcGxpY2F0aW9uL3gtZm9udC10dGZcIl0sXG5dKTtcblxuY29uc3QgZXh0VG9CaW5hcnlFbmNvZGluZyA9IG5ldyBTZXQ8c3RyaW5nPihbXCJnaWZcIiwgXCJqcGVnXCIsIFwianBnXCIsIFwib3RmXCIsIFwicG5nXCIsIFwidHRmXCJdKTtcblxudHlwZSBDYWNoZU1vZGUgPSBcImRlZmF1bHRcIiB8IFwiY2FjaGVfZmlyc3RcIiB8IFwibm9fY2FjaGVcIiB8IFwiY2FjaGVfb25seVwiO1xuXG4vLyNyZWdpb24gYW5kcm9pZF9uYXRpdmVfY2xhc3Nlc1xubGV0IGNhY2hlTW9kZU1hcDogTWFwPENhY2hlTW9kZSwgbnVtYmVyPjtcblxuLy8gTWlub3IgZXh0ZW50aW9uIG9mIHRoZSBOYXRpdmUgaW50ZXJmYWNlIHRvIGFsbG93IGZvciBvd25lclxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIGRrIHtcbiAgICBuYW1lc3BhY2Ugbm90YSB7XG4gICAgICAgIG5hbWVzcGFjZSB3ZWJ2aWV3aW50ZXJmYWNlIHtcbiAgICAgICAgICAgIGNsYXNzIFdlYlZpZXdCcmlkZ2VJbnRlcmZhY2UgZXh0ZW5kcyBqYXZhLmxhbmcuT2JqZWN0IHtcbiAgICAgICAgICAgICAgICBwdWJsaWMgb3duZXI/OiBXZWJWaWV3RXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFuZHJvaWRXZWJWaWV3Q2xpZW50IGV4dGVuZHMgYW5kcm9pZC53ZWJraXQuV2ViVmlld0NsaWVudCB7XG4gICAgb3duZXI6IFdlYlZpZXdFeHQgfCBudWxsO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFuZHJvaWRXZWJWaWV3IGV4dGVuZHMgYW5kcm9pZC53ZWJraXQuV2ViVmlldyB7XG4gICAgY2xpZW50OiBBbmRyb2lkV2ViVmlld0NsaWVudCB8IG51bGw7XG4gICAgYnJpZGdlSW50ZXJmYWNlPzogZGsubm90YS53ZWJ2aWV3aW50ZXJmYWNlLldlYlZpZXdCcmlkZ2VJbnRlcmZhY2U7XG59XG5cbmxldCBXZWJWaWV3RXh0Q2xpZW50OiBuZXcgKG93bmVyOiBXZWJWaWV3RXh0KSA9PiBBbmRyb2lkV2ViVmlld0NsaWVudDtcbmxldCBXZWJWaWV3QnJpZGdlSW50ZXJmYWNlOiBuZXcgKG93bmVyOiBXZWJWaWV3RXh0KSA9PiBkay5ub3RhLndlYnZpZXdpbnRlcmZhY2UuV2ViVmlld0JyaWRnZUludGVyZmFjZTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVdlYlZpZXdDbGllbnQoKTogdm9pZCB7XG4gICAgaWYgKFdlYlZpZXdFeHRDbGllbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNhY2hlTW9kZU1hcCA9IG5ldyBNYXA8Q2FjaGVNb2RlLCBudW1iZXI+KFtcbiAgICAgICAgW1wiY2FjaGVfZmlyc3RcIiwgYW5kcm9pZC53ZWJraXQuV2ViU2V0dGluZ3MuTE9BRF9DQUNIRV9FTFNFX05FVFdPUktdLFxuICAgICAgICBbXCJjYWNoZV9vbmx5XCIsIGFuZHJvaWQud2Via2l0LldlYlNldHRpbmdzLkxPQURfQ0FDSEVfT05MWV0sXG4gICAgICAgIFtcImRlZmF1bHRcIiwgYW5kcm9pZC53ZWJraXQuV2ViU2V0dGluZ3MuTE9BRF9ERUZBVUxUXSxcbiAgICAgICAgW1wibm9fY2FjaGVcIiwgYW5kcm9pZC53ZWJraXQuV2ViU2V0dGluZ3MuTE9BRF9OT19DQUNIRV0sXG4gICAgXSk7XG5cbiAgICBjbGFzcyBXZWJWaWV3RXh0Q2xpZW50SW1wbCBleHRlbmRzIGFuZHJvaWQud2Via2l0LldlYlZpZXdDbGllbnQge1xuICAgICAgICBjb25zdHJ1Y3RvcihwdWJsaWMgb3duZXI6IFdlYlZpZXdFeHQpIHtcbiAgICAgICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgICAgIHJldHVybiBnbG9iYWwuX19uYXRpdmUodGhpcyk7XG4gICAgICAgIH1cblxuICAgICAgICBwdWJsaWMgc2hvdWxkT3ZlcnJpZGVVcmxMb2FkaW5nKHZpZXc6IGFuZHJvaWQud2Via2l0LldlYlZpZXcsIHJlcXVlc3Q6IGFueSkge1xuICAgICAgICAgICAgY29uc3Qgb3duZXIgPSB0aGlzLm93bmVyO1xuICAgICAgICAgICAgaWYgKCFvd25lcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIldlYlZpZXdFeHRDbGllbnRJbXBsLnNob3VsZE92ZXJyaWRlVXJsTG9hZGluZyguLi4pIC0gbm8gb3duZXJcIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCB1cmwgPSByZXF1ZXN0IGFzIHN0cmluZztcbiAgICAgICAgICAgIGxldCBodHRwTWV0aG9kID0gXCJHRVRcIjtcbiAgICAgICAgICAgIGxldCBpc1JlZGlyZWN0ID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgaGFzR2VzdHVyZSA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGlzRm9yTWFpbkZyYW1lID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgcmVxdWVzdEhlYWRlcnM6IGphdmEudXRpbC5NYXA8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbCA9IG51bGw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHJlcXVlc3QgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICBodHRwTWV0aG9kID0gcmVxdWVzdC5nZXRNZXRob2QoKTtcbiAgICAgICAgICAgICAgICBpc1JlZGlyZWN0ID0gcmVxdWVzdC5pc1JlZGlyZWN0KCk7XG4gICAgICAgICAgICAgICAgaGFzR2VzdHVyZSA9IHJlcXVlc3QuaGFzR2VzdHVyZSgpO1xuICAgICAgICAgICAgICAgIGlzRm9yTWFpbkZyYW1lID0gcmVxdWVzdC5pc0Zvck1haW5GcmFtZSgpO1xuICAgICAgICAgICAgICAgIHJlcXVlc3RIZWFkZXJzID0gcmVxdWVzdC5nZXRSZXF1ZXN0SGVhZGVycygpO1xuXG4gICAgICAgICAgICAgICAgdXJsID0gcmVxdWVzdC5nZXRVcmwoKS50b1N0cmluZygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBvd25lci53cml0ZVRyYWNlKFxuICAgICAgICAgICAgICAgIGBXZWJWaWV3