mirror of
https://github.com/GoogleChrome/chrome-extensions-samples.git
synced 2026-03-27 13:29:34 +07:00
Cookie Clearer example (#552)
Adds cookie example extension originally by Ghazale
This commit is contained in:
26
README.md
26
README.md
@@ -11,7 +11,7 @@ For more information on extensions, see [Chrome Developers](https://developer.ch
|
||||
|
||||
The directory structure is as follows:
|
||||
|
||||
* (To be added) [api/](api/) - extensions focused on a single API package
|
||||
* [api/](api/) - extensions focused on a single API package
|
||||
* (To be added) [howto/](howto/) - extensions that show how to perform a particular task
|
||||
* [tutorials/](tutorials/) - multi-step walkthroughs referenced inline in the docs
|
||||
* (To be added) [extensions/](extensions/) - full featured extensions spanning multiple API packages
|
||||
@@ -20,3 +20,27 @@ The directory structure is as follows:
|
||||
|
||||
To experiment with these samples, please clone this repo and use 'Load Unpacked Extension'.
|
||||
Read more on [Getting Started](https://developer.chrome.com/extensions/getstarted).
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Sample</th>
|
||||
<th>Calls</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="vertical-align:top;">
|
||||
Cookie Clearer <br>
|
||||
<a href="api/cookies/cookie-clearer"><code>api/cookies/cookie-clearer</code></a>
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
<ul>
|
||||
<li><a href="https://developer.chrome.com/docs/extensions/reference/cookies/#method-getAll">cookies.getAll</a></li>
|
||||
<li><a href="https://developer.chrome.com/docs/extensions/reference/cookies/#method-remove">cookies.remove</a></li>
|
||||
<li><a href="https://developer.chrome.com/docs/extensions/reference/tabs/#method-query">tabs.query</a></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
10
api/cookies/cookie-clearer/manifest.json
Normal file
10
api/cookies/cookie-clearer/manifest.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Cookie Clearer",
|
||||
"manifest_version": 3,
|
||||
"version": "1.0",
|
||||
"permissions": ["cookies"],
|
||||
"host_permissions": ["<all_urls>"],
|
||||
"action": {
|
||||
"default_popup": "popup.html"
|
||||
}
|
||||
}
|
||||
15
api/cookies/cookie-clearer/popup.html
Normal file
15
api/cookies/cookie-clearer/popup.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="popup.js" type="module"></script>
|
||||
</head>
|
||||
<body>
|
||||
<form id="control-row">
|
||||
<label for="input">Domain:</label>
|
||||
<input type="text" id="input">
|
||||
<br>
|
||||
<button id="go">Clear Cookies</button>
|
||||
</form>
|
||||
<span id="message" hidden></span>
|
||||
</body>
|
||||
</html>
|
||||
102
api/cookies/cookie-clearer/popup.js
Normal file
102
api/cookies/cookie-clearer/popup.js
Normal file
@@ -0,0 +1,102 @@
|
||||
const form = document.getElementById("control-row");
|
||||
const go = document.getElementById("go");
|
||||
const input = document.getElementById("input");
|
||||
const message = document.getElementById("message");
|
||||
|
||||
// The async IIFE is necessary because Chrome <89 does not support top level await.
|
||||
(async function initPopupWindow() {
|
||||
let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||
|
||||
if (tab?.url) {
|
||||
try {
|
||||
let url = new URL(tab.url);
|
||||
input.value = url.hostname;
|
||||
} catch {}
|
||||
}
|
||||
|
||||
input.focus();
|
||||
})();
|
||||
|
||||
form.addEventListener("submit", handleFormSubmit);
|
||||
|
||||
async function handleFormSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
clearMessage();
|
||||
|
||||
let url = stringToUrl(input.value);
|
||||
if (!url) {
|
||||
setMessage("Invalid URL");
|
||||
return;
|
||||
}
|
||||
|
||||
let message = await deleteDomainCookies(url.hostname);
|
||||
setMessage(message);
|
||||
}
|
||||
|
||||
function stringToUrl(input) {
|
||||
// Start with treating the provided value as a URL
|
||||
try {
|
||||
return new URL(input);
|
||||
} catch {}
|
||||
// If that fails, try assuming the provided input is an HTTP host
|
||||
try {
|
||||
return new URL("http://" + input);
|
||||
} catch {}
|
||||
// If that fails ¯\_(ツ)_/¯
|
||||
return null;
|
||||
}
|
||||
|
||||
async function deleteDomainCookies(domain) {
|
||||
let cookiesDeleted = 0;
|
||||
try {
|
||||
const cookies = await chrome.cookies.getAll({ domain });
|
||||
|
||||
if (cookies.length === 0) {
|
||||
return "No cookies found";
|
||||
}
|
||||
|
||||
let pending = cookies.map(deleteCookie);
|
||||
await Promise.all(pending);
|
||||
|
||||
cookiesDeleted = pending.length;
|
||||
} catch (error) {
|
||||
return `Unexpected error: ${error.message}`;
|
||||
}
|
||||
|
||||
return `Deleted ${cookiesDeleted} cookie(s).`;
|
||||
}
|
||||
|
||||
function deleteCookie(cookie) {
|
||||
// Cookie deletion is largely modeled off of how deleting cookies works when using HTTP headers.
|
||||
// Specific flags on the cookie object like `secure` or `hostOnly` are not exposed for deletion
|
||||
// purposes. Instead, cookies are deleted by URL, name, and storeId. Unlike HTTP headers, though,
|
||||
// we don't have to delete cookies by setting Max-Age=0; we have a method for that ;)
|
||||
//
|
||||
// To remove cookies set with a Secure attribute, we must provide the correct protocol in the
|
||||
// details object's `url` property.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Secure
|
||||
const protocol = cookie.secure ? "https:" : "http:";
|
||||
|
||||
// Note that the final URL may not be valid. The domain value for a standard cookie is prefixed
|
||||
// with a period (invalid) while cookies that are set to `cookie.hostOnly == true` do not have
|
||||
// this prefix (valid).
|
||||
// https://developer.chrome.com/docs/extensions/reference/cookies/#type-Cookie
|
||||
const cookieUrl = `${protocol}//${cookie.domain}${cookie.path}`;
|
||||
|
||||
return chrome.cookies.remove({
|
||||
url: cookieUrl,
|
||||
name: cookie.name,
|
||||
storeId: cookie.storeId,
|
||||
});
|
||||
}
|
||||
|
||||
function setMessage(str) {
|
||||
message.textContent = str;
|
||||
message.hidden = false;
|
||||
}
|
||||
|
||||
function clearMessage() {
|
||||
message.hidden = true;
|
||||
message.textContent = "";
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
{
|
||||
"name": "My Bookmarks",
|
||||
"version": "1.1",
|
||||
"description": "A browser action with a popup dump of all bookmarks, including search, add, edit and delete.",
|
||||
"version": "1.1",
|
||||
"manifest_version": 2,
|
||||
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlegJOMs1YaY52Thy0EG1ACPm2XGj2+DH2NinxeWZ1qVhihlkzkBT5+91pEC/gRkVXB+OUHrZxSLmQeKxJSVp8uQtve1+z6q4INSqVb7ggpqrHV4+j8yq2B5hq0qEA3avIQ/kU1eRlW0apKw6KqDZ5qt/ab6tztN/XZAXPe0dd1gq55B1/1ZjMqoLuKRjifxYd1h9XANaZA4VnE38Mv9f2G3VyydiLsRHz4UoYJPLy3rrwKJtcwokFDMzLZZFoNuVJvogwd9V8mDIajnX811pqmO898Fhlci3FVtcIvvEJTl3WFSeMt3emmEmW33mU1tlSI+PmNL++uK0FvDx9nQMyQIDAQAB",
|
||||
"permissions": [
|
||||
"bookmarks"
|
||||
],
|
||||
@@ -10,6 +12,5 @@
|
||||
"default_icon": "icon.png",
|
||||
"default_popup": "popup.html"
|
||||
},
|
||||
"manifest_version": 2,
|
||||
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<script src="popup.js"></script>
|
||||
</head>
|
||||
<body style="width: 400px">
|
||||
<div>Search Bookmarks: <input id="search"></div>
|
||||
<div>Search Bookmarks (MV2): <input id="search"></div>
|
||||
<div id="bookmarks"></div>
|
||||
<div id="editdialog"></div>
|
||||
<div id="deletedialog"></div>
|
||||
|
||||
BIN
tutorials/getting-started-images.zip
Normal file
BIN
tutorials/getting-started-images.zip
Normal file
Binary file not shown.
BIN
tutorials/getting-started.zip
Normal file
BIN
tutorials/getting-started.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user