mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 16:55:40 +00:00
Bug 1531964 - Permissions tab on add-on details page r=rpl,flod
Differential Revision: https://phabricator.services.mozilla.com/D30429 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
2748936152
commit
40e016aded
@ -391,6 +391,7 @@ preferences-addon-button =
|
||||
}
|
||||
details-addon-button = Details
|
||||
release-notes-addon-button = Release Notes
|
||||
permissions-addon-button = Permissions
|
||||
|
||||
addons-enabled-heading = Enabled
|
||||
addons-disabled-heading = Disabled
|
||||
@ -452,3 +453,5 @@ recent-updates-heading = Recent Updates
|
||||
|
||||
release-notes-loading = Loading…
|
||||
release-notes-error = Sorry, but there was an error loading the release notes.
|
||||
|
||||
addon-permissions-empty = This extension doesn’t require any permissions
|
||||
|
@ -362,6 +362,10 @@ panel-item-separator[hidden] {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
addon-permissions-list > .addon-detail-row:first-of-type {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.deck-tab-group {
|
||||
border-bottom: 1px solid var(--grey-90-a20);
|
||||
border-top: 1px solid var(--grey-90-a20);
|
||||
|
@ -87,6 +87,7 @@
|
||||
<template name="addon-details">
|
||||
<div class="deck-tab-group">
|
||||
<named-deck-button deck="details-deck" name="details" data-l10n-id="details-addon-button"></named-deck-button>
|
||||
<named-deck-button deck="details-deck" name="permissions" data-l10n-id="permissions-addon-button"></named-deck-button>
|
||||
<named-deck-button deck="details-deck" name="release-notes" data-l10n-id="release-notes-addon-button"></named-deck-button>
|
||||
</div>
|
||||
<named-deck id="details-deck">
|
||||
@ -156,6 +157,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<addon-permissions-list name="permissions"></addon-permissions-list>
|
||||
<update-release-notes name="release-notes"></update-release-notes>
|
||||
</named-deck>
|
||||
</template>
|
||||
|
@ -18,6 +18,15 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "browserBundle", () => {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://browser/locale/browser.properties");
|
||||
});
|
||||
XPCOMUtils.defineLazyGetter(this, "brandBundle", () => {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://branding/locale/brand.properties");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this, "allowPrivateBrowsingByDefault",
|
||||
"extensions.allowPrivateBrowsingByDefault", true);
|
||||
@ -753,6 +762,49 @@ class UpdateReleaseNotes extends HTMLElement {
|
||||
}
|
||||
customElements.define("update-release-notes", UpdateReleaseNotes);
|
||||
|
||||
class AddonPermissionsList extends HTMLElement {
|
||||
setAddon(addon) {
|
||||
this.addon = addon;
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
let appName = brandBundle.GetStringFromName("brandShortName");
|
||||
let {msgs} = Extension.formatPermissionStrings({
|
||||
permissions: this.addon.userPermissions,
|
||||
appName,
|
||||
}, browserBundle);
|
||||
|
||||
this.textContent = "";
|
||||
|
||||
if (msgs.length > 0) {
|
||||
// Add a row for each permission message.
|
||||
for (let msg of msgs) {
|
||||
let row = document.createElement("div");
|
||||
row.classList.add("addon-detail-row", "permission-info");
|
||||
row.textContent = msg;
|
||||
this.appendChild(row);
|
||||
}
|
||||
} else {
|
||||
let emptyMessage = document.createElement("div");
|
||||
emptyMessage.classList.add("addon-detail-row");
|
||||
document.l10n.setAttributes(emptyMessage, "addon-permissions-empty");
|
||||
this.appendChild(emptyMessage);
|
||||
}
|
||||
|
||||
// Add a learn more link.
|
||||
let learnMoreRow = document.createElement("div");
|
||||
learnMoreRow.classList.add("addon-detail-row");
|
||||
let learnMoreLink = document.createElement("a");
|
||||
learnMoreLink.setAttribute("target", "_blank");
|
||||
learnMoreLink.href = SUPPORT_URL + "extension-permissions";
|
||||
learnMoreLink.textContent =
|
||||
browserBundle.GetStringFromName("webextPerms.learnMore");
|
||||
learnMoreRow.appendChild(learnMoreLink);
|
||||
this.appendChild(learnMoreRow);
|
||||
}
|
||||
}
|
||||
customElements.define("addon-permissions-list", AddonPermissionsList);
|
||||
|
||||
class AddonDetails extends HTMLElement {
|
||||
connectedCallback() {
|
||||
@ -793,6 +845,8 @@ class AddonDetails extends HTMLElement {
|
||||
// Hide tab buttons that won't have any content.
|
||||
let getButtonByName =
|
||||
name => this.tabGroup.querySelector(`[name="${name}"]`);
|
||||
let permsBtn = getButtonByName("permissions");
|
||||
permsBtn.hidden = addon.type != "extension";
|
||||
let notesBtn = getButtonByName("release-notes");
|
||||
notesBtn.hidden = !this.releaseNotesUri;
|
||||
|
||||
@ -828,6 +882,10 @@ class AddonDetails extends HTMLElement {
|
||||
this.deck = this.querySelector("named-deck");
|
||||
this.tabGroup = this.querySelector(".deck-tab-group");
|
||||
|
||||
// Set the add-on for the permissions section.
|
||||
this.permissionsList = this.querySelector("addon-permissions-list");
|
||||
this.permissionsList.setAddon(addon);
|
||||
|
||||
// Full description.
|
||||
let description = this.querySelector(".addon-detail-description");
|
||||
if (addon.getFullDescription) {
|
||||
|
@ -61,6 +61,26 @@ function checkOptions(doc, options, expectedOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
function assertDeckHeadingHidden(group) {
|
||||
ok(group.hidden, "The tab group is hidden");
|
||||
for (let button of group.children) {
|
||||
ok(button.offsetHeight == 0, `The ${button.name} is hidden`);
|
||||
}
|
||||
}
|
||||
|
||||
function assertDeckHeadingButtons(group, visibleButtons) {
|
||||
ok(!group.hidden, "The tab group is shown");
|
||||
ok(group.children.length >= visibleButtons.length,
|
||||
`There should be at least ${visibleButtons.length} buttons`);
|
||||
for (let button of group.children) {
|
||||
if (visibleButtons.includes(button.name)) {
|
||||
ok(!button.hidden, `The ${button.name} is shown`);
|
||||
} else {
|
||||
ok(button.hidden, `The ${button.name} is hidden`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function hasPrivateAllowed(id) {
|
||||
let perms = await ExtensionPermissions.get(id);
|
||||
return perms.permissions.includes("internal:privateBrowsingAllowed");
|
||||
@ -83,6 +103,10 @@ add_task(async function enableHtmlViews() {
|
||||
type: "extension",
|
||||
contributionURL: "http://foo.com",
|
||||
averageRating: 4.279,
|
||||
userPermissions: {
|
||||
origins: ["<all_urls>", "file://*/*"],
|
||||
permissions: ["alarms", "contextMenus", "tabs", "webNavigation"],
|
||||
},
|
||||
reviewCount: 5,
|
||||
reviewURL: "http://example.com/reviews",
|
||||
homepageURL: "http://example.com/addon1",
|
||||
@ -93,6 +117,10 @@ add_task(async function enableHtmlViews() {
|
||||
name: "Test add-on 2",
|
||||
creator: {name: "I made it"},
|
||||
description: "Short description",
|
||||
userPermissions: {
|
||||
origins: [],
|
||||
permissions: ["alarms", "contextMenus"],
|
||||
},
|
||||
type: "extension",
|
||||
}, {
|
||||
id: "theme1@mochi.test",
|
||||
@ -284,6 +312,10 @@ add_task(async function testFullDetails() {
|
||||
is(preview.hidden, true, "The preview is hidden");
|
||||
|
||||
let details = card.querySelector("addon-details");
|
||||
|
||||
// Check all the deck buttons are hidden.
|
||||
assertDeckHeadingButtons(details.tabGroup, ["details", "permissions"]);
|
||||
|
||||
let desc = details.querySelector(".addon-detail-description");
|
||||
is(desc.innerHTML, "Longer description<br>With brs!",
|
||||
"The full description replaces newlines with <br>");
|
||||
@ -291,7 +323,8 @@ add_task(async function testFullDetails() {
|
||||
let contrib = details.querySelector(".addon-detail-contribute");
|
||||
ok(contrib, "The contribution section is visible");
|
||||
|
||||
let rows = Array.from(details.querySelectorAll(".addon-detail-row"));
|
||||
let rows = Array.from(
|
||||
card.querySelectorAll('[name="details"] .addon-detail-row'));
|
||||
|
||||
// Auto updates.
|
||||
let row = rows.shift();
|
||||
@ -396,13 +429,17 @@ add_task(async function testMinimalExtension() {
|
||||
card = getAddonCard(doc, "addon2@mochi.test");
|
||||
let details = card.querySelector("addon-details");
|
||||
|
||||
// Check all the deck buttons are hidden.
|
||||
assertDeckHeadingButtons(details.tabGroup, ["details", "permissions"]);
|
||||
|
||||
let desc = details.querySelector(".addon-detail-description");
|
||||
is(desc.textContent, "", "There is no full description");
|
||||
|
||||
let contrib = details.querySelector(".addon-detail-contribute");
|
||||
ok(!contrib, "There is no contribution element");
|
||||
|
||||
let rows = Array.from(details.querySelectorAll(".addon-detail-row"));
|
||||
let rows = Array.from(
|
||||
card.querySelectorAll('[name="details"] .addon-detail-row'));
|
||||
|
||||
// Automatic updates.
|
||||
let row = rows.shift();
|
||||
@ -454,7 +491,11 @@ add_task(async function testDefaultTheme() {
|
||||
ok(preview, "There is a preview");
|
||||
is(preview.hidden, true, "The preview is hidden");
|
||||
|
||||
let rows = Array.from(card.querySelectorAll(".addon-detail-row"));
|
||||
// Check all the deck buttons are hidden.
|
||||
assertDeckHeadingHidden(card.details.tabGroup);
|
||||
|
||||
let rows = Array.from(
|
||||
card.querySelectorAll('[name="details"] .addon-detail-row'));
|
||||
|
||||
// Author.
|
||||
let author = rows.shift();
|
||||
@ -508,7 +549,11 @@ add_task(async function testStaticTheme() {
|
||||
is(preview.height, "90", "The height is set");
|
||||
is(preview.hidden, false, "The preview is visible");
|
||||
|
||||
let rows = Array.from(card.querySelectorAll(".addon-detail-row"));
|
||||
// Check all the deck buttons are hidden.
|
||||
assertDeckHeadingHidden(card.details.tabGroup);
|
||||
|
||||
let rows = Array.from(
|
||||
card.querySelectorAll('[name="details"] .addon-detail-row'));
|
||||
|
||||
// Automatic updates.
|
||||
let row = rows.shift();
|
||||
@ -621,3 +666,61 @@ add_task(async function testPrivateBrowsingAllowedListView() {
|
||||
await extension.unload();
|
||||
await closeView(win);
|
||||
});
|
||||
|
||||
add_task(async function testPermissions() {
|
||||
async function runTest(id, permissions) {
|
||||
let win = await loadInitialView("extension");
|
||||
let doc = win.document;
|
||||
|
||||
let card = getAddonCard(doc, id);
|
||||
ok(!card.hasAttribute("expanded"), "The list card is not expanded");
|
||||
let loaded = waitForViewLoad(win);
|
||||
card.querySelector('[action="expand"]').click();
|
||||
await loaded;
|
||||
|
||||
card = getAddonCard(doc, id);
|
||||
let {deck, tabGroup} = card.details;
|
||||
|
||||
// Check all the deck buttons are hidden.
|
||||
assertDeckHeadingButtons(tabGroup, ["details", "permissions"]);
|
||||
|
||||
let permsBtn = tabGroup.querySelector('[name="permissions"]');
|
||||
let permsShown = BrowserTestUtils.waitForEvent(deck, "view-changed");
|
||||
permsBtn.click();
|
||||
await permsShown;
|
||||
|
||||
let permsSection = card.querySelector("addon-permissions-list");
|
||||
let rows = Array.from(permsSection.querySelectorAll(".addon-detail-row"));
|
||||
|
||||
info("Check displayed permissions");
|
||||
if (permissions) {
|
||||
for (let name in permissions) {
|
||||
// Check the permission-info class to make sure it's for a permission.
|
||||
let row = rows.shift();
|
||||
ok(row.classList.contains("permission-info"),
|
||||
`There's a row for ${name}`);
|
||||
}
|
||||
} else {
|
||||
let row = rows.shift();
|
||||
is(doc.l10n.getAttributes(row).id, "addon-permissions-empty",
|
||||
"There's a message when no permissions are shown");
|
||||
}
|
||||
|
||||
info("Check learn more link");
|
||||
let row = rows.shift();
|
||||
is(row.children.length, 1, "There's one child for learn more");
|
||||
let link = row.firstElementChild;
|
||||
let rootUrl = Services.urlFormatter.formatURLPref("app.support.baseURL");
|
||||
let url = rootUrl + "extension-permissions";
|
||||
is(link.href, url, "The URL is set");
|
||||
is(link.getAttribute("target"), "_blank", "The link opens in a new tab");
|
||||
|
||||
await closeView(win);
|
||||
}
|
||||
|
||||
info("Check permissions for add-on with permission message");
|
||||
await runTest("addon1@mochi.test", ["<all_urls>", "tabs", "webNavigation"]);
|
||||
|
||||
info("Check permissions for add-on without permission messages");
|
||||
await runTest("addon2@mochi.test");
|
||||
});
|
||||
|
@ -218,8 +218,7 @@ function assertUpdateState({
|
||||
`The update check button is ${shown ? "hidden" : "shown"}`);
|
||||
|
||||
let {tabGroup} = card.details;
|
||||
is(tabGroup.hidden, !releaseNotes,
|
||||
`The tab group is ${releaseNotes ? "shown" : "hidden"}`);
|
||||
is(tabGroup.hidden, false, "The tab group is shown");
|
||||
let notesBtn = tabGroup.querySelector('[name="release-notes"]');
|
||||
is(notesBtn.hidden, !releaseNotes,
|
||||
`The release notes button is ${releaseNotes ? "shown" : "hidden"}`);
|
||||
|
Loading…
Reference in New Issue
Block a user