Expand permissions test cases

Include support for host permissions and data permissions.
This commit is contained in:
Simeon Vincent
2025-12-10 12:14:29 -08:00
parent 4307cc14e8
commit 1d76ddf353
9 changed files with 247 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
{
"parserOptions": {
"ecmaVersion": 8
}
}

View File

@@ -0,0 +1,9 @@
# Permissions Example
## What it does
An example using the permissions API to grant and revoke an optional permission.
## What it shows
How to request a permission, catching error conditions from the request and querying the permissions API.

View File

@@ -0,0 +1,7 @@
self.browser ??= self.chrome;
browser.action.onClicked.addListener(() => {
browser.tabs.create({
url: browser.runtime.getURL("page.html")
});
});

6
permissions-mv3/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

1
permissions-mv3/icon.svg Normal file
View File

@@ -0,0 +1 @@
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 500 500" height="500px" id="Layer_1" version="1.1" viewBox="0 0 500 500" width="500px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path clip-rule="evenodd" d="M131.889,150.061v63.597h-27.256 c-20.079,0-36.343,16.263-36.343,36.342v181.711c0,20.078,16.264,36.34,36.343,36.34h290.734c20.078,0,36.345-16.262,36.345-36.34 V250c0-20.079-16.267-36.342-36.345-36.342h-27.254v-63.597c0-65.232-52.882-118.111-118.112-118.111 S131.889,84.828,131.889,150.061z M177.317,213.658v-63.597c0-40.157,32.525-72.685,72.683-72.685 c40.158,0,72.685,32.528,72.685,72.685v63.597H177.317z M213.658,313.599c0-20.078,16.263-36.341,36.342-36.341 s36.341,16.263,36.341,36.341c0,12.812-6.634,24.079-16.625,30.529c0,0,3.55,21.446,7.542,46.699 c0,7.538-6.087,13.625-13.629,13.625h-27.258c-7.541,0-13.627-6.087-13.627-13.625l7.542-46.699 C220.294,337.678,213.658,326.41,213.658,313.599z" fill="#010101" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,39 @@
{
"manifest_version": 3,
"name": "Permissions Example (MV3)",
"description": "Permissions Example (MV3)",
"version": "1.1",
"background": {
"scripts": ["background.js"],
"service_worker": "background.js"
},
"icons": {
"48": "icon.svg"
},
"action": {
"default_title": "Permissions Example",
"default_icon": "icon.svg"
},
"permissions": [
"tabs"
],
"optional_permissions": [
"history"
],
"host_permissions": [
"*://*.example.com/*"
],
"optional_host_permissions": [
"*://*.example.org/*"
],
"browser_specific_settings": {
"gecko": {
"strict_min_version": "55.0a2",
"data_collection_permissions": {
"required": ["browsingActivity"],
"optional": ["technicalAndInteraction", "locationInfo"]
}
}
}
}

27
permissions-mv3/page.css Normal file
View File

@@ -0,0 +1,27 @@
h4 {
margin-top: 2rem;
}
p.bg-danger, p.bg-success, p.bg-warning {
padding: 1em;
}
#grants tr > * {
padding: 5px 10px;
border: 1px solid #ddd;
}
#grants th {
background-color: #eee;
}
#permissions, #host-permissions, #data-permissions {
&:empty:before {
content: "none";
font-style: italic;
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
background-color: #f9f2f4;
border-radius: 4px;
font-family: monospace;
}
}

95
permissions-mv3/page.html Normal file
View File

