Bug 1777343 - Implement simple origin controls attention indicator, r=willdurand,desktop-theme-reviewers,Itiel

Differential Revision: https://phabricator.services.mozilla.com/D158476
This commit is contained in:
Tomislav Jovanovic 2022-10-13 22:04:52 +00:00
Родитель 1778c775fe
Коммит 28b6c5c09f
7 изменённых файлов: 82 добавлений и 7 удалений

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

@ -1335,6 +1335,12 @@ customElements.define(
this.setAttribute("extension-id", this.addon.id);
let policy = WebExtensionPolicy.getByID(this.addon.id);
this.setAttribute(
"attention",
lazy.OriginControls.getAttention(policy, this.ownerGlobal)
);
this.querySelector(
".unified-extensions-item-name"
).textContent = this.addon.name;

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

@ -36,6 +36,11 @@ ChromeUtils.defineModuleGetter(
"BrowserUsageTelemetry",
"resource:///modules/BrowserUsageTelemetry.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"OriginControls",
"resource://gre/modules/ExtensionPermissions.jsm"
);
var { DefaultWeakMap } = ExtensionUtils;
@ -249,7 +254,7 @@ this.browserAction = class extends ExtensionAPIPersistent {
node.onmouseout = event => this.handleEvent(event);
node.onauxclick = event => this.handleEvent(event);
this.updateButton(node, this.action.getContextData(null), true);
this.updateButton(node, this.action.getContextData(null), true, false);
},
onBeforeCommand: event => {
@ -566,12 +571,14 @@ this.browserAction = class extends ExtensionAPIPersistent {
// Update the toolbar button |node| with the tab context data
// in |tabData|.
updateButton(node, tabData, sync = false) {
updateButton(node, tabData, sync = false, attention = false) {
let title = tabData.title || this.extension.name;
let callback = () => {
node.setAttribute("tooltiptext", title);
node.setAttribute("label", title);
node.setAttribute("attention", attention);
if (tabData.badgeText) {
node.setAttribute("badge", tabData.badgeText);
} else {
@ -640,7 +647,12 @@ this.browserAction = class extends ExtensionAPIPersistent {
let node = this.widget.forWindow(window).node;
if (node) {
let tab = window.gBrowser.selectedTab;
this.updateButton(node, this.action.getContextData(tab));
this.updateButton(
node,
this.action.getContextData(tab),
false,
OriginControls.getAttention(this.extension.policy, window)
);
}
}

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

@ -57,24 +57,27 @@ async function makeExtension({ id, permissions, host_permissions, granted }) {
async function testOriginControls(
extension,
{ win, contextMenuId },
{ items, selected, click, granted, revoked }
{ items, selected, click, granted, revoked, attention }
) {
info(
`Testing ${extension.id} on ${gBrowser.currentURI.spec} with contextMenuId=${contextMenuId}.`
);
let button;
let menu;
let manageExtensionClassName;
switch (contextMenuId) {
case "toolbar-context-menu":
let target = `#${CSS.escape(makeWidgetId(extension.id))}-browser-action`;
button = win.document.querySelector(target);
menu = await openChromeContextMenu(contextMenuId, target);
manageExtensionClassName = "customize-context-manageExtension";
break;
case "unified-extensions-context-menu":
await openExtensionsPanel(win);
button = getUnifiedExtensionsItem(win, extension.id);
menu = await openUnifiedExtensionsContextMenu(win, extension.id);
manageExtensionClassName =
"unified-extensions-context-menu-manage-extension";
@ -102,6 +105,12 @@ async function testOriginControls(
"All items accounted for."
);
is(
button.getAttribute("attention"),
attention ? "true" : "false",
"Expected attention badge before clicking."
);
let itemToClick;
if (click) {
itemToClick = menu.children[click];
@ -178,18 +187,21 @@ const originControlsInContextMenu = async options => {
await testOriginControls(ext2, options, {
items: [ACCESS_OPTIONS, WHEN_CLICKED],
selected: 1,
attention: true,
});
// Could access mochi.test when clicked.
await testOriginControls(ext3, options, {
items: [ACCESS_OPTIONS, WHEN_CLICKED, ALWAYS_ON],
selected: 1,
attention: true,
});
// Has <all_urls> granted.
await testOriginControls(ext4, options, {
items: [ACCESS_OPTIONS, ALL_SITES],
selected: 1,
attention: false,
});
});
@ -206,16 +218,19 @@ const originControlsInContextMenu = async options => {
items: [ACCESS_OPTIONS, WHEN_CLICKED, ALWAYS_ON],
selected: 1,
click: 1,
attention: true,
});
await testOriginControls(ext3, options, {
items: [ACCESS_OPTIONS, WHEN_CLICKED, ALWAYS_ON],
selected: 2,
click: 2,
attention: false,
});
await testOriginControls(ext4, options, {
items: [ACCESS_OPTIONS, ALL_SITES],
selected: 1,
click: 1,
attention: false,
});
// Click the other option, expect example.com permission granted/revoked.
@ -224,22 +239,26 @@ const originControlsInContextMenu = async options => {
selected: 1,
click: 2,
granted: ["*://example.com/*"],
attention: true,
});
await testOriginControls(ext3, options, {
items: [ACCESS_OPTIONS, WHEN_CLICKED, ALWAYS_ON],
selected: 2,
click: 1,
revoked: ["*://example.com/*"],
attention: false,
});
// Other option is now selected.
await testOriginControls(ext2, options, {
items: [ACCESS_OPTIONS, WHEN_CLICKED, ALWAYS_ON],
selected: 2,
attention: false,
});
await testOriginControls(ext3, options, {
items: [ACCESS_OPTIONS, WHEN_CLICKED, ALWAYS_ON],
selected: 1,
attention: true,
});
});

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

@ -4,11 +4,33 @@
/* Style for the custom element "unified-extensions-item". */
:root {
--icon-size: 32px;
--dot-position: calc(var(--icon-size) / 2 + var(--arrowpanel-menuitem-margin-inline) + var(--arrowpanel-menuitem-padding-inline) - 4px);
}
:root[uidensity="compact"] {
--icon-size: 24px;
}
unified-extensions-item {
align-items: center;
display: flex;
}
/* Larger attention indicator for use below larger icons, see for reference:
* https://searchfox.org/mozilla-central/rev/560b7b1b17/browser/themes/shared/tabs.css#624 */
unified-extensions-item[attention="true"] {
background-image: radial-gradient(circle, var(--tab-attention-icon-color), var(--tab-attention-icon-color) 3px, transparent 3px);
background-position: left var(--dot-position) bottom 3px;
background-size: 8px 8px;
background-repeat: no-repeat;
}
unified-extensions-item[attention="true"]:-moz-locale-dir(rtl) {
background-position-x: right var(--dot-position);
}
.unified-extensions-item-action {
overflow: hidden;
}
@ -33,8 +55,8 @@ unified-extensions-item[secondary-button-hovered="true"] .unified-extensions-ite
}
.unified-extensions-item-icon {
height: 32px;
width: 32px;
height: var(--icon-size);
width: var(--icon-size);
margin-inline-end: 6px;
}

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

@ -621,13 +621,18 @@ toolbar[brighttext] {
.tabbrowser-tab:is([image], [pinned]) > .tab-stack > .tab-content[attention]:not([selected="true"]),
.tabbrowser-tab > .tab-stack > .tab-content[pinned][titlechanged]:not([selected="true"]),
#firefox-view-button[attention] {
#firefox-view-button[attention],
.webextension-browser-action[attention="true"] {
background-image: radial-gradient(circle, var(--tab-attention-icon-color), var(--tab-attention-icon-color) 2px, transparent 2px);
background-position: center bottom calc(6.5px + var(--tabs-navbar-shadow-size));
background-size: 4px 4px;
background-repeat: no-repeat;
}
:root[uidensity="compact"] .webextension-browser-action[attention="true"] {
background-position-y: bottom 4.5px;
}
.tabbrowser-tab[image] > .tab-stack > .tab-content[attention]:not([pinned], [selected="true"]) {
background-position-x: left 14px;
}

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

@ -62,6 +62,11 @@ class PanelActionBase {
this.updateOnChange(tab);
});
// eslint-disable-next-line mozilla/balanced-listeners
extension.on("add-permissions", () => this.updateOnChange());
// eslint-disable-next-line mozilla/balanced-listeners
extension.on("remove-permissions", () => this.updateOnChange());
// When preloading a popup we temporarily grant active tab permissions to
// the preloaded popup. If we don't end up opening we need to clear this
// permission when clearing the popup.

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

@ -463,6 +463,12 @@ var OriginControls = {
};
},
// Whether to show the attention indicator for extension on current tab.
getAttention(policy, window) {
let state = this.getState(policy, window.gBrowser.currentURI);
return !!state.whenClicked && !state.hasAccess;
},
// Grant extension host permission to always run on this host.
setAlwaysOn(policy, uri) {
if (!policy.active) {