UNPKG

matrix-react-sdk

Version:
859 lines (708 loc) 95.4 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _randomstring = require("matrix-js-sdk/src/randomstring"); var _languageHandler = require("./languageHandler"); var _PlatformPeg = _interopRequireDefault(require("./PlatformPeg")); var _SdkConfig = _interopRequireDefault(require("./SdkConfig")); var _MatrixClientPeg = require("./MatrixClientPeg"); var _promise = require("./utils/promise"); var _RoomViewStore = _interopRequireDefault(require("./stores/RoomViewStore")); var TextEncodingUtf8 = _interopRequireWildcard(require("text-encoding-utf-8")); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } let TextEncoder = window.TextEncoder; if (!TextEncoder) { TextEncoder = TextEncodingUtf8.TextEncoder; } const INACTIVITY_TIME = 20; // seconds const HEARTBEAT_INTERVAL = 5000; // ms const SESSION_UPDATE_INTERVAL = 60; // seconds const MAX_PENDING_EVENTS = 1000; var Orientation; /* eslint-disable camelcase */ (function (Orientation) { Orientation["Landscape"] = "landscape"; Orientation["Portrait"] = "portrait"; })(Orientation || (Orientation = {})); /* eslint-enable camelcase */ const hashHex = async (input /*: string*/ ) => /*: Promise<string>*/ { const buf = new TextEncoder().encode(input); const digestBuf = await window.crypto.subtle.digest("sha-256", buf); return [...new Uint8Array(digestBuf)].map((b /*: number*/ ) => b.toString(16).padStart(2, "0")).join(""); }; const knownScreens = new Set(["register", "login", "forgot_password", "soft_logout", "new", "settings", "welcome", "home", "start", "directory", "start_sso", "start_cas", "groups", "complete_security", "post_registration", "room", "user", "group"]); // Apply fn to all hash path parts after the 1st one async function getViewData(anonymous = true) /*: Promise<IViewData>*/ { const rand = (0, _randomstring.randomString)(8); const { origin, hash } = window.location; let { pathname } = window.location; // Redact paths which could contain unexpected PII if (origin.startsWith('file://')) { pathname = `/<redacted_${rand}>/`; // XXX: inject rand because Count.ly doesn't like X->X transitions } let [_, screen, ...parts] = hash.split("/"); if (!knownScreens.has(screen)) { screen = `<redacted_${rand}>`; } for (let i = 0; i < parts.length; i++) { parts[i] = anonymous ? `<redacted_${rand}>` : await hashHex(parts[i]); } const hashStr = `${_}/${screen}/${parts.join("/")}`; const url = origin + pathname + hashStr; const meta = {}; let name = "$/" + hash; switch (screen) { case "room": { name = "view_room"; const roomId = _RoomViewStore.default.getRoomId(); name += " " + parts[0]; // XXX: workaround Count.ly missing X->X transitions meta["room_id"] = parts[0]; Object.assign(meta, getRoomStats(roomId)); break; } } return { name, url, meta }; } const getRoomStats = (roomId /*: string*/ ) => { const cli = _MatrixClientPeg.MatrixClientPeg.get(); const room = cli?.getRoom(roomId); return { "num_users": room?.getJoinedMemberCount(), "is_encrypted": cli?.isRoomEncrypted(roomId), // eslint-disable-next-line camelcase "is_public": room?.currentState.getStateEvents("m.room.join_rules", "")?.getContent()?.join_rule === "public" }; }; // async wrapper for regex-powered String.prototype.replace const strReplaceAsync = async (str /*: string*/ , regex /*: RegExp*/ , fn /*: (...args: string[]) => Promise<string>*/ ) => { const promises /*: Promise<string>[]*/ = []; // dry-run to calculate the replace values str.replace(regex, (...args) => { promises.push(fn(...args)); return ""; }); const values = await Promise.all(promises); return str.replace(regex, () => values.shift()); }; class CountlyAnalytics { constructor() { (0, _defineProperty2.default)(this, "baseUrl", null); (0, _defineProperty2.default)(this, "appKey", null); (0, _defineProperty2.default)(this, "userKey", null); (0, _defineProperty2.default)(this, "anonymous", void 0); (0, _defineProperty2.default)(this, "appPlatform", void 0); (0, _defineProperty2.default)(this, "appVersion", "unknown"); (0, _defineProperty2.default)(this, "initTime", CountlyAnalytics.getTimestamp()); (0, _defineProperty2.default)(this, "firstPage", true); (0, _defineProperty2.default)(this, "heartbeatIntervalId", void 0); (0, _defineProperty2.default)(this, "activityIntervalId", void 0); (0, _defineProperty2.default)(this, "trackTime", true); (0, _defineProperty2.default)(this, "lastBeat", void 0); (0, _defineProperty2.default)(this, "storedDuration", 0); (0, _defineProperty2.default)(this, "lastView", void 0); (0, _defineProperty2.default)(this, "lastViewTime", 0); (0, _defineProperty2.default)(this, "lastViewStoredDuration", 0); (0, _defineProperty2.default)(this, "sessionStarted", false); (0, _defineProperty2.default)(this, "heartbeatEnabled", false); (0, _defineProperty2.default)(this, "inactivityCounter", 0); (0, _defineProperty2.default)(this, "pendingEvents", []); (0, _defineProperty2.default)(this, "lastMsTs", 0); (0, _defineProperty2.default)(this, "getOrientation", () => /*: Orientation*/ { return window.innerWidth > window.innerHeight ? Orientation.Landscape : Orientation.Portrait; }); (0, _defineProperty2.default)(this, "reportOrientation", () => { this.track("[CLY]_orientation", { mode: this.getOrientation() }); }); (0, _defineProperty2.default)(this, "endSession", () => { if (this.sessionStarted) { window.removeEventListener("resize", this.reportOrientation); this.reportViewDuration(); this.request({ end_session: 1, session_duration: CountlyAnalytics.getTimestamp() - this.lastBeat }); } this.sessionStarted = false; }); (0, _defineProperty2.default)(this, "onVisibilityChange", () => { if (document.hidden) { this.stopTime(); } else { this.startTime(); } }); (0, _defineProperty2.default)(this, "onUserActivity", () => { if (this.inactivityCounter >= INACTIVITY_TIME) { this.startTime(); } this.inactivityCounter = 0; }); } static get instance() /*: CountlyAnalytics*/ { return CountlyAnalytics.internalInstance; } get disabled() { return !this.baseUrl; } canEnable() { const config = _SdkConfig.default.get(); return Boolean(navigator.doNotTrack !== "1" && config?.countly?.url && config?.countly?.appKey); } async changeUserKey(userKey /*: string*/ , merge = false) { const oldUserKey = this.userKey; this.userKey = userKey; if (oldUserKey && merge) { await this.request({ old_device_id: oldUserKey }); } } async enable(anonymous = true) { if (!this.disabled && this.anonymous === anonymous) return; if (!this.canEnable()) return; if (!this.disabled) { // flush request queue as our userKey is going to change, no need to await it this.request(); } const config = _SdkConfig.default.get(); this.baseUrl = new URL("/i", config.countly.url); this.appKey = config.countly.appKey; this.anonymous = anonymous; if (anonymous) { await this.changeUserKey((0, _randomstring.randomString)(64)); } else { await this.changeUserKey(await hashHex(_MatrixClientPeg.MatrixClientPeg.get().getUserId()), true); } const platform = _PlatformPeg.default.get(); this.appPlatform = platform.getHumanReadableName(); try { this.appVersion = await platform.getAppVersion(); } catch (e) { console.warn("Failed to get app version, using 'unknown'"); } // start heartbeat this.heartbeatIntervalId = setInterval(this.heartbeat.bind(this), HEARTBEAT_INTERVAL); this.trackSessions(); this.trackErrors(); } async disable() { if (this.disabled) return; await this.track("Opt-Out"); this.endSession(); window.clearInterval(this.heartbeatIntervalId); window.clearTimeout(this.activityIntervalId); this.baseUrl = null; // remove listeners bound in trackSessions() window.removeEventListener("beforeunload", this.endSession); window.removeEventListener("unload", this.endSession); window.removeEventListener("visibilitychange", this.onVisibilityChange); window.removeEventListener("mousemove", this.onUserActivity); window.removeEventListener("click", this.onUserActivity); window.removeEventListener("keydown", this.onUserActivity); window.removeEventListener("scroll", this.onUserActivity); } reportFeedback(rating /*: 1 | 2 | 3 | 4 | 5*/ , comment /*: string*/ ) { this.track("[CLY]_star_rating", { rating, comment }, null, {}, true); } trackPageChange(generationTimeMs /*: number*/ ) { if (this.disabled) return; // TODO use generationTimeMs this.trackPageView(); } async trackPageView() { this.reportViewDuration(); await (0, _promise.sleep)(0); // XXX: we sleep here because otherwise we get the old hash and not the new one const viewData = await getViewData(this.anonymous); const page = viewData.name; this.lastView = page; this.lastViewTime = CountlyAnalytics.getTimestamp(); const segments = _objectSpread(_objectSpread({}, viewData.meta), {}, { name: page, visit: 1, domain: window.location.hostname, view: viewData.url, segment: this.appPlatform, start: this.firstPage }); if (this.firstPage) { this.firstPage = false; } this.track("[CLY]_view", segments); } static getTimestamp() { return Math.floor(new Date().getTime() / 1000); } // store the last ms timestamp returned // we do this to prevent the ts from ever decreasing in the case of system time changing getMsTimestamp() { const ts = new Date().getTime(); if (this.lastMsTs >= ts) { // increment ts as to keep our data points well-ordered this.lastMsTs++; } else { this.lastMsTs = ts; } return this.lastMsTs; } async recordError(err /*: Error | string*/ , fatal = false) { if (this.disabled || this.anonymous) return; let error = ""; if (typeof err === "object") { if (typeof err.stack !== "undefined") { error = err.stack; } else { if (typeof err.name !== "undefined") { error += err.name + ":"; } if (typeof err.message !== "undefined") { error += err.message + "\n"; } if (typeof err.fileName !== "undefined") { error += "in " + err.fileName + "\n"; } if (typeof err.lineNumber !== "undefined") { error += "on " + err.lineNumber; } if (typeof err.columnNumber !== "undefined") { error += ":" + err.columnNumber; } } } else { error = err + ""; } // sanitize the error from identifiers error = await strReplaceAsync(error, /([!@+#]).+?:[\w:.]+/g, async (substring /*: string*/ , glyph /*: string*/ ) => { return glyph + (await hashHex(substring.substring(1))); }); const metrics = this.getMetrics(); const ob /*: ICrash*/ = { _resolution: metrics?._resolution, _error: error, _app_version: this.appVersion, _run: CountlyAnalytics.getTimestamp() - this.initTime, _nonfatal: !fatal, _view: this.lastView }; if (typeof navigator.onLine !== "undefined") { ob._online = navigator.onLine; } ob._background = document.hasFocus(); this.request({ crash: JSON.stringify(ob) }); } trackErrors() { //override global uncaught error handler window.onerror = (msg, url, line, col, err) => { if (typeof err !== "undefined") { this.recordError(err, false); } else { let error = ""; if (typeof msg !== "undefined") { error += msg + "\n"; } if (typeof url !== "undefined") { error += "at " + url; } if (typeof line !== "undefined") { error += ":" + line; } if (typeof col !== "undefined") { error += ":" + col; } error += "\n"; try { const stack = []; // eslint-disable-next-line no-caller let f = arguments.callee.caller; while (f) { stack.push(f.name); f = f.caller; } error += stack.join("\n"); } catch (ex) {//silent error } this.recordError(error, false); } }; window.addEventListener('unhandledrejection', event => { this.recordError(new Error(`Unhandled rejection (reason: ${event.reason?.stack || event.reason}).`), true); }); } heartbeat() { const args /*: Pick<IParams, "session_duration">*/ = {}; // extend session if needed if (this.sessionStarted && this.trackTime) { const last = CountlyAnalytics.getTimestamp(); if (last - this.lastBeat >= SESSION_UPDATE_INTERVAL) { args.session_duration = last - this.lastBeat; this.lastBeat = last; } } // process event queue if (this.pendingEvents.length > 0 || args.session_duration) { this.request(args); } } async request(args /*: Omit<IParams, "app_key" | "device_id" | "timestamp" | "hour" | "dow"> & Partial<Pick<IParams, "device_id">>*/ = {}) { const request /*: IParams*/ = _objectSpread(_objectSpread({ app_key: this.appKey, device_id: this.userKey }, this.getTimeParams()), args); if (this.pendingEvents.length > 0) { const EVENT_BATCH_SIZE = 10; const events = this.pendingEvents.splice(0, EVENT_BATCH_SIZE); request.events = JSON.stringify(events); } const params = new URLSearchParams(request); try { await window.fetch(this.baseUrl.toString(), { method: "POST", mode: "no-cors", cache: "no-cache", redirect: "follow", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: params }); } catch (e) { console.error("Analytics error: ", e); } } getTimeParams() /*: Pick<IParams, "timestamp" | "hour" | "dow">*/ { const date = new Date(); return { timestamp: this.getMsTimestamp(), hour: date.getHours(), dow: date.getDay() }; } queue(args /*: Omit<IEvent, "timestamp" | "hour" | "dow" | "count"> & Partial<Pick<IEvent, "count">>*/ ) { const { count = 1 } = args, rest = (0, _objectWithoutProperties2.default)(args, ["count"]); const ev = _objectSpread(_objectSpread(_objectSpread({}, this.getTimeParams()), rest), {}, { count, platform: this.appPlatform, app_version: this.appVersion }); this.pendingEvents.push(ev); if (this.pendingEvents.length > MAX_PENDING_EVENTS) { this.pendingEvents.shift(); } } startTime() { if (!this.trackTime) { this.trackTime = true; this.lastBeat = CountlyAnalytics.getTimestamp() - this.storedDuration; this.lastViewTime = CountlyAnalytics.getTimestamp() - this.lastViewStoredDuration; this.lastViewStoredDuration = 0; } } stopTime() { if (this.trackTime) { this.trackTime = false; this.storedDuration = CountlyAnalytics.getTimestamp() - this.lastBeat; this.lastViewStoredDuration = CountlyAnalytics.getTimestamp() - this.lastViewTime; } } getMetrics() /*: IMetrics*/ { if (this.anonymous) return undefined; const metrics /*: IMetrics*/ = {}; // getting app version metrics._app_version = this.appVersion; metrics._ua = navigator.userAgent; // getting resolution if (screen.width && screen.height) { metrics._resolution = `${screen.width}x${screen.height}`; } // getting density ratio if (window.devicePixelRatio) { metrics._density = window.devicePixelRatio; } // getting locale metrics._locale = (0, _languageHandler.getCurrentLanguage)(); return metrics; } async beginSession(heartbeat = true) { if (!this.sessionStarted) { this.reportOrientation(); window.addEventListener("resize", this.reportOrientation); this.lastBeat = CountlyAnalytics.getTimestamp(); this.sessionStarted = true; this.heartbeatEnabled = heartbeat; const userDetails /*: IUserDetails*/ = { custom: { "home_server": _MatrixClientPeg.MatrixClientPeg.get() && _MatrixClientPeg.MatrixClientPeg.getHomeserverName(), // TODO hash? "anonymous": this.anonymous } }; const request /*: Parameters<typeof CountlyAnalytics.prototype.request>[0]*/ = { begin_session: 1, user_details: JSON.stringify(userDetails) }; const metrics = this.getMetrics(); if (metrics) { request.metrics = JSON.stringify(metrics); } await this.request(request); } } reportViewDuration() { if (this.lastView) { this.track("[CLY]_view", { name: this.lastView }, null, { dur: this.trackTime ? CountlyAnalytics.getTimestamp() - this.lastViewTime : this.lastViewStoredDuration }); this.lastView = null; } } trackSessions() { this.beginSession(); this.startTime(); window.addEventListener("beforeunload", this.endSession); window.addEventListener("unload", this.endSession); window.addEventListener("visibilitychange", this.onVisibilityChange); window.addEventListener("mousemove", this.onUserActivity); window.addEventListener("click", this.onUserActivity); window.addEventListener("keydown", this.onUserActivity); window.addEventListener("scroll", this.onUserActivity); this.activityIntervalId = setInterval(() => { this.inactivityCounter++; if (this.inactivityCounter >= INACTIVITY_TIME) { this.stopTime(); } }, 60000); } trackBeginInvite(roomId /*: string*/ ) { this.track("begin_invite", {}, roomId); } trackSendInvite(startTime /*: number*/ , roomId /*: string*/ , qty /*: number*/ ) { this.track("send_invite", {}, roomId, { dur: CountlyAnalytics.getTimestamp() - startTime, sum: qty }); } async trackRoomCreate(startTime /*: number*/ , roomId /*: string*/ ) { if (this.disabled) return; let endTime = CountlyAnalytics.getTimestamp(); const cli = _MatrixClientPeg.MatrixClientPeg.get(); if (!cli.getRoom(roomId)) { await new Promise(resolve => { const handler = room => { if (room.roomId === roomId) { cli.off("Room", handler); resolve(); } }; cli.on("Room", handler); }); endTime = CountlyAnalytics.getTimestamp(); } this.track("create_room", {}, roomId, { dur: endTime - startTime }); } trackRoomJoin(startTime /*: number*/ , roomId /*: string*/ , type /*: IJoinRoomEvent["segmentation"]["type"]*/ ) { this.track("join_room", { type }, roomId, { dur: CountlyAnalytics.getTimestamp() - startTime }); } async trackSendMessage(startTime /*: number*/ , // eslint-disable-next-line camelcase sendPromise /*: Promise<{event_id: string}>*/ , roomId /*: string*/ , isEdit /*: boolean*/ , isReply /*: boolean*/ , content /*: {format?: string, msgtype: string}*/ ) { if (this.disabled) return; const cli = _MatrixClientPeg.MatrixClientPeg.get(); const room = cli.getRoom(roomId); const eventId = (await sendPromise).event_id; let endTime = CountlyAnalytics.getTimestamp(); if (!room.findEventById(eventId)) { await new Promise(resolve => { const handler = ev => { if (ev.getId() === eventId) { room.off("Room.localEchoUpdated", handler); resolve(); } }; room.on("Room.localEchoUpdated", handler); }); endTime = CountlyAnalytics.getTimestamp(); } this.track("send_message", { is_edit: isEdit, is_reply: isReply, msgtype: content.msgtype, format: content.format }, roomId, { dur: endTime - startTime }); } trackStartCall(roomId /*: string*/ , isVideo = false, isJitsi = false) { this.track("start_call", { is_video: isVideo, is_jitsi: isJitsi }, roomId); } trackJoinCall(roomId /*: string*/ , isVideo = false, isJitsi = false) { this.track("join_call", { is_video: isVideo, is_jitsi: isJitsi }, roomId); } trackRoomDirectoryBegin() { this.track("room_directory"); } trackRoomDirectory(startTime /*: number*/ ) { this.track("room_directory_done", {}, null, { dur: CountlyAnalytics.getTimestamp() - startTime }); } trackRoomDirectorySearch(numResults /*: number*/ , query /*: string*/ ) { this.track("room_directory_search", { query_length: query.length, query_num_words: query.split(" ").length }, null, { sum: numResults }); } async track(key /*: E["key"]*/ , segments /*: Omit<E["segmentation"], "room_id" | "num_users" | "is_encrypted" | "is_public">*/ , roomId /*: string*/ , args /*: Partial<Pick<E, "dur" | "sum" | "timestamp">>*/ , anonymous = false) { if (this.disabled && !anonymous) return; let segmentation = segments || {}; if (roomId) { segmentation = _objectSpread(_objectSpread({ room_id: await hashHex(roomId) }, getRoomStats(roomId)), segments); } this.queue(_objectSpread({ key, count: 1, segmentation }, args)); // if this event can be sent anonymously and we are disabled then dispatch it right away if (this.disabled && anonymous) { await this.request({ device_id: (0, _randomstring.randomString)(64) }); } } } // expose on window for easy access from the console exports.default = CountlyAnalytics; (0, _defineProperty2.default)(CountlyAnalytics, "internalInstance", new CountlyAnalytics()); window.mxCountlyAnalytics = CountlyAnalytics; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Db3VudGx5QW5hbHl0aWNzLnRzIl0sIm5hbWVzIjpbIlRleHRFbmNvZGVyIiwid2luZG93IiwiVGV4dEVuY29kaW5nVXRmOCIsIklOQUNUSVZJVFlfVElNRSIsIkhFQVJUQkVBVF9JTlRFUlZBTCIsIlNFU1NJT05fVVBEQVRFX0lOVEVSVkFMIiwiTUFYX1BFTkRJTkdfRVZFTlRTIiwiT3JpZW50YXRpb24iLCJoYXNoSGV4IiwiaW5wdXQiLCJidWYiLCJlbmNvZGUiLCJkaWdlc3RCdWYiLCJjcnlwdG8iLCJzdWJ0bGUiLCJkaWdlc3QiLCJVaW50OEFycmF5IiwibWFwIiwiYiIsInRvU3RyaW5nIiwicGFkU3RhcnQiLCJqb2luIiwia25vd25TY3JlZW5zIiwiU2V0IiwiZ2V0Vmlld0RhdGEiLCJhbm9ueW1vdXMiLCJyYW5kIiwib3JpZ2luIiwiaGFzaCIsImxvY2F0aW9uIiwicGF0aG5hbWUiLCJzdGFydHNXaXRoIiwiXyIsInNjcmVlbiIsInBhcnRzIiwic3BsaXQiLCJoYXMiLCJpIiwibGVuZ3RoIiwiaGFzaFN0ciIsInVybCIsIm1ldGEiLCJuYW1lIiwicm9vbUlkIiwiUm9vbVZpZXdTdG9yZSIsImdldFJvb21JZCIsIk9iamVjdCIsImFzc2lnbiIsImdldFJvb21TdGF0cyIsImNsaSIsIk1hdHJpeENsaWVudFBlZyIsImdldCIsInJvb20iLCJnZXRSb29tIiwiZ2V0Sm9pbmVkTWVtYmVyQ291bnQiLCJpc1Jvb21FbmNyeXB0ZWQiLCJjdXJyZW50U3RhdGUiLCJnZXRTdGF0ZUV2ZW50cyIsImdldENvbnRlbnQiLCJqb2luX3J1bGUiLCJzdHJSZXBsYWNlQXN5bmMiLCJzdHIiLCJyZWdleCIsImZuIiwicHJvbWlzZXMiLCJyZXBsYWNlIiwiYXJncyIsInB1c2giLCJ2YWx1ZXMiLCJQcm9taXNlIiwiYWxsIiwic2hpZnQiLCJDb3VudGx5QW5hbHl0aWNzIiwiZ2V0VGltZXN0YW1wIiwiaW5uZXJXaWR0aCIsImlubmVySGVpZ2h0IiwiTGFuZHNjYXBlIiwiUG9ydHJhaXQiLCJ0cmFjayIsIm1vZGUiLCJnZXRPcmllbnRhdGlvbiIsInNlc3Npb25TdGFydGVkIiwicmVtb3ZlRXZlbnRMaXN0ZW5lciIsInJlcG9ydE9yaWVudGF0aW9uIiwicmVwb3J0Vmlld0R1cmF0aW9uIiwicmVxdWVzdCIsImVuZF9zZXNzaW9uIiwic2Vzc2lvbl9kdXJhdGlvbiIsImxhc3RCZWF0IiwiZG9jdW1lbnQiLCJoaWRkZW4iLCJzdG9wVGltZSIsInN0YXJ0VGltZSIsImluYWN0aXZpdHlDb3VudGVyIiwiaW5zdGFuY2UiLCJpbnRlcm5hbEluc3RhbmNlIiwiZGlzYWJsZWQiLCJiYXNlVXJsIiwiY2FuRW5hYmxlIiwiY29uZmlnIiwiU2RrQ29uZmlnIiwiQm9vbGVhbiIsIm5hdmlnYXRvciIsImRvTm90VHJhY2siLCJjb3VudGx5IiwiYXBwS2V5IiwiY2hhbmdlVXNlcktleSIsInVzZXJLZXkiLCJtZXJnZSIsIm9sZFVzZXJLZXkiLCJvbGRfZGV2aWNlX2lkIiwiZW5hYmxlIiwiVVJMIiwiZ2V0VXNlcklkIiwicGxhdGZvcm0iLCJQbGF0Zm9ybVBlZyIsImFwcFBsYXRmb3JtIiwiZ2V0SHVtYW5SZWFkYWJsZU5hbWUiLCJhcHBWZXJzaW9uIiwiZ2V0QXBwVmVyc2lvbiIsImUiLCJjb25zb2xlIiwid2FybiIsImhlYXJ0YmVhdEludGVydmFsSWQiLCJzZXRJbnRlcnZhbCIsImhlYXJ0YmVhdCIsImJpbmQiLCJ0cmFja1Nlc3Npb25zIiwidHJhY2tFcnJvcnMiLCJkaXNhYmxlIiwiZW5kU2Vzc2lvbiIsImNsZWFySW50ZXJ2YWwiLCJjbGVhclRpbWVvdXQiLCJhY3Rpdml0eUludGVydmFsSWQiLCJvblZpc2liaWxpdHlDaGFuZ2UiLCJvblVzZXJBY3Rpdml0eSIsInJlcG9ydEZlZWRiYWNrIiwicmF0aW5nIiwiY29tbWVudCIsInRyYWNrUGFnZUNoYW5nZSIsImdlbmVyYXRpb25UaW1lTXMiLCJ0cmFja1BhZ2VWaWV3Iiwidmlld0RhdGEiLCJwYWdlIiwibGFzdFZpZXciLCJsYXN0Vmlld1RpbWUiLCJzZWdtZW50cyIsInZpc2l0IiwiZG9tYWluIiwiaG9zdG5hbWUiLCJ2aWV3Iiwic2VnbWVudCIsInN0YXJ0IiwiZmlyc3RQYWdlIiwiTWF0aCIsImZsb29yIiwiRGF0ZSIsImdldFRpbWUiLCJnZXRNc1RpbWVzdGFtcCIsInRzIiwibGFzdE1zVHMiLCJyZWNvcmRFcnJvciIsImVyciIsImZhdGFsIiwiZXJyb3IiLCJzdGFjayIsIm1lc3NhZ2UiLCJmaWxlTmFtZSIsImxpbmVOdW1iZXIiLCJjb2x1bW5OdW1iZXIiLCJzdWJzdHJpbmciLCJnbHlwaCIsIm1ldHJpY3MiLCJnZXRNZXRyaWNzIiwib2IiLCJfcmVzb2x1dGlvbiIsIl9lcnJvciIsIl9hcHBfdmVyc2lvbiIsIl9ydW4iLCJpbml0VGltZSIsIl9ub25mYXRhbCIsIl92aWV3Iiwib25MaW5lIiwiX29ubGluZSIsIl9iYWNrZ3JvdW5kIiwiaGFzRm9jdXMiLCJjcmFzaCIsIkpTT04iLCJzdHJpbmdpZnkiLCJvbmVycm9yIiwibXNnIiwibGluZSIsImNvbCIsImYiLCJhcmd1bWVudHMiLCJjYWxsZWUiLCJjYWxsZXIiLCJleCIsImFkZEV2ZW50TGlzdGVuZXIiLCJldmVudCIsIkVycm9yIiwicmVhc29uIiwidHJhY2tUaW1lIiwibGFzdCIsInBlbmRpbmdFdmVudHMiLCJhcHBfa2V5IiwiZGV2aWNlX2lkIiwiZ2V0VGltZVBhcmFtcyIsIkVWRU5UX0JBVENIX1NJWkUiLCJldmVudHMiLCJzcGxpY2UiLCJwYXJhbXMiLCJVUkxTZWFyY2hQYXJhbXMiLCJmZXRjaCIsIm1ldGhvZCIsImNhY2hlIiwicmVkaXJlY3QiLCJoZWFkZXJzIiwiYm9keSIsImRhdGUiLCJ0aW1lc3RhbXAiLCJob3VyIiwiZ2V0SG91cnMiLCJkb3ciLCJnZXREYXkiLCJxdWV1ZSIsImNvdW50IiwicmVzdCIsImV2IiwiYXBwX3ZlcnNpb24iLCJzdG9yZWREdXJhdGlvbiIsImxhc3RWaWV3U3RvcmVkRHVyYXRpb24iLCJ1bmRlZmluZWQiLCJfdWEiLCJ1c2VyQWdlbnQiLCJ3aWR0aCIsImhlaWdodCIsImRldmljZVBpeGVsUmF0aW8iLCJfZGVuc2l0eSIsIl9sb2NhbGUiLCJiZWdpblNlc3Npb24iLCJoZWFydGJlYXRFbmFibGVkIiwidXNlckRldGFpbHMiLCJjdXN0b20iLCJnZXRIb21lc2VydmVyTmFtZSIsImJlZ2luX3Nlc3Npb24iLCJ1c2VyX2RldGFpbHMiLCJkdXIiLCJ0cmFja0JlZ2luSW52aXRlIiwidHJhY2tTZW5kSW52aXRlIiwicXR5Iiwic3VtIiwidHJhY2tSb29tQ3JlYXRlIiwiZW5kVGltZSIsInJlc29sdmUiLCJoYW5kbGVyIiwib2ZmIiwib24iLCJ0cmFja1Jvb21Kb2luIiwidHlwZSIsInRyYWNrU2VuZE1lc3NhZ2UiLCJzZW5kUHJvbWlzZSIsImlzRWRpdCIsImlzUmVwbHkiLCJjb250ZW50IiwiZXZlbnRJZCIsImV2ZW50X2lkIiwiZmluZEV2ZW50QnlJZCIsImdldElkIiwiaXNfZWRpdCIsImlzX3JlcGx5IiwibXNndHlwZSIsImZvcm1hdCIsInRyYWNrU3RhcnRDYWxsIiwiaXNWaWRlbyIsImlzSml0c2kiLCJpc192aWRlbyIsImlzX2ppdHNpIiwidHJhY2tKb2luQ2FsbCIsInRyYWNrUm9vbURpcmVjdG9yeUJlZ2luIiwidHJhY2tSb29tRGlyZWN0b3J5IiwidHJhY2tSb29tRGlyZWN0b3J5U2VhcmNoIiwibnVtUmVzdWx0cyIsInF1ZXJ5IiwicXVlcnlfbGVuZ3RoIiwicXVlcnlfbnVtX3dvcmRzIiwia2V5Iiwic2VnbWVudGF0aW9uIiwicm9vbV9pZCIsIm14Q291bnRseUFuYWx5dGljcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JBOztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUdBOzs7Ozs7QUFDQSxJQUFJQSxXQUFXLEdBQUdDLE1BQU0sQ0FBQ0QsV0FBekI7O0FBQ0EsSUFBSSxDQUFDQSxXQUFMLEVBQWtCO0FBQ2RBLEVBQUFBLFdBQVcsR0FBR0UsZ0JBQWdCLENBQUNG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