Backed out 5 changesets (bug 1866802) for causing failures at test_TopSitesFeed.js. CLOSED TREE

Backed out changeset af9fbbc9ae50 (bug 1866802)
Backed out changeset 81d5b7de7178 (bug 1866802)
Backed out changeset e4d0863ed222 (bug 1866802)
Backed out changeset c0deb681b193 (bug 1866802)
Backed out changeset dda3e5e39f8c (bug 1866802)
This commit is contained in:
Butkovits Atila 2023-12-14 03:22:48 +02:00
Родитель d433a7d264
Коммит 8582db0ea5
46 изменённых файлов: 2200 добавлений и 17481 удалений

Просмотреть файл

@ -233,7 +233,6 @@ module.exports = {
"browser/components/Browser*",
"browser/components/aboutlogins/**",
"browser/components/aboutwelcome/**",
"browser/components/asrouter/**",
"browser/components/attribution/**",
"browser/components/customizableui/**",
"browser/components/downloads/**",
@ -499,7 +498,6 @@ module.exports = {
extends: ["plugin:react-hooks/recommended"],
files: [
"browser/components/aboutwelcome/**",
"browser/components/asrouter/**",
"browser/components/newtab/**",
"browser/components/pocket/**",
"devtools/**",

8
.gitignore поставляемый
Просмотреть файл

@ -56,20 +56,12 @@ security/manager/.nss.checkout
# gecko.log is generated by various test harnesses
/gecko.log
# Ignore all node_modules directories
node_modules/
# ...but allow ones under third_party
!/third_party/**/node_modules/
# Ignore newtab component build assets
browser/components/newtab/logs/
# Ignore about:welcome component build assets
browser/components/aboutwelcome/logs/
# Ignore ASRouter component build assets
browser/components/asrouter/logs/
# Ignore ASRouter generated test files
browser/components/newtab/content-src/asrouter/schemas/corpus/CFRMessageProvider.messages.json
browser/components/newtab/content-src/asrouter/schemas/corpus/OnboardingMessageProvider.messages.json

Просмотреть файл

@ -60,9 +60,6 @@ compile_commands\.json
# Ignore about:welcome build assets
^browser/components/aboutwelcome/logs/
# Ignore ASRouter component build assets
^browser/components/asrouter/logs/
# Ignore ASRouter generated test files
^browser/components/newtab/content-src/asrouter/schemas/corpus/CFRMessageProvider.messages.json
^browser/components/newtab/content-src/asrouter/schemas/corpus/OnboardingMessageProvider.messages.json
@ -201,7 +198,6 @@ _OPT\.OBJ/
^node_modules/
^tools/browsertime/node_modules/
^tools/lint/eslint/eslint-plugin-mozilla/node_modules/
^browser/components/asrouter/node_modules/
^browser/components/newtab/node_modules/
^browser/components/aboutwelcome/node_modules/
^tools/esmify/node_modules/

Просмотреть файл

@ -1449,9 +1449,6 @@ xpcom/io/crc32c.c
.gradle/
browser/components/aboutwelcome/content/aboutwelcome.bundle.js
browser/components/asrouter/node_modules/
browser/components/asrouter/content/asrouter-admin.bundle.js
browser/components/asrouter/logs/
browser/components/newtab/content-src/asrouter/schemas/BackgroundTaskMessagingExperiment.schema.json
browser/components/newtab/content-src/asrouter/schemas/MessagingExperiment.schema.json
browser/components/newtab/logs/

Просмотреть файл

@ -26,7 +26,6 @@ obj*/
browser/components/pocket/content/panels/css/main.compiled.css
browser/components/newtab/**/*.css
browser/components/aboutwelcome/**/*.css
browser/components/asrouter/**/*.css
# Note that the debugger has its own stylelint setup, but that currently
# produces errors. Bug 1831302 tracks making this better

Просмотреть файл

@ -260,7 +260,6 @@ module.exports = {
{
files: [
"browser/components/aboutwelcome/**",
"browser/components/asrouter/**",
"browser/components/newtab/**",
],
customSyntax: "postcss-scss",

Просмотреть файл

@ -581,7 +581,6 @@ let JSWINDOWACTORS = {
includeChrome: true,
allFrames: true,
matches: [
"about:asrouter",
"about:home",
"about:newtab",
"about:welcome",
@ -797,7 +796,6 @@ let JSWINDOWACTORS = {
},
},
matches: [
"about:asrouter*",
"about:home*",
"about:newtab*",
"about:welcome*",

Просмотреть файл

@ -44,11 +44,6 @@ struct RedirEntry {
browser/components/about/components.conf
*/
static const RedirEntry kRedirMap[] = {
{"asrouter", "chrome://browser/content/asrouter/asrouter-admin.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS |
nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT},
{"blocked", "chrome://browser/content/blockedSite.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT |

Просмотреть файл

@ -5,7 +5,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
pages = [
'asrouter',
'blocked',
'certerror',
'downloads',

Просмотреть файл

@ -1,169 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module.exports = {
// When adding items to this file please check for effects on sub-directories.
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
plugins: ["import", "react", "jsx-a11y"],
settings: {
react: {
version: "16.2.0",
},
},
extends: ["plugin:jsx-a11y/recommended"],
overrides: [
{
// Only mark the files as modules which are actually modules.
files: ["content-src/**", "tests/unit/**"],
parserOptions: {
sourceType: "module",
},
},
{
files: ["./*.js", "content-src/**", "tests/unit/**"],
env: {
node: true,
},
},
{
// Use a configuration that's appropriate for modules, workers and
// non-production files.
files: ["tests/**"],
rules: {
"no-implicit-globals": "off",
},
},
{
files: ["content-src/**", "tests/unit/**"],
rules: {
// Disallow commonjs in these directories.
"import/no-commonjs": 2,
// Allow JSX with arrow functions.
"react/jsx-no-bind": 0,
},
},
{
// These tests simulate the browser environment.
files: "tests/unit/**",
env: {
browser: true,
mocha: true,
},
globals: {
assert: true,
chai: true,
sinon: true,
},
},
{
files: "tests/**",
rules: {
"func-name-matching": 0,
"lines-between-class-members": 0,
"require-await": 0,
},
},
],
rules: {
"fetch-options/no-fetch-credentials": "error",
"react/jsx-boolean-value": ["error", "always"],
"react/jsx-key": "error",
"react/jsx-no-bind": "error",
"react/jsx-no-comment-textnodes": "error",
"react/jsx-no-duplicate-props": "error",
"react/jsx-no-target-blank": "error",
"react/jsx-no-undef": "error",
"react/jsx-pascal-case": "error",
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"react/no-access-state-in-setstate": "error",
"react/no-danger": "error",
"react/no-deprecated": "error",
"react/no-did-mount-set-state": "error",
"react/no-did-update-set-state": "error",
"react/no-direct-mutation-state": "error",
"react/no-is-mounted": "error",
"react/no-unknown-property": "error",
"react/require-render-return": "error",
"accessor-pairs": ["error", { setWithoutGet: true, getWithoutSet: false }],
"array-callback-return": "error",
"block-scoped-var": "error",
"consistent-this": ["error", "use-bind"],
eqeqeq: "error",
"for-direction": "error",
"func-name-matching": "error",
"getter-return": "error",
"guard-for-in": "error",
"handle-callback-err": "error",
"lines-between-class-members": "error",
"max-depth": ["error", 4],
"max-nested-callbacks": ["error", 4],
"max-params": ["error", 6],
"max-statements": ["error", 50],
"max-statements-per-line": ["error", { max: 2 }],
"new-cap": ["error", { newIsCap: true, capIsNew: false }],
"no-alert": "error",
"no-buffer-constructor": "error",
"no-console": ["error", { allow: ["error"] }],
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-eq-null": "error",
"no-extend-native": "error",
"no-extra-label": "error",
"no-implicit-coercion": ["error", { allow: ["!!"] }],
"no-implicit-globals": "error",
"no-loop-func": "error",
"no-mixed-requires": "error",
"no-multi-assign": "error",
"no-multi-str": "error",
"no-new": "error",
"no-new-func": "error",
"no-new-require": "error",
"no-octal-escape": "error",
"no-param-reassign": "error",
"no-path-concat": "error",
"no-process-exit": "error",
"no-proto": "error",
"no-prototype-builtins": "error",
"no-return-assign": ["error", "except-parens"],
"no-script-url": "error",
"no-shadow": "error",
"no-template-curly-in-string": "error",
"no-undef-init": "error",
"no-unmodified-loop-condition": "error",
"no-unused-expressions": "error",
"no-use-before-define": "error",
"no-useless-computed-key": "error",
"no-useless-constructor": "error",
"no-useless-rename": "error",
"no-var": "error",
"no-void": ["error", { allowAsStatement: true }],
"one-var": ["error", "never"],
"operator-assignment": ["error", "always"],
"prefer-destructuring": [
"error",
{
AssignmentExpression: { array: true },
VariableDeclarator: { array: true, object: true },
},
],
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"prefer-template": "error",
radix: ["error", "always"],
"require-await": "error",
"sort-vars": "error",
"symbol-description": "error",
"vars-on-top": "error",
yoda: ["error", "never"],
},
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,38 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'none'; object-src 'none'; script-src resource: chrome:;"
/>
<meta name="color-scheme" content="light dark" />
<title>ASRouter Admin</title>
<link
rel="icon"
type="image/png"
href="chrome://branding/content/icon32.png"
/>
<link rel="localization" href="branding/brand.ftl" />
<link rel="localization" href="toolkit/branding/brandings.ftl" />
<link
rel="stylesheet"
href="chrome://browser/content/asrouter/components/ASRouterAdmin/ASRouterAdmin.css"
/>
</head>
<body>
<div id="root"></div>
<script src="chrome://browser/content/contentTheme.js"></script>
<script src="resource://activity-stream/vendor/react.js"></script>
<script src="resource://activity-stream/vendor/react-dom.js"></script>
<script src="resource://activity-stream/vendor/prop-types.js"></script>
<script src="chrome://browser/content/asrouter/asrouter-admin.bundle.js"></script>
<!-- The render.js script is the main entrypoint for the page. -->
<script src="chrome://browser/content/asrouter/render.js"></script>
</body>
</html>

Просмотреть файл

@ -1,546 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* stylelint-disable max-nesting-depth */
:root {
--newtab-background-color: #F9F9FB;
--newtab-background-color-secondary: #FFF;
--newtab-text-primary-color: #15141a;
--newtab-primary-action-background: #0061e0;
--newtab-primary-action-background-pocket: #008078;
--newtab-text-secondary-color: color-mix(in srgb, var(--newtab-text-primary-color) 70%, transparent);
--newtab-element-hover-color: color-mix(in srgb, var(--newtab-background-color) 90%, #000);
--newtab-element-active-color: color-mix(in srgb, var(--newtab-background-color) 80%, #000);
--newtab-element-secondary-color: color-mix(in srgb, currentColor 5%, transparent);
--newtab-element-secondary-hover-color: color-mix(in srgb, currentColor 12%, transparent);
--newtab-element-secondary-active-color: color-mix(in srgb, currentColor 25%, transparent);
--newtab-primary-element-hover-color: color-mix(in srgb, var(--newtab-primary-action-background) 90%, #000);
--newtab-primary-element-hover-pocket-color: color-mix(in srgb, var(--newtab-primary-action-background-pocket) 90%, #000);
--newtab-primary-element-active-color: color-mix(in srgb, var(--newtab-primary-action-background) 80%, #000);
--newtab-primary-element-text-color: #FFF;
--newtab-primary-action-background-dimmed: color-mix(in srgb, var(--newtab-primary-action-background) 25%, transparent);
--newtab-primary-action-background-pocket-dimmed: color-mix(in srgb, var(--newtab-primary-action-background-pocket) 25%, transparent);
--newtab-border-color: color-mix(in srgb, var(--newtab-background-color) 75%, #000);
--newtab-wordmark-color: #20123A;
--newtab-status-success: #058B00;
--newtab-status-error: #D70022;
--newtab-inner-box-shadow-color: rgba(0, 0, 0, 0.1);
--newtab-overlay-color: color-mix(in srgb, var(--newtab-background-color) 85%, transparent);
--newtab-textbox-focus-color: var(--newtab-primary-action-background);
--newtab-textbox-focus-boxshadow: 0 0 0 1px var(--newtab-primary-action-background), 0 0 0 4px rgba(var(--newtab-primary-action-background), 0.3);
--newtab-button-secondary-color: inherit;
}
:root[lwt-newtab-brighttext] {
--newtab-background-color: #2B2A33;
--newtab-background-color-secondary: #42414d;
--newtab-text-primary-color: #fbfbfe;
--newtab-primary-action-background: #00ddff;
--newtab-primary-action-background-pocket: #00ddff;
--newtab-primary-action-background-pocket-dimmed: color-mix(in srgb, var(--newtab-primary-action-background) 25%, transparent);
--newtab-primary-element-hover-color: color-mix(in srgb, var(--newtab-primary-action-background) 55%, #FFF);
--newtab-primary-element-hover-pocket-color: color-mix(in srgb, var(--newtab-primary-action-background-pocket) 55%, #FFF);
--newtab-element-hover-color: color-mix(in srgb, var(--newtab-background-color) 80%, #FFF);
--newtab-element-active-color: color-mix(in srgb, var(--newtab-background-color) 60%, #FFF);
--newtab-element-secondary-color: color-mix(in srgb, currentColor 10%, transparent);
--newtab-element-secondary-hover-color: color-mix(in srgb, currentColor 17%, transparent);
--newtab-element-secondary-active-color: color-mix(in srgb, currentColor 30%, transparent);
--newtab-border-color: color-mix(in srgb, var(--newtab-background-color) 75%, #FFF);
--newtab-primary-element-text-color: #2b2a33;
--newtab-wordmark-color: #fbfbfe;
--newtab-status-success: #7C6;
}
@media (prefers-contrast) {
:root {
--newtab-text-secondary-color: var(--newtab-text-primary-color);
}
}
.icon {
background-position: center center;
background-repeat: no-repeat;
background-size: 16px;
-moz-context-properties: fill;
display: inline-block;
color: var(--newtab-text-primary-color);
fill: currentColor;
height: 16px;
vertical-align: middle;
width: 16px;
}
.icon.icon-spacer {
margin-inline-end: 8px;
}
.icon.icon-small-spacer {
margin-inline-end: 6px;
}
.icon.icon-button-style {
fill: var(--newtab-text-secondary-color);
border: 0;
}
.icon.icon-button-style:focus, .icon.icon-button-style:hover {
fill: var(--newtab-text-primary-color);
}
.icon.icon-bookmark-added {
background-image: url("chrome://browser/skin/bookmark.svg");
}
.icon.icon-bookmark-hollow {
background-image: url("chrome://browser/skin/bookmark-hollow.svg");
}
.icon.icon-clear-input {
background-image: url("chrome://global/skin/icons/close-fill.svg");
}
.icon.icon-delete {
background-image: url("chrome://global/skin/icons/delete.svg");
}
.icon.icon-search {
background-image: url("chrome://global/skin/icons/search-glass.svg");
}
.icon.icon-modal-delete {
flex-shrink: 0;
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-modal-delete-20.svg");
background-size: 32px;
height: 32px;
width: 32px;
}
.icon.icon-mail {
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-mail-16.svg");
}
.icon.icon-dismiss {
background-image: url("chrome://global/skin/icons/close.svg");
}
.icon.icon-info {
background-image: url("chrome://global/skin/icons/info.svg");
}
.icon.icon-new-window {
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-newWindow-16.svg");
}
.icon.icon-new-window:dir(rtl) {
transform: scaleX(-1);
}
.icon.icon-new-window-private {
background-image: url("chrome://browser/skin/privateBrowsing.svg");
}
.icon.icon-settings {
background-image: url("chrome://global/skin/icons/settings.svg");
}
.icon.icon-pin {
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-pin-16.svg");
}
.icon.icon-pin:dir(rtl) {
transform: scaleX(-1);
}
.icon.icon-unpin {
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-unpin-16.svg");
}
.icon.icon-unpin:dir(rtl) {
transform: scaleX(-1);
}
.icon.icon-edit {
background-image: url("chrome://global/skin/icons/edit.svg");
}
.icon.icon-pocket {
background-image: url("chrome://global/skin/icons/pocket.svg");
}
.icon.icon-pocket-save {
background-image: url("chrome://global/skin/icons/pocket.svg");
fill: #FFF;
}
.icon.icon-pocket-delete {
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-pocket-delete-16.svg");
}
.icon.icon-pocket-archive {
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-pocket-archive-16.svg");
}
.icon.icon-history-item {
background-image: url("chrome://browser/skin/history.svg");
}
.icon.icon-trending {
background-image: url("chrome://browser/skin/trending.svg");
transform: translateY(2px);
}
.icon.icon-now {
background-image: url("chrome://browser/skin/history.svg");
}
.icon.icon-topsites {
background-image: url("chrome://browser/skin/topsites.svg");
}
.icon.icon-pin-small {
background-image: url("chrome://browser/skin/pin-12.svg");
background-size: 12px;
height: 12px;
width: 12px;
}
.icon.icon-pin-small:dir(rtl) {
transform: scaleX(-1);
}
.icon.icon-check {
background-image: url("chrome://global/skin/icons/check.svg");
}
.icon.icon-download {
background-image: url("chrome://browser/skin/downloads/downloads.svg");
}
.icon.icon-copy {
background-image: url("chrome://global/skin/icons/edit-copy.svg");
}
.icon.icon-open-file {
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-open-file-16.svg");
}
.icon.icon-webextension {
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-webextension-16.svg");
}
.icon.icon-highlights {
background-image: url("chrome://global/skin/icons/highlights.svg");
}
.icon.icon-arrowhead-down {
background-image: url("chrome://global/skin/icons/arrow-down.svg");
}
.icon.icon-arrowhead-down-small {
background-image: url("chrome://global/skin/icons/arrow-down-12.svg");
background-size: 12px;
height: 12px;
width: 12px;
}
.icon.icon-arrowhead-forward-small {
background-image: url("chrome://global/skin/icons/arrow-right-12.svg");
background-size: 12px;
height: 12px;
width: 12px;
}
.icon.icon-arrowhead-forward-small:dir(rtl) {
background-image: url("chrome://global/skin/icons/arrow-left-12.svg");
}
.icon.icon-arrowhead-up {
background-image: url("chrome://global/skin/icons/arrow-up.svg");
}
.icon.icon-add {
background-image: url("chrome://global/skin/icons/plus.svg");
}
.icon.icon-minimize {
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-minimize-16.svg");
}
.icon.icon-maximize {
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-maximize-16.svg");
}
.icon.icon-arrow {
background-image: url("chrome://global/skin/icons/arrow-right-12.svg");
}
.ASRouterButton {
font-weight: 600;
font-size: 14px;
white-space: nowrap;
border-radius: 2px;
border: 0;
font-family: inherit;
padding: 8px 15px;
margin-inline-start: 12px;
color: inherit;
cursor: pointer;
}
.tall .ASRouterButton {
margin-inline-start: 20px;
}
.ASRouterButton.test-only {
width: 0;
height: 0;
overflow: hidden;
display: block;
visibility: hidden;
}
.ASRouterButton.primary {
border: 1px solid var(--newtab-primary-action-background);
background-color: var(--newtab-primary-action-background);
color: var(--newtab-primary-element-text-color);
}
.ASRouterButton.primary:hover {
background-color: var(--newtab-primary-element-hover-color);
}
.ASRouterButton.primary:active {
background-color: var(--newtab-primary-element-active-color);
}
.ASRouterButton.slim {
border: 1px solid var(--newtab-border-color);
margin-inline-start: 0;
font-size: 12px;
padding: 6px 12px;
}
.ASRouterButton.slim:hover, .ASRouterButton.slim:focus {
box-shadow: 0 0 0 5px var(--newtab-element-secondary-color);
transition: box-shadow 150ms;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Ubuntu, "Helvetica Neue", sans-serif;
}
/**
* These styles are copied verbatim from _activity-stream.scss in order to maintain
* a continuity of styling while also decoupling from the newtab code. This should
* be removed when about:asrouter starts using the default in-content style sheets.
*/
.button,
.actions button {
background-color: var(--newtab-button-secondary-color);
border: 1px solid var(--newtab-border-color);
border-radius: 4px;
color: inherit;
cursor: pointer;
margin-bottom: 15px;
padding: 10px 30px;
white-space: nowrap;
}
.button:hover:not(.dismiss), .button:focus:not(.dismiss),
.actions button:hover:not(.dismiss),
.actions button:focus:not(.dismiss) {
box-shadow: 0 0 0 5px var(--newtab-element-secondary-color);
transition: box-shadow 150ms;
}
.button.dismiss,
.actions button.dismiss {
background-color: transparent;
border: 0;
padding: 0;
text-decoration: underline;
}
.button.primary, .button.done,
.actions button.primary,
.actions button.done {
background-color: var(--newtab-primary-action-background);
border: solid 1px var(--newtab-primary-action-background);
color: var(--newtab-primary-element-text-color);
margin-inline-start: auto;
}
.asrouter-admin {
max-width: 1300px;
font-size: 14px;
padding-inline-start: 240px;
color: var(--newtab-text-primary-color);
}
.asrouter-admin.collapsed {
display: none;
}
.asrouter-admin .sidebar {
inset-inline-start: 0;
position: fixed;
width: 240px;
}
.asrouter-admin .sidebar ul {
margin: 0;
padding: 0;
list-style: none;
}
.asrouter-admin .sidebar li a {
padding: 10px 34px;
display: block;
color: var(--lwt-sidebar-text-color);
}
.asrouter-admin .sidebar li a:hover {
background: var(--newtab-background-color-secondary);
}
.asrouter-admin h1 {
font-weight: 200;
font-size: 32px;
}
.asrouter-admin h2 .button,
.asrouter-admin p .button {
font-size: 14px;
padding: 6px 12px;
margin-inline-start: 5px;
margin-bottom: 0;
}
.asrouter-admin .general-textarea {
direction: ltr;
width: 740px;
height: 500px;
overflow: auto;
resize: none;
border-radius: 4px;
display: flex;
}
.asrouter-admin .wnp-textarea {
direction: ltr;
width: 740px;
height: 500px;
overflow: auto;
resize: none;
border-radius: 4px;
display: flex;
}
.asrouter-admin .json-button {
display: inline-flex;
font-size: 10px;
padding: 4px 10px;
margin-bottom: 6px;
margin-inline-end: 4px;
}
.asrouter-admin .json-button:hover {
background-color: var(--newtab-element-hover-color);
box-shadow: none;
}
.asrouter-admin table {
border-collapse: collapse;
}
.asrouter-admin table.minimal-table {
border-collapse: collapse;
border: 1px solid var(--newtab-border-color);
}
.asrouter-admin table.minimal-table td {
padding: 8px;
}
.asrouter-admin table.minimal-table td:first-child {
width: 1%;
white-space: nowrap;
}
.asrouter-admin table.minimal-table td:not(:first-child) {
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
}
.asrouter-admin table.errorReporting tr {
border: 1px solid var(--newtab-background-color-secondary);
}
.asrouter-admin table.errorReporting td {
padding: 4px;
}
.asrouter-admin table.errorReporting td[rowspan] {
border: 1px solid var(--newtab-background-color-secondary);
}
.asrouter-admin .sourceLabel {
background: var(--newtab-background-color-secondary);
padding: 2px 5px;
border-radius: 3px;
}
.asrouter-admin .sourceLabel.isDisabled {
background: rgba(215, 0, 34, 0.3);
color: var(--newtab-status-error);
}
.asrouter-admin .message-item:first-child td {
border-top: 1px solid var(--newtab-border-color);
}
.asrouter-admin .message-item td {
vertical-align: top;
padding: 8px;
border-bottom: 1px solid var(--newtab-border-color);
}
.asrouter-admin .message-item td.min {
width: 1%;
white-space: nowrap;
}
.asrouter-admin .message-item td.message-summary {
width: 60%;
}
.asrouter-admin .message-item td.button-column {
width: 15%;
}
.asrouter-admin .message-item td:first-child {
border-inline-start: 1px solid var(--newtab-border-color);
}
.asrouter-admin .message-item td:last-child {
border-inline-end: 1px solid var(--newtab-border-color);
}
.asrouter-admin .message-item.blocked .message-id,
.asrouter-admin .message-item.blocked .message-summary {
opacity: 0.5;
}
.asrouter-admin .message-item.blocked .message-id {
opacity: 0.5;
}
.asrouter-admin .message-item .message-id {
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
font-size: 12px;
}
.asrouter-admin .providerUrl {
font-size: 12px;
}
.asrouter-admin pre {
background: var(--newtab-background-color-secondary);
margin: 0;
padding: 8px;
font-size: 12px;
max-width: 750px;
overflow: auto;
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
}
.asrouter-admin .errorState {
border: 1px solid var(--newtab-status-error);
}
.asrouter-admin .helpLink {
padding: 10px;
display: flex;
background: rgba(0, 0, 0, 0.1);
border-radius: 3px;
align-items: center;
}
.asrouter-admin .helpLink a {
text-decoration: underline;
}
.asrouter-admin .helpLink .icon {
min-width: 18px;
min-height: 18px;
}
.asrouter-admin .ds-component {
margin-bottom: 20px;
}
.asrouter-admin .modalOverlayInner {
height: 80%;
}
.asrouter-admin .clearButton {
border: 0;
padding: 4px;
border-radius: 4px;
display: flex;
}
.asrouter-admin .clearButton:hover {
background: var(--newtab-element-hover-color);
}
.asrouter-admin .collapsed {
display: none;
}
.asrouter-admin .icon {
display: inline-table;
cursor: pointer;
width: 18px;
height: 18px;
}
.asrouter-admin .button:disabled, .asrouter-admin .button:disabled:active {
opacity: 0.5;
cursor: unset;
box-shadow: none;
}
.asrouter-admin .impressions-section {
display: flex;
flex-direction: column;
gap: 16px;
}
.asrouter-admin .impressions-section .impressions-item {
display: flex;
flex-flow: column nowrap;
padding: 8px;
border: 1px solid var(--newtab-border-color);
border-radius: 5px;
}
.asrouter-admin .impressions-section .impressions-item .impressions-inner-box {
display: flex;
flex-flow: row nowrap;
gap: 8px;
}
.asrouter-admin .impressions-section .impressions-item .impressions-category {
font-size: 1.15em;
white-space: nowrap;
flex-grow: 0.1;
}
.asrouter-admin .impressions-section .impressions-item .impressions-buttons {
display: flex;
flex-direction: column;
gap: 8px;
}
.asrouter-admin .impressions-section .impressions-item .impressions-buttons button {
margin: 0;
}
.asrouter-admin .impressions-section .impressions-item .impressions-editor {
display: flex;
flex-grow: 1.5;
}
.asrouter-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
width: auto;
flex-grow: 1;
}

Просмотреть файл

@ -1,7 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// exported by asrouter-admin.bundle.js
window.ASRouterAdminRenderUtils.renderASRouterAdmin();

Просмотреть файл

@ -1,9 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
browser.jar:
content/browser/asrouter/asrouter-admin.html (content/asrouter-admin.html)
content/browser/asrouter/asrouter-admin.bundle.js (content/asrouter-admin.bundle.js)
content/browser/asrouter/components/ASRouterAdmin/ASRouterAdmin.css (content/components/ASRouterAdmin/ASRouterAdmin.css)
content/browser/asrouter/render.js (content/render.js)

Просмотреть файл

@ -1,203 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const path = require("path");
const webpack = require("webpack");
const { ResourceUriPlugin } = require("../newtab/tools/resourceUriPlugin");
const PATHS = {
// Where is the entry point for the unit tests?
testEntryFile: path.resolve(__dirname, "./tests/unit/unit-entry.js"),
// A glob-style pattern matching all unit tests
testFilesPattern: "./tests/unit/unit-entry.js",
// The base directory of all source files (used for path resolution in webpack importing)
moduleResolveDirectory: __dirname,
newtabResolveDirectory: "../newtab",
// a RegEx matching all Cu.import statements of local files
resourcePathRegEx: /^resource:\/\/activity-stream\//,
coverageReportingPath: "logs/coverage/",
};
// When tweaking here, be sure to review the docs about the execution ordering
// semantics of the preprocessors array, as they are somewhat odd.
const preprocessors = {};
preprocessors[PATHS.testFilesPattern] = [
"webpack", // require("karma-webpack")
"sourcemap", // require("karma-sourcemap-loader")
];
module.exports = function (config) {
const isTDD = config.tdd;
const browsers = isTDD ? ["Firefox"] : ["FirefoxHeadless"]; // require("karma-firefox-launcher")
config.set({
singleRun: !isTDD,
browsers,
customLaunchers: {
FirefoxHeadless: {
base: "Firefox",
flags: ["--headless"],
},
},
frameworks: [
"chai", // require("chai") require("karma-chai")
"mocha", // require("mocha") require("karma-mocha")
"sinon", // require("sinon") require("karma-sinon")
],
reporters: [
"coverage-istanbul", // require("karma-coverage")
"mocha", // require("karma-mocha-reporter")
// for bin/try-runner.js to parse the output easily
"json", // require("karma-json-reporter")
],
jsonReporter: {
// So this doesn't get interleaved with other karma output
stdout: false,
outputFile: path.join("logs", "karma-run-results.json"),
},
coverageIstanbulReporter: {
reports: ["lcov", "text-summary"], // for some reason "lcov" reallys means "lcov" and "html"
"report-config": {
// so the full m-c path gets printed; needed for https://coverage.moz.tools/ integration
lcov: {
projectRoot: "../../..",
},
},
dir: PATHS.coverageReportingPath,
// This will make karma fail if coverage reporting is less than the minimums here
thresholds: !isTDD && {
each: {
statements: 100,
lines: 100,
functions: 100,
branches: 66,
overrides: {
"content-src/components/ASRouterAdmin/*.jsx": {
statements: 0,
lines: 0,
functions: 0,
branches: 0,
},
},
},
},
},
files: [PATHS.testEntryFile],
preprocessors,
webpack: {
mode: "none",
devtool: "inline-source-map",
// This loader allows us to override required files in tests
resolveLoader: {
alias: {
inject: path.join(__dirname, "../newtab/loaders/inject-loader"),
},
},
// This resolve config allows us to import with paths relative to the root directory, e.g. "lib/ActivityStream.jsm"
resolve: {
extensions: [".js", ".jsx"],
modules: [
PATHS.moduleResolveDirectory,
"node_modules",
PATHS.newtabResolveDirectory,
],
fallback: {
stream: require.resolve("stream-browserify"),
buffer: require.resolve("buffer"),
},
alias: {
newtab: path.join(__dirname, "../newtab"),
},
},
plugins: [
// The ResourceUriPlugin handles translating resource URIs in import
// statements in .mjs files, in a similar way to what
// babel-jsm-to-commonjs does for jsm files.
new ResourceUriPlugin({
resourcePathRegEx: PATHS.resourcePathRegEx,
}),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("development"),
}),
],
externals: {
// enzyme needs these for backwards compatibility with 0.13.
// see https://github.com/airbnb/enzyme/blob/master/docs/guides/webpack.md#using-enzyme-with-webpack
"react/addons": true,
"react/lib/ReactContext": true,
"react/lib/ExecutionEnvironment": true,
},
module: {
rules: [
// This rule rewrites importing/exporting in .jsm files to be compatible with esmodules
{
test: /\.jsm$/,
exclude: [/node_modules/],
use: [
{
loader: "babel-loader", // require("babel-core")
options: {
plugins: [
// Converts .jsm files into common-js modules
[
"../newtab/tools/babel-jsm-to-commonjs.js",
{
basePath: PATHS.resourcePathRegEx,
removeOtherImports: true,
replace: true,
},
],
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-class-properties",
],
},
},
],
},
{
test: /\.js$/,
exclude: [/node_modules\/(?!@fluent\/).*/, /tests/],
loader: "babel-loader",
options: {
// This is a workaround for bug 1787278. It can be removed once
// that bug is fixed.
plugins: ["@babel/plugin-proposal-optional-chaining"],
},
},
{
test: /\.jsx$/,
exclude: /node_modules/,
loader: "babel-loader",
options: {
presets: ["@babel/preset-react"],
plugins: [
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining",
],
},
},
{
test: /\.md$/,
use: "raw-loader",
},
{
enforce: "post",
test: /\.js[mx]?$/,
loader: "@jsdevtools/coverage-istanbul-loader",
options: { esModules: true },
include: [path.resolve("content-src"), path.resolve("modules")],
exclude: [path.resolve("tests"), path.resolve("../newtab")],
},
],
},
},
// Silences some overly-verbose logging of individual module builds
webpackMiddleware: { noInfo: true },
});
};

Просмотреть файл

@ -1,10 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
JAR_MANIFESTS += ["jar.mn"]
with Files("**"):
BUG_COMPONENT = ("Firefox", "Messaging System")

12194
browser/components/asrouter/package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,83 +0,0 @@
{
"name": "ASRouter",
"description": "Task running for ASRouter",
"version": "1.0.0",
"author": "Mozilla (https://mozilla.org/)",
"dependencies": {
"@fluent/bundle": "0.17.1",
"@fluent/react": "0.15.0",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-redux": "7.2.6",
"redux": "4.1.2"
},
"devDependencies": {
"@babel/plugin-proposal-class-properties": "7.16.0",
"@babel/plugin-proposal-optional-chaining": "7.16.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.16.0",
"@babel/preset-react": "7.16.0",
"@jsdevtools/coverage-istanbul-loader": "^3.0.5",
"babel-loader": "8.2.3",
"babel-plugin-jsm-to-esmodules": "0.6.0",
"chai": "4.3.4",
"chai-json-schema": "1.5.1",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"karma": "6.3.8",
"karma-chai": "0.1.0",
"karma-coverage-istanbul-reporter": "3.0.3",
"karma-firefox-launcher": "2.1.2",
"karma-json-reporter": "1.2.1",
"karma-mocha": "2.0.1",
"karma-mocha-reporter": "2.2.5",
"karma-sinon": "1.0.5",
"karma-sourcemap-loader": "0.3.8",
"karma-webpack": "5.0.0",
"mocha": "9.1.3",
"npm-run-all": "4.1.5",
"sass": "1.43.4",
"sinon": "12.0.1",
"stream-browserify": "3.0.0",
"webpack": "5.56.0",
"webpack-cli": "4.9.1",
"yamscripts": "0.1.0"
},
"engines": {
"firefox": ">=45.0 <=*",
"//": "when changing node versions, also edit .nvmrc",
"node": "16.19.*",
"npm": "8.19.3"
},
"license": "MPL-2.0",
"config": {
"mc_root": "../../..",
"asrouter_path": "browser/components/asrouter"
},
"scripts": {
"bundle": "npm-run-all bundle:*",
"bundle:admin": "webpack-cli --config webpack.asrouter-admin.config.js",
"bundle:css": "sass content-src:content --no-source-map",
"watchmc": "npm-run-all --parallel watchmc:*",
"watchmc:bundle": "npm run bundle:admin -- --env development -w",
"watchmc:css": "npm run bundle:css -- --source-map --embed-sources --embed-source-map -w",
"testmc": "npm-run-all testmc:*",
"testmc:lint": "npm run lint",
"testmc:build": "npm run bundle:admin",
"testmc:unit": "karma start karma.mc.config.js",
"tddmc": "karma start karma.mc.config.js --tdd",
"debugcoverage": "open logs/coverage/lcov-report/index.html",
"lint": "npm-run-all lint:*",
"lint:codespell": "(cd $npm_package_config_mc_root && ./mach lint -l codespell $npm_package_config_asrouter_path)",
"lint:eslint": "(cd $npm_package_config_mc_root && ./mach lint -l eslint $npm_package_config_asrouter_path)",
"lint:license": "(cd $npm_package_config_mc_root && ./mach lint -l license $npm_package_config_asrouter_path)",
"lint:stylelint": "(cd $npm_package_config_mc_root && ./mach lint -l stylelint $npm_package_config_asrouter_path)",
"test": "npm run testmc",
"tdd": "npm run tddmc",
"fix": "npm-run-all fix:*",
"fix:eslint": "npm run lint:eslint -- --fix",
"fix:stylelint": "npm run lint:stylelint -- --fix",
"help": "yamscripts help",
"yamscripts": "yamscripts compile",
"__": "# NOTE: THESE SCRIPTS ARE COMPILED!!! EDIT yamscripts.yml instead!!!"
}
}

Просмотреть файл

@ -1,720 +0,0 @@
import {
EventEmitter,
FakePrefs,
FakensIPrefService,
GlobalOverrider,
FakeConsoleAPI,
FakeLogger,
} from "newtab/test/unit/utils";
import Adapter from "enzyme-adapter-react-16";
import { chaiAssertions } from "newtab/test/schemas/pings";
import chaiJsonSchema from "chai-json-schema";
import enzyme from "enzyme";
import FxMSCommonSchema from "newtab/content-src/asrouter/schemas/FxMSCommon.schema.json";
enzyme.configure({ adapter: new Adapter() });
// Cause React warnings to make tests that trigger them fail
const origConsoleError = console.error;
console.error = function (msg, ...args) {
origConsoleError.apply(console, [msg, ...args]);
if (
/(Invalid prop|Failed prop type|Check the render method|React Intl)/.test(
msg
)
) {
throw new Error(msg);
}
};
const req = require.context(".", true, /\.test\.jsx?$/);
const files = req.keys();
// This exposes sinon assertions to chai.assert
sinon.assert.expose(assert, { prefix: "" });
chai.use(chaiAssertions);
chai.use(chaiJsonSchema);
chai.tv4.addSchema("file:///FxMSCommon.schema.json", FxMSCommonSchema);
const overrider = new GlobalOverrider();
const RemoteSettings = name => ({
get: () => {
if (name === "attachment") {
return Promise.resolve([{ attachment: {} }]);
}
return Promise.resolve([]);
},
on: () => {},
off: () => {},
});
RemoteSettings.pollChanges = () => {};
class JSWindowActorParent {
sendAsyncMessage(name, data) {
return { name, data };
}
}
class JSWindowActorChild {
sendAsyncMessage(name, data) {
return { name, data };
}
sendQuery(name, data) {
return Promise.resolve({ name, data });
}
get contentWindow() {
return {
Promise,
};
}
}
// Detect plain object passed to lazy getter APIs, and set its prototype to
// global object, and return the global object for further modification.
// Returns the object if it's not plain object.
//
// This is a workaround to make the existing testharness and testcase keep
// working even after lazy getters are moved to plain `lazy` object.
const cachedPlainObject = new Set();
function updateGlobalOrObject(object) {
// Given this function modifies the prototype, and the following
// condition doesn't meet on the second call, cache the result.
if (cachedPlainObject.has(object)) {
return global;
}
if (Object.getPrototypeOf(object).constructor.name !== "Object") {
return object;
}
cachedPlainObject.add(object);
Object.setPrototypeOf(object, global);
return global;
}
const TEST_GLOBAL = {
JSWindowActorParent,
JSWindowActorChild,
AboutReaderParent: {
addMessageListener: (messageName, listener) => {},
removeMessageListener: (messageName, listener) => {},
},
AboutWelcomeTelemetry: class {
submitGleanPingForPing() {}
},
AddonManager: {
getActiveAddons() {
return Promise.resolve({ addons: [], fullData: false });
},
},
AppConstants: {
MOZILLA_OFFICIAL: true,
MOZ_APP_VERSION: "69.0a1",
isChinaRepack() {
return false;
},
isPlatformAndVersionAtMost() {
return false;
},
platform: "win",
},
ASRouterPreferences: {
console: new FakeConsoleAPI({
maxLogLevel: "off", // set this to "debug" or "all" to get more ASRouter logging in tests
prefix: "ASRouter",
}),
},
AWScreenUtils: {
evaluateTargetingAndRemoveScreens() {
return true;
},
async removeScreens() {
return true;
},
evaluateScreenTargeting() {
return true;
},
},
BrowserUtils: {
sendToDeviceEmailsSupported() {
return true;
},
},
UpdateUtils: { getUpdateChannel() {} },
BasePromiseWorker: class {
constructor() {
this.ExceptionHandlers = [];
}
post() {}
},
browserSearchRegion: "US",
BrowserWindowTracker: { getTopWindow() {} },
ChromeUtils: {
defineModuleGetter: updateGlobalOrObject,
defineESModuleGetters: updateGlobalOrObject,
generateQI() {
return {};
},
import() {
return global;
},
importESModule() {
return global;
},
},
ClientEnvironment: {
get userId() {
return "foo123";
},
},
Components: {
Constructor(classId) {
switch (classId) {
case "@mozilla.org/referrer-info;1":
return function (referrerPolicy, sendReferrer, originalReferrer) {
this.referrerPolicy = referrerPolicy;
this.sendReferrer = sendReferrer;
this.originalReferrer = originalReferrer;
};
}
return function () {};
},
isSuccessCode: () => true,
},
ConsoleAPI: FakeConsoleAPI,
// NB: These are functions/constructors
// eslint-disable-next-line object-shorthand
ContentSearchUIController: function () {},
// eslint-disable-next-line object-shorthand
ContentSearchHandoffUIController: function () {},
Cc: {
"@mozilla.org/browser/nav-bookmarks-service;1": {
addObserver() {},
getService() {
return this;
},
removeObserver() {},
SOURCES: {},
TYPE_BOOKMARK: {},
},
"@mozilla.org/browser/nav-history-service;1": {
addObserver() {},
executeQuery() {},
getNewQuery() {},
getNewQueryOptions() {},
getService() {
return this;
},
insert() {},
markPageAsTyped() {},
removeObserver() {},
},
"@mozilla.org/io/string-input-stream;1": {
createInstance() {
return {};
},
},
"@mozilla.org/security/hash;1": {
createInstance() {
return {
init() {},
updateFromStream() {},
finish() {
return "0";
},
};
},
},
"@mozilla.org/updates/update-checker;1": { createInstance() {} },
"@mozilla.org/widget/useridleservice;1": {
getService() {
return {
idleTime: 0,
addIdleObserver() {},
removeIdleObserver() {},
};
},
},
"@mozilla.org/streamConverters;1": {
getService() {
return this;
},
},
"@mozilla.org/network/stream-loader;1": {
createInstance() {
return {};
},
},
},
Ci: {
nsICryptoHash: {},
nsIReferrerInfo: { UNSAFE_URL: 5 },
nsITimer: { TYPE_ONE_SHOT: 1 },
nsIWebProgressListener: { LOCATION_CHANGE_SAME_DOCUMENT: 1 },
nsIDOMWindow: Object,
nsITrackingDBService: {
TRACKERS_ID: 1,
TRACKING_COOKIES_ID: 2,
CRYPTOMINERS_ID: 3,
FINGERPRINTERS_ID: 4,
SOCIAL_ID: 5,
},
nsICookieBannerService: {
MODE_DISABLED: 0,
MODE_REJECT: 1,
MODE_REJECT_OR_ACCEPT: 2,
MODE_UNSET: 3,
},
},
Cu: {
importGlobalProperties() {},
now: () => window.performance.now(),
cloneInto: o => JSON.parse(JSON.stringify(o)),
},
console: {
...console,
error() {},
},
dump() {},
EveryWindow: {
registerCallback: (id, init, uninit) => {},
unregisterCallback: id => {},
},
setTimeout: window.setTimeout.bind(window),
clearTimeout: window.clearTimeout.bind(window),
fetch() {},
// eslint-disable-next-line object-shorthand
Image: function () {}, // NB: This is a function/constructor
IOUtils: {
writeJSON() {
return Promise.resolve(0);
},
readJSON() {
return Promise.resolve({});
},
read() {
return Promise.resolve(new Uint8Array());
},
makeDirectory() {
return Promise.resolve(0);
},
write() {
return Promise.resolve(0);
},
exists() {
return Promise.resolve(0);
},
remove() {
return Promise.resolve(0);
},
stat() {
return Promise.resolve(0);
},
},
NewTabUtils: {
activityStreamProvider: {
getTopFrecentSites: () => [],
executePlacesQuery: async (sql, options) => ({ sql, options }),
},
},
OS: {
File: {
writeAtomic() {},
makeDir() {},
stat() {},
Error: {},
read() {},
exists() {},
remove() {},
removeEmptyDir() {},
},
Path: {
join() {
return "/";
},
},
Constants: {
Path: {
localProfileDir: "/",
},
},
},
PathUtils: {
join(...parts) {
return parts[parts.length - 1];
},
joinRelative(...parts) {
return parts[parts.length - 1];
},
getProfileDir() {
return Promise.resolve("/");
},
getLocalProfileDir() {
return Promise.resolve("/");
},
},
PlacesUtils: {
get bookmarks() {
return TEST_GLOBAL.Cc["@mozilla.org/browser/nav-bookmarks-service;1"];
},
get history() {
return TEST_GLOBAL.Cc["@mozilla.org/browser/nav-history-service;1"];
},
observers: {
addListener() {},
removeListener() {},
},
},
Preferences: FakePrefs,
PrivateBrowsingUtils: {
isBrowserPrivate: () => false,
isWindowPrivate: () => false,
permanentPrivateBrowsing: false,
},
DownloadsViewUI: {
getDisplayName: () => "filename.ext",
getSizeWithUnits: () => "1.5 MB",
},
FileUtils: {
// eslint-disable-next-line object-shorthand
File: function () {}, // NB: This is a function/constructor
},
Region: {
home: "US",
REGION_TOPIC: "browser-region-updated",
},
Services: {
dirsvc: {
get: () => ({ parent: { parent: { path: "appPath" } } }),
},
env: {
set: () => undefined,
},
locale: {
get appLocaleAsBCP47() {
return "en-US";
},
negotiateLanguages() {},
},
urlFormatter: { formatURL: str => str, formatURLPref: str => str },
mm: {
addMessageListener: (msg, cb) => this.receiveMessage(),
removeMessageListener() {},
},
obs: {
addObserver() {},
removeObserver() {},
notifyObservers() {},
},
telemetry: {
setEventRecordingEnabled: () => {},
recordEvent: eventDetails => {},
scalarSet: () => {},
keyedScalarAdd: () => {},
},
uuid: {
generateUUID() {
return "{foo-123-foo}";
},
},
console: { logStringMessage: () => {} },
prefs: new FakensIPrefService(),
tm: {
dispatchToMainThread: cb => cb(),
idleDispatchToMainThread: cb => cb(),
},
eTLD: {
getBaseDomain({ spec }) {
return spec.match(/\/([^/]+)/)[1];
},
getBaseDomainFromHost(host) {
return host.match(/.*?(\w+\.\w+)$/)[1];
},
getPublicSuffix() {},
},
io: {
newURI: spec => ({
mutate: () => ({
setRef: ref => ({
finalize: () => ({
ref,
spec,
}),
}),
}),
spec,
}),
},
search: {
init() {
return Promise.resolve();
},
getVisibleEngines: () =>
Promise.resolve([{ identifier: "google" }, { identifier: "bing" }]),
defaultEngine: {
identifier: "google",
searchForm:
"https://www.google.com/search?q=&ie=utf-8&oe=utf-8&client=firefox-b",
aliases: ["@google"],
},
defaultPrivateEngine: {
identifier: "bing",
searchForm: "https://www.bing.com",
aliases: ["@bing"],
},
getEngineByAlias: async () => null,
},
scriptSecurityManager: {
createNullPrincipal() {},
getSystemPrincipal() {},
},
wm: {
getMostRecentWindow: () => window,
getMostRecentBrowserWindow: () => window,
getEnumerator: () => [],
},
ww: { registerNotification() {}, unregisterNotification() {} },
appinfo: { appBuildID: "20180710100040", version: "69.0a1" },
scriptloader: { loadSubScript: () => {} },
startup: {
getStartupInfo() {
return {
process: {
getTime() {
return 1588010448000;
},
},
};
},
},
},
XPCOMUtils: {
defineLazyGetter(object, name, f) {
updateGlobalOrObject(object)[name] = f();
},
defineLazyGlobalGetters: updateGlobalOrObject,
defineLazyModuleGetters: updateGlobalOrObject,
defineLazyServiceGetter: updateGlobalOrObject,
defineLazyServiceGetters: updateGlobalOrObject,
defineLazyPreferenceGetter(object, name) {
updateGlobalOrObject(object)[name] = "";
},
generateQI() {
return {};
},
},
EventEmitter,
ShellService: {
doesAppNeedPin: () => false,
isDefaultBrowser: () => true,
},
FilterExpressions: {
eval() {
return Promise.resolve(false);
},
},
RemoteSettings,
Localization: class {
async formatMessages(stringsIds) {
return Promise.resolve(
stringsIds.map(({ id, args }) => ({ value: { string_id: id, args } }))
);
}
async formatValue(stringId) {
return Promise.resolve(stringId);
}
},
FxAccountsConfig: {
promiseConnectAccountURI(id) {
return Promise.resolve(id);
},
},
FX_MONITOR_OAUTH_CLIENT_ID: "fake_client_id",
ExperimentAPI: {
getExperiment() {},
getExperimentMetaData() {},
getRolloutMetaData() {},
},
NimbusFeatures: {
glean: {
getVariable() {},
},
newtab: {
getVariable() {},
getAllVariables() {},
onUpdate() {},
offUpdate() {},
},
pocketNewtab: {
getVariable() {},
getAllVariables() {},
onUpdate() {},
offUpdate() {},
},
cookieBannerHandling: {
getVariable() {},
},
},
TelemetryEnvironment: {
setExperimentActive() {},
currentEnvironment: {
profile: {
creationDate: 16587,
},
settings: {},
},
},
TelemetryStopwatch: {
start: () => {},
finish: () => {},
},
Sampling: {
ratioSample(seed, ratios) {
return Promise.resolve(0);
},
},
BrowserHandler: {
get kiosk() {
return false;
},
},
TelemetrySession: {
getMetadata(reason) {
return {
reason,
sessionId: "fake_session_id",
};
},
},
PageThumbs: {
addExpirationFilter() {},
removeExpirationFilter() {},
},
Logger: FakeLogger,
getFxAccountsSingleton() {},
AboutNewTab: {},
Glean: {
newtab: {
opened: {
record() {},
},
closed: {
record() {},
},
locale: {
set() {},
},
newtabCategory: {
set() {},
},
homepageCategory: {
set() {},
},
blockedSponsors: {
set() {},
},
sovAllocation: {
set() {},
},
},
newtabSearch: {
enabled: {
set() {},
},
},
pocket: {
enabled: {
set() {},
},
impression: {
record() {},
},
isSignedIn: {
set() {},
},
sponsoredStoriesEnabled: {
set() {},
},
click: {
record() {},
},
save: {
record() {},
},
topicClick: {
record() {},
},
},
topsites: {
enabled: {
set() {},
},
sponsoredEnabled: {
set() {},
},
impression: {
record() {},
},
click: {
record() {},
},
rows: {
set() {},
},
showPrivacyClick: {
record() {},
},
dismiss: {
record() {},
},
prefChanged: {
record() {},
},
},
topSites: {
pingType: {
set() {},
},
position: {
set() {},
},
source: {
set() {},
},
tileId: {
set() {},
},
reportingUrl: {
set() {},
},
advertiser: {
set() {},
},
contextId: {
set() {},
},
},
},
GleanPings: {
newtab: {
submit() {},
},
topSites: {
submit() {},
},
},
Utils: {
SERVER_URL: "bogus://foo",
},
};
overrider.set(TEST_GLOBAL);
describe("asrouter", () => {
after(() => overrider.restore());
files.forEach(file => req(file));
});

Просмотреть файл

@ -1,34 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const path = require("path");
const config = require("../newtab/webpack.system-addon.config.js");
const webpack = require("webpack");
const absolute = relPath => path.join(__dirname, relPath);
const banner = `
NOTE: This file is generated by webpack from ASRouterAdmin.jsx
using the npm bundle task.
`;
module.exports = Object.assign({}, config(), {
entry: absolute("content-src/components/ASRouterAdmin/ASRouterAdmin.jsx"),
output: {
path: absolute("content"),
filename: "asrouter-admin.bundle.js",
library: "ASRouterAdminRenderUtils",
},
externals: {
"prop-types": "PropTypes",
react: "React",
"react-dom": "ReactDOM",
},
plugins: [new webpack.BannerPlugin(banner)],
// This resolve config allows us to import with paths relative to the root directory, e.g. "lib/ActivityStream.jsm"
resolve: {
extensions: [".js", ".jsx"],
alias: {
newtab: absolute("../newtab"),
common: absolute("../newtab/common"),
},
},
});

Просмотреть файл

@ -1,44 +0,0 @@
# This file compiles to package.json scripts.
# When you add or modify anything, you *MUST* run:
# npm run yamscripts
# to compile your changes.
scripts:
# bundle: Build all assets for ASRouter
bundle:
admin: webpack-cli --config webpack.asrouter-admin.config.js
css: sass content-src:content --no-source-map
# watchmc: Automatically rebuild when files are changed. NOTE: Includes sourcemaps, do not use for profiling/perf testing.
watchmc:
_parallel: true
bundle: =>bundle:admin -- --env development -w
css: =>bundle:css -- --source-map --embed-sources --embed-source-map -w
testmc:
lint: =>lint
build: =>bundle:admin
unit: karma start karma.mc.config.js
tddmc: karma start karma.mc.config.js --tdd
debugcoverage: open logs/coverage/lcov-report/index.html
# lint: Run various linters with mach or local dev dependencies
lint:
codespell: (cd $npm_package_config_mc_root && ./mach lint -l codespell $npm_package_config_asrouter_path)
eslint: (cd $npm_package_config_mc_root && ./mach lint -l eslint $npm_package_config_asrouter_path)
license: (cd $npm_package_config_mc_root && ./mach lint -l license $npm_package_config_asrouter_path)
stylelint: (cd $npm_package_config_mc_root && ./mach lint -l stylelint $npm_package_config_asrouter_path)
# test: Run all tests once
test: =>testmc
# tdd: Run content tests continuously
tdd: =>tddmc
fix:
# Note that since we're currently running eslint-plugin-prettier,
# running fix:eslint will also reformat changed JS files using prettier.
eslint: =>lint:eslint -- --fix
stylelint: =>lint:stylelint -- --fix

Просмотреть файл

@ -30,7 +30,6 @@ DIRS += [
"about",
"aboutlogins",
"aboutwelcome",
"asrouter",
"attribution",
"contentanalysis",
"contextualidentity",

Просмотреть файл

@ -2,7 +2,7 @@
## How to enable ASRouter devtools
- In `about:config`, set `browser.newtabpage.activity-stream.asrouter.devtoolsEnabled` to `true`
- Visit `about:asrouter` to see the devtools.
- Visit `about:newtab#asrouter` to see the devtools.
## Overview of ASRouter devtools

Просмотреть файл

@ -2,9 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import { ASRouterUtils } from "newtab/content-src/asrouter/asrouter-utils";
import {
actionCreators as ac,
actionTypes as at,
} from "common/Actions.sys.mjs";
import { ASRouterUtils } from "../../asrouter/asrouter-utils";
import { connect } from "react-redux";
import React from "react";
import ReactDOM from "react-dom";
import { SimpleHashRouter } from "./SimpleHashRouter";
import { CopyButton } from "./CopyButton";
import { ImpressionsSection } from "./ImpressionsSection";
@ -95,6 +99,316 @@ export class TogglePrefCheckbox extends React.PureComponent {
}
}
export class Personalization extends React.PureComponent {
constructor(props) {
super(props);
this.togglePersonalization = this.togglePersonalization.bind(this);
}
togglePersonalization() {
this.props.dispatch(
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_PERSONALIZATION_TOGGLE,
})
);
}
render() {
const { lastUpdated, initialized } = this.props.state.Personalization;
return (
<React.Fragment>
<table>
<tbody>
<Row>
<td colSpan="2">
<TogglePrefCheckbox
checked={this.props.personalized}
pref="personalized"
onChange={this.togglePersonalization}
/>
</td>
</Row>
<Row>
<td className="min">Personalization Last Updated</td>
<td>{relativeTime(lastUpdated) || "(no data)"}</td>
</Row>
<Row>
<td className="min">Personalization Initialized</td>
<td>{initialized ? "true" : "false"}</td>
</Row>
</tbody>
</table>
</React.Fragment>
);
}
}
export class DiscoveryStreamAdmin extends React.PureComponent {
constructor(props) {
super(props);
this.restorePrefDefaults = this.restorePrefDefaults.bind(this);
this.setConfigValue = this.setConfigValue.bind(this);
this.expireCache = this.expireCache.bind(this);
this.refreshCache = this.refreshCache.bind(this);
this.idleDaily = this.idleDaily.bind(this);
this.systemTick = this.systemTick.bind(this);
this.syncRemoteSettings = this.syncRemoteSettings.bind(this);
this.onStoryToggle = this.onStoryToggle.bind(this);
this.state = {
toggledStories: {},
};
}
setConfigValue(name, value) {
this.props.dispatch(
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_SET_VALUE,
data: { name, value },
})
);
}
restorePrefDefaults(event) {
this.props.dispatch(
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS,
})
);
}
refreshCache() {
const { config } = this.props.state.DiscoveryStream;
this.props.dispatch(
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_CHANGE,
data: config,
})
);
}
dispatchSimpleAction(type) {
this.props.dispatch(
ac.OnlyToMain({
type,
})
);
}
systemTick() {
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_SYSTEM_TICK);
}
expireCache() {
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_EXPIRE_CACHE);
}
idleDaily() {
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_IDLE_DAILY);
}
syncRemoteSettings() {
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_SYNC_RS);
}
renderComponent(width, component) {
return (
<table>
<tbody>
<Row>
<td className="min">Type</td>
<td>{component.type}</td>
</Row>
<Row>
<td className="min">Width</td>
<td>{width}</td>
</Row>
{component.feed && this.renderFeed(component.feed)}
</tbody>
</table>
);
}
renderFeedData(url) {
const { feeds } = this.props.state.DiscoveryStream;
const feed = feeds.data[url].data;
return (
<React.Fragment>
<h4>Feed url: {url}</h4>
<table>
<tbody>
{feed.recommendations?.map(story => this.renderStoryData(story))}
</tbody>
</table>
</React.Fragment>
);
}
renderFeedsData() {
const { feeds } = this.props.state.DiscoveryStream;
return (
<React.Fragment>
{Object.keys(feeds.data).map(url => this.renderFeedData(url))}
</React.Fragment>
);
}
renderSpocs() {
const { spocs } = this.props.state.DiscoveryStream;
let spocsData = [];
if (spocs.data && spocs.data.spocs && spocs.data.spocs.items) {
spocsData = spocs.data.spocs.items || [];
}
return (
<React.Fragment>
<table>
<tbody>
<Row>
<td className="min">spocs_endpoint</td>
<td>{spocs.spocs_endpoint}</td>
</Row>
<Row>
<td className="min">Data last fetched</td>
<td>{relativeTime(spocs.lastUpdated)}</td>
</Row>
</tbody>
</table>
<h4>Spoc data</h4>
<table>
<tbody>{spocsData.map(spoc => this.renderStoryData(spoc))}</tbody>
</table>
<h4>Spoc frequency caps</h4>
<table>
<tbody>
{spocs.frequency_caps.map(spoc => this.renderStoryData(spoc))}
</tbody>
</table>
</React.Fragment>
);
}
onStoryToggle(story) {
const { toggledStories } = this.state;
this.setState({
toggledStories: {
...toggledStories,
[story.id]: !toggledStories[story.id],
},
});
}
renderStoryData(story) {
let storyData = "";
if (this.state.toggledStories[story.id]) {
storyData = JSON.stringify(story, null, 2);
}
return (
<tr className="message-item" key={story.id}>
<td className="message-id">
<span>
{story.id} <br />
</span>
<ToggleStoryButton story={story} onClick={this.onStoryToggle} />
</td>
<td className="message-summary">
<pre>{storyData}</pre>
</td>
</tr>
);
}
renderFeed(feed) {
const { feeds } = this.props.state.DiscoveryStream;
if (!feed.url) {
return null;
}
return (
<React.Fragment>
<Row>
<td className="min">Feed url</td>
<td>{feed.url}</td>
</Row>
<Row>
<td className="min">Data last fetched</td>
<td>
{relativeTime(
feeds.data[feed.url] ? feeds.data[feed.url].lastUpdated : null
) || "(no data)"}
</td>
</Row>
</React.Fragment>
);
}
render() {
const prefToggles = "enabled collapsible".split(" ");
const { config, layout } = this.props.state.DiscoveryStream;
const personalized =
this.props.otherPrefs["discoverystream.personalization.enabled"];
return (
<div>
<button className="button" onClick={this.restorePrefDefaults}>
Restore Pref Defaults
</button>{" "}
<button className="button" onClick={this.refreshCache}>
Refresh Cache
</button>
<br />
<button className="button" onClick={this.expireCache}>
Expire Cache
</button>{" "}
<button className="button" onClick={this.systemTick}>
Trigger System Tick
</button>{" "}
<button className="button" onClick={this.idleDaily}>
Trigger Idle Daily
</button>
<br />
<button className="button" onClick={this.syncRemoteSettings}>
Sync Remote Settings
</button>
<table>
<tbody>
{prefToggles.map(pref => (
<Row key={pref}>
<td>
<TogglePrefCheckbox
checked={config[pref]}
pref={pref}
onChange={this.setConfigValue}
/>
</td>
</Row>
))}
</tbody>
</table>
<h3>Layout</h3>
{layout.map((row, rowIndex) => (
<div key={`row-${rowIndex}`}>
{row.components.map((component, componentIndex) => (
<div key={`component-${componentIndex}`} className="ds-component">
{this.renderComponent(row.width, component)}
</div>
))}
</div>
))}
<h3>Personalization</h3>
<Personalization
personalized={personalized}
dispatch={this.props.dispatch}
state={{
Personalization: this.props.state.Personalization,
}}
/>
<h3>Spocs</h3>
{this.renderSpocs()}
<h3>Feeds Data</h3>
{this.renderFeedsData()}
</div>
);
}
}
export class ASRouterAdminInner extends React.PureComponent {
constructor(props) {
super(props);
@ -181,10 +495,6 @@ export class ASRouterAdminInner extends React.PureComponent {
}).then(this.setStateFromParent);
}
componentWillUnmount() {
ASRouterUtils.removeListener(this.onMessageFromParent);
}
handleBlock(msg) {
return () => ASRouterUtils.blockById(msg.id);
}
@ -214,6 +524,9 @@ export class ASRouterAdminInner extends React.PureComponent {
return () =>
ASRouterUtils.overrideMessage(id).then(state => {
this.setStateFromParent(state);
this.props.notifyContent({
message: state.message,
});
});
}
@ -598,6 +911,9 @@ export class ASRouterAdminInner extends React.PureComponent {
);
return ASRouterUtils.modifyMessageJson(message).then(state => {
this.setStateFromParent(state);
this.props.notifyContent({
message: state.message,
});
});
}
@ -1399,6 +1715,20 @@ export class ASRouterAdminInner extends React.PureComponent {
/>
</React.Fragment>
);
case "ds":
return (
<React.Fragment>
<h2>Discovery Stream</h2>
<DiscoveryStreamAdmin
state={{
DiscoveryStream: this.props.DiscoveryStream,
Personalization: this.props.Personalization,
}}
otherPrefs={this.props.Prefs.values}
dispatch={this.props.dispatch}
/>
</React.Fragment>
);
case "errors":
return (
<React.Fragment>
@ -1429,18 +1759,6 @@ export class ASRouterAdminInner extends React.PureComponent {
}
render() {
if (!this.state.devtoolsEnabled) {
return (
<div className="asrouter-admin">
You must enable the ASRouter Admin page by setting{" "}
<code>
browser.newtabpage.activity-stream.asrouter.devtoolsEnabled
</code>{" "}
to <code>true</code> and then reloading this page.
</div>
);
}
return (
<div
className={`asrouter-admin ${
@ -1464,6 +1782,9 @@ export class ASRouterAdminInner extends React.PureComponent {
<li>
<a href="#devtools-impressions">Impressions</a>
</li>
<li>
<a href="#devtools-ds">Discovery Stream</a>
</li>
<li>
<a href="#devtools-errors">Errors</a>
</li>
@ -1492,12 +1813,83 @@ export class ASRouterAdminInner extends React.PureComponent {
}
}
export const ASRouterAdmin = props => (
export class CollapseToggle extends React.PureComponent {
constructor(props) {
super(props);
this.onCollapseToggle = this.onCollapseToggle.bind(this);
this.state = { collapsed: false };
}
get renderAdmin() {
const { props } = this;
return (
props.location.hash &&
(props.location.hash.startsWith("#asrouter") ||
props.location.hash.startsWith("#devtools"))
);
}
onCollapseToggle(e) {
e.preventDefault();
this.setState(state => ({ collapsed: !state.collapsed }));
}
setBodyClass() {
if (this.renderAdmin && !this.state.collapsed) {
global.document.body.classList.add("no-scroll");
} else {
global.document.body.classList.remove("no-scroll");
}
}
componentDidMount() {
this.setBodyClass();
}
componentDidUpdate() {
this.setBodyClass();
}
componentWillUnmount() {
global.document.body.classList.remove("no-scroll");
ASRouterUtils.removeListener(this.onMessageFromParent);
}
render() {
const { props } = this;
const { renderAdmin } = this;
const isCollapsed = this.state.collapsed || !renderAdmin;
const label = `${isCollapsed ? "Expand" : "Collapse"} devtools`;
return (
<React.Fragment>
<a
href="#devtools"
title={label}
aria-label={label}
className={`asrouter-toggle ${
isCollapsed ? "collapsed" : "expanded"
}`}
onClick={this.renderAdmin ? this.onCollapseToggle : null}
>
<span className="icon icon-devtools" />
</a>
{renderAdmin ? (
<ASRouterAdminInner {...props} collapsed={this.state.collapsed} />
) : null}
</React.Fragment>
);
}
}
const _ASRouterAdmin = props => (
<SimpleHashRouter>
<ASRouterAdminInner {...props} />
<CollapseToggle {...props} />
</SimpleHashRouter>
);
export function renderASRouterAdmin() {
ReactDOM.render(<ASRouterAdmin />, document.getElementById("root"));
}
export const ASRouterAdmin = connect(state => ({
Sections: state.Sections,
DiscoveryStream: state.DiscoveryStream,
Personalization: state.Personalization,
Prefs: state.Prefs,
}))(_ASRouterAdmin);

Просмотреть файл

@ -1,64 +1,46 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* stylelint-disable max-nesting-depth */
@import '../../../../newtab/content-src/styles/variables';
@import '../../../../newtab/content-src/styles/theme';
@import '../../../../newtab/content-src/styles/icons';
@import '../../../../newtab/content-src/asrouter/components/Button/Button';
.asrouter-toggle {
position: fixed;
top: 50px;
inset-inline-end: 15px;
border: 0;
background: none;
z-index: 1;
border-radius: 2px;
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif;
}
/**
* These styles are copied verbatim from _activity-stream.scss in order to maintain
* a continuity of styling while also decoupling from the newtab code. This should
* be removed when about:asrouter starts using the default in-content style sheets.
*/
.button,
.actions button {
background-color: var(--newtab-button-secondary-color);
border: $border-primary;
border-radius: 4px;
color: inherit;
cursor: pointer;
margin-bottom: 15px;
padding: 10px 30px;
white-space: nowrap;
&:hover:not(.dismiss),
&:focus:not(.dismiss) {
box-shadow: $shadow-primary;
transition: box-shadow 150ms;
.icon-devtools {
background-image: url('chrome://global/skin/icons/developer.svg');
padding: 15px;
}
&.dismiss {
background-color: transparent;
border: 0;
padding: 0;
text-decoration: underline;
&:dir(rtl) {
transform: scaleX(-1);
}
// Blue button
&.primary,
&.done {
background-color: var(--newtab-primary-action-background);
border: solid 1px var(--newtab-primary-action-background);
color: var(--newtab-primary-element-text-color);
margin-inline-start: auto;
&:hover {
background: var(--newtab-element-hover-color);
}
&.expanded {
background: $black-20;
}
}
.asrouter-admin {
max-width: 1300px;
$border-color: var(--newtab-border-color);
$monospace: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Mono', 'Droid Sans Mono',
'Source Code Pro', monospace;
$sidebar-width: 240px;
position: fixed;
top: 0;
inset-inline-start: 0;
width: 100%;
background: var(--newtab-background-color);
height: 100%;
overflow-y: scroll;
margin: 0 auto;
font-size: 14px;
padding-inline-start: $sidebar-width;
color: var(--newtab-text-primary-color);
@ -71,6 +53,7 @@ body {
inset-inline-start: 0;
position: fixed;
width: $sidebar-width;
padding: 30px 20px;
ul {
margin: 0;
@ -137,6 +120,7 @@ body {
table {
border-collapse: collapse;
width: 100%;
&.minimal-table {
border-collapse: collapse;

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { ASRouterUtils } from "newtab/content-src/asrouter/asrouter-utils";
import { ASRouterUtils } from "../../asrouter/asrouter-utils";
import React, {
useState,
useMemo,

Просмотреть файл

@ -6,7 +6,7 @@ import {
actionCreators as ac,
actionTypes as at,
} from "common/Actions.sys.mjs";
import { DiscoveryStreamAdmin } from "content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin";
import { ASRouterAdmin } from "content-src/components/ASRouterAdmin/ASRouterAdmin";
import { ConfirmDialog } from "content-src/components/ConfirmDialog/ConfirmDialog";
import { connect } from "react-redux";
import { DiscoveryStreamBase } from "content-src/components/DiscoveryStreamBase/DiscoveryStreamBase";
@ -93,7 +93,7 @@ export class _Base extends React.PureComponent {
<React.Fragment>
<BaseContent {...this.props} adminContent={this.state} />
{isDevtoolsEnabled ? (
<DiscoveryStreamAdmin notifyContent={this.notifyContent} />
<ASRouterAdmin notifyContent={this.notifyContent} />
) : null}
</React.Fragment>
</ErrorBoundary>

Просмотреть файл

@ -1,506 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import {
actionCreators as ac,
actionTypes as at,
} from "common/Actions.sys.mjs";
import { connect } from "react-redux";
import React from "react";
import { SimpleHashRouter } from "./SimpleHashRouter";
const Row = props => (
<tr className="message-item" {...props}>
{props.children}
</tr>
);
function relativeTime(timestamp) {
if (!timestamp) {
return "";
}
const seconds = Math.floor((Date.now() - timestamp) / 1000);
const minutes = Math.floor((Date.now() - timestamp) / 60000);
if (seconds < 2) {
return "just now";
} else if (seconds < 60) {
return `${seconds} seconds ago`;
} else if (minutes === 1) {
return "1 minute ago";
} else if (minutes < 600) {
return `${minutes} minutes ago`;
}
return new Date(timestamp).toLocaleString();
}
export class ToggleStoryButton extends React.PureComponent {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.props.onClick(this.props.story);
}
render() {
return <button onClick={this.handleClick}>collapse/open</button>;
}
}
export class TogglePrefCheckbox extends React.PureComponent {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
}
onChange(event) {
this.props.onChange(this.props.pref, event.target.checked);
}
render() {
return (
<>
<input
type="checkbox"
checked={this.props.checked}
onChange={this.onChange}
disabled={this.props.disabled}
/>{" "}
{this.props.pref}{" "}
</>
);
}
}
export class Personalization extends React.PureComponent {
constructor(props) {
super(props);
this.togglePersonalization = this.togglePersonalization.bind(this);
}
togglePersonalization() {
this.props.dispatch(
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_PERSONALIZATION_TOGGLE,
})
);
}
render() {
const { lastUpdated, initialized } = this.props.state.Personalization;
return (
<React.Fragment>
<table>
<tbody>
<Row>
<td colSpan="2">
<TogglePrefCheckbox
checked={this.props.personalized}
pref="personalized"
onChange={this.togglePersonalization}
/>
</td>
</Row>
<Row>
<td className="min">Personalization Last Updated</td>
<td>{relativeTime(lastUpdated) || "(no data)"}</td>
</Row>
<Row>
<td className="min">Personalization Initialized</td>
<td>{initialized ? "true" : "false"}</td>
</Row>
</tbody>
</table>
</React.Fragment>
);
}
}
export class DiscoveryStreamAdminUI extends React.PureComponent {
constructor(props) {
super(props);
this.restorePrefDefaults = this.restorePrefDefaults.bind(this);
this.setConfigValue = this.setConfigValue.bind(this);
this.expireCache = this.expireCache.bind(this);
this.refreshCache = this.refreshCache.bind(this);
this.idleDaily = this.idleDaily.bind(this);
this.systemTick = this.systemTick.bind(this);
this.syncRemoteSettings = this.syncRemoteSettings.bind(this);
this.onStoryToggle = this.onStoryToggle.bind(this);
this.state = {
toggledStories: {},
};
}
setConfigValue(name, value) {
this.props.dispatch(
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_SET_VALUE,
data: { name, value },
})
);
}
restorePrefDefaults(event) {
this.props.dispatch(
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS,
})
);
}
refreshCache() {
const { config } = this.props.state.DiscoveryStream;
this.props.dispatch(
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_CHANGE,
data: config,
})
);
}
dispatchSimpleAction(type) {
this.props.dispatch(
ac.OnlyToMain({
type,
})
);
}
systemTick() {
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_SYSTEM_TICK);
}
expireCache() {
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_EXPIRE_CACHE);
}
idleDaily() {
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_IDLE_DAILY);
}
syncRemoteSettings() {
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_SYNC_RS);
}
renderComponent(width, component) {
return (
<table>
<tbody>
<Row>
<td className="min">Type</td>
<td>{component.type}</td>
</Row>
<Row>
<td className="min">Width</td>
<td>{width}</td>
</Row>
{component.feed && this.renderFeed(component.feed)}
</tbody>
</table>
);
}
renderFeedData(url) {
const { feeds } = this.props.state.DiscoveryStream;
const feed = feeds.data[url].data;
return (
<React.Fragment>
<h4>Feed url: {url}</h4>
<table>
<tbody>
{feed.recommendations?.map(story => this.renderStoryData(story))}
</tbody>
</table>
</React.Fragment>
);
}
renderFeedsData() {
const { feeds } = this.props.state.DiscoveryStream;
return (
<React.Fragment>
{Object.keys(feeds.data).map(url => this.renderFeedData(url))}
</React.Fragment>
);
}
renderSpocs() {
const { spocs } = this.props.state.DiscoveryStream;
let spocsData = [];
if (spocs.data && spocs.data.spocs && spocs.data.spocs.items) {
spocsData = spocs.data.spocs.items || [];
}
return (
<React.Fragment>
<table>
<tbody>
<Row>
<td className="min">spocs_endpoint</td>
<td>{spocs.spocs_endpoint}</td>
</Row>
<Row>
<td className="min">Data last fetched</td>
<td>{relativeTime(spocs.lastUpdated)}</td>
</Row>
</tbody>
</table>
<h4>Spoc data</h4>
<table>
<tbody>{spocsData.map(spoc => this.renderStoryData(spoc))}</tbody>
</table>
<h4>Spoc frequency caps</h4>
<table>
<tbody>
{spocs.frequency_caps.map(spoc => this.renderStoryData(spoc))}
</tbody>
</table>
</React.Fragment>
);
}
onStoryToggle(story) {
const { toggledStories } = this.state;
this.setState({
toggledStories: {
...toggledStories,
[story.id]: !toggledStories[story.id],
},
});
}
renderStoryData(story) {
let storyData = "";
if (this.state.toggledStories[story.id]) {
storyData = JSON.stringify(story, null, 2);
}
return (
<tr className="message-item" key={story.id}>
<td className="message-id">
<span>
{story.id} <br />
</span>
<ToggleStoryButton story={story} onClick={this.onStoryToggle} />
</td>
<td className="message-summary">
<pre>{storyData}</pre>
</td>
</tr>
);
}
renderFeed(feed) {
const { feeds } = this.props.state.DiscoveryStream;
if (!feed.url) {
return null;
}
return (
<React.Fragment>
<Row>
<td className="min">Feed url</td>
<td>{feed.url}</td>
</Row>
<Row>
<td className="min">Data last fetched</td>
<td>
{relativeTime(
feeds.data[feed.url] ? feeds.data[feed.url].lastUpdated : null
) || "(no data)"}
</td>
</Row>
</React.Fragment>
);
}
render() {
const prefToggles = "enabled collapsible".split(" ");
const { config, layout } = this.props.state.DiscoveryStream;
const personalized =
this.props.otherPrefs["discoverystream.personalization.enabled"];
return (
<div>
<button className="button" onClick={this.restorePrefDefaults}>
Restore Pref Defaults
</button>{" "}
<button className="button" onClick={this.refreshCache}>
Refresh Cache
</button>
<br />
<button className="button" onClick={this.expireCache}>
Expire Cache
</button>{" "}
<button className="button" onClick={this.systemTick}>
Trigger System Tick
</button>{" "}
<button className="button" onClick={this.idleDaily}>
Trigger Idle Daily
</button>
<br />
<button className="button" onClick={this.syncRemoteSettings}>
Sync Remote Settings
</button>
<table>
<tbody>
{prefToggles.map(pref => (
<Row key={pref}>
<td>
<TogglePrefCheckbox
checked={config[pref]}
pref={pref}
onChange={this.setConfigValue}
/>
</td>
</Row>
))}
</tbody>
</table>
<h3>Layout</h3>
{layout.map((row, rowIndex) => (
<div key={`row-${rowIndex}`}>
{row.components.map((component, componentIndex) => (
<div key={`component-${componentIndex}`} className="ds-component">
{this.renderComponent(row.width, component)}
</div>
))}
</div>
))}
<h3>Personalization</h3>
<Personalization
personalized={personalized}
dispatch={this.props.dispatch}
state={{
Personalization: this.props.state.Personalization,
}}
/>
<h3>Spocs</h3>
{this.renderSpocs()}
<h3>Feeds Data</h3>
{this.renderFeedsData()}
</div>
);
}
}
export class DiscoveryStreamAdminInner extends React.PureComponent {
constructor(props) {
super(props);
this.setState = this.setState.bind(this);
}
render() {
return (
<div
className={`discoverystream-admin ${
this.props.collapsed ? "collapsed" : "expanded"
}`}
>
<main className="main-panel">
<h1>Discovery Stream Admin</h1>
<p className="helpLink">
<span className="icon icon-small-spacer icon-info" />{" "}
<span>
Need to access the ASRouter Admin dev tools?{" "}
<a target="blank" href="about:asrouter">
Click here
</a>
</span>
</p>
<React.Fragment>
<DiscoveryStreamAdminUI
state={{
DiscoveryStream: this.props.DiscoveryStream,
Personalization: this.props.Personalization,
}}
otherPrefs={this.props.Prefs.values}
dispatch={this.props.dispatch}
/>
</React.Fragment>
</main>
</div>
);
}
}
export class CollapseToggle extends React.PureComponent {
constructor(props) {
super(props);
this.onCollapseToggle = this.onCollapseToggle.bind(this);
this.state = { collapsed: false };
}
get renderAdmin() {
const { props } = this;
return props.location.hash && props.location.hash.startsWith("#devtools");
}
onCollapseToggle(e) {
e.preventDefault();
this.setState(state => ({ collapsed: !state.collapsed }));
}
setBodyClass() {
if (this.renderAdmin && !this.state.collapsed) {
global.document.body.classList.add("no-scroll");
} else {
global.document.body.classList.remove("no-scroll");
}
}
componentDidMount() {
this.setBodyClass();
}
componentDidUpdate() {
this.setBodyClass();
}
componentWillUnmount() {
global.document.body.classList.remove("no-scroll");
}
render() {
const { props } = this;
const { renderAdmin } = this;
const isCollapsed = this.state.collapsed || !renderAdmin;
const label = `${isCollapsed ? "Expand" : "Collapse"} devtools`;
return (
<React.Fragment>
<a
href="#devtools"
title={label}
aria-label={label}
className={`discoverystream-admin-toggle ${
isCollapsed ? "collapsed" : "expanded"
}`}
onClick={this.renderAdmin ? this.onCollapseToggle : null}
>
<span className="icon icon-devtools" />
</a>
{renderAdmin ? (
<DiscoveryStreamAdminInner
{...props}
collapsed={this.state.collapsed}
/>
) : null}
</React.Fragment>
);
}
}
const _DiscoveryStreamAdmin = props => (
<SimpleHashRouter>
<CollapseToggle {...props} />
</SimpleHashRouter>
);
export const DiscoveryStreamAdmin = connect(state => ({
Sections: state.Sections,
DiscoveryStream: state.DiscoveryStream,
Personalization: state.Personalization,
Prefs: state.Prefs,
}))(_DiscoveryStreamAdmin);

Просмотреть файл

@ -1,337 +0,0 @@
/* stylelint-disable max-nesting-depth */
.discoverystream-admin-toggle {
position: fixed;
top: 50px;
inset-inline-end: 15px;
border: 0;
background: none;
z-index: 1;
border-radius: 2px;
.icon-devtools {
background-image: url('chrome://global/skin/icons/developer.svg');
padding: 15px;
}
&:dir(rtl) {
transform: scaleX(-1);
}
&:hover {
background: var(--newtab-element-hover-color);
}
&.expanded {
background: $black-20;
}
}
.discoverystream-admin {
$border-color: var(--newtab-border-color);
$monospace: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Mono', 'Droid Sans Mono',
'Source Code Pro', monospace;
$sidebar-width: 240px;
position: fixed;
top: 0;
inset-inline-start: 0;
width: 100%;
background: var(--newtab-background-color);
height: 100%;
overflow-y: scroll;
margin: 0 auto;
font-size: 14px;
padding-inline-start: $sidebar-width;
color: var(--newtab-text-primary-color);
&.collapsed {
display: none;
}
.sidebar {
inset-inline-start: 0;
position: fixed;
width: $sidebar-width;
padding: 30px 20px;
ul {
margin: 0;
padding: 0;
list-style: none;
}
li a {
padding: 10px 34px;
display: block;
color: var(--lwt-sidebar-text-color);
&:hover {
background: var(--newtab-background-color-secondary);
}
}
}
h1 {
font-weight: 200;
font-size: 32px;
}
h2 .button,
p .button {
font-size: 14px;
padding: 6px 12px;
margin-inline-start: 5px;
margin-bottom: 0;
}
.general-textarea {
direction: ltr;
width: 740px;
height: 500px;
overflow: auto;
resize: none;
border-radius: 4px;
display: flex;
}
.wnp-textarea {
direction: ltr;
width: 740px;
height: 500px;
overflow: auto;
resize: none;
border-radius: 4px;
display: flex;
}
.json-button {
display: inline-flex;
font-size: 10px;
padding: 4px 10px;
margin-bottom: 6px;
margin-inline-end: 4px;
&:hover {
background-color: var(--newtab-element-hover-color);
box-shadow: none;
}
}
table {
border-collapse: collapse;
width: 100%;
&.minimal-table {
border-collapse: collapse;
border: 1px solid $border-color;
td {
padding: 8px;
}
td:first-child {
width: 1%;
white-space: nowrap;
}
td:not(:first-child) {
font-family: $monospace;
}
}
&.errorReporting {
tr {
border: 1px solid var(--newtab-background-color-secondary);
}
td {
padding: 4px;
&[rowspan] {
border: 1px solid var(--newtab-background-color-secondary);
}
}
}
}
.sourceLabel {
background: var(--newtab-background-color-secondary);
padding: 2px 5px;
border-radius: 3px;
&.isDisabled {
background: $email-input-invalid;
color: var(--newtab-status-error);
}
}
.message-item {
&:first-child td {
border-top: 1px solid $border-color;
}
td {
vertical-align: top;
padding: 8px;
border-bottom: 1px solid $border-color;
&.min {
width: 1%;
white-space: nowrap;
}
&.message-summary {
width: 60%;
}
&.button-column {
width: 15%;
}
&:first-child {
border-inline-start: 1px solid $border-color;
}
&:last-child {
border-inline-end: 1px solid $border-color;
}
}
&.blocked {
.message-id,
.message-summary {
opacity: 0.5;
}
.message-id {
opacity: 0.5;
}
}
.message-id {
font-family: $monospace;
font-size: 12px;
}
}
.providerUrl {
font-size: 12px;
}
pre {
background: var(--newtab-background-color-secondary);
margin: 0;
padding: 8px;
font-size: 12px;
max-width: 750px;
overflow: auto;
font-family: $monospace;
}
.errorState {
border: $input-error-border;
}
.helpLink {
padding: 10px;
display: flex;
background: $black-10;
border-radius: 3px;
align-items: center;
a {
text-decoration: underline;
}
.icon {
min-width: 18px;
min-height: 18px;
}
}
.ds-component {
margin-bottom: 20px;
}
.modalOverlayInner {
height: 80%;
}
.clearButton {
border: 0;
padding: 4px;
border-radius: 4px;
display: flex;
&:hover {
background: var(--newtab-element-hover-color);
}
}
.collapsed {
display: none;
}
.icon {
display: inline-table;
cursor: pointer;
width: 18px;
height: 18px;
}
.button {
&:disabled,
&:disabled:active {
opacity: 0.5;
cursor: unset;
box-shadow: none;
}
}
.impressions-section {
display: flex;
flex-direction: column;
gap: 16px;
.impressions-item {
display: flex;
flex-flow: column nowrap;
padding: 8px;
border: 1px solid $border-color;
border-radius: 5px;
.impressions-inner-box {
display: flex;
flex-flow: row nowrap;
gap: 8px;
}
.impressions-category {
font-size: 1.15em;
white-space: nowrap;
flex-grow: 0.1;
}
.impressions-buttons {
display: flex;
flex-direction: column;
gap: 8px;
button {
margin: 0;
}
}
.impressions-editor {
display: flex;
flex-grow: 1.5;
.general-textarea {
width: auto;
flex-grow: 1;
}
}
}
}
}

Просмотреть файл

@ -1,35 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
export class SimpleHashRouter extends React.PureComponent {
constructor(props) {
super(props);
this.onHashChange = this.onHashChange.bind(this);
this.state = { hash: global.location.hash };
}
onHashChange() {
this.setState({ hash: global.location.hash });
}
componentWillMount() {
global.addEventListener("hashchange", this.onHashChange);
}
componentWillUnmount() {
global.removeEventListener("hashchange", this.onHashChange);
}
render() {
const [, ...routes] = this.state.hash.split("-");
return React.cloneElement(this.props.children, {
location: {
hash: this.state.hash,
routes,
},
});
}
}

Просмотреть файл

@ -139,7 +139,7 @@ input {
@import '../components/CustomizeMenu/CustomizeMenu';
@import '../components/Card/Card';
@import '../components/CollapsibleSection/CollapsibleSection';
@import '../components/DiscoveryStreamAdmin/DiscoveryStreamAdmin';
@import '../components/ASRouterAdmin/ASRouterAdmin';
@import '../components/PocketLoggedInCta/PocketLoggedInCta';
@import '../components/MoreRecommendations/MoreRecommendations';
@import '../components/DiscoveryStreamBase/DiscoveryStreamBase';

Просмотреть файл

@ -2161,7 +2161,7 @@ main section {
}
/* stylelint-disable max-nesting-depth */
.discoverystream-admin-toggle {
.asrouter-toggle {
position: fixed;
top: 50px;
inset-inline-end: 15px;
@ -2170,21 +2170,21 @@ main section {
z-index: 1;
border-radius: 2px;
}
.discoverystream-admin-toggle .icon-devtools {
.asrouter-toggle .icon-devtools {
background-image: url("chrome://global/skin/icons/developer.svg");
padding: 15px;
}
.discoverystream-admin-toggle:dir(rtl) {
.asrouter-toggle:dir(rtl) {
transform: scaleX(-1);
}
.discoverystream-admin-toggle:hover {
.asrouter-toggle:hover {
background: var(--newtab-element-hover-color);
}
.discoverystream-admin-toggle.expanded {
.asrouter-toggle.expanded {
background: rgba(0, 0, 0, 0.2);
}
.discoverystream-admin {
.asrouter-admin {
position: fixed;
top: 0;
inset-inline-start: 0;
@ -2197,40 +2197,40 @@ main section {
padding-inline-start: 240px;
color: var(--newtab-text-primary-color);
}
.discoverystream-admin.collapsed {
.asrouter-admin.collapsed {
display: none;
}
.discoverystream-admin .sidebar {
.asrouter-admin .sidebar {
inset-inline-start: 0;
position: fixed;
width: 240px;
padding: 30px 20px;
}
.discoverystream-admin .sidebar ul {
.asrouter-admin .sidebar ul {
margin: 0;
padding: 0;
list-style: none;
}
.discoverystream-admin .sidebar li a {
.asrouter-admin .sidebar li a {
padding: 10px 34px;
display: block;
color: var(--lwt-sidebar-text-color);
}
.discoverystream-admin .sidebar li a:hover {
.asrouter-admin .sidebar li a:hover {
background: var(--newtab-background-color-secondary);
}
.discoverystream-admin h1 {
.asrouter-admin h1 {
font-weight: 200;
font-size: 32px;
}
.discoverystream-admin h2 .button,
.discoverystream-admin p .button {
.asrouter-admin h2 .button,
.asrouter-admin p .button {
font-size: 14px;
padding: 6px 12px;
margin-inline-start: 5px;
margin-bottom: 0;
}
.discoverystream-admin .general-textarea {
.asrouter-admin .general-textarea {
direction: ltr;
width: 740px;
height: 500px;
@ -2239,7 +2239,7 @@ main section {
border-radius: 4px;
display: flex;
}
.discoverystream-admin .wnp-textarea {
.asrouter-admin .wnp-textarea {
direction: ltr;
width: 740px;
height: 500px;
@ -2248,92 +2248,92 @@ main section {
border-radius: 4px;
display: flex;
}
.discoverystream-admin .json-button {
.asrouter-admin .json-button {
display: inline-flex;
font-size: 10px;
padding: 4px 10px;
margin-bottom: 6px;
margin-inline-end: 4px;
}
.discoverystream-admin .json-button:hover {
.asrouter-admin .json-button:hover {
background-color: var(--newtab-element-hover-color);
box-shadow: none;
}
.discoverystream-admin table {
.asrouter-admin table {
border-collapse: collapse;
width: 100%;
}
.discoverystream-admin table.minimal-table {
.asrouter-admin table.minimal-table {
border-collapse: collapse;
border: 1px solid var(--newtab-border-color);
}
.discoverystream-admin table.minimal-table td {
.asrouter-admin table.minimal-table td {
padding: 8px;
}
.discoverystream-admin table.minimal-table td:first-child {
.asrouter-admin table.minimal-table td:first-child {
width: 1%;
white-space: nowrap;
}
.discoverystream-admin table.minimal-table td:not(:first-child) {
.asrouter-admin table.minimal-table td:not(:first-child) {
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
}
.discoverystream-admin table.errorReporting tr {
.asrouter-admin table.errorReporting tr {
border: 1px solid var(--newtab-background-color-secondary);
}
.discoverystream-admin table.errorReporting td {
.asrouter-admin table.errorReporting td {
padding: 4px;
}
.discoverystream-admin table.errorReporting td[rowspan] {
.asrouter-admin table.errorReporting td[rowspan] {
border: 1px solid var(--newtab-background-color-secondary);
}
.discoverystream-admin .sourceLabel {
.asrouter-admin .sourceLabel {
background: var(--newtab-background-color-secondary);
padding: 2px 5px;
border-radius: 3px;
}
.discoverystream-admin .sourceLabel.isDisabled {
.asrouter-admin .sourceLabel.isDisabled {
background: rgba(215, 0, 34, 0.3);
color: var(--newtab-status-error);
}
.discoverystream-admin .message-item:first-child td {
.asrouter-admin .message-item:first-child td {
border-top: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item td {
.asrouter-admin .message-item td {
vertical-align: top;
padding: 8px;
border-bottom: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item td.min {
.asrouter-admin .message-item td.min {
width: 1%;
white-space: nowrap;
}
.discoverystream-admin .message-item td.message-summary {
.asrouter-admin .message-item td.message-summary {
width: 60%;
}
.discoverystream-admin .message-item td.button-column {
.asrouter-admin .message-item td.button-column {
width: 15%;
}
.discoverystream-admin .message-item td:first-child {
.asrouter-admin .message-item td:first-child {
border-inline-start: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item td:last-child {
.asrouter-admin .message-item td:last-child {
border-inline-end: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item.blocked .message-id,
.discoverystream-admin .message-item.blocked .message-summary {
.asrouter-admin .message-item.blocked .message-id,
.asrouter-admin .message-item.blocked .message-summary {
opacity: 0.5;
}
.discoverystream-admin .message-item.blocked .message-id {
.asrouter-admin .message-item.blocked .message-id {
opacity: 0.5;
}
.discoverystream-admin .message-item .message-id {
.asrouter-admin .message-item .message-id {
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
font-size: 12px;
}
.discoverystream-admin .providerUrl {
.asrouter-admin .providerUrl {
font-size: 12px;
}
.discoverystream-admin pre {
.asrouter-admin pre {
background: var(--newtab-background-color-secondary);
margin: 0;
padding: 8px;
@ -2342,87 +2342,87 @@ main section {
overflow: auto;
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
}
.discoverystream-admin .errorState {
.asrouter-admin .errorState {
border: 1px solid var(--newtab-status-error);
}
.discoverystream-admin .helpLink {
.asrouter-admin .helpLink {
padding: 10px;
display: flex;
background: rgba(0, 0, 0, 0.1);
border-radius: 3px;
align-items: center;
}
.discoverystream-admin .helpLink a {
.asrouter-admin .helpLink a {
text-decoration: underline;
}
.discoverystream-admin .helpLink .icon {
.asrouter-admin .helpLink .icon {
min-width: 18px;
min-height: 18px;
}
.discoverystream-admin .ds-component {
.asrouter-admin .ds-component {
margin-bottom: 20px;
}
.discoverystream-admin .modalOverlayInner {
.asrouter-admin .modalOverlayInner {
height: 80%;
}
.discoverystream-admin .clearButton {
.asrouter-admin .clearButton {
border: 0;
padding: 4px;
border-radius: 4px;
display: flex;
}
.discoverystream-admin .clearButton:hover {
.asrouter-admin .clearButton:hover {
background: var(--newtab-element-hover-color);
}
.discoverystream-admin .collapsed {
.asrouter-admin .collapsed {
display: none;
}
.discoverystream-admin .icon {
.asrouter-admin .icon {
display: inline-table;
cursor: pointer;
width: 18px;
height: 18px;
}
.discoverystream-admin .button:disabled, .discoverystream-admin .button:disabled:active {
.asrouter-admin .button:disabled, .asrouter-admin .button:disabled:active {
opacity: 0.5;
cursor: unset;
box-shadow: none;
}
.discoverystream-admin .impressions-section {
.asrouter-admin .impressions-section {
display: flex;
flex-direction: column;
gap: 16px;
}
.discoverystream-admin .impressions-section .impressions-item {
.asrouter-admin .impressions-section .impressions-item {
display: flex;
flex-flow: column nowrap;
padding: 8px;
border: 1px solid var(--newtab-border-color);
border-radius: 5px;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-inner-box {
.asrouter-admin .impressions-section .impressions-item .impressions-inner-box {
display: flex;
flex-flow: row nowrap;
gap: 8px;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-category {
.asrouter-admin .impressions-section .impressions-item .impressions-category {
font-size: 1.15em;
white-space: nowrap;
flex-grow: 0.1;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons {
.asrouter-admin .impressions-section .impressions-item .impressions-buttons {
display: flex;
flex-direction: column;
gap: 8px;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons button {
.asrouter-admin .impressions-section .impressions-item .impressions-buttons button {
margin: 0;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-editor {
.asrouter-admin .impressions-section .impressions-item .impressions-editor {
display: flex;
flex-grow: 1.5;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
.asrouter-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
width: auto;
flex-grow: 1;
}

Просмотреть файл

@ -2165,7 +2165,7 @@ main section {
}
/* stylelint-disable max-nesting-depth */
.discoverystream-admin-toggle {
.asrouter-toggle {
position: fixed;
top: 50px;
inset-inline-end: 15px;
@ -2174,21 +2174,21 @@ main section {
z-index: 1;
border-radius: 2px;
}
.discoverystream-admin-toggle .icon-devtools {
.asrouter-toggle .icon-devtools {
background-image: url("chrome://global/skin/icons/developer.svg");
padding: 15px;
}
.discoverystream-admin-toggle:dir(rtl) {
.asrouter-toggle:dir(rtl) {
transform: scaleX(-1);
}
.discoverystream-admin-toggle:hover {
.asrouter-toggle:hover {
background: var(--newtab-element-hover-color);
}
.discoverystream-admin-toggle.expanded {
.asrouter-toggle.expanded {
background: rgba(0, 0, 0, 0.2);
}
.discoverystream-admin {
.asrouter-admin {
position: fixed;
top: 0;
inset-inline-start: 0;
@ -2201,40 +2201,40 @@ main section {
padding-inline-start: 240px;
color: var(--newtab-text-primary-color);
}
.discoverystream-admin.collapsed {
.asrouter-admin.collapsed {
display: none;
}
.discoverystream-admin .sidebar {
.asrouter-admin .sidebar {
inset-inline-start: 0;
position: fixed;
width: 240px;
padding: 30px 20px;
}
.discoverystream-admin .sidebar ul {
.asrouter-admin .sidebar ul {
margin: 0;
padding: 0;
list-style: none;
}
.discoverystream-admin .sidebar li a {
.asrouter-admin .sidebar li a {
padding: 10px 34px;
display: block;
color: var(--lwt-sidebar-text-color);
}
.discoverystream-admin .sidebar li a:hover {
.asrouter-admin .sidebar li a:hover {
background: var(--newtab-background-color-secondary);
}
.discoverystream-admin h1 {
.asrouter-admin h1 {
font-weight: 200;
font-size: 32px;
}
.discoverystream-admin h2 .button,
.discoverystream-admin p .button {
.asrouter-admin h2 .button,
.asrouter-admin p .button {
font-size: 14px;
padding: 6px 12px;
margin-inline-start: 5px;
margin-bottom: 0;
}
.discoverystream-admin .general-textarea {
.asrouter-admin .general-textarea {
direction: ltr;
width: 740px;
height: 500px;
@ -2243,7 +2243,7 @@ main section {
border-radius: 4px;
display: flex;
}
.discoverystream-admin .wnp-textarea {
.asrouter-admin .wnp-textarea {
direction: ltr;
width: 740px;
height: 500px;
@ -2252,92 +2252,92 @@ main section {
border-radius: 4px;
display: flex;
}
.discoverystream-admin .json-button {
.asrouter-admin .json-button {
display: inline-flex;
font-size: 10px;
padding: 4px 10px;
margin-bottom: 6px;
margin-inline-end: 4px;
}
.discoverystream-admin .json-button:hover {
.asrouter-admin .json-button:hover {
background-color: var(--newtab-element-hover-color);
box-shadow: none;
}
.discoverystream-admin table {
.asrouter-admin table {
border-collapse: collapse;
width: 100%;
}
.discoverystream-admin table.minimal-table {
.asrouter-admin table.minimal-table {
border-collapse: collapse;
border: 1px solid var(--newtab-border-color);
}
.discoverystream-admin table.minimal-table td {
.asrouter-admin table.minimal-table td {
padding: 8px;
}
.discoverystream-admin table.minimal-table td:first-child {
.asrouter-admin table.minimal-table td:first-child {
width: 1%;
white-space: nowrap;
}
.discoverystream-admin table.minimal-table td:not(:first-child) {
.asrouter-admin table.minimal-table td:not(:first-child) {
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
}
.discoverystream-admin table.errorReporting tr {
.asrouter-admin table.errorReporting tr {
border: 1px solid var(--newtab-background-color-secondary);
}
.discoverystream-admin table.errorReporting td {
.asrouter-admin table.errorReporting td {
padding: 4px;
}
.discoverystream-admin table.errorReporting td[rowspan] {
.asrouter-admin table.errorReporting td[rowspan] {
border: 1px solid var(--newtab-background-color-secondary);
}
.discoverystream-admin .sourceLabel {
.asrouter-admin .sourceLabel {
background: var(--newtab-background-color-secondary);
padding: 2px 5px;
border-radius: 3px;
}
.discoverystream-admin .sourceLabel.isDisabled {
.asrouter-admin .sourceLabel.isDisabled {
background: rgba(215, 0, 34, 0.3);
color: var(--newtab-status-error);
}
.discoverystream-admin .message-item:first-child td {
.asrouter-admin .message-item:first-child td {
border-top: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item td {
.asrouter-admin .message-item td {
vertical-align: top;
padding: 8px;
border-bottom: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item td.min {
.asrouter-admin .message-item td.min {
width: 1%;
white-space: nowrap;
}
.discoverystream-admin .message-item td.message-summary {
.asrouter-admin .message-item td.message-summary {
width: 60%;
}
.discoverystream-admin .message-item td.button-column {
.asrouter-admin .message-item td.button-column {
width: 15%;
}
.discoverystream-admin .message-item td:first-child {
.asrouter-admin .message-item td:first-child {
border-inline-start: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item td:last-child {
.asrouter-admin .message-item td:last-child {
border-inline-end: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item.blocked .message-id,
.discoverystream-admin .message-item.blocked .message-summary {
.asrouter-admin .message-item.blocked .message-id,
.asrouter-admin .message-item.blocked .message-summary {
opacity: 0.5;
}
.discoverystream-admin .message-item.blocked .message-id {
.asrouter-admin .message-item.blocked .message-id {
opacity: 0.5;
}
.discoverystream-admin .message-item .message-id {
.asrouter-admin .message-item .message-id {
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
font-size: 12px;
}
.discoverystream-admin .providerUrl {
.asrouter-admin .providerUrl {
font-size: 12px;
}
.discoverystream-admin pre {
.asrouter-admin pre {
background: var(--newtab-background-color-secondary);
margin: 0;
padding: 8px;
@ -2346,87 +2346,87 @@ main section {
overflow: auto;
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
}
.discoverystream-admin .errorState {
.asrouter-admin .errorState {
border: 1px solid var(--newtab-status-error);
}
.discoverystream-admin .helpLink {
.asrouter-admin .helpLink {
padding: 10px;
display: flex;
background: rgba(0, 0, 0, 0.1);
border-radius: 3px;
align-items: center;
}
.discoverystream-admin .helpLink a {
.asrouter-admin .helpLink a {
text-decoration: underline;
}
.discoverystream-admin .helpLink .icon {
.asrouter-admin .helpLink .icon {
min-width: 18px;
min-height: 18px;
}
.discoverystream-admin .ds-component {
.asrouter-admin .ds-component {
margin-bottom: 20px;
}
.discoverystream-admin .modalOverlayInner {
.asrouter-admin .modalOverlayInner {
height: 80%;
}
.discoverystream-admin .clearButton {
.asrouter-admin .clearButton {
border: 0;
padding: 4px;
border-radius: 4px;
display: flex;
}
.discoverystream-admin .clearButton:hover {
.asrouter-admin .clearButton:hover {
background: var(--newtab-element-hover-color);
}
.discoverystream-admin .collapsed {
.asrouter-admin .collapsed {
display: none;
}
.discoverystream-admin .icon {
.asrouter-admin .icon {
display: inline-table;
cursor: pointer;
width: 18px;
height: 18px;
}
.discoverystream-admin .button:disabled, .discoverystream-admin .button:disabled:active {
.asrouter-admin .button:disabled, .asrouter-admin .button:disabled:active {
opacity: 0.5;
cursor: unset;
box-shadow: none;
}
.discoverystream-admin .impressions-section {
.asrouter-admin .impressions-section {
display: flex;
flex-direction: column;
gap: 16px;
}
.discoverystream-admin .impressions-section .impressions-item {
.asrouter-admin .impressions-section .impressions-item {
display: flex;
flex-flow: column nowrap;
padding: 8px;
border: 1px solid var(--newtab-border-color);
border-radius: 5px;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-inner-box {
.asrouter-admin .impressions-section .impressions-item .impressions-inner-box {
display: flex;
flex-flow: row nowrap;
gap: 8px;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-category {
.asrouter-admin .impressions-section .impressions-item .impressions-category {
font-size: 1.15em;
white-space: nowrap;
flex-grow: 0.1;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons {
.asrouter-admin .impressions-section .impressions-item .impressions-buttons {
display: flex;
flex-direction: column;
gap: 8px;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons button {
.asrouter-admin .impressions-section .impressions-item .impressions-buttons button {
margin: 0;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-editor {
.asrouter-admin .impressions-section .impressions-item .impressions-editor {
display: flex;
flex-grow: 1.5;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
.asrouter-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
width: auto;
flex-grow: 1;
}

Просмотреть файл

@ -2161,7 +2161,7 @@ main section {
}
/* stylelint-disable max-nesting-depth */
.discoverystream-admin-toggle {
.asrouter-toggle {
position: fixed;
top: 50px;
inset-inline-end: 15px;
@ -2170,21 +2170,21 @@ main section {
z-index: 1;
border-radius: 2px;
}
.discoverystream-admin-toggle .icon-devtools {
.asrouter-toggle .icon-devtools {
background-image: url("chrome://global/skin/icons/developer.svg");
padding: 15px;
}
.discoverystream-admin-toggle:dir(rtl) {
.asrouter-toggle:dir(rtl) {
transform: scaleX(-1);
}
.discoverystream-admin-toggle:hover {
.asrouter-toggle:hover {
background: var(--newtab-element-hover-color);
}
.discoverystream-admin-toggle.expanded {
.asrouter-toggle.expanded {
background: rgba(0, 0, 0, 0.2);
}
.discoverystream-admin {
.asrouter-admin {
position: fixed;
top: 0;
inset-inline-start: 0;
@ -2197,40 +2197,40 @@ main section {
padding-inline-start: 240px;
color: var(--newtab-text-primary-color);
}
.discoverystream-admin.collapsed {
.asrouter-admin.collapsed {
display: none;
}
.discoverystream-admin .sidebar {
.asrouter-admin .sidebar {
inset-inline-start: 0;
position: fixed;
width: 240px;
padding: 30px 20px;
}
.discoverystream-admin .sidebar ul {
.asrouter-admin .sidebar ul {
margin: 0;
padding: 0;
list-style: none;
}
.discoverystream-admin .sidebar li a {
.asrouter-admin .sidebar li a {
padding: 10px 34px;
display: block;
color: var(--lwt-sidebar-text-color);
}
.discoverystream-admin .sidebar li a:hover {
.asrouter-admin .sidebar li a:hover {
background: var(--newtab-background-color-secondary);
}
.discoverystream-admin h1 {
.asrouter-admin h1 {
font-weight: 200;
font-size: 32px;
}
.discoverystream-admin h2 .button,
.discoverystream-admin p .button {
.asrouter-admin h2 .button,
.asrouter-admin p .button {
font-size: 14px;
padding: 6px 12px;
margin-inline-start: 5px;
margin-bottom: 0;
}
.discoverystream-admin .general-textarea {
.asrouter-admin .general-textarea {
direction: ltr;
width: 740px;
height: 500px;
@ -2239,7 +2239,7 @@ main section {
border-radius: 4px;
display: flex;
}
.discoverystream-admin .wnp-textarea {
.asrouter-admin .wnp-textarea {
direction: ltr;
width: 740px;
height: 500px;
@ -2248,92 +2248,92 @@ main section {
border-radius: 4px;
display: flex;
}
.discoverystream-admin .json-button {
.asrouter-admin .json-button {
display: inline-flex;
font-size: 10px;
padding: 4px 10px;
margin-bottom: 6px;
margin-inline-end: 4px;
}
.discoverystream-admin .json-button:hover {
.asrouter-admin .json-button:hover {
background-color: var(--newtab-element-hover-color);
box-shadow: none;
}
.discoverystream-admin table {
.asrouter-admin table {
border-collapse: collapse;
width: 100%;
}
.discoverystream-admin table.minimal-table {
.asrouter-admin table.minimal-table {
border-collapse: collapse;
border: 1px solid var(--newtab-border-color);
}
.discoverystream-admin table.minimal-table td {
.asrouter-admin table.minimal-table td {
padding: 8px;
}
.discoverystream-admin table.minimal-table td:first-child {
.asrouter-admin table.minimal-table td:first-child {
width: 1%;
white-space: nowrap;
}
.discoverystream-admin table.minimal-table td:not(:first-child) {
.asrouter-admin table.minimal-table td:not(:first-child) {
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
}
.discoverystream-admin table.errorReporting tr {
.asrouter-admin table.errorReporting tr {
border: 1px solid var(--newtab-background-color-secondary);
}
.discoverystream-admin table.errorReporting td {
.asrouter-admin table.errorReporting td {
padding: 4px;
}
.discoverystream-admin table.errorReporting td[rowspan] {
.asrouter-admin table.errorReporting td[rowspan] {
border: 1px solid var(--newtab-background-color-secondary);
}
.discoverystream-admin .sourceLabel {
.asrouter-admin .sourceLabel {
background: var(--newtab-background-color-secondary);
padding: 2px 5px;
border-radius: 3px;
}
.discoverystream-admin .sourceLabel.isDisabled {
.asrouter-admin .sourceLabel.isDisabled {
background: rgba(215, 0, 34, 0.3);
color: var(--newtab-status-error);
}
.discoverystream-admin .message-item:first-child td {
.asrouter-admin .message-item:first-child td {
border-top: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item td {
.asrouter-admin .message-item td {
vertical-align: top;
padding: 8px;
border-bottom: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item td.min {
.asrouter-admin .message-item td.min {
width: 1%;
white-space: nowrap;
}
.discoverystream-admin .message-item td.message-summary {
.asrouter-admin .message-item td.message-summary {
width: 60%;
}
.discoverystream-admin .message-item td.button-column {
.asrouter-admin .message-item td.button-column {
width: 15%;
}
.discoverystream-admin .message-item td:first-child {
.asrouter-admin .message-item td:first-child {
border-inline-start: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item td:last-child {
.asrouter-admin .message-item td:last-child {
border-inline-end: 1px solid var(--newtab-border-color);
}
.discoverystream-admin .message-item.blocked .message-id,
.discoverystream-admin .message-item.blocked .message-summary {
.asrouter-admin .message-item.blocked .message-id,
.asrouter-admin .message-item.blocked .message-summary {
opacity: 0.5;
}
.discoverystream-admin .message-item.blocked .message-id {
.asrouter-admin .message-item.blocked .message-id {
opacity: 0.5;
}
.discoverystream-admin .message-item .message-id {
.asrouter-admin .message-item .message-id {
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
font-size: 12px;
}
.discoverystream-admin .providerUrl {
.asrouter-admin .providerUrl {
font-size: 12px;
}
.discoverystream-admin pre {
.asrouter-admin pre {
background: var(--newtab-background-color-secondary);
margin: 0;
padding: 8px;
@ -2342,87 +2342,87 @@ main section {
overflow: auto;
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
}
.discoverystream-admin .errorState {
.asrouter-admin .errorState {
border: 1px solid var(--newtab-status-error);
}
.discoverystream-admin .helpLink {
.asrouter-admin .helpLink {
padding: 10px;
display: flex;
background: rgba(0, 0, 0, 0.1);
border-radius: 3px;
align-items: center;
}
.discoverystream-admin .helpLink a {
.asrouter-admin .helpLink a {
text-decoration: underline;
}
.discoverystream-admin .helpLink .icon {
.asrouter-admin .helpLink .icon {
min-width: 18px;
min-height: 18px;
}
.discoverystream-admin .ds-component {
.asrouter-admin .ds-component {
margin-bottom: 20px;
}
.discoverystream-admin .modalOverlayInner {
.asrouter-admin .modalOverlayInner {
height: 80%;
}
.discoverystream-admin .clearButton {
.asrouter-admin .clearButton {
border: 0;
padding: 4px;
border-radius: 4px;
display: flex;
}
.discoverystream-admin .clearButton:hover {
.asrouter-admin .clearButton:hover {
background: var(--newtab-element-hover-color);
}
.discoverystream-admin .collapsed {
.asrouter-admin .collapsed {
display: none;
}
.discoverystream-admin .icon {
.asrouter-admin .icon {
display: inline-table;
cursor: pointer;
width: 18px;
height: 18px;
}
.discoverystream-admin .button:disabled, .discoverystream-admin .button:disabled:active {
.asrouter-admin .button:disabled, .asrouter-admin .button:disabled:active {
opacity: 0.5;
cursor: unset;
box-shadow: none;
}
.discoverystream-admin .impressions-section {
.asrouter-admin .impressions-section {
display: flex;
flex-direction: column;
gap: 16px;
}
.discoverystream-admin .impressions-section .impressions-item {
.asrouter-admin .impressions-section .impressions-item {
display: flex;
flex-flow: column nowrap;
padding: 8px;
border: 1px solid var(--newtab-border-color);
border-radius: 5px;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-inner-box {
.asrouter-admin .impressions-section .impressions-item .impressions-inner-box {
display: flex;
flex-flow: row nowrap;
gap: 8px;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-category {
.asrouter-admin .impressions-section .impressions-item .impressions-category {
font-size: 1.15em;
white-space: nowrap;
flex-grow: 0.1;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons {
.asrouter-admin .impressions-section .impressions-item .impressions-buttons {
display: flex;
flex-direction: column;
gap: 8px;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons button {
.asrouter-admin .impressions-section .impressions-item .impressions-buttons button {
margin: 0;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-editor {
.asrouter-admin .impressions-section .impressions-item .impressions-editor {
display: flex;
flex-grow: 1.5;
}
.discoverystream-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
.asrouter-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
width: auto;
flex-grow: 1;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -99,15 +99,6 @@ running
./mach npm test --prefix=browser/components/newtab &&
./mach npm run debugcoverage --prefix=browser/components/newtab
Discovery Stream Developer tools
--------------------------------
You can access the developer tools for the Discovery Stream components of about:newtab by
visiting `about:config` and setting `browser.newtabpage.activity-stream.asrouter.devtoolsEnabled`
to `true`.
Then, go to any `about:newtab` page and click on the wrench icon in the top-right corner.
Detailed Docs
-------------
.. toctree::

Просмотреть файл

@ -97,8 +97,8 @@ module.exports = function (config) {
"content-src/asrouter/asrouter-utils.js": {
statements: 66,
lines: 66,
functions: 76,
branches: 33,
functions: 78,
branches: 50,
},
"lib/TelemetryFeed.jsm": {
statements: 98,
@ -188,7 +188,7 @@ module.exports = function (config) {
functions: 60,
branches: 50,
},
"content-src/components/DiscoveryStreamAdmin/*.jsx": {
"content-src/components/ASRouterAdmin/*.jsx": {
statements: 0,
lines: 0,
functions: 0,

Просмотреть файл

@ -1116,7 +1116,6 @@ class _ASRouter {
userPrefs: lazy.ASRouterPreferences.getAllUserPreferences(),
targetingParameters,
errors: this.errors,
devtoolsEnabled: lazy.ASRouterPreferences.devtoolsEnabled,
}));
}

Просмотреть файл

@ -1594,7 +1594,6 @@ describe("ASRouter", () => {
userPrefs: ASRouterPreferences.getAllUserPreferences(),
targetingParameters: {},
errors: Router.errors,
devtoolsEnabled: ASRouterPreferences.devtoolsEnabled,
});
assert.deepEqual(msg, expected);

Просмотреть файл

@ -1,4 +1,14 @@
import { ASRouterAdminInner } from "content-src/components/ASRouterAdmin/ASRouterAdmin";
import {
actionCreators as ac,
actionTypes as at,
} from "common/Actions.sys.mjs";
import {
ASRouterAdminInner,
CollapseToggle,
DiscoveryStreamAdmin,
Personalization,
ToggleStoryButton,
} from "content-src/components/ASRouterAdmin/ASRouterAdmin";
import { ASRouterUtils } from "content-src/asrouter/asrouter-utils";
import { GlobalOverrider } from "test/unit/utils";
import React from "react";
@ -36,8 +46,9 @@ describe("ASRouterAdmin", () => {
ASRouterRemoveParentListener: sandbox.stub(),
};
globalOverrider.set(globals);
wrapper = shallow(<ASRouterAdminInner location={{ routes: [""] }} />);
wrapper.setState({ devtoolsEnabled: true });
wrapper = shallow(
<ASRouterAdminInner collapsed={false} location={{ routes: [""] }} />
);
});
afterEach(() => {
sandbox.restore();
@ -53,6 +64,15 @@ describe("ASRouterAdmin", () => {
data: { endpoint: "foo" },
});
});
it("should set a .collapsed class on the outer div if props.collapsed is true", () => {
wrapper.setProps({ collapsed: true });
assert.isTrue(wrapper.find(".asrouter-admin").hasClass("collapsed"));
});
it("should set a .expanded class on the outer div if props.collapsed is false", () => {
wrapper.setProps({ collapsed: false });
assert.isTrue(wrapper.find(".asrouter-admin").hasClass("expanded"));
assert.isFalse(wrapper.find(".asrouter-admin").hasClass("collapsed"));
});
describe("#getSection", () => {
it("should render a message provider section by default", () => {
assert.equal(wrapper.find("h2").at(1).text(), "Messages");
@ -61,14 +81,22 @@ describe("ASRouterAdmin", () => {
wrapper = shallow(
<ASRouterAdminInner location={{ routes: ["targeting"] }} />
);
wrapper.setState({ devtoolsEnabled: true });
assert.equal(wrapper.find("h2").at(0).text(), "Targeting Utilities");
});
it("should render a DS section for DS route", () => {
wrapper = shallow(
<ASRouterAdminInner
location={{ routes: ["ds"] }}
Sections={[]}
Prefs={{}}
/>
);
assert.equal(wrapper.find("h2").at(0).text(), "Discovery Stream");
});
it("should render two error messages", () => {
wrapper = shallow(
<ASRouterAdminInner location={{ routes: ["errors"] }} Sections={[]} />
);
wrapper.setState({ devtoolsEnabled: true });
const firstError = {
timestamp: Date.now() + 100,
error: { message: "first" },
@ -259,4 +287,229 @@ describe("ASRouterAdmin", () => {
});
});
});
describe("#DiscoveryStream", () => {
let state = {};
let dispatch;
beforeEach(() => {
dispatch = sandbox.stub();
state = {
config: {
enabled: true,
},
layout: [],
spocs: {
frequency_caps: [],
},
feeds: {
data: {},
},
};
wrapper = shallow(
<DiscoveryStreamAdmin
dispatch={dispatch}
otherPrefs={{}}
state={{
DiscoveryStream: state,
}}
/>
);
});
it("should render a DiscoveryStreamAdmin component", () => {
assert.equal(wrapper.find("h3").at(0).text(), "Layout");
});
it("should render a spoc in DiscoveryStreamAdmin component", () => {
state.spocs = {
frequency_caps: [],
data: {
spocs: {
items: [
{
id: 12345,
},
],
},
},
};
wrapper = shallow(
<DiscoveryStreamAdmin
otherPrefs={{}}
state={{ DiscoveryStream: state }}
/>
);
wrapper.instance().onStoryToggle({ id: 12345 });
const messageSummary = wrapper.find(".message-summary").at(0);
const pre = messageSummary.find("pre").at(0);
const spocText = pre.text();
assert.equal(spocText, '{\n "id": 12345\n}');
});
it("should fire restorePrefDefaults with DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS", () => {
wrapper.find("button").at(0).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS,
})
);
});
it("should fire config change with DISCOVERY_STREAM_CONFIG_CHANGE", () => {
wrapper.find("button").at(1).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_CHANGE,
data: { enabled: true },
})
);
});
it("should fire expireCache with DISCOVERY_STREAM_DEV_EXPIRE_CACHE", () => {
wrapper.find("button").at(2).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_DEV_EXPIRE_CACHE,
})
);
});
it("should fire systemTick with DISCOVERY_STREAM_DEV_SYSTEM_TICK", () => {
wrapper.find("button").at(3).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_DEV_SYSTEM_TICK,
})
);
});
it("should fire idleDaily with DISCOVERY_STREAM_DEV_IDLE_DAILY", () => {
wrapper.find("button").at(4).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_DEV_IDLE_DAILY,
})
);
});
it("should fire syncRemoteSettings with DISCOVERY_STREAM_DEV_SYNC_RS", () => {
wrapper.find("button").at(5).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_DEV_SYNC_RS,
})
);
});
it("should fire setConfigValue with DISCOVERY_STREAM_CONFIG_SET_VALUE", () => {
const name = "name";
const value = "value";
wrapper.instance().setConfigValue(name, value);
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_SET_VALUE,
data: { name, value },
})
);
});
});
describe("#Personalization", () => {
let dispatch;
beforeEach(() => {
dispatch = sandbox.stub();
wrapper = shallow(
<Personalization
dispatch={dispatch}
state={{
Personalization: {
lastUpdated: 1000,
initialized: true,
},
}}
/>
);
});
it("should render with pref checkbox, lastUpdated, and initialized", () => {
assert.lengthOf(wrapper.find("TogglePrefCheckbox"), 1);
assert.equal(
wrapper.find("td").at(1).text(),
"Personalization Last Updated"
);
assert.equal(
wrapper.find("td").at(2).text(),
new Date(1000).toLocaleString()
);
assert.equal(
wrapper.find("td").at(3).text(),
"Personalization Initialized"
);
assert.equal(wrapper.find("td").at(4).text(), "true");
});
it("should render with no data with no last updated", () => {
wrapper = shallow(
<Personalization
dispatch={dispatch}
state={{
Personalization: {
version: 2,
lastUpdated: 0,
initialized: true,
},
}}
/>
);
assert.equal(wrapper.find("td").at(2).text(), "(no data)");
});
it("should dispatch DISCOVERY_STREAM_PERSONALIZATION_TOGGLE", () => {
wrapper.instance().togglePersonalization();
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_PERSONALIZATION_TOGGLE,
})
);
});
});
describe("#ToggleStoryButton", () => {
it("should fire onClick in toggle button", async () => {
let result = "";
function onClick(spoc) {
result = spoc;
}
wrapper = shallow(<ToggleStoryButton story="spoc" onClick={onClick} />);
wrapper.find("button").simulate("click");
assert.equal(result, "spoc");
});
});
});
describe("CollapseToggle", () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<CollapseToggle location={{ routes: [""] }} />);
});
describe("rendering inner content", () => {
it("should not render ASRouterAdminInner for about:newtab (no hash)", () => {
wrapper.setProps({ location: { hash: "", routes: [""] } });
assert.lengthOf(wrapper.find(ASRouterAdminInner), 0);
});
it("should render ASRouterAdminInner for about:newtab#asrouter and subroutes", () => {
wrapper.setProps({ location: { hash: "#asrouter", routes: [""] } });
assert.lengthOf(wrapper.find(ASRouterAdminInner), 1);
wrapper.setProps({ location: { hash: "#asrouter-foo", routes: [""] } });
assert.lengthOf(wrapper.find(ASRouterAdminInner), 1);
});
it("should render ASRouterAdminInner for about:newtab#devtools and subroutes", () => {
wrapper.setProps({ location: { hash: "#devtools", routes: [""] } });
assert.lengthOf(wrapper.find(ASRouterAdminInner), 1);
wrapper.setProps({ location: { hash: "#devtools-foo", routes: [""] } });
assert.lengthOf(wrapper.find(ASRouterAdminInner), 1);
});
});
});

Просмотреть файл

@ -3,7 +3,7 @@ import {
BaseContent,
PrefsButton,
} from "content-src/components/Base/Base";
import { DiscoveryStreamAdmin } from "content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin";
import { ASRouterAdmin } from "content-src/components/ASRouterAdmin/ASRouterAdmin";
import { ErrorBoundary } from "content-src/components/ErrorBoundary/ErrorBoundary";
import React from "react";
import { Search } from "content-src/components/Search/Search";
@ -47,24 +47,24 @@ describe("<Base>", () => {
);
});
it("should render an DiscoveryStreamAdmin if the devtools pref is true", () => {
it("should render an ASRouterAdmin if the devtools pref is true", () => {
const wrapper = shallow(
<Base
{...DEFAULT_PROPS}
Prefs={{ values: { "asrouter.devtoolsEnabled": true } }}
/>
);
assert.lengthOf(wrapper.find(DiscoveryStreamAdmin), 1);
assert.lengthOf(wrapper.find(ASRouterAdmin), 1);
});
it("should not render an DiscoveryStreamAdmin if the devtools pref is false", () => {
it("should not render an ASRouterAdmin if the devtools pref is false", () => {
const wrapper = shallow(
<Base
{...DEFAULT_PROPS}
Prefs={{ values: { "asrouter.devtoolsEnabled": false } }}
/>
);
assert.lengthOf(wrapper.find(DiscoveryStreamAdmin), 0);
assert.lengthOf(wrapper.find(ASRouterAdmin), 0);
});
});

Просмотреть файл

@ -1,267 +0,0 @@
import {
actionCreators as ac,
actionTypes as at,
} from "common/Actions.sys.mjs";
import {
DiscoveryStreamAdminInner,
CollapseToggle,
DiscoveryStreamAdminUI,
Personalization,
ToggleStoryButton,
} from "content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin";
import React from "react";
import { shallow } from "enzyme";
describe("DiscoveryStreamAdmin", () => {
let sandbox;
let wrapper;
beforeEach(() => {
sandbox = sinon.createSandbox();
wrapper = shallow(
<DiscoveryStreamAdminInner
collapsed={false}
location={{ routes: [""] }}
Prefs={{}}
/>
);
});
afterEach(() => {
sandbox.restore();
});
it("should render DiscoveryStreamAdmin component", () => {
assert.ok(wrapper.exists());
});
it("should set a .collapsed class on the outer div if props.collapsed is true", () => {
wrapper.setProps({ collapsed: true });
assert.isTrue(wrapper.find(".discoverystream-admin").hasClass("collapsed"));
});
it("should set a .expanded class on the outer div if props.collapsed is false", () => {
wrapper.setProps({ collapsed: false });
assert.isTrue(wrapper.find(".discoverystream-admin").hasClass("expanded"));
assert.isFalse(
wrapper.find(".discoverystream-admin").hasClass("collapsed")
);
});
it("should render a DS section", () => {
assert.equal(wrapper.find("h1").at(0).text(), "Discovery Stream Admin");
});
describe("#DiscoveryStream", () => {
let state = {};
let dispatch;
beforeEach(() => {
dispatch = sandbox.stub();
state = {
config: {
enabled: true,
},
layout: [],
spocs: {
frequency_caps: [],
},
feeds: {
data: {},
},
};
wrapper = shallow(
<DiscoveryStreamAdminUI
dispatch={dispatch}
otherPrefs={{}}
state={{
DiscoveryStream: state,
}}
/>
);
});
it("should render a DiscoveryStreamAdminUI component", () => {
assert.equal(wrapper.find("h3").at(0).text(), "Layout");
});
it("should render a spoc in DiscoveryStreamAdminUI component", () => {
state.spocs = {
frequency_caps: [],
data: {
spocs: {
items: [
{
id: 12345,
},
],
},
},
};
wrapper = shallow(
<DiscoveryStreamAdminUI
otherPrefs={{}}
state={{ DiscoveryStream: state }}
/>
);
wrapper.instance().onStoryToggle({ id: 12345 });
const messageSummary = wrapper.find(".message-summary").at(0);
const pre = messageSummary.find("pre").at(0);
const spocText = pre.text();
assert.equal(spocText, '{\n "id": 12345\n}');
});
it("should fire restorePrefDefaults with DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS", () => {
wrapper.find("button").at(0).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS,
})
);
});
it("should fire config change with DISCOVERY_STREAM_CONFIG_CHANGE", () => {
wrapper.find("button").at(1).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_CHANGE,
data: { enabled: true },
})
);
});
it("should fire expireCache with DISCOVERY_STREAM_DEV_EXPIRE_CACHE", () => {
wrapper.find("button").at(2).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_DEV_EXPIRE_CACHE,
})
);
});
it("should fire systemTick with DISCOVERY_STREAM_DEV_SYSTEM_TICK", () => {
wrapper.find("button").at(3).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_DEV_SYSTEM_TICK,
})
);
});
it("should fire idleDaily with DISCOVERY_STREAM_DEV_IDLE_DAILY", () => {
wrapper.find("button").at(4).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_DEV_IDLE_DAILY,
})
);
});
it("should fire syncRemoteSettings with DISCOVERY_STREAM_DEV_SYNC_RS", () => {
wrapper.find("button").at(5).simulate("click");
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_DEV_SYNC_RS,
})
);
});
it("should fire setConfigValue with DISCOVERY_STREAM_CONFIG_SET_VALUE", () => {
const name = "name";
const value = "value";
wrapper.instance().setConfigValue(name, value);
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_CONFIG_SET_VALUE,
data: { name, value },
})
);
});
});
describe("#Personalization", () => {
let dispatch;
beforeEach(() => {
dispatch = sandbox.stub();
wrapper = shallow(
<Personalization
dispatch={dispatch}
state={{
Personalization: {
lastUpdated: 1000,
initialized: true,
},
}}
/>
);
});
it("should render with pref checkbox, lastUpdated, and initialized", () => {
assert.lengthOf(wrapper.find("TogglePrefCheckbox"), 1);
assert.equal(
wrapper.find("td").at(1).text(),
"Personalization Last Updated"
);
assert.equal(
wrapper.find("td").at(2).text(),
new Date(1000).toLocaleString()
);
assert.equal(
wrapper.find("td").at(3).text(),
"Personalization Initialized"
);
assert.equal(wrapper.find("td").at(4).text(), "true");
});
it("should render with no data with no last updated", () => {
wrapper = shallow(
<Personalization
dispatch={dispatch}
state={{
Personalization: {
version: 2,
lastUpdated: 0,
initialized: true,
},
}}
/>
);
assert.equal(wrapper.find("td").at(2).text(), "(no data)");
});
it("should dispatch DISCOVERY_STREAM_PERSONALIZATION_TOGGLE", () => {
wrapper.instance().togglePersonalization();
assert.calledWith(
dispatch,
ac.OnlyToMain({
type: at.DISCOVERY_STREAM_PERSONALIZATION_TOGGLE,
})
);
});
});
describe("#ToggleStoryButton", () => {
it("should fire onClick in toggle button", async () => {
let result = "";
function onClick(spoc) {
result = spoc;
}
wrapper = shallow(<ToggleStoryButton story="spoc" onClick={onClick} />);
wrapper.find("button").simulate("click");
assert.equal(result, "spoc");
});
});
});
describe("CollapseToggle", () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<CollapseToggle location={{ routes: [""] }} />);
});
describe("rendering inner content", () => {
it("should not render DiscoveryStreamAdminInner for about:newtab (no hash)", () => {
wrapper.setProps({ location: { hash: "", routes: [""] } });
assert.lengthOf(wrapper.find(DiscoveryStreamAdminInner), 0);
});
it("should render DiscoveryStreamAdminInner for about:newtab#devtools and subroutes", () => {
wrapper.setProps({ location: { hash: "#devtools", routes: [""] } });
assert.lengthOf(wrapper.find(DiscoveryStreamAdminInner), 1);
wrapper.setProps({ location: { hash: "#devtools-foo", routes: [""] } });
assert.lengthOf(wrapper.find(DiscoveryStreamAdminInner), 1);
});
});
});

Просмотреть файл

@ -4,9 +4,6 @@ build/vs/vs2022.yaml
browser/components/aboutwelcome/content/aboutwelcome.bundle.js
browser/components/aboutwelcome/logs/
browser/components/aboutwelcome/node_modules/
browser/components/asrouter/node_modules/
browser/components/asrouter/content/asrouter-admin.bundle.js
browser/components/asrouter/logs/
browser/components/newtab/content-src/asrouter/schemas/BackgroundTaskMessagingExperiment.schema.json
browser/components/newtab/content-src/asrouter/schemas/MessagingExperiment.schema.json
browser/components/newtab/logs/