tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

asrouter-admin.bundle.js (75428B)


      1 /*!
      2 * 
      3 *  NOTE: This file is generated by webpack from ASRouterAdmin.jsx
      4 *  using the npm bundle task.
      5 *
      6 */
      7 var ASRouterAdminRenderUtils;
      8 /******/ (() => { // webpackBootstrap
      9 /******/ 	"use strict";
     10 /******/ 	var __webpack_modules__ = ([
     11 /* 0 */,
     12 /* 1 */
     13 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
     14 
     15 __webpack_require__.r(__webpack_exports__);
     16 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
     17 /* harmony export */   ASRouterUtils: () => (/* binding */ ASRouterUtils)
     18 /* harmony export */ });
     19 /* harmony import */ var _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
     20 /* This Source Code Form is subject to the terms of the Mozilla Public
     21 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     22 * You can obtain one at http://mozilla.org/MPL/2.0/. */
     23 
     24 
     25 
     26 const ASRouterUtils = {
     27  addListener(listener) {
     28    if (globalThis.ASRouterAddParentListener) {
     29      globalThis.ASRouterAddParentListener(listener);
     30    }
     31  },
     32  removeListener(listener) {
     33    if (globalThis.ASRouterRemoveParentListener) {
     34      globalThis.ASRouterRemoveParentListener(listener);
     35    }
     36  },
     37  sendMessage(action) {
     38    if (globalThis.ASRouterMessage) {
     39      return globalThis.ASRouterMessage(action);
     40    }
     41    throw new Error(`Unexpected call:\n${JSON.stringify(action, null, 3)}`);
     42  },
     43  blockById(id, options) {
     44    return ASRouterUtils.sendMessage({
     45      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.BLOCK_MESSAGE_BY_ID,
     46      data: { id, ...options },
     47    });
     48  },
     49  modifyMessageJson(content) {
     50    return ASRouterUtils.sendMessage({
     51      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.MODIFY_MESSAGE_JSON,
     52      data: { content },
     53    });
     54  },
     55  executeAction(button_action) {
     56    return ASRouterUtils.sendMessage({
     57      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.USER_ACTION,
     58      data: button_action,
     59    });
     60  },
     61  unblockById(id) {
     62    return ASRouterUtils.sendMessage({
     63      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.UNBLOCK_MESSAGE_BY_ID,
     64      data: { id },
     65    });
     66  },
     67  unblockAll() {
     68    return ASRouterUtils.sendMessage({
     69      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.UNBLOCK_ALL,
     70    });
     71  },
     72  resetGroupImpressions() {
     73    return ASRouterUtils.sendMessage({
     74      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.RESET_GROUPS_STATE,
     75    });
     76  },
     77  resetMessageImpressions() {
     78    return ASRouterUtils.sendMessage({
     79      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.RESET_MESSAGE_STATE,
     80    });
     81  },
     82  resetScreenImpressions() {
     83    return ASRouterUtils.sendMessage({
     84      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.RESET_SCREEN_IMPRESSIONS,
     85    });
     86  },
     87  blockBundle(bundle) {
     88    return ASRouterUtils.sendMessage({
     89      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.BLOCK_BUNDLE,
     90      data: { bundle },
     91    });
     92  },
     93  unblockBundle(bundle) {
     94    return ASRouterUtils.sendMessage({
     95      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.UNBLOCK_BUNDLE,
     96      data: { bundle },
     97    });
     98  },
     99  overrideMessage(id) {
    100    return ASRouterUtils.sendMessage({
    101      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.OVERRIDE_MESSAGE,
    102      data: { id },
    103    });
    104  },
    105  editState(key, value) {
    106    return ASRouterUtils.sendMessage({
    107      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.EDIT_STATE,
    108      data: { [key]: value },
    109    });
    110  },
    111  openPBWindow(content) {
    112    ASRouterUtils.sendMessage({
    113      type: "FORCE_PRIVATE_BROWSING_WINDOW",
    114      data: { message: { content } },
    115    });
    116  },
    117  sendTelemetry(ping) {
    118    return ASRouterUtils.sendMessage({
    119      type: _modules_ActorConstants_mjs__WEBPACK_IMPORTED_MODULE_0__.MESSAGE_TYPE_HASH.AS_ROUTER_TELEMETRY_USER_EVENT,
    120      data: ping,
    121    });
    122  },
    123  getPreviewEndpoint() {
    124    return null;
    125  },
    126 };
    127 
    128 
    129 /***/ }),
    130 /* 2 */
    131 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
    132 
    133 __webpack_require__.r(__webpack_exports__);
    134 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
    135 /* harmony export */   MESSAGE_TYPE_HASH: () => (/* binding */ MESSAGE_TYPE_HASH),
    136 /* harmony export */   MESSAGE_TYPE_LIST: () => (/* binding */ MESSAGE_TYPE_LIST)
    137 /* harmony export */ });
    138 /* vim: set ts=2 sw=2 sts=2 et tw=80: */
    139 /* This Source Code Form is subject to the terms of the Mozilla Public
    140 * License, v. 2.0. If a copy of the MPL was not distributed with this
    141 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    142 
    143 const MESSAGE_TYPE_LIST = [
    144  "BLOCK_MESSAGE_BY_ID",
    145  "USER_ACTION",
    146  "IMPRESSION",
    147  "TRIGGER",
    148  // PB is Private Browsing
    149  "PBNEWTAB_MESSAGE_REQUEST",
    150  "DOORHANGER_TELEMETRY",
    151  "TOOLBAR_BADGE_TELEMETRY",
    152  "MOMENTS_PAGE_TELEMETRY",
    153  "INFOBAR_TELEMETRY",
    154  "SPOTLIGHT_TELEMETRY",
    155  "TOAST_NOTIFICATION_TELEMETRY",
    156  "MENU_MESSAGE_TELEMETRY",
    157  "NEWTAB_MESSAGE_TELEMETRY",
    158  "AS_ROUTER_TELEMETRY_USER_EVENT",
    159 
    160  // Admin types
    161  "ADMIN_CONNECT_STATE",
    162  "UNBLOCK_MESSAGE_BY_ID",
    163  "UNBLOCK_ALL",
    164  "BLOCK_BUNDLE",
    165  "UNBLOCK_BUNDLE",
    166  "DISABLE_PROVIDER",
    167  "ENABLE_PROVIDER",
    168  "EVALUATE_JEXL_EXPRESSION",
    169  "EXPIRE_QUERY_CACHE",
    170  "FORCE_ATTRIBUTION",
    171  "FORCE_PRIVATE_BROWSING_WINDOW",
    172  "OVERRIDE_MESSAGE",
    173  "MODIFY_MESSAGE_JSON",
    174  "RESET_PROVIDER_PREF",
    175  "SET_PROVIDER_USER_PREF",
    176  "RESET_GROUPS_STATE",
    177  "RESET_MESSAGE_STATE",
    178  "RESET_SCREEN_IMPRESSIONS",
    179  "EDIT_STATE",
    180 ];
    181 
    182 const MESSAGE_TYPE_HASH = MESSAGE_TYPE_LIST.reduce((hash, value) => {
    183  hash[value] = value;
    184  return hash;
    185 }, {});
    186 
    187 
    188 /***/ }),
    189 /* 3 */
    190 /***/ ((module) => {
    191 
    192 module.exports = React;
    193 
    194 /***/ }),
    195 /* 4 */
    196 /***/ ((module) => {
    197 
    198 module.exports = ReactDOM;
    199 
    200 /***/ }),
    201 /* 5 */
    202 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
    203 
    204 __webpack_require__.r(__webpack_exports__);
    205 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
    206 /* harmony export */   SimpleHashRouter: () => (/* binding */ SimpleHashRouter)
    207 /* harmony export */ });
    208 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
    209 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
    210 /* This Source Code Form is subject to the terms of the Mozilla Public
    211 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    212 * You can obtain one at http://mozilla.org/MPL/2.0/. */
    213 
    214 
    215 class SimpleHashRouter extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComponent) {
    216  constructor(props) {
    217    super(props);
    218    this.onHashChange = this.onHashChange.bind(this);
    219    this.state = {
    220      hash: __webpack_require__.g.location.hash
    221    };
    222  }
    223  onHashChange() {
    224    this.setState({
    225      hash: __webpack_require__.g.location.hash
    226    });
    227  }
    228  componentWillMount() {
    229    __webpack_require__.g.addEventListener("hashchange", this.onHashChange);
    230  }
    231  componentWillUnmount() {
    232    __webpack_require__.g.removeEventListener("hashchange", this.onHashChange);
    233  }
    234  render() {
    235    const [, ...routes] = this.state.hash.split("-");
    236    return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().cloneElement(this.props.children, {
    237      location: {
    238        hash: this.state.hash,
    239        routes
    240      }
    241    });
    242  }
    243 }
    244 
    245 /***/ }),
    246 /* 6 */
    247 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
    248 
    249 __webpack_require__.r(__webpack_exports__);
    250 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
    251 /* harmony export */   CopyButton: () => (/* binding */ CopyButton)
    252 /* harmony export */ });
    253 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
    254 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
    255 function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
    256 /* This Source Code Form is subject to the terms of the Mozilla Public
    257 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    258 * You can obtain one at http://mozilla.org/MPL/2.0/. */
    259 
    260 
    261 const CopyButton = ({
    262  className,
    263  label,
    264  copiedLabel,
    265  inputSelector,
    266  transformer,
    267  ...props
    268 }) => {
    269  const [copied, setCopied] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
    270  const timeout = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);
    271  const onClick = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => {
    272    let text = document.querySelector(inputSelector).value;
    273    if (transformer) {
    274      text = transformer(text);
    275    }
    276    navigator.clipboard.writeText(text);
    277    clearTimeout(timeout.current);
    278    setCopied(true);
    279    timeout.current = setTimeout(() => setCopied(false), 1500);
    280  }, [inputSelector, transformer]);
    281  return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", _extends({
    282    className: className,
    283    onClick: () => onClick()
    284  }, props), copied && copiedLabel || label);
    285 };
    286 
    287 /***/ }),
    288 /* 7 */
    289 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
    290 
    291 __webpack_require__.r(__webpack_exports__);
    292 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
    293 /* harmony export */   ImpressionsSection: () => (/* binding */ ImpressionsSection)
    294 /* harmony export */ });
    295 /* harmony import */ var _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
    296 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
    297 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
    298 /* This Source Code Form is subject to the terms of the Mozilla Public
    299 * License, v. 2.0. If a copy of the MPL was not distributed with this
    300 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    301 
    302 
    303 
    304 const stringify = json => JSON.stringify(json, null, 2);
    305 const ImpressionsSection = ({
    306  messageImpressions,
    307  groupImpressions,
    308  screenImpressions
    309 }) => {
    310  const handleSaveMessageImpressions = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(newImpressions => {
    311    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.editState("messageImpressions", newImpressions);
    312  }, []);
    313  const handleSaveGroupImpressions = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(newImpressions => {
    314    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.editState("groupImpressions", newImpressions);
    315  }, []);
    316  const handleSaveScreenImpressions = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(newImpressions => {
    317    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.editState("screenImpressions", newImpressions);
    318  }, []);
    319  const handleResetMessageImpressions = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {
    320    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    321      type: "RESET_MESSAGE_STATE"
    322    });
    323  }, []);
    324  const handleResetGroupImpressions = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {
    325    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    326      type: "RESET_GROUPS_STATE"
    327    });
    328  }, []);
    329  const handleResetScreenImpressions = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {
    330    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    331      type: "RESET_SCREEN_IMPRESSIONS"
    332    });
    333  }, []);
    334  return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
    335    className: "impressions-section"
    336  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(ImpressionsItem, {
    337    impressions: messageImpressions,
    338    label: "Message Impressions",
    339    description: "Message impressions are stored in an object, where each key is a message ID and each value is an array of timestamps. They are cleaned up when a message with that ID stops existing in ASRouter state (such as at the end of an experiment).",
    340    onSave: handleSaveMessageImpressions,
    341    onReset: handleResetMessageImpressions
    342  }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(ImpressionsItem, {
    343    impressions: groupImpressions,
    344    label: "Group Impressions",
    345    description: "Group impressions are stored in an object, where each key is a group ID and each value is an array of timestamps. They are never cleaned up.",
    346    onSave: handleSaveGroupImpressions,
    347    onReset: handleResetGroupImpressions
    348  }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(ImpressionsItem, {
    349    impressions: screenImpressions,
    350    label: "Screen Impressions",
    351    description: "Screen impressions are stored in an object, where each key is a screen ID and each value is the most recent timestamp that screen was shown. They are never cleaned up.",
    352    onSave: handleSaveScreenImpressions,
    353    onReset: handleResetScreenImpressions
    354  }));
    355 };
    356 const ImpressionsItem = ({
    357  impressions,
    358  label,
    359  description,
    360  validator,
    361  onSave,
    362  onReset
    363 }) => {
    364  const [json, setJson] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(stringify(impressions));
    365  const modified = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(false);
    366  const isValidJson = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(text => {
    367    try {
    368      JSON.parse(text);
    369      return validator ? validator(text) : true;
    370    } catch (e) {
    371      return false;
    372    }
    373  }, [validator]);
    374  const jsonIsInvalid = (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(() => !isValidJson(json), [json, isValidJson]);
    375  const handleChange = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(e => {
    376    setJson(e.target.value);
    377    modified.current = true;
    378  }, []);
    379  const handleSave = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {
    380    if (jsonIsInvalid) {
    381      return;
    382    }
    383    const newImpressions = JSON.parse(json);
    384    modified.current = false;
    385    onSave(newImpressions);
    386  }, [json, jsonIsInvalid, onSave]);
    387  const handleReset = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {
    388    modified.current = false;
    389    onReset();
    390  }, [onReset]);
    391  (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {
    392    if (!modified.current) {
    393      setJson(stringify(impressions));
    394    }
    395  }, [impressions]);
    396  return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
    397    className: "impressions-item"
    398  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
    399    className: "impressions-category"
    400  }, label), description ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("p", {
    401    className: "impressions-description"
    402  }, description) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
    403    className: "impressions-inner-box"
    404  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
    405    className: "impressions-buttons"
    406  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
    407    className: "button primary",
    408    disabled: jsonIsInvalid,
    409    onClick: handleSave
    410  }, "Save"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
    411    className: "button reset",
    412    onClick: handleReset
    413  }, "Reset")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
    414    className: "impressions-editor"
    415  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("textarea", {
    416    rows: "15",
    417    value: json,
    418    onChange: handleChange
    419  }))));
    420 };
    421 
    422 /***/ })
    423 /******/ 	]);
    424 /************************************************************************/
    425 /******/ 	// The module cache
    426 /******/ 	var __webpack_module_cache__ = {};
    427 /******/ 	
    428 /******/ 	// The require function
    429 /******/ 	function __webpack_require__(moduleId) {
    430 /******/ 		// Check if module is in cache
    431 /******/ 		var cachedModule = __webpack_module_cache__[moduleId];
    432 /******/ 		if (cachedModule !== undefined) {
    433 /******/ 			return cachedModule.exports;
    434 /******/ 		}
    435 /******/ 		// Create a new module (and put it into the cache)
    436 /******/ 		var module = __webpack_module_cache__[moduleId] = {
    437 /******/ 			// no module.id needed
    438 /******/ 			// no module.loaded needed
    439 /******/ 			exports: {}
    440 /******/ 		};
    441 /******/ 	
    442 /******/ 		// Execute the module function
    443 /******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
    444 /******/ 	
    445 /******/ 		// Return the exports of the module
    446 /******/ 		return module.exports;
    447 /******/ 	}
    448 /******/ 	
    449 /************************************************************************/
    450 /******/ 	/* webpack/runtime/compat get default export */
    451 /******/ 	(() => {
    452 /******/ 		// getDefaultExport function for compatibility with non-harmony modules
    453 /******/ 		__webpack_require__.n = (module) => {
    454 /******/ 			var getter = module && module.__esModule ?
    455 /******/ 				() => (module['default']) :
    456 /******/ 				() => (module);
    457 /******/ 			__webpack_require__.d(getter, { a: getter });
    458 /******/ 			return getter;
    459 /******/ 		};
    460 /******/ 	})();
    461 /******/ 	
    462 /******/ 	/* webpack/runtime/define property getters */
    463 /******/ 	(() => {
    464 /******/ 		// define getter functions for harmony exports
    465 /******/ 		__webpack_require__.d = (exports, definition) => {
    466 /******/ 			for(var key in definition) {
    467 /******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
    468 /******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
    469 /******/ 				}
    470 /******/ 			}
    471 /******/ 		};
    472 /******/ 	})();
    473 /******/ 	
    474 /******/ 	/* webpack/runtime/global */
    475 /******/ 	(() => {
    476 /******/ 		__webpack_require__.g = (function() {
    477 /******/ 			if (typeof globalThis === 'object') return globalThis;
    478 /******/ 			try {
    479 /******/ 				return this || new Function('return this')();
    480 /******/ 			} catch (e) {
    481 /******/ 				if (typeof window === 'object') return window;
    482 /******/ 			}
    483 /******/ 		})();
    484 /******/ 	})();
    485 /******/ 	
    486 /******/ 	/* webpack/runtime/hasOwnProperty shorthand */
    487 /******/ 	(() => {
    488 /******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
    489 /******/ 	})();
    490 /******/ 	
    491 /******/ 	/* webpack/runtime/make namespace object */
    492 /******/ 	(() => {
    493 /******/ 		// define __esModule on exports
    494 /******/ 		__webpack_require__.r = (exports) => {
    495 /******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
    496 /******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
    497 /******/ 			}
    498 /******/ 			Object.defineProperty(exports, '__esModule', { value: true });
    499 /******/ 		};
    500 /******/ 	})();
    501 /******/ 	
    502 /************************************************************************/
    503 var __webpack_exports__ = {};
    504 // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
    505 (() => {
    506 __webpack_require__.r(__webpack_exports__);
    507 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
    508 /* harmony export */   ASRouterAdmin: () => (/* binding */ ASRouterAdmin),
    509 /* harmony export */   ASRouterAdminInner: () => (/* binding */ ASRouterAdminInner),
    510 /* harmony export */   ToggleMessageJSON: () => (/* binding */ ToggleMessageJSON),
    511 /* harmony export */   renderASRouterAdmin: () => (/* binding */ renderASRouterAdmin),
    512 /* harmony export */   toBinary: () => (/* binding */ toBinary)
    513 /* harmony export */ });
    514 /* harmony import */ var _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
    515 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
    516 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
    517 /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
    518 /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);
    519 /* harmony import */ var _SimpleHashRouter__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5);
    520 /* harmony import */ var _CopyButton__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6);
    521 /* harmony import */ var _ImpressionsSection__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7);
    522 /* This Source Code Form is subject to the terms of the Mozilla Public
    523 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    524 * You can obtain one at http://mozilla.org/MPL/2.0/. */
    525 
    526 
    527 
    528 
    529 
    530 
    531 
    532 
    533 // Convert a UTF-8 string to a string in which only one byte of each
    534 // 16-bit unit is occupied. This is necessary to comply with `btoa` API constraints.
    535 function toBinary(string) {
    536  const codeUnits = new Uint16Array(string.length);
    537  for (let i = 0; i < codeUnits.length; i++) {
    538    codeUnits[i] = string.charCodeAt(i);
    539  }
    540  return btoa(String.fromCharCode(...Array.from(new Uint8Array(codeUnits.buffer))));
    541 }
    542 function relativeTime(timestamp) {
    543  if (!timestamp) {
    544    return "";
    545  }
    546  const seconds = Math.floor((Date.now() - timestamp) / 1000);
    547  const minutes = Math.floor((Date.now() - timestamp) / 60000);
    548  if (seconds < 2) {
    549    return "just now";
    550  } else if (seconds < 60) {
    551    return `${seconds} seconds ago`;
    552  } else if (minutes === 1) {
    553    return "1 minute ago";
    554  } else if (minutes < 600) {
    555    return `${minutes} minutes ago`;
    556  }
    557  return new Date(timestamp).toLocaleString();
    558 }
    559 class ToggleMessageJSON extends (react__WEBPACK_IMPORTED_MODULE_1___default().PureComponent) {
    560  constructor(props) {
    561    super(props);
    562    this.handleClick = this.handleClick.bind(this);
    563  }
    564  handleClick() {
    565    this.props.toggleJSON(this.props.msgId);
    566  }
    567  render() {
    568    let direction = this.props.isCollapsed ? "forward" : "down";
    569    return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
    570      className: "clearButton",
    571      onClick: this.handleClick
    572    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
    573      className: `icon small icon-arrowhead-${direction}`
    574    }));
    575  }
    576 }
    577 class ASRouterAdminInner extends (react__WEBPACK_IMPORTED_MODULE_1___default().PureComponent) {
    578  constructor(props) {
    579    super(props);
    580    this.handleEnabledToggle = this.handleEnabledToggle.bind(this);
    581    this.handleUserPrefToggle = this.handleUserPrefToggle.bind(this);
    582    this.onChangeFilters = this.onChangeFilters.bind(this);
    583    this.onClearFilters = this.onClearFilters.bind(this);
    584    this.unblockAll = this.unblockAll.bind(this);
    585    this.resetAllJSON = this.resetAllJSON.bind(this);
    586    this.handleExpressionEval = this.handleExpressionEval.bind(this);
    587    this.onChangeTargetingParameters = this.onChangeTargetingParameters.bind(this);
    588    this.onChangeAttributionParameters = this.onChangeAttributionParameters.bind(this);
    589    this.setAttribution = this.setAttribution.bind(this);
    590    this.onCopyTargetingParams = this.onCopyTargetingParams.bind(this);
    591    this.onNewTargetingParams = this.onNewTargetingParams.bind(this);
    592    this.resetMessageState = this.resetMessageState.bind(this);
    593    this.toggleJSON = this.toggleJSON.bind(this);
    594    this.toggleAllMessages = this.toggleAllMessages.bind(this);
    595    this.resetGroupImpressions = this.resetGroupImpressions.bind(this);
    596    this.onMessageFromParent = this.onMessageFromParent.bind(this);
    597    this.setStateFromParent = this.setStateFromParent.bind(this);
    598    this.setState = this.setState.bind(this);
    599    this.state = {
    600      filterGroups: [],
    601      filterProviders: [],
    602      filterTemplates: [],
    603      filtersCollapsed: true,
    604      collapsedMessages: [],
    605      modifiedMessages: [],
    606      messageBlockList: [],
    607      multiProfileMessageBlocklist: [],
    608      evaluationStatus: {},
    609      stringTargetingParameters: null,
    610      newStringTargetingParameters: null,
    611      copiedToClipboard: false,
    612      attributionParameters: {
    613        source: "addons.mozilla.org",
    614        medium: "referral",
    615        campaign: "non-fx-button",
    616        content: `rta:${btoa("uBlock0@raymondhill.net")}`,
    617        experiment: "ua-onboarding",
    618        variation: "chrome",
    619        ua: "Google Chrome 123",
    620        dltoken: "00000000-0000-0000-0000-000000000000"
    621      }
    622    };
    623  }
    624  onMessageFromParent({
    625    type,
    626    data
    627  }) {
    628    // These only exists due to onPrefChange events in ASRouter
    629    switch (type) {
    630      case "UpdateAdminState":
    631        {
    632          this.setStateFromParent(data);
    633          break;
    634        }
    635    }
    636  }
    637  async setStateFromParent(data) {
    638    await this.setState(data);
    639    if (!this.state.stringTargetingParameters) {
    640      const stringTargetingParameters = {};
    641      for (const param of Object.keys(data.targetingParameters)) {
    642        stringTargetingParameters[param] = JSON.stringify(data.targetingParameters[param], null, 2);
    643      }
    644      await this.setState({
    645        stringTargetingParameters
    646      });
    647    }
    648  }
    649  componentWillMount() {
    650    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.addListener(this.onMessageFromParent);
    651    const endpoint = _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.getPreviewEndpoint();
    652    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    653      type: "ADMIN_CONNECT_STATE",
    654      data: {
    655        endpoint
    656      }
    657    }).then(this.setStateFromParent);
    658  }
    659  componentWillUnmount() {
    660    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.removeListener(this.onMessageFromParent);
    661  }
    662  handleBlock(msg) {
    663    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.blockById(msg.id);
    664  }
    665  handleUnblock(msg) {
    666    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.unblockById(msg.id);
    667  }
    668  resetJSON(msg) {
    669    // reset the displayed JSON for the given message
    670    let textarea = document.getElementById(`${msg.id}-textarea`);
    671    textarea.value = JSON.stringify(msg, null, 2);
    672    textarea.classList.remove("errorState");
    673    // remove the message from the list of modified IDs
    674    let index = this.state.modifiedMessages.indexOf(msg.id);
    675    this.setState(prevState => ({
    676      modifiedMessages: [...prevState.modifiedMessages.slice(0, index), ...prevState.modifiedMessages.slice(index + 1)]
    677    }));
    678  }
    679  resetAllJSON() {
    680    // reset the displayed JSON for each modified message
    681    for (const msgId of this.state.modifiedMessages) {
    682      const msg = this.state.messages.find(m => m.id === msgId);
    683      const textarea = document.getElementById(`${msgId}-textarea`);
    684      if (textarea) {
    685        textarea.value = JSON.stringify(msg, null, 2);
    686        textarea.classList.remove("errorState");
    687      }
    688    }
    689    this.setState({
    690      modifiedMessages: []
    691    });
    692  }
    693  showMessage(msg) {
    694    if (msg.template === "pb_newtab") {
    695      _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.openPBWindow(msg.content);
    696    } else {
    697      _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.overrideMessage(msg.id).then(state => this.setStateFromParent(state));
    698    }
    699  }
    700  async resetMessageState() {
    701    await Promise.all([_asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.resetMessageImpressions(), _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.resetGroupImpressions(), _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.resetScreenImpressions(), _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.unblockAll()]);
    702    let data = await _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    703      type: "ADMIN_CONNECT_STATE",
    704      data: {
    705        endpoint: _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.getPreviewEndpoint()
    706      }
    707    });
    708    await this.setStateFromParent(data);
    709  }
    710  expireCache() {
    711    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    712      type: "EXPIRE_QUERY_CACHE"
    713    });
    714  }
    715  resetPref() {
    716    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    717      type: "RESET_PROVIDER_PREF"
    718    });
    719  }
    720  resetGroupImpressions() {
    721    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.resetGroupImpressions().then(this.setStateFromParent);
    722  }
    723  resetMessageImpressions() {
    724    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.resetMessageImpressions().then(this.setStateFromParent);
    725  }
    726  handleExpressionEval() {
    727    const context = {};
    728    for (const param of Object.keys(this.state.stringTargetingParameters)) {
    729      const value = this.state.stringTargetingParameters[param];
    730      context[param] = value ? JSON.parse(value) : null;
    731    }
    732    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    733      type: "EVALUATE_JEXL_EXPRESSION",
    734      data: {
    735        expression: this.refs.expressionInput.value || "undefined",
    736        context
    737      }
    738    }).then(this.setStateFromParent);
    739  }
    740  onChangeTargetingParameters(event) {
    741    const {
    742      name: eventName
    743    } = event.target;
    744    const {
    745      value
    746    } = event.target;
    747    let targetingParametersError = null;
    748    try {
    749      JSON.parse(value);
    750      event.target.classList.remove("errorState");
    751    } catch (e) {
    752      console.error(`Error parsing value of parameter ${eventName}`);
    753      event.target.classList.add("errorState");
    754      targetingParametersError = {
    755        id: eventName
    756      };
    757    }
    758    this.setState(({
    759      stringTargetingParameters
    760    }) => {
    761      const updatedParameters = {
    762        ...stringTargetingParameters
    763      };
    764      updatedParameters[eventName] = value;
    765      return {
    766        copiedToClipboard: false,
    767        evaluationStatus: {},
    768        stringTargetingParameters: updatedParameters,
    769        targetingParametersError
    770      };
    771    });
    772  }
    773  unblockAll() {
    774    return _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.unblockAll().then(this.setStateFromParent);
    775  }
    776  async handleEnabledToggle(event) {
    777    const provider = this.state.providerPrefs.find(p => p.id === event.target.dataset.provider);
    778    const userPrefInfo = this.state.userPrefs;
    779    const isUserEnabled = provider.id in userPrefInfo ? userPrefInfo[provider.id] : true;
    780    const isSystemEnabled = provider.enabled;
    781    const isEnabling = event.target.checked;
    782    if (isEnabling) {
    783      if (!isUserEnabled) {
    784        await _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    785          type: "SET_PROVIDER_USER_PREF",
    786          data: {
    787            id: provider.id,
    788            value: true
    789          }
    790        });
    791      }
    792      if (!isSystemEnabled) {
    793        await _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    794          type: "ENABLE_PROVIDER",
    795          data: provider.id
    796        });
    797      }
    798    } else {
    799      await _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
    800        type: "DISABLE_PROVIDER",
    801        data: provider.id
    802      });
    803    }
    804    this.setState({
    805      filterProviders: []
    806    });
    807  }
    808  handleUserPrefToggle(event) {
    809    const action = {
    810      type: "SET_PROVIDER_USER_PREF",
    811      data: {
    812        id: event.target.dataset.provider,
    813        value: event.target.checked
    814      }
    815    };
    816    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage(action);
    817    this.setState({
    818      filterProviders: []
    819    });
    820  }
    821  onChangeFilters(event) {
    822    // this function handles both provider filter and group filter. the checkbox
    823    // will have dataset.provider if it's a provider checkbox, and dataset.group
    824    // if it's a group checkbox.
    825    let stateKey;
    826    let itemValue;
    827    let {
    828      checked
    829    } = event.target;
    830    if (event.target.dataset.provider) {
    831      stateKey = "filterProviders";
    832      itemValue = event.target.dataset.provider;
    833    } else if (event.target.dataset.group) {
    834      stateKey = "filterGroups";
    835      itemValue = event.target.dataset.group;
    836    } else if (event.target.dataset.template) {
    837      stateKey = "filterTemplates";
    838      itemValue = event.target.dataset.template;
    839    } else {
    840      return;
    841    }
    842    this.setState(prevState => {
    843      let newValue;
    844      if (checked) {
    845        newValue = prevState[stateKey].includes(itemValue) ? prevState[stateKey] : prevState[stateKey].concat(itemValue);
    846      } else {
    847        newValue = prevState[stateKey].filter(item => item !== itemValue);
    848      }
    849      return {
    850        [stateKey]: newValue
    851      };
    852    });
    853  }
    854  onClearFilters() {
    855    this.setState({
    856      filterProviders: [],
    857      filterGroups: [],
    858      filterTemplates: []
    859    });
    860  }
    861 
    862  // Simulate a copy event that sets to clipboard all targeting paramters and values
    863  onCopyTargetingParams() {
    864    const stringTargetingParameters = {
    865      ...this.state.stringTargetingParameters
    866    };
    867    for (const key of Object.keys(stringTargetingParameters)) {
    868      // If the value is not set the parameter will be lost when we stringify
    869      if (stringTargetingParameters[key] === undefined) {
    870        stringTargetingParameters[key] = null;
    871      }
    872    }
    873    const setClipboardData = e => {
    874      e.preventDefault();
    875      e.clipboardData.setData("text", JSON.stringify(stringTargetingParameters, null, 2));
    876      document.removeEventListener("copy", setClipboardData);
    877      this.setState({
    878        copiedToClipboard: true
    879      });
    880    };
    881    document.addEventListener("copy", setClipboardData);
    882    document.execCommand("copy");
    883  }
    884  onNewTargetingParams(event) {
    885    this.setState({
    886      newStringTargetingParameters: event.target.value
    887    });
    888    event.target.classList.remove("errorState");
    889    this.refs.targetingParamsEval.innerText = "";
    890    try {
    891      const stringTargetingParameters = JSON.parse(event.target.value);
    892      this.setState({
    893        stringTargetingParameters
    894      });
    895    } catch (e) {
    896      event.target.classList.add("errorState");
    897      this.refs.targetingParamsEval.innerText = e.message;
    898    }
    899  }
    900  toggleJSON(msgId) {
    901    if (this.state.collapsedMessages.includes(msgId)) {
    902      let index = this.state.collapsedMessages.indexOf(msgId);
    903      this.setState(prevState => ({
    904        collapsedMessages: [...prevState.collapsedMessages.slice(0, index), ...prevState.collapsedMessages.slice(index + 1)]
    905      }));
    906    } else {
    907      this.setState(prevState => ({
    908        collapsedMessages: prevState.collapsedMessages.concat(msgId)
    909      }));
    910    }
    911  }
    912  onMessageChanged(msgId) {
    913    if (!this.state.modifiedMessages.includes(msgId)) {
    914      this.setState(prevState => ({
    915        modifiedMessages: prevState.modifiedMessages.concat(msgId)
    916      }));
    917    }
    918  }
    919  renderMessageItem(msg) {
    920    const isBlockedByGroup = this.state.groups.filter(group => msg.groups.includes(group.id)).some(group => !group.enabled);
    921    const msgProvider = this.state.providers.find(provider => provider.id === msg.provider) || {};
    922    const isProviderExcluded = msgProvider.exclude && msgProvider.exclude.includes(msg.id);
    923    const isMessageBlocked = this.state.messageBlockList.includes(msg.id) || this.state.messageBlockList.includes(msg.campaign) || this.state.multiProfileMessageBlocklist.includes(msg.id);
    924    const isBlocked = isMessageBlocked || isBlockedByGroup || isProviderExcluded;
    925    const impressions = this.state.messageImpressions[msg.id] ? this.state.messageImpressions[msg.id].length : 0;
    926    const isCollapsed = this.state.collapsedMessages.includes(msg.id);
    927    const isModified = this.state.modifiedMessages.includes(msg.id);
    928    const aboutMessagePreviewSupported = ["infobar", "spotlight", "cfr_doorhanger", "feature_callout", "pb_newtab"].includes(msg.template);
    929    let itemClassName = "message-item";
    930    if (isBlocked) {
    931      itemClassName += " blocked";
    932    }
    933    let messageStats = [];
    934    let messageStatsString;
    935    if (impressions) {
    936      messageStats.push(`${impressions} impressions`);
    937    }
    938    if (isMessageBlocked) {
    939      messageStats.push("message blocked");
    940    } else if (isBlockedByGroup) {
    941      messageStats.push("message group blocked");
    942    } else if (isProviderExcluded) {
    943      messageStats.push("excluded by provider");
    944    }
    945    if (messageStats.length) {
    946      messageStatsString = `(${messageStats.join(", ")})`;
    947    }
    948    return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
    949      className: itemClassName,
    950      key: `${msg.id}-${msg.provider}`
    951    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
    952      className: "button-box baseline"
    953    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
    954      className: "message-id monospace"
    955    }, msg.id), " ", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
    956      className: "message-stats small-text"
    957    }, messageStatsString)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
    958      className: "button-box"
    959    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(ToggleMessageJSON, {
    960      msgId: `${msg.id}`,
    961      toggleJSON: this.toggleJSON,
    962      isCollapsed: isCollapsed
    963    }),
    964    // eslint-disable-next-line no-nested-ternary
    965    isBlocked ? null : isModified ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
    966      className: "restore",
    967      onClick: () => this.resetJSON(msg)
    968    }, "Reset") : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
    969      className: "primary show",
    970      onClick: () => this.showMessage(msg)
    971    }, "Show"), isBlocked || !isModified ? null : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
    972      className: "primary modify",
    973      onClick: () => this.modifyJson(msg)
    974    }, "Modify"), aboutMessagePreviewSupported ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_CopyButton__WEBPACK_IMPORTED_MODULE_4__.CopyButton, {
    975      transformer: text => `about:messagepreview?json=${encodeURIComponent(toBinary(text))}`,
    976      label: "Share",
    977      copiedLabel: "Copied!",
    978      inputSelector: `#${msg.id}-textarea`,
    979      className: "share"
    980    }) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
    981      className: `button${isBlocked ? " primary" : ""}`,
    982      onClick: () => isBlocked ? this.handleUnblock(msg) : this.handleBlock(msg)
    983    }, isBlocked ? "Unblock" : "Block")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("pre", {
    984      className: isCollapsed ? "collapsed" : "expanded"
    985    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("textarea", {
    986      id: `${msg.id}-textarea`,
    987      name: msg.id,
    988      className: "message-textarea",
    989      disabled: isBlocked,
    990      rows: "30",
    991      onChange: event => {
    992        try {
    993          JSON.parse(event.target.value);
    994          event.target.classList.remove("errorState");
    995        } catch (e) {
    996          event.target.classList.add("errorState");
    997        }
    998        this.onMessageChanged(msg.id);
    999      },
   1000      spellCheck: "false"
   1001    }, JSON.stringify(msg, null, 2))));
   1002  }
   1003  modifyJson(content) {
   1004    const message = JSON.parse(document.getElementById(`${content.id}-textarea`).value);
   1005    if (message.template === "pb_newtab") {
   1006      _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.openPBWindow(message.content);
   1007    } else {
   1008      _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.modifyMessageJson(message).then(state => {
   1009        this.setStateFromParent(state);
   1010      });
   1011    }
   1012  }
   1013  toggleAllMessages(messagesToShow) {
   1014    if (this.state.collapsedMessages.length) {
   1015      this.setState({
   1016        collapsedMessages: []
   1017      });
   1018    } else {
   1019      Array.prototype.forEach.call(messagesToShow, msg => {
   1020        this.setState(prevState => ({
   1021          collapsedMessages: prevState.collapsedMessages.concat(msg.id)
   1022        }));
   1023      });
   1024    }
   1025  }
   1026  filterMessages() {
   1027    let messages = [...this.state.messages];
   1028    if (this.state.filterProviders.length) {
   1029      messages = messages.filter(msg => this.state.filterProviders.includes(msg.provider));
   1030    }
   1031    if (this.state.filterGroups.length) {
   1032      messages = messages.filter(msg => msg.groups?.some(group => this.state.filterGroups.includes(group)) || !msg.groups?.length && this.state.filterGroups.includes("none"));
   1033    }
   1034    if (this.state.filterTemplates.length) {
   1035      messages = messages.filter(msg => this.state.filterTemplates.includes(msg.template));
   1036    }
   1037    return messages;
   1038  }
   1039  renderMessages() {
   1040    if (!this.state.messages) {
   1041      return null;
   1042    }
   1043    const messagesToShow = this.filterMessages();
   1044    return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("p", {
   1045      className: "helpLink"
   1046    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
   1047      className: "icon icon-small-spacer icon-info"
   1048    }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("ul", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("li", null, "To modify a message, change the JSON and click 'Modify' to see your changes."), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("li", null, "Click \"Reset\" to restore the JSON to the original."), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("li", null, "Click \"Share\" to copy a link to the clipboard that can be used to preview the message by opening the link in Nightly/local builds."))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1049      className: "button-box"
   1050    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1051      className: "small no-margins",
   1052      onClick: () => this.toggleAllMessages(messagesToShow)
   1053    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
   1054      className: `icon small icon-small-spacer icon-arrowhead-${this.state.collapsedMessages.length ? "forward" : "down"}`
   1055    }), this.state.collapsedMessages.length ? "Expand all" : "Collapse all"), this.state.modifiedMessages.length ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1056      className: "small no-margins messages-reset",
   1057      onClick: this.resetAllJSON
   1058    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
   1059      className: "icon small icon-small-spacer icon-undo"
   1060    }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", null, "Reset all JSON")) : null, this.state.messageBlockList.length ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1061      className: "small no-margins unblock-all",
   1062      onClick: this.unblockAll
   1063    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", null, "Unblock all")) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1064      className: "small no-margins",
   1065      onClick: this.resetMessageState
   1066    }, "Reset FxMS state")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1067      className: "messages-list"
   1068    }, messagesToShow.map(msg => this.renderMessageItem(msg))));
   1069  }
   1070  renderFilters() {
   1071    return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1072      className: "filters"
   1073    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1074      className: "button-box"
   1075    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1076      className: "small no-margins",
   1077      onClick: () => this.setState(prevState => ({
   1078        filtersCollapsed: !prevState.filtersCollapsed
   1079      }))
   1080    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
   1081      className: `icon small icon-small-spacer icon-arrowhead-${this.state.filtersCollapsed ? "forward" : "down"}`
   1082    }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", null, "Filters")), this.state.filterProviders.length || this.state.filterGroups.length || this.state.filterTemplates.length ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1083      className: "small no-margins",
   1084      onClick: this.onClearFilters
   1085    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
   1086      className: "icon small icon-small-spacer icon-dismiss"
   1087    }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", null, "Clear")) : null), this.state.filtersCollapsed ? null : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1088      className: "row"
   1089    }, this.state.messages ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h3", null, "Templates"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1090      className: "col"
   1091    }, this.state.messages.map(message => message.template).filter(
   1092    // eslint-disable-next-line no-shadow
   1093    (value, index, self) => self.indexOf(value) === index).map(template => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("label", {
   1094      key: template
   1095    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1096      type: "checkbox",
   1097      "data-template": template,
   1098      checked: this.state.filterTemplates.includes(template),
   1099      onChange: this.onChangeFilters
   1100    }), template)))) : null, this.state.groups ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h3", null, "Groups"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1101      className: "col"
   1102    }, this.state.groups.map(group => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("label", {
   1103      key: group.id
   1104    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1105      type: "checkbox",
   1106      "data-group": group.id,
   1107      checked: this.state.filterGroups.includes(group.id),
   1108      onChange: this.onChangeFilters
   1109    }), group.id)))) : null, this.state.providers ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h3", null, "Providers"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1110      className: "col"
   1111    }, this.state.providers.map(provider => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("label", {
   1112      key: provider.id
   1113    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1114      type: "checkbox",
   1115      "data-provider": provider.id,
   1116      checked: this.state.filterProviders.includes(provider.id),
   1117      onChange: this.onChangeFilters
   1118    }), provider.id)))) : null));
   1119  }
   1120  renderProviders() {
   1121    const providersConfig = this.state.providerPrefs;
   1122    const providerInfo = this.state.providers;
   1123    const userPrefInfo = this.state.userPrefs;
   1124    return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("table", {
   1125      className: "bordered-table",
   1126      id: "providers-table"
   1127    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("thead", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1128      className: "fixed-width"
   1129    }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1130      className: "no-wrap"
   1131    }, "Provider"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "Source"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1132      className: "no-wrap"
   1133    }, "Last Updated"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tbody", null, providersConfig.map((provider, i) => {
   1134      const isTestProvider = provider.id.includes("_local_testing");
   1135      const info = providerInfo.find(p => p.id === provider.id) || {};
   1136      const isUserEnabled = provider.id in userPrefInfo ? userPrefInfo[provider.id] : true;
   1137      const isSystemEnabled = isTestProvider || provider.enabled;
   1138      let label = "local";
   1139      if (provider.type === "remote") {
   1140        label = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", null, "endpoint (", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("a", {
   1141          className: "small-text",
   1142          target: "_blank",
   1143          href: info.url,
   1144          rel: "noopener noreferrer"
   1145        }, info.url), ")");
   1146      } else if (provider.type === "remote-settings") {
   1147        label = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", null, "remote settings (", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("a", {
   1148          className: "small-text",
   1149          target: "_blank",
   1150          href: `https://firefox.settings.services.mozilla.com/v1/buckets/main/collections/${provider.collection}/records`,
   1151          rel: "noopener noreferrer"
   1152        }, provider.collection), ")");
   1153      } else if (provider.type === "remote-experiments") {
   1154        label = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", null, "remote settings (", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("a", {
   1155          className: "small-text",
   1156          target: "_blank",
   1157          href: "https://firefox.settings.services.mozilla.com/v1/buckets/main/collections/nimbus-desktop-experiments/records",
   1158          rel: "noopener noreferrer"
   1159        }, "nimbus-desktop-experiments"), ")");
   1160      }
   1161      let reasonsDisabled = [];
   1162      if (!isSystemEnabled) {
   1163        reasonsDisabled.push("system pref");
   1164      }
   1165      if (!isUserEnabled) {
   1166        reasonsDisabled.push("user pref");
   1167      }
   1168      if (reasonsDisabled.length) {
   1169        label = `disabled via ${reasonsDisabled.join(", ")}`;
   1170      }
   1171      return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", {
   1172        key: i
   1173      }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, isTestProvider ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1174        type: "checkbox",
   1175        disabled: true,
   1176        readOnly: true,
   1177        checked: true
   1178      }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1179        type: "checkbox",
   1180        "data-provider": provider.id,
   1181        checked: isUserEnabled && isSystemEnabled,
   1182        onChange: this.handleEnabledToggle
   1183      })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, provider.id), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
   1184        className: `sourceLabel${isUserEnabled && isSystemEnabled ? "" : " isDisabled"}`
   1185      }, label)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1186        className: "no-wrap"
   1187      }, info.lastUpdated ? relativeTime(info.lastUpdated) : ""));
   1188    })));
   1189  }
   1190  renderMessageGroups() {
   1191    return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("table", {
   1192      className: "bordered-table",
   1193      id: "groups-table"
   1194    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("thead", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1195      className: "fixed-width"
   1196    }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1197      className: "no-wrap"
   1198    }, "Group"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1199      className: "no-wrap"
   1200    }, "Impressions"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "Frequency caps"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "User preferences"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tbody", null, this.state.groups && this.state.groups.map(({
   1201      id,
   1202      enabled,
   1203      frequency,
   1204      userPreferences = []
   1205    }) => {
   1206      let frequencyCaps = [];
   1207      if (!frequency) {
   1208        frequencyCaps.push("n/a");
   1209      } else {
   1210        if (frequency.custom) {
   1211          for (let f of frequency.custom) {
   1212            let {
   1213              period
   1214            } = f;
   1215            let periodString = "";
   1216            if (period >= 2419200000 && period % 2419200000 < 604800000) {
   1217              let months = Math.round(period / 2419200000);
   1218              periodString = months === 1 ? "/month" : ` in ${months}mos`;
   1219            } else if (period >= 604800000 && period % 604800000 < 86400000) {
   1220              let weeks = Math.round(period / 604800000);
   1221              periodString = weeks === 1 ? "/week" : ` in ${weeks}wks`;
   1222            } else if (period >= 86400000 && period % 86400000 < 3600000) {
   1223              let days = Math.round(period / 86400000);
   1224              periodString = days === 1 ? "/day" : ` in ${days}d`;
   1225            } else {
   1226              periodString = ` in ${period}ms`;
   1227            }
   1228            frequencyCaps.push(`${f.cap}${periodString}`);
   1229          }
   1230        }
   1231        if ("lifetime" in frequency) {
   1232          frequencyCaps.push(`${frequency.lifetime}/lifetime`);
   1233        }
   1234      }
   1235      return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", {
   1236        key: id
   1237      }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1238        className: "fixed-width"
   1239      }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1240        type: "checkbox",
   1241        checked: enabled,
   1242        disabled: true
   1243      })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1244        className: "no-wrap"
   1245      }, id), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1246        className: "no-wrap"
   1247      }, this._getGroupImpressionsCount(id, frequency)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", null, frequencyCaps.join(", "))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
   1248        className: "monospace small-text"
   1249      }, userPreferences.join(", "))));
   1250    })));
   1251  }
   1252  renderTargetingParameters() {
   1253    // There was no error and the result is truthy
   1254    const success = this.state.evaluationStatus.success && !!this.state.evaluationStatus.result;
   1255    const result = JSON.stringify(this.state.evaluationStatus.result, null, 2) || "";
   1256    return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("table", {
   1257      className: "targeting-table"
   1258    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tbody", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1259      colSpan: "2"
   1260    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "Evaluate JEXL expression"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", {
   1261      className: "jexl-evaluator-row"
   1262    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1263      colSpan: "2"
   1264    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1265      className: "jexl-evaluator"
   1266    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1267      className: "jexl-evaluator-textareas"
   1268    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1269      className: "jexl-evaluator-input"
   1270    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("textarea", {
   1271      className: "monospace no-margins",
   1272      ref: "expressionInput",
   1273      rows: "10",
   1274      cols: "60",
   1275      placeholder: "Evaluate JEXL expressions and mock parameters by changing their values below",
   1276      spellCheck: "false"
   1277    }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1278      className: "primary no-margins",
   1279      onClick: this.handleExpressionEval
   1280    }, "Evaluate")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1281      className: "jexl-evaluator-output"
   1282    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("textarea", {
   1283      className: "monospace no-margins",
   1284      readOnly: true,
   1285      rows: "10",
   1286      cols: "40",
   1287      placeholder: "<evaluation result>",
   1288      value: result,
   1289      spellCheck: "false"
   1290    }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
   1291      className: "jexl-status"
   1292    }, "Status: ", success ? "✅" : "❌")))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1293      colSpan: "2"
   1294    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "Modify targeting parameters"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1295      className: "no-margins",
   1296      onClick: this.onCopyTargetingParams,
   1297      disabled: this.state.copiedToClipboard
   1298    }, this.state.copiedToClipboard ? "Parameters copied!" : "Copy parameters"))), this.state.stringTargetingParameters && Object.keys(this.state.stringTargetingParameters).map((param, i) => {
   1299      const value = this.state.stringTargetingParameters[param];
   1300      const errorState = this.state.targetingParametersError && this.state.targetingParametersError.id === param;
   1301      const largeEditor = value?.length > 30 || value?.match(/[\nR]/);
   1302      const className = `monospace no-margins targeting-editor${errorState ? " errorState" : ""}${largeEditor ? " large" : " small"}`;
   1303      const inputComp = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("textarea", {
   1304        name: param,
   1305        className: className,
   1306        value: value,
   1307        rows: largeEditor ? "10" : "1",
   1308        cols: largeEditor ? "60" : "28",
   1309        onChange: this.onChangeTargetingParameters,
   1310        spellCheck: "false"
   1311      });
   1312      return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", {
   1313        key: i
   1314      }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, param), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, inputComp));
   1315    }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1316      colSpan: "2"
   1317    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "Attribution parameters"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1318      colSpan: "2"
   1319    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("p", null, "This forces the browser to set some attribution parameters, useful for testing the Return To AMO feature. Clicking on 'Force Attribution', with the default values in each field, will demo the Return To AMO flow with the addon called 'uBlock Origin'. If you wish to try different attribution parameters, enter them in the text boxes. If you wish to try a different addon with the Return To AMO flow, make sure the 'content' text box has a string that is 'rta:base64(addonID)', the base64 string of the addonID prefixed with 'rta:'. The addon must currently be a recommended addon on AMO. Then click 'Force Attribution'. Clicking on 'Force Attribution' with blank text boxes reset attribution data."))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "Source"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1320      className: "monospace no-margins",
   1321      type: "text",
   1322      size: "36",
   1323      name: "source",
   1324      placeholder: "addons.mozilla.org",
   1325      value: this.state.attributionParameters.source,
   1326      onChange: this.onChangeAttributionParameters
   1327    }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "Medium"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1328      className: "monospace no-margins",
   1329      type: "text",
   1330      size: "36",
   1331      name: "medium",
   1332      placeholder: "referral",
   1333      value: this.state.attributionParameters.medium,
   1334      onChange: this.onChangeAttributionParameters
   1335    }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "Campaign"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1336      className: "monospace no-margins",
   1337      type: "text",
   1338      size: "36",
   1339      name: "campaign",
   1340      placeholder: "non-fx-button",
   1341      value: this.state.attributionParameters.campaign,
   1342      onChange: this.onChangeAttributionParameters
   1343    }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "Content"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1344      className: "monospace no-margins",
   1345      type: "text",
   1346      size: "36",
   1347      name: "content",
   1348      placeholder: `rta:${btoa("uBlock0@raymondhill.net")}`,
   1349      value: this.state.attributionParameters.content,
   1350      onChange: this.onChangeAttributionParameters
   1351    }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "Experiment"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1352      className: "monospace no-margins",
   1353      type: "text",
   1354      size: "36",
   1355      name: "experiment",
   1356      placeholder: "ua-onboarding",
   1357      value: this.state.attributionParameters.experiment,
   1358      onChange: this.onChangeAttributionParameters
   1359    }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "Variation"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1360      className: "monospace no-margins",
   1361      type: "text",
   1362      size: "36",
   1363      name: "variation",
   1364      placeholder: "chrome",
   1365      value: this.state.attributionParameters.variation,
   1366      onChange: this.onChangeAttributionParameters
   1367    }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "User Agent"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1368      className: "monospace no-margins",
   1369      type: "text",
   1370      size: "36",
   1371      name: "ua",
   1372      placeholder: "Google Chrome 123",
   1373      value: this.state.attributionParameters.ua,
   1374      onChange: this.onChangeAttributionParameters
   1375    }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, "Download Token"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("input", {
   1376      className: "monospace no-margins",
   1377      type: "text",
   1378      size: "36",
   1379      name: "dltoken",
   1380      placeholder: "00000000-0000-0000-0000-000000000000",
   1381      value: this.state.attributionParameters.dltoken,
   1382      onChange: this.onChangeAttributionParameters
   1383    }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1384      colSpan: "2"
   1385    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1386      className: "primary no-margins",
   1387      onClick: this.setAttribution
   1388    }, "Force attribution")))));
   1389  }
   1390  onChangeAttributionParameters(event) {
   1391    const {
   1392      name: eventName,
   1393      value
   1394    } = event.target;
   1395    this.setState(({
   1396      attributionParameters
   1397    }) => {
   1398      const updatedParameters = {
   1399        ...attributionParameters
   1400      };
   1401      updatedParameters[eventName] = value;
   1402      return {
   1403        attributionParameters: updatedParameters
   1404      };
   1405    });
   1406  }
   1407  setAttribution() {
   1408    _asrouter_utils_mjs__WEBPACK_IMPORTED_MODULE_0__.ASRouterUtils.sendMessage({
   1409      type: "FORCE_ATTRIBUTION",
   1410      data: this.state.attributionParameters
   1411    }).then(this.setStateFromParent);
   1412  }
   1413  _getGroupImpressionsCount(id, frequency) {
   1414    if (frequency) {
   1415      return this.state.groupImpressions[id] ? this.state.groupImpressions[id].length : 0;
   1416    }
   1417    return "n/a";
   1418  }
   1419  renderErrorMessage({
   1420    id,
   1421    errors
   1422  }) {
   1423    const providerId = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
   1424      rowSpan: errors.length
   1425    }, id);
   1426    // .reverse() so that the last error (most recent) is first
   1427    return errors.map(({
   1428      error,
   1429      timestamp
   1430    }, cellKey) => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", {
   1431      key: cellKey
   1432    }, cellKey === errors.length - 1 ? providerId : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, error.message), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", null, relativeTime(timestamp)))).reverse();
   1433  }
   1434  renderErrors() {
   1435    const providersWithErrors = this.state.providers && this.state.providers.filter(p => p.errors && p.errors.length);
   1436    if (providersWithErrors && providersWithErrors.length) {
   1437      return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("table", {
   1438        className: "errorReporting"
   1439      }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("thead", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("th", null, "Provider"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("th", null, "Message"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("th", null, "Timestamp"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tbody", null, providersWithErrors.map(this.renderErrorMessage)));
   1440    }
   1441    return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("p", null, "No errors");
   1442  }
   1443  renderSection() {
   1444    const [section] = this.props.location.routes;
   1445    switch (section) {
   1446      case "targeting":
   1447        return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement((react__WEBPACK_IMPORTED_MODULE_1___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "Targeting utilities"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1448          className: "button-box"
   1449        }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1450          className: "no-margins",
   1451          onClick: this.expireCache,
   1452          title: "Values are cached for some targeting attributes (see ASRouterTargeting). This expires the query cache."
   1453        }, "Expire cache")), this.renderTargetingParameters());
   1454      case "impressions":
   1455        return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement((react__WEBPACK_IMPORTED_MODULE_1___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "Impressions"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_ImpressionsSection__WEBPACK_IMPORTED_MODULE_5__.ImpressionsSection, {
   1456          messageImpressions: this.state.messageImpressions,
   1457          groupImpressions: this.state.groupImpressions,
   1458          screenImpressions: this.state.screenImpressions
   1459        }));
   1460      case "errors":
   1461        return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement((react__WEBPACK_IMPORTED_MODULE_1___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "ASRouter errors"), this.renderErrors());
   1462      default:
   1463        return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement((react__WEBPACK_IMPORTED_MODULE_1___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "Message providers", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1464          className: "small",
   1465          title: "Restore all provider settings that ship with Firefox",
   1466          onClick: this.resetPref
   1467        }, "Restore default prefs")), this.state.providers ? this.renderProviders() : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "Message groups", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1468          className: "small",
   1469          onClick: this.resetGroupImpressions
   1470        }, "Reset group impressions")), this.state.groups ? this.renderMessageGroups() : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "Messages", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
   1471          className: "small",
   1472          onClick: this.resetMessageImpressions
   1473        }, "Reset message impressions")), this.renderFilters(), this.renderMessages());
   1474    }
   1475  }
   1476  render() {
   1477    if (!this.state.devtoolsEnabled) {
   1478      return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1479        className: "asrouter-admin"
   1480      }, "You must enable the ASRouter Admin page by setting", " ", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("code", null, "browser.newtabpage.activity-stream.asrouter.devtoolsEnabled"), " ", "to ", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("code", null, "true"), " and then reloading this page.");
   1481    }
   1482    const [section] = this.props.location.routes;
   1483    return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", {
   1484      className: "asrouter-admin"
   1485    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("aside", {
   1486      className: "sidebar"
   1487    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("ul", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("li", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("a", {
   1488      href: "#devtools",
   1489      className: "category",
   1490      "data-selected": section ? null : ""
   1491    }, "General")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("li", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("a", {
   1492      href: "#devtools-targeting",
   1493      className: "category",
   1494      "data-selected": section === "targeting" ? "" : null
   1495    }, "Targeting")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("li", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("a", {
   1496      href: "#devtools-impressions",
   1497      className: "category",
   1498      "data-selected": section === "impressions" ? "" : null
   1499    }, "Impressions")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("li", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("a", {
   1500      href: "#devtools-errors",
   1501      className: "category",
   1502      "data-selected": section === "errors" ? "" : null
   1503    }, "Errors")))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("main", {
   1504      className: "main-panel"
   1505    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h1", null, "ASRouter Admin"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("p", {
   1506      className: "helpLink"
   1507    }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
   1508      className: "icon icon-small-spacer icon-info"
   1509    }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", null, "Need help using these tools? Check out our", " ", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("a", {
   1510      target: "blank",
   1511      href: "https://firefox-source-docs.mozilla.org/browser/components/asrouter/docs/debugging-docs.html"
   1512    }, "documentation"))), this.renderSection()));
   1513  }
   1514 }
   1515 const ASRouterAdmin = props => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_SimpleHashRouter__WEBPACK_IMPORTED_MODULE_3__.SimpleHashRouter, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(ASRouterAdminInner, props));
   1516 function renderASRouterAdmin() {
   1517  react_dom__WEBPACK_IMPORTED_MODULE_2___default().render(/*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(ASRouterAdmin, null), document.getElementById("root"));
   1518 }
   1519 })();
   1520 
   1521 ASRouterAdminRenderUtils = __webpack_exports__;
   1522 /******/ })()
   1523 ;