/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ 666:
/***/ ((module) => {

/* global browser, chrome */

const apis = [
  'alarms',
  'bookmarks',
  'browserAction',
  'action',
  'commands',
  'contextMenus',
  'cookies',
  'downloads',
  'events',
  'extension',
  'extensionTypes',
  'history',
  'i18n',
  'idle',
  'notifications',
  'pageAction',
  'offscreen',
  'runtime',
  'storage',
  'tabs',
  'activeTab',
  'webNavigation',
  'webRequest',
  'windows',
  'clipboardWrite',
  'tabCapture',
  'desktopCapture',
  'browsingData',
  'scripting'
];

/**
 * API Extension Class
 */
function Extension() {
  const _this = this;

  apis.forEach((api) => {
    _this[api] = null;

    try {
      if (chrome[api]) {
        _this[api] = chrome[api];
      }
    } catch (e) {}

    try {
      if (window[api]) {
        _this[api] = window[api];
      }
    } catch (e) {}

    try {
      if (browser[api]) {
        _this[api] = browser[api];
      }
    } catch (e) {}
    try {
      _this.api = browser.extension[api];
    } catch (e) {}
  });

  try {
    if (browser && browser.runtime) {
      this.runtime = browser.runtime;
    }
  } catch (e) {}

  try {
    if (browser && (browser.browserAction || browser.action)) {
      this.browserAction = browser.browserAction || browser.action;
    }
  } catch (e) {}
}

module.exports = new Extension();


/***/ }),

/***/ 615:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   y: () => (/* binding */ blobToDataURL)
/* harmony export */ });
/* unused harmony export dataURLtoBlob */
// These functions are used to convert a blob to a base64 data URL and
// back. They are potentially duplicative of other base64 encode operations
// but these were the only thing that seemed to allow passing a blob in an
// extension message payload.
const blobToDataURL = (blob, cb) => {
  const reader = new FileReader();
  reader.onload = () => {
    const dataUrl = reader.result;
    cb(dataUrl);
  };
  reader.readAsDataURL(blob);
};

const dataURLtoBlob = (dataURL) => {
  const base64 = dataURL.split(",")[1];
  const byteString = atob(base64);
  const mimeString = dataURL.split(",")[0].split(":")[1].split(";")[0];

  const ab = new ArrayBuffer(byteString.length);
  const ia = new Uint8Array(ab);
  // eslint-disable-next-line no-plusplus
  for (let i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }

  const blob = new Blob([ia], { type: mimeString });
  return blob;
};


/***/ }),

/***/ 482:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   ICONS: () => (/* binding */ ICONS)
/* harmony export */ });
/* unused harmony exports DEFAULT_RECORDING_LIMIT, MAX_RECORDING_LIMIT, RDP_SOAP_URL, SAML_URL, PASSWORD_EXPIRED_URL, LICENSES_URL, GASETUP_URL, SSGUID, NATIVE_HOST, CM_NATIVE_HOST, WPF_HINTS_SECTION, RECORDING_FAILED_RETRY_COUNT, INPUT_THRESHOLD, URL_PATTERN, SALESFORCE_SUBDOMAINS, PLATFORM_DOMAIN1, PLATFORM_DOMAIN2, KEYWORDS, UNKNOWN_VERSION, REDIRCTION_URLS, CLIENT_ID, APP_NAME, ACTIVE_TAB_QUERY, ACTIVE_TAB_QUERY_MIN_REQ, MULTI_DOMAIN, secretStates, CONTENT, SERVER_TYPE, API, secretAction, MFA_OPTIONS, PERMISSIONS, ssCloud */
/* harmony import */ var _core_ext__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(666);
/* harmony import */ var _core_ext__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_core_ext__WEBPACK_IMPORTED_MODULE_0__);


