matrix-react-sdk
Version:
SDK for matrix.org using React
859 lines (708 loc) • 95.4 kB
JavaScript
"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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