@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Permissions Example (MV3)</title>
<link rel="stylesheet" href="bootstrap.min.css"/>
<link rel="stylesheet" href="page.css"/>
</head>
<body>
<div class="container">
<h3>Permissions Example</h3>
<p><strong>Current grants</strong></p>
<table id="grants">
<tbody>
<tr>
<th>permissions</th>
<td><span id="permissions"></span></td>
</tr>
<tr>
<th>origins</th>
<td><span id="host-permissions"></span></td>
</tr>
<tr>
<th>data_collection</th>
<td><span id="data-permissions"></span></td>
</tr>
</tbody>
</table><br>
<p style="display: none" id="result"></p>
<h4>Permissions</h4>
<ul>
<li>The <code>tabs</code> permission has been <b>granted</b> on install.</li>
<li>The <code>history</code> permission is an optional permission that can be
<a href="#" class="permission" data-permission-type="permissions" data-permission="history" data-action="grant">granted</a> or
<a href="#" class="permission" data-permission-type="permissions" data-permission="history" data-action="revoke">revoked</a>.
</li>
<li>The <code>cookies</code> permission cannot be
<a href="#" class="permission" data-permission-type="permissions" data-permission="cookies" data-action="grant">granted</a>,
because it was not included in the <code>optional_permissions</code> manifest key.
</li>
<li>The <code>foo</code> permission cannot be
<a href="#" class="permission" data-permission-type="permissions" data-permission="foo" data-action="grant">granted</a>,
because it is not a valid permission name.
</li>
</ul>
<h4>Host permissions</h4>
<ul>
<li>The <code>*://*.example.com/*</code> host permission is required, so it was <b>granted</b> on install. It can be
<a href="#" class="permission" data-permission-type="origins" data-permission="*://*.example.com/*" data-action="grant">granted</a> or
<a href="#" class="permission" data-permission-type="origins" data-permission="*://*.example.com/*" data-action="revoke">revoked</a> after installation.
</li>
<li>The <code>*://*.example.org/*</code> host permission is optional and can be
<a href="#" class="permission" data-permission-type="origins" data-permission="*://*.example.org/*" data-action="grant">granted</a> or
<a href="#" class="permission" data-permission-type="origins" data-permission="*://*.example.org/*" data-action="revoke">revoked</a>.
</li>
<li>The <code>https://www.example.org/*</code> host permission can be
<a href="#" class="permission" data-permission-type="origins" data-permission="https://www.example.org/*" data-action="grant">granted</a> or
<a href="#" class="permission" data-permission-type="origins" data-permission="https://www.example.org/*" data-action="revoke">revoked</a>,
because it is matched by the <code>*://*.example.org/*</code> optional host permission,
</li>
<li>The <code>https://mozilla.org/*</code> host permission cannot be
<a href="#" class="permission" data-permission-type="origins" data-permission="https://mozilla.org/*" data-action="grant">granted</a>,
because it (or a broader pattern) was not declared in the manifest.
</li>
<li>The <code>bar</code> host permission cannot be
<a href="#" class="permission" data-permission-type="origins" data-permission="bar" data-action="grant">granted</a>,
because it is not a valid host permission.
</li>
</ul>
<h4>Data permissions</h4>
<ul>
<li>The <code>browsingActivity</code> data permission is required, so it was <b>granted</b> on install. It cannot be
<a href="#" class="permission" data-permission-type="data_collection" data-permission="browsingActivity" data-action="revoke">revoked</a> (the call succeeds, but the grant does not change).
</li>
<li>The <code>technicalAndInteraction</code> data permission is special. It must be declared as optional, but it is granted by default when installed normally (not as a temporary add-on). It can be
<a href="#" class="permission" data-permission-type="data_collection" data-permission="technicalAndInteraction" data-action="grant">granted</a> or
<a href="#" class="permission" data-permission-type="data_collection" data-permission="technicalAndInteraction" data-action="revoke">revoked</a> after installation.
</li>
<li>The <code>locationInfo</code> data permission is optional, so it can be
<a href="#" class="permission" data-permission-type="data_collection" data-permission="locationInfo" data-action="grant">granted</a> or
<a href="#" class="permission" data-permission-type="data_collection" data-permission="locationInfo" data-action="revoke">revoked</a> after installation.
</li>
<li>The <code>baz</code> data permission cannot be
<a href="#" class="permission" data-permission-type="data_collection" data-permission="baz" data-action="grant">granted</a>,
because it is not a valid data permission name.
</li>
</ul>
</div>
<script src="page.js"></script>
</body>
</html>

58
permissions-mv3/page.js Normal file
View File

@@ -0,0 +1,58 @@
let isDataCollectionSupported;
async function updatePermissions() {
const permissions = await browser.permissions.getAll();
isDataCollectionSupported ??= Array.isArray(permissions.data_collection);
document.getElementById('permissions').innerText = permissions.permissions.join(', ');
document.getElementById('host-permissions').innerText = permissions.origins.join(', ');
document.getElementById('data-permissions').innerText = permissions.data_collection.join(', ');
return permissions;
}
async function processChange(event) {
let action = event.target.dataset.action;
let permission = event.target.dataset.permission;
let type = event.target.dataset.permissionType;
let result = document.getElementById('result');
const change = {
permissions: [],
origins: [],
data_collection: [],
};
if (type in change) {
change[type].push(permission);
}
if (action === 'grant') {
try {
const requestResult = await browser.permissions.request(change);
result.className = 'bg-success';
result.textContent = `Call successful. Request ${requestResult ? 'granted' : 'denied'}.`;
} catch (err) {
// Catch the case where the permission cannot be granted.
result.className = 'bg-warning';
result.textContent = err.message;
}
} else {
try {
await browser.permissions.remove(change);
result.className = 'bg-success';
result.textContent = 'Call successful. Permissions removed.';
} catch (err) {
// Catch the case where the permission is completely wrong.
result.className = 'bg-danger';
result.textContent = err.message;
}
}
result.style.display = 'block';
await updatePermissions();
event.preventDefault();
}
for (let element of document.querySelectorAll('.permission, .host-permission, .data-permission')) {
element.addEventListener('click', processChange);
}
updatePermissions();