const DEFAULT_RECORDING_LIMIT = 120; // in minutes (2 Hours)
const MAX_RECORDING_LIMIT = 480; // in minutes (8 Hours)
const RDP_SOAP_URL = "/Rdp/v2/rdpwebservice.asmx";
const SAML_URL = "/AlreadyLoggedIn.aspx";
const PASSWORD_EXPIRED_URL = "/PasswordExpired.aspx";
const LICENSES_URL = "/licenses.aspx";
const GASETUP_URL = "/GASetup.aspx";
const SSGUID = "f8f49a36873c4d579b30b4238c2563fb";
const NATIVE_HOST = "com.thycotic.wpf.host";
const CM_NATIVE_HOST = "com.delinea.cm.message_host";
const WPF_HINTS_SECTION = "WPFHints";
const RECORDING_FAILED_RETRY_COUNT = 15;
const INPUT_THRESHOLD = 10;
const URL_PATTERN = (/* unused pure expression or super */ null && (["http://*/*", "https://*/*"]));
const SALESFORCE_SUBDOMAINS = /https:\/\/.*\.my\.salesforce\.com/i;
const PLATFORM_DOMAIN1 = /(https|http)?:\/\/([\w\d-]+\.)*?secureplatform\.io(\/)?$/;
const PLATFORM_DOMAIN2 = /(https|http)?:\/\/([\w\d-]+\.)*?delinea\.app(\/)?$/;
const KEYWORDS = (/* unused pure expression or super */ null && (["captureInterval", "matchUrl"]));
const UNKNOWN_VERSION = "0.0.0";
const REDIRCTION_URLS = [PASSWORD_EXPIRED_URL, LICENSES_URL, GASETUP_URL];
const CLIENT_ID = 'a654aa7b-46c1-4138-81b2-67e8392426e8';
const APP_NAME = 'Web Password Filler';

/* eslint-disable max-len */
const ICONS = {
  GLOBE: (_core_ext__WEBPACK_IMPORTED_MODULE_0___default()) && (_core_ext__WEBPACK_IMPORTED_MODULE_0___default().runtime) && _core_ext__WEBPACK_IMPORTED_MODULE_0___default().runtime.getURL("images/globe.svg"),

  DELINEA: (_core_ext__WEBPACK_IMPORTED_MODULE_0___default()) && (_core_ext__WEBPACK_IMPORTED_MODULE_0___default().runtime) && _core_ext__WEBPACK_IMPORTED_MODULE_0___default().runtime.getURL("icons/icon.png"),

  RECORDING: (_core_ext__WEBPACK_IMPORTED_MODULE_0___default()) && (_core_ext__WEBPACK_IMPORTED_MODULE_0___default().runtime) && _core_ext__WEBPACK_IMPORTED_MODULE_0___default().runtime.getURL("icons/record.png"),

  MOUSE_POINTER: (_core_ext__WEBPACK_IMPORTED_MODULE_0___default()) && (_core_ext__WEBPACK_IMPORTED_MODULE_0___default().runtime) && _core_ext__WEBPACK_IMPORTED_MODULE_0___default().runtime.getURL("icons/handCursor.png"),

  FOLDER: `<svg  width="17px" height="13px" viewBox="0 0 17 13" version="1.1"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>outline-folder-24px (1)</title>
  <g id="UX-Flow" stroke="none" stroke-width="1"
  fill="none" fill-rule="evenodd">
  <g id="Web-Password-Filler-(Add)---Folder-Selection"
  transform="translate(-140.000000, -257.000000)">
  <g id="outline-folder-24px-(1)"
  transform="translate(138.000000, 254.000000)">
  <polygon id="Path" points="0 0 20 0 20 20 0 20"></polygon>
  <polygon id="Path" points="0 0 20 0 20 20 0 20"></polygon>
  <path d="M8.0945,4.625 L9.7945,6.25 L17.3,6.25 L17.3,
  14.375 L3.7,14.375 L3.7,4.625 L8.0945,4.625 L8.0945,
  4.625 Z M8.8,3 L3.7,3 C2.765,3 2.0085,3.73125 2.0085,
  4.625 L2,14.375 C2,15.26875 2.765,16 3.7,16 L17.3,
  16 C18.235,16 19,15.26875 19,14.375 L19,6.25 C19,
  5.35625 18.235,4.625 17.3,4.625 L10.5,4.625 L8.8,3 Z"
  id="Shape" fill="#C2CFDA" fill-rule="nonzero"></path>
  </g></g></g></svg> `,
};

const ACTIVE_TAB_QUERY = {
  active: true,
  currentWindow: true,
  windowType: "normal",
  highlighted: true,
  // url: URL_PATTERN,
};

const ACTIVE_TAB_QUERY_MIN_REQ = {
  active: true,
  currentWindow: true,
};

const MULTI_DOMAIN = [
  {
    name: "MICROSOFT",
    values: ["https://login.live.com", "https://login.microsoftonline.com/"],
    domains: ["live.com", "microsoftonline.com"],
  },
];

const secretStates = {
  none: "none",
  requiresComment: "requirescomment",
  requiresCheckoutAndComment: "requirescheckoutandcomment",
  requiresCheckout: "requirescheckout",
  requiresApproval: "requiresapproval",
  requiresMFAChallenge: "requiresmfachallenge",
};

