{"version":3,"sources":["../index.js"],"names":["window","undefined","_cloneError","err","name","message","stack","_union","arr1","arr2","concat","filter","key","i","arr","indexOf","_isWindowFramed","isNotChildWindow","opener","hasWindowAncestors","top","parent","_isFrameElement","el","result","nodeType","test","nodeName","hasAttribute","getAttribute","setAttribute","_getFrame","errback","frameEl","frameElement","_getEffectiveScriptOrigin","effectiveScriptOrigin","document","domain","_defaultAllowancesMapForNullAllowances","forms","modals","orientationLock","pointerLock","popups","popupsToEscapeSandbox","presentation","sameOrigin","scripts","topNavigation","topNavigationByUserActivation","_createAllowancesMap","allowancesString","allowanceList","allowancesMap","replace","toLowerCase","split","_sandboxAllowancesMatch","sbAllowances1","sbAllowances2","allUsedKeys","len","prop","allMatched","Object","keys","length","hasOwnProperty","_analyzeSandboxing","sandboxAllowances","resandboxable","resandboxAllowances","resandboxLossless","sandboxed","unsandboxable","errors","sandboxErr","removeAttribute","SandBlaster","sb","this","_initialState","detect","_unsandboxState","_slice","Array","prototype","slice","frame","frameError","subResult","results","framed","crossOrigin","sandboxable","push","frameErrback","unsandbox","_current","_init","resandbox","sandbox","_currentAllowances","isLockingDown","sandboxAttr","forEach","allowance","sort","join","reload","attrs","newFrameEl","replacedFrameEl","parentNode","ownerDocument","call","attributes","map","item","value","createElement","replaceChild","sandblaster"],"mappings":"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","file":"sandblaster.min.js","sourcesContent":["(function(window, undefined) {\n\n\"use strict\";\n\n/********************\n *                  *\n *   Utility code   *\n *                  *\n ********************/\n\nvar _slice = Array.prototype.slice;\n\nfunction _cloneError(err) {\n  // Some browsers and/or Error types do not need to clone correctly via\n  // JSON serialization, so we may need to manually update the copy instead.\n  //\n  // This likely means that the Error instance's properties are:\n  //   (a) non-enumerable;\n  //   (b) prototypically inherited; or\n  //   (c) getter functions\n\n  return {\n    name: err.name,\n    message: err.message,\n    stack: err.stack\n  };\n}\n\nfunction _union(arr1, arr2) {\n  return (\n    (arr1 || [])\n      .concat(arr2 || [])\n      .filter(function(key, i, arr) {\n        return arr.indexOf(key) === i;\n      })\n  );\n}\n\nfunction _isWindowFramed() {\n  /*jshint eqeqeq:false */\n  // Cannot compare WindowProxy objects with ===/!==\n\n  var isNotChildWindow = !window.opener,\n      hasWindowAncestors = !!((window.top && window != window.top) || (window.parent && window != window.parent));\n  return isNotChildWindow && hasWindowAncestors;\n}\n\nfunction _isFrameElement(el) {\n  var result;\n  try {\n    result = (\n      typeof el === \"object\" &&\n      el !== null &&\n      el.nodeType === 1 &&\n      /^I?FRAME$/.test(el.nodeName || \"\") &&\n      !!el.hasAttribute && !!el.getAttribute && !!el.setAttribute\n    );\n  }\n  catch (err) {\n    result = false;\n  }\n  return result;\n}\n\nfunction _getFrame(errback) {\n  var frameEl;\n  try {\n    frameEl = window.frameElement;\n    if (!_isFrameElement(frameEl)) {\n      frameEl = null;\n    }\n  }\n  catch (err) {\n    frameEl = null;\n    if (typeof errback === \"function\") {\n      errback(_cloneError(err));\n    }\n  }\n  return frameEl;\n}\n\nfunction _getEffectiveScriptOrigin(errback) {\n  var effectiveScriptOrigin;\n  try {\n    effectiveScriptOrigin = document.domain || null;\n  }\n  catch (err) {\n    effectiveScriptOrigin = null;\n    if (typeof errback === \"function\") {\n      errback(_cloneError(err));\n    }\n  }\n  return effectiveScriptOrigin;\n}\n\nfunction _defaultAllowancesMapForNullAllowances() {\n  return {\n    forms: null,\n    modals: null,\n    orientationLock: null,\n    pointerLock: null,\n    popups: null,\n    popupsToEscapeSandbox: null,\n    presentation: null,\n    sameOrigin: true,\n    scripts: true,\n    topNavigation: null,\n    topNavigationByUserActivation: null\n  };\n}\n\nfunction _createAllowancesMap(allowancesString) {\n  var allowanceList,\n      allowancesMap = null;\n\n  if (allowancesString === null) {\n    allowancesMap = _defaultAllowancesMapForNullAllowances();\n  }\n  else if (typeof allowancesString === \"string\") {\n    allowanceList =\n      allowancesString\n        .replace(/^\\s+|\\s+$/g, \"\")\n        .toLowerCase()\n        .split(/\\s+/);\n\n    allowancesMap = {\n      forms: allowanceList.indexOf(\"allow-forms\") !== -1,\n      modals: allowanceList.indexOf(\"allow-modals\") !== -1,\n      orientationLock: allowanceList.indexOf(\"allow-orientation-lock\") !== -1,\n      pointerLock: allowanceList.indexOf(\"allow-pointer-lock\") !== -1,\n      popups: allowanceList.indexOf(\"allow-popups\") !== -1,\n      popupsToEscapeSandbox: allowanceList.indexOf(\"allow-popups-to-escape-sandbox\") !== -1,\n      presentation: allowanceList.indexOf(\"allow-presentation\") !== -1,\n      sameOrigin: allowanceList.indexOf(\"allow-same-origin\") !== -1,\n      scripts: allowanceList.indexOf(\"allow-scripts\") !== -1,\n      topNavigation: allowanceList.indexOf(\"allow-top-navigation\") !== -1,\n      topNavigationByUserActivation: allowanceList.indexOf(\"allow-top-navigation-by-user-activation\") !== -1\n    };\n  }\n\n  return allowancesMap;\n}\n\nfunction _sandboxAllowancesMatch(sbAllowances1, sbAllowances2) {\n  var allUsedKeys, i, len, prop,\n      allMatched = false;\n\n  if (\n    sbAllowances1 && typeof sbAllowances1 === \"object\" &&\n    sbAllowances2 && typeof sbAllowances2 === \"object\"\n  ) {\n    allUsedKeys = _union(Object.keys(sbAllowances1), Object.keys(sbAllowances2));\n\n    allMatched = true;\n    for (i = 0, len = allUsedKeys.length; i < len; i++) {\n      prop = allUsedKeys[i];\n      if (!(\n        sbAllowances1.hasOwnProperty(prop) &&\n        sbAllowances2.hasOwnProperty(prop) &&\n        sbAllowances1[prop] === sbAllowances2[prop]\n      )) {\n        allMatched = false;\n        break;\n      }\n    }\n  }\n\n  return allMatched;\n}\n\n\n/*********************\n *                   *\n *   Analysis code   *\n *                   *\n *********************/\n\nfunction _analyzeSandboxing(frameEl, errback) {\n  /*jshint maxstatements:45 */\n\n  //\n  // An interesting note from: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe\n  //\n  // NOTE:\n  //   \"When the embedded document has the same origin as the main\n  //    page, it is strongly discouraged to use both allow-scripts\n  //    and allow-same-origin at the same time, as that allows the\n  //    embedded document to programmatically remove the sandbox\n  //    attribute. Although it is accepted, this case is no more\n  //    secure than not using the sandbox attribute.\"\n  //\n  // So... let's give that a try, too! >=D\n  //\n  var sandboxAllowances, resandboxable, resandboxAllowances, resandboxLossless,\n      result = {\n        sandboxed: undefined,\n        sandboxAllowances: undefined,\n        unsandboxable: undefined,\n        resandboxable: undefined,\n        errors: []\n      };\n\n  if (_isFrameElement(frameEl)) {\n\n    // Is sandboxed?\n    try {\n      result.sandboxed = frameEl.hasAttribute(\"sandbox\");\n    }\n    catch (sandboxErr) {\n      result.sandboxed = null;\n      if (typeof errback === \"function\") {\n        errback(sandboxErr);\n      }\n    }\n\n    // Get sandbox configuration\n    if (result.sandboxed) {\n      try {\n        sandboxAllowances = frameEl.getAttribute(\"sandbox\") || \"\";\n      }\n      catch (sandboxErr) {\n        sandboxAllowances = null;\n        if (typeof errback === \"function\") {\n          errback(sandboxErr);\n        }\n      }\n    }\n    else if (result.sandboxed === null) {\n      sandboxAllowances = null;\n    }\n\n    if (sandboxAllowances === null || typeof sandboxAllowances === \"string\") {\n      result.sandboxAllowances =_createAllowancesMap(sandboxAllowances);\n    }\n\n    // Analyze desandboxability\n    if (result.sandboxed) {\n      try {\n        frameEl.removeAttribute(\"sandbox\");\n        result.unsandboxable = !frameEl.hasAttribute(\"sandbox\");\n      }\n      catch (sandboxErr) {\n        result.unsandboxable = false;\n        if (typeof errback === \"function\") {\n          errback(sandboxErr);\n        }\n      }\n    }\n\n    // Analyze resandboxability\n    if (result.unsandboxable && typeof sandboxAllowances === \"string\") {\n      try {\n        frameEl.setAttribute(\"sandbox\", sandboxAllowances);\n        resandboxable = frameEl.hasAttribute(\"sandbox\");\n      }\n      catch (sandboxErr) {\n        resandboxable = false;\n        if (typeof errback === \"function\") {\n          errback(sandboxErr);\n        }\n      }\n    }\n\n    // Get resandboxed configuration\n    if (resandboxable && result.sandboxAllowances) {\n      try {\n        resandboxAllowances = frameEl.getAttribute(\"sandbox\") || \"\";\n      }\n      catch (sandboxErr) {\n        resandboxAllowances = null;\n        if (typeof errback === \"function\") {\n          errback(sandboxErr);\n        }\n      }\n    }\n    else if (resandboxable === null) {\n      resandboxAllowances = null;\n    }\n\n    if (resandboxAllowances === null || typeof resandboxAllowances === \"string\") {\n      resandboxAllowances = _createAllowancesMap(resandboxAllowances);\n    }\n\n    // Analyze quality of resandboxability\n    if (resandboxable) {\n      resandboxLossless = null;\n\n      if (result.sandboxAllowances && resandboxAllowances) {\n        resandboxLossless = _sandboxAllowancesMatch(result.sandboxAllowances, resandboxAllowances);\n      }\n    }\n    result.resandboxable = resandboxLossless;\n  }\n\n  return result;\n}\n\n\n/**\n * Underlying \"class\" for the sandblaster API.\n *\n * @constructor\n */\nfunction SandBlaster() {\n  var sb = this;\n\n  if (!(sb instanceof SandBlaster)) {\n    return new SandBlaster();\n  }\n\n  sb._initialState = sb.detect();\n  sb._unsandboxState = null;\n}\n\n\n/**\n * ???\n *\n * @returns Object detailing the current page's frame-related state and capabilities\n * @public\n */\nSandBlaster.prototype.detect = function sandblaster$detect() {\n  var frame, frameError, subResult,\n      results = {\n        framed: false,\n        crossOrigin: null,\n        sandboxed: null,\n        sandboxAllowances: undefined,\n        unsandboxable: undefined,\n        resandboxable: undefined,\n        sandboxable: undefined,\n        errors: []\n      },\n      errback = function(err) {\n        results.errors.push(_cloneError(err));\n      },\n      frameErrback = function(err) {\n        frameError = _cloneError(err);\n        results.errors.push(frameError);\n      };\n\n  try {\n    results.framed = _isWindowFramed();\n    if (!results.framed) {\n      results.crossOrigin = undefined;\n      results.sandboxed = undefined;\n      results.errors = undefined;\n    }\n    else {\n      frame = _getFrame(frameErrback);\n\n      if (frame != null) {\n        results.crossOrigin = false;\n\n        subResult = _analyzeSandboxing(frame, errback);\n        results.sandboxed = subResult.sandboxed;\n        results.sandboxAllowances = subResult.sandboxAllowances;\n        results.unsandboxable = subResult.unsandboxable;\n        results.resandboxable = subResult.resandboxable;\n      }\n      else {\n\n        // IMPORTANT:\n        // Firefox will return `frame == null` and NOT throw any Error for\n        // cross-origin `frameElement` access:\n        //   https://bugzilla.mozilla.org/show_bug.cgi?id=868235\n\n        // Set the most frequent default values\n        results.crossOrigin = true;\n        results.sandboxed = null;\n        results.sandboxAllowances = {\n          forms: null,\n          modals: null,\n          orientationLock: null,\n          pointerLock: null,\n          popups: null,\n          popupsToEscapeSandbox: null,\n          presentation: null,\n          sameOrigin: null,\n          scripts: true,\n          topNavigation: null,\n          topNavigationByUserActivation: null\n        };\n        results.unsandboxable = false;\n        results.resandboxable = false;\n\n        // `document.domain` has been rendered useless by sandboxing\n        // without granting `allow-same-origin`\n        if (_getEffectiveScriptOrigin(errback) === null) {\n          results.sandboxed = true;\n          results.sandboxAllowances.sameOrigin = false;\n        }\n        else if (frameError) {\n          if (frameError.name !== \"SecurityError\") {\n            // Retract previous value... we're not sure anymore!\n            results.crossOrigin = null;\n          }\n          else if (/(^|[\\s\\(\\[@])sandbox(es|ed|ing|[\\s\\.,!\\)\\]@]|$)/.test(frameError.message.toLowerCase())) {\n            results.sandboxed = true;\n            results.sandboxAllowances.sameOrigin = true;\n          }\n        }\n      }\n\n      // Finally, do some analysis to see if we can authoritatively add sandboxing (e.g. if not sandboxed already)\n      results.sandboxable = (\n        results.resandboxable ||\n        (\n          results.framed === true &&\n          results.crossOrigin === false &&\n          (results.sandboxed === false || results.sandboxAllowances.sameOrigin)\n        ) ||\n        false\n      );\n    }\n  }\n  catch (err) {\n    errback(err);\n  }\n\n  return results;\n};\n\n\n/*******************\n *                 *\n *   Action code   *\n *                 *\n *******************/\n\n/**\n * ???\n */\nSandBlaster.prototype.unsandbox = function sandblaster$unsandbox() {\n  var _current, frameEl,\n      result = false,\n      sb = this,\n      _init = sb._initialState;\n\n  // If the page was never framed, bail out early because it will never change\n  if (_init.framed === false) {\n    result = true;\n  }\n  else if (_init.crossOrigin === false) {\n    _current = sb.detect();\n    result = _current.sandboxed === false;\n\n    // Unsandbox it\n    if (_current.sandboxed && _current.unsandboxable) {\n\n      // Keep track of the state of the frame before unsandboxing for potential resandboxing later\n      sb._unsandboxState = _current;\n\n      frameEl = _getFrame(function(/* err */) { result = false; });\n      if (frameEl) {\n        try {\n          frameEl.removeAttribute(\"sandbox\");\n          result = !frameEl.hasAttribute(\"sandbox\");\n        }\n        catch (err) {\n          result = false;\n        }\n      }\n    }\n  }\n\n  return result;\n};\n\n\n/**\n * ???\n */\nSandBlaster.prototype.resandbox = function sandblaster$resandbox() {\n  var result = false,\n      sb = this;\n\n  // If the page was unsandboxed, try to resandbox it\n  if (sb._unsandboxState != null) {\n    result = sb.sandbox(sb._unsandboxState.sandboxAllowances);\n  }\n\n  // If it succeeded, don't keep track of the previous unsandboxed state anymore\n  if (result === true) {\n    sb._unsandboxState = null;\n  }\n\n  return result;\n};\n\n\n/**\n * ???\n */\nSandBlaster.prototype.sandbox = function sandblaster$sandbox(sandboxAllowances) {\n  var allowancesString, keys, _current, _currentAllowances, isLockingDown, frameEl, sandboxAttr,\n      result = false,\n      sb = this,\n      _init = sb._initialState,\n      allowanceList = [];\n\n  if (\n    sandboxAllowances && typeof sandboxAllowances === \"object\" &&\n    _init.framed && _init.crossOrigin !== false\n  ) {\n    // Verify the state before continuing\n    _current = sb.detect();\n\n    // BUT also conduct some other live checks before attempting to sandbox it\n    if (\n      (_current.sandboxed === false && _current.sandboxable) ||\n      (_current.sandboxed && _current.unsandboxable)\n    ) {\n      _currentAllowances = _current.sandboxAllowances;\n\n      keys = _union(Object.keys(sandboxAllowances), Object.keys(_currentAllowances || {}));\n      keys.forEach(function(allowance) {\n        if (\n          sandboxAllowances[allowance] === true ||\n          (\n            sandboxAllowances[allowance] == null &&\n            _currentAllowances &&\n            _currentAllowances[allowance] === true\n          )\n        ) {\n          allowanceList.push(\"allow-\" + allowance.replace(/[A-Z]/g, \"-$1\").toLowerCase());\n        }\n      });\n\n      if (allowanceList.length > 0 && (frameEl = _getFrame())) {\n        isLockingDown = (\n          allowanceList.indexOf(\"allow-same-origin\") === -1 ||\n          allowanceList.indexOf(\"allow-scripts\") === -1\n        );\n        allowancesString = allowanceList.sort().join(\" \");\n\n        try {\n          // Add/update the sandbox\n          frameEl.setAttribute(\"sandbox\", allowancesString);\n          result = isLockingDown;\n        }\n        catch (err) {\n          result = false;\n        }\n\n        // Get a fresh element reference (or `null`)\n        if ((frameEl = _getFrame())) {\n          // May throw a SecurityError now, depending on the new sandbox configuration\n          try {\n            sandboxAttr =\n              (frameEl.getAttribute(\"sandbox\") || \"\")\n                .replace(/^\\s+|\\s+$/g, \"\")\n                .split(/\\s+/)\n                .sort()\n                .join(\" \");\n\n            result =\n              sandboxAttr === allowancesString ||\n              (isLockingDown && (sandboxAttr === \"\" || _getEffectiveScriptOrigin() === null));\n          }\n          catch (err) {\n            // May not be able to touch the sandbox anymore due to security lockdown and/or\n            // script disabling (if it even lets this event loop iteration finish!?)\n            result = isLockingDown;\n          }\n        }\n      }\n    }\n  }\n\n  return result;\n};\n\n\n/**\n * ???\n */\nSandBlaster.prototype.reload = function sandblaster$unsandboxAndReload() {\n  var frameEl, attrs, newFrameEl, replacedFrameEl,\n      result = false,\n      sb = this,\n      _init = sb._initialState;\n\n  // If the page was never framed or was cross-origin, bail out early because it will never change\n  if (_init.framed && _init.crossOrigin === false) {\n    frameEl = _getFrame();\n    if (frameEl) {\n      try {\n        if (frameEl.parentNode && frameEl.parentNode.ownerDocument) {\n          attrs = _slice.call(frameEl.attributes).map(function(item) {\n            return { name: item.name, value: item.value };\n          });\n\n          newFrameEl = frameEl.parentNode.ownerDocument.createElement(\"iframe\");\n          attrs.forEach(function(item) {\n              newFrameEl.setAttribute(item.name, item.value);\n          });\n          replacedFrameEl = frameEl.parentNode.replaceChild(newFrameEl, frameEl);\n          result = frameEl === replacedFrameEl;\n        }\n      }\n      catch (err) {\n        result = false;\n      }\n    }\n  }\n\n  return result;\n};\n\n\n/**********************\n *                    *\n *   Export the API   *\n *                    *\n **********************/\n\nwindow.sandblaster = new SandBlaster();\n\n})(window);\n"]}