const CONTENT = {
  APP_JSON: "application/json",
  APP_URL_ENCODED: "application/x-www-form-urlencoded",
  TEXT_XML: "text/xml",
};

const SERVER_TYPE = {
  SS: "Secret Server",
  PLATFORM: "Delinea Platform",
};

const API = {
  GOOGLE_FAVICON: "https://www.google.com/s2/favicons?domain=",
};

const secretAction = {
  launch: "launch-secret",
  view: "view-secret",
  fillSecret: "fill-secret",
  copyUsername: "copy-username",
  copyPassword: "copy-password",
  copyOtp: "copy-otp-code",
};

const MFA_OPTIONS = {
  PUSH: "push",
  SMS: "SMS",
  PHONE: "phone",
};

const PERMISSIONS = {
  AddSecret: "Add Secret",
  EditSecret: "Edit Secret",
  ViewSecret: "View Secret",
};

const ssCloud = {
  PUSH: "push",
  SMS: "SMS",
  PHONE: "phone",
};


/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => (module['default']) :
/******/ 				() => (module);
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
(() => {
"use strict";

// UNUSED EXPORTS: endRecording, setCallback, startRecording

// EXTERNAL MODULE: ./src/scripts/core/ext.js
var ext = __webpack_require__(666);
var ext_default = /*#__PURE__*/__webpack_require__.n(ext);
// EXTERNAL MODULE: ./src/scripts/utils/constants.js
var constants = __webpack_require__(482);
// EXTERNAL MODULE: ./src/scripts/recording/blob-conversion.js
var blob_conversion = __webpack_require__(615);
;// CONCATENATED MODULE: ./src/scripts/recording/lib/OffscreenSession.js
/* eslint-disable import/prefer-default-export */
/* eslint-disable no-console */
/* eslint-disable class-methods-use-this */




class OffscreenSession {
  constructor(id, config = {}, callback) {
    this.config = {
      videoFps: 30,
      videoBitsPerSecond: 4500000,
      segmentSeconds: 1,
      ...config,
    };
    this.id = id;
    this.canvas = this.createCanvas();
    this.meadiaRecorder = this.createMediaRecorder();
    this.mousePointer = new Image();
    this.mousePointer.src = constants.ICONS.MOUSE_POINTER;
    this.oldX = 0;
    this.oldY = 0;
    this.sendVideoSegment = callback;
  }

  createCanvas() {
    const canvas = document.createElement("canvas");
    // eslint-disable-next-line no-restricted-globals
    canvas.width = Math.floor(screen.availWidth) * window.devicePixelRatio;
    // eslint-disable-next-line no-restricted-globals
    canvas.height = Math.floor(screen.availHeight) * window.devicePixelRatio;
    document.body.appendChild(canvas);
    return canvas;
  }

  createMediaRecorder() {
    const stream = this.canvas.captureStream(this.config.videoFps);
    if (!stream) {
      console.error("Failed to create stream");
      return null;
    }
    const mr = new MediaRecorder(stream, {
      mimeType: "video/webm",
      videoBitsPerSecond: this.config.videoBitsPerSecond,
    });

    mr.ondataavailable = (e) => {
      this.dataAvailable(e);
    };

    mr.onstop = () => {
      this.recordingStopped();
    };

    mr.start(1000 * this.config.segmentSeconds);
    return mr;
  } 

  drawToCanvas(imageData, clearCanvas, mousePositions) {
    const ctx = this.canvas.getContext("2d");

    const image = new Image();
    image.onload = async () => {
      if (!ctx) throw new Error("could not get context");
      if (!clearCanvas) {
        ctx.drawImage(image, 0, 0);
        return;
      }
     
      ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
      ctx.drawImage(image, 0, 0);
      if (mousePositions.length === 0) return;  
      let { clientX, clientY } = mousePositions.pop();
      ctx.drawImage(this.mousePointer, clientX, clientY);
    };

    image.src = imageData;
  }


  dataAvailable(e) {
    (0,blob_conversion/* blobToDataURL */.y)(e.data, (data) => {
      if(this.sendVideoSegment) {
        this.sendVideoSegment({
          type: "sendVideoSegment",
          sessionGuid: this.id,
          data,
        });
        return;
      }
      ext_default().runtime.sendMessage({
        type: "sendVideoSegment",
        sessionGuid: this.id,
        data,
      });    
    });
  }

  recordingStopped() {
    console.log("Recording stopped");
  }

  end() {
    this.meadiaRecorder.stop();
    document.body.removeChild(this.canvas);
  }
}

;// CONCATENATED MODULE: ./src/scripts/recording/lib/SessionRecorder.js
/* eslint-disable operator-linebreak */
/* eslint-disable no-console */
/* eslint-disable class-methods-use-this */

// import logger from "../../helpers/logger";


const CLEAR_PNG =
  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=";

// eslint-disable-next-line import/prefer-default-export
class SessionRecorder {
  constructor(config = {}) {
    this.config = {
      videoFps: 30,
      getImageInterval: 500,
      segmentSeconds: 1,
      videoBitsPerSecond: 4500000,
      ...config,
    };
    this.interval = null;
    this.recording = false;
    this.sessions = {};
    this.callbackGetActiveTabData = null;
  }

  setActiveTabData(callback) {
    this.callbackGetActiveTabData = callback;
  }

  startSession(sessionGuid, callback) {
    console.log("Starting session", sessionGuid);
   // logger.logInfo(`Starting session ${sessionGuid}`);
    this.recording = true;

    if (this.sessions[sessionGuid]) {
      console.error("Session already exists");
      return;
    }

    const config = {
      videoFps: this.config.videoFps,
      videoBitsPerSecond: this.config.videoBitsPerSecond,
      segmentSeconds: this.config.segmentSeconds
    };
    this.sessions[sessionGuid] = new OffscreenSession(sessionGuid, config, callback);
    this.ensureInterval();
  }

  endSession(sessionGuid) {
    console.log("Ending session", sessionGuid);
    if (!this.sessions[sessionGuid]) {
      console.error("Could not find session to end");
      return;
    }

    this.sessions[sessionGuid].end();
    delete this.sessions[sessionGuid];

    const ongoingSessions = Object.values(this.sessions).length;
    if (ongoingSessions === 0) {
      this.recording = false;
      clearInterval(this.interval);
      this.interval = null;
    }
  }

  ensureInterval() {
    console.log("Ensuring recording", this.interval);
    if (this.interval) return;

    this.interval = setInterval(
      () => this.updateSessions(),
      this.config.getImageInterval
    );
  }
  async getActiveTabData() {
    if(this.callbackGetActiveTabData) {
     return await this.callbackGetActiveTabData()
    }
    
    return await ext_default().runtime.sendMessage({
      from: "Background",
      type: "getActiveTabData",
    });
  }

  async updateSessions() {
    // console.log("Updating sessions:", this.recording);
    if (!this.recording) return;
  
    const { image, applicableSessionIds, mousePositions } = await this.getActiveTabData()

    Object.values(this.sessions).forEach((session) => {
      if (image && applicableSessionIds.includes(session.id)) {
        session.drawToCanvas(image, true, mousePositions );
        session.lastCapturedDate = Date.now();
        return;
      }  

      if(session.lastCapturedDate) {
        const lapsed = Date.now() - session.lastCapturedDate;
        if (lapsed < 105000) return; // every 105 seconds
      }
      // when there's no applicable image, write a clear png to the canvas
      // to keep the data stream consistent
      session.drawToCanvas(CLEAR_PNG, false, mousePositions);
      session.lastCapturedDate = Date.now();
    });
  }
}

;// CONCATENATED MODULE: ./src/scripts/offscreen.js



const VIDEO_FPS = 30;
// 500 is exceeding the 2 per second limit
const GET_IMAGE_INTERVAL = 550;
const SEGMENT_SECONDS = 1;
const VIDEO_BITS_PER_SECOND = 4500000;

const sessionRecorder = new SessionRecorder({
  videoFps: VIDEO_FPS,
  getImageInterval: GET_IMAGE_INTERVAL,
  segmentSeconds: SEGMENT_SECONDS,
  videoBitsPerSecond: VIDEO_BITS_PER_SECOND,
});

function setCallback(callback) {
  sessionRecorder.setActiveTabData(callback);
}

function startRecording(sessionGuid, callback) {
  sessionRecorder.startSession(sessionGuid, callback);
}

function endRecording(sessionGuid) {
  sessionRecorder.endSession(sessionGuid);
}

ext_default().runtime.onMessage.addListener((message, sender, sendResponse) => {  
  // console.log("Message received:", message); 
  if (message.type === "startRecording") {
    sessionRecorder.startSession(message.sessionGuid);
  }
  if (message.type === "endingSession") {
    sessionRecorder.endSession(message.sessionGuid);
  } 
});

 
})();

/******/ })()
;
//# sourceMappingURL=offscreen.js.map