Skip to content

Commit c7030e7

Browse files
AprilSylphmarcustyphoon
andauthoredJan 19, 2025··
feat: upgrade to Manifest V3 (#101)
Co-authored-by: Marcus <[email protected]>
1 parent 7d51184 commit c7030e7

10 files changed

+51
-59
lines changed
 

‎.eslintrc.json

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
{
22
"env": {
33
"browser": true,
4-
"es2021": true,
5-
"webextensions": true
4+
"es2021": true
65
},
76
"extends": [
87
"semistandard"
98
],
9+
"globals": {
10+
"chrome": "readonly"
11+
},
1012
"parserOptions": {
1113
"ecmaVersion": 12
1214
},
@@ -19,8 +21,5 @@
1921
"no-extend-native": "off"
2022
}
2123
}
22-
],
23-
"ignorePatterns": [
24-
"*.min.js"
2524
]
2625
}

‎.github/workflows/publish.yml

-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ jobs:
2929
env:
3030
WEB_EXT_API_KEY: ${{ secrets.WEB_EXT_API_KEY }}
3131
WEB_EXT_API_SECRET: ${{ secrets.WEB_EXT_API_SECRET }}
32-
WEB_EXT_ID: ${{ secrets.WEB_EXT_ID }}
3332
chrome:
3433
name: Chrome
3534
runs-on: ubuntu-latest

‎dev/copy-libs.sh

-1
This file was deleted.

‎package-lock.json

+1-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
"web-ext": "^7.12.0"
2121
},
2222
"dependencies": {
23-
"normalize.css": "^8.0.1",
24-
"webextension-polyfill": "^0.12.0"
23+
"normalize.css": "^8.0.1"
2524
},
2625
"webExt": {
2726
"sourceDir": "src/",

‎src/background.js

+29-20
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
browser.browserAction.onClicked.addListener(() => browser.runtime.openOptionsPage());
1+
chrome.action.onClicked.addListener(() => chrome.runtime.openOptionsPage());
22

33
const handledRequests = new Map();
44

5-
browser.webRequest.onBeforeRequest.addListener(({ method, requestBody, requestId, timeStamp, url }) => {
5+
chrome.webRequest.onBeforeRequest.addListener(({ method, requestBody, requestId, timeStamp, url }) => {
66
if (handledRequests.has(requestId)) {
77
return;
88
} else {
99
handledRequests.set(requestId, timeStamp);
10+
chrome.storage.session.set({ [requestId]: timeStamp });
1011
}
1112

1213
if (['POST', 'PUT'].includes(method) === false) { return; }
@@ -26,7 +27,7 @@ browser.webRequest.onBeforeRequest.addListener(({ method, requestBody, requestId
2627
const isPrivateAnswer = state === undefined && isPrivate === true && layout.some(({ type }) => type === 'ask');
2728

2829
if (hasContent && (isAsk || isPrivateAnswer)) {
29-
browser.storage.local.set({ [timeStamp]: { recipient, content, layout } });
30+
chrome.storage.local.set({ [timeStamp]: { recipient, content, layout } });
3031
}
3132
}, {
3233
urls: [
@@ -38,11 +39,12 @@ browser.webRequest.onBeforeRequest.addListener(({ method, requestBody, requestId
3839
'requestBody'
3940
]);
4041

41-
browser.webRequest.onBeforeRequest.addListener(({ method, requestBody, requestId, timeStamp }) => {
42+
chrome.webRequest.onBeforeRequest.addListener(({ method, requestBody, requestId, timeStamp }) => {
4243
if (handledRequests.has(requestId)) {
4344
return;
4445
} else {
4546
handledRequests.set(requestId, timeStamp);
47+
chrome.storage.session.set({ [requestId]: timeStamp });
4648
}
4749

4850
if (method !== 'POST') { return; }
@@ -53,7 +55,7 @@ browser.webRequest.onBeforeRequest.addListener(({ method, requestBody, requestId
5355
const parsedData = JSON.parse(decodedData);
5456
const { question, recipient } = parsedData;
5557

56-
browser.storage.local.set({
58+
chrome.storage.local.set({
5759
[timeStamp]: {
5860
recipient,
5961
content: [{ type: 'text', text: question, formatting: [] }],
@@ -67,11 +69,12 @@ browser.webRequest.onBeforeRequest.addListener(({ method, requestBody, requestId
6769
'requestBody'
6870
]);
6971

70-
browser.webRequest.onBeforeRequest.addListener(({ documentUrl, method, requestBody: { formData }, requestId, timeStamp, url }) => {
72+
chrome.webRequest.onBeforeRequest.addListener(({ documentUrl, method, requestBody: { formData }, requestId, timeStamp, url }) => {
7173
if (handledRequests.has(requestId)) {
7274
return;
7375
} else {
7476
handledRequests.set(requestId, timeStamp);
77+
chrome.storage.session.set({ [requestId]: timeStamp });
7578
}
7679

7780
if (method !== 'POST') { return; }
@@ -86,7 +89,7 @@ browser.webRequest.onBeforeRequest.addListener(({ documentUrl, method, requestBo
8689
recipientUrl = `${protocol}//${pathname.replace('/ask_form/', '')}/`;
8790
}
8891

89-
browser.storage.local.set({
92+
chrome.storage.local.set({
9093
[timeStamp]: {
9194
recipientUrl,
9295
content: formData['post[one]'].map(text => ({ type: 'text', text, formatting: [] })),
@@ -100,12 +103,15 @@ browser.webRequest.onBeforeRequest.addListener(({ documentUrl, method, requestBo
100103
'requestBody'
101104
]);
102105

103-
browser.webRequest.onErrorOccurred.addListener(async ({ requestId }) => {
104-
if (handledRequests.has(requestId)) {
105-
const timeStamp = handledRequests.get(requestId);
106-
const { [timeStamp]: item } = await browser.storage.local.get(timeStamp.toString());
106+
chrome.webRequest.onErrorOccurred.addListener(async ({ requestId }) => {
107+
const timeStamp =
108+
handledRequests.get(requestId) ??
109+
await chrome.storage.session.get(requestId).then(({ [requestId]: timeStamp }) => timeStamp);
110+
111+
if (timeStamp) {
112+
const { [timeStamp]: item } = await chrome.storage.local.get(timeStamp.toString());
107113
item.error = true;
108-
browser.storage.local.set({ [timeStamp]: item });
114+
chrome.storage.local.set({ [timeStamp]: item });
109115
}
110116
}, {
111117
urls: [
@@ -116,12 +122,15 @@ browser.webRequest.onErrorOccurred.addListener(async ({ requestId }) => {
116122
]
117123
});
118124

119-
browser.webRequest.onCompleted.addListener(async ({ requestId, statusCode }) => {
120-
if (/[45]\d\d/.test(statusCode) && handledRequests.has(requestId)) {
121-
const timeStamp = handledRequests.get(requestId);
122-
const { [timeStamp]: item } = await browser.storage.local.get(timeStamp.toString());
125+
chrome.webRequest.onCompleted.addListener(async ({ requestId, statusCode }) => {
126+
const timeStamp =
127+
handledRequests.get(requestId) ??
128+
await chrome.storage.session.get(requestId).then(({ [requestId]: timeStamp }) => timeStamp);
129+
130+
if (/[45]\d\d/.test(statusCode) && timeStamp) {
131+
const { [timeStamp]: item } = await chrome.storage.local.get(timeStamp.toString());
123132
item.error = true;
124-
browser.storage.local.set({ [timeStamp]: item });
133+
chrome.storage.local.set({ [timeStamp]: item });
125134
}
126135
}, {
127136
urls: [
@@ -132,10 +141,10 @@ browser.webRequest.onCompleted.addListener(async ({ requestId, statusCode }) =>
132141
]
133142
});
134143

135-
browser.storage.onChanged.addListener(async (changes, areaName) => {
136-
const storageObject = await browser.storage[areaName].get();
144+
chrome.storage.onChanged.addListener(async (changes, areaName) => {
145+
const storageObject = await chrome.storage[areaName].get();
137146
const storageKeys = Object.keys(storageObject).sort((a, b) => a - b);
138147
const keysToRemove = storageKeys.splice(0, storageKeys.length - 512);
139148

140-
if (keysToRemove.length > 0) browser.storage[areaName].remove(keysToRemove);
149+
if (keysToRemove.length > 0) chrome.storage[areaName].remove(keysToRemove);
141150
});

‎src/lib/browser-polyfill.min.js

-8
This file was deleted.

‎src/manifest.json

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"manifest_version": 2,
2+
"manifest_version": 3,
33
"name": "Outbox for Tumblr",
44
"version": "1.0.4",
55

@@ -10,7 +10,7 @@
1010
"128": "icons/128.png"
1111
},
1212

13-
"browser_action": {
13+
"action": {
1414
"default_icon": {
1515
"16": "icons/16.png",
1616
"48": "icons/48.png",
@@ -19,27 +19,30 @@
1919
},
2020

2121
"background": {
22-
"scripts": [ "lib/browser-polyfill.min.js", "background.js" ],
23-
"persistent": true
22+
"service_worker": "background.js",
23+
"scripts": [ "background.js" ]
2424
},
2525
"homepage_url": "https://github.com/AprilSylph/Outbox-for-Tumblr#readme",
2626
"permissions": [
2727
"storage",
28-
"webRequest",
28+
"webRequest"
29+
],
30+
"host_permissions": [
2931
"*://*.tumblr.com/*"
3032
],
31-
"optional_permissions": [
33+
"optional_host_permissions": [
3234
"<all_urls>"
3335
],
3436
"options_ui": {
3537
"page": "outbox.html",
3638
"open_in_tab": true
3739
},
3840

39-
"minimum_chrome_version": "80",
41+
"minimum_chrome_version": "121",
4042
"browser_specific_settings": {
4143
"gecko": {
42-
"strict_min_version": "74.0a1"
44+
"id": "{ff20bd71-d65d-439f-b48a-c12627f3f2a3}",
45+
"strict_min_version": "128.0"
4346
}
4447
}
4548
}

‎src/outbox.html

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
<link rel="stylesheet" href="lib/npf.css">
1010
<link rel="stylesheet" href="outbox.css">
1111
<link rel="stylesheet" href="https://assets.tumblr.com/fonts/favorit/stylesheet.css">
12-
<script src="lib/browser-polyfill.min.js"></script>
1312
<script type="module" src="outbox.js"></script>
1413
<script type="module" src="lib/navigation.js"></script>
1514
</head>

‎src/outbox.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const onDeleteButtonClicked = ({ currentTarget }) => {
2121

2222
const articleElement = currentTarget.closest('article');
2323
const { timestamp } = articleElement.dataset;
24-
browser.storage.local.remove(timestamp);
24+
chrome.storage.local.remove(timestamp);
2525
};
2626

2727
const constructItem = ([timestamp, { recipient, recipientUrl, error, content, layout }]) => {
@@ -84,7 +84,7 @@ const constructItem = ([timestamp, { recipient, recipientUrl, error, content, la
8484
};
8585

8686
const updateExportDownload = () => {
87-
browser.storage.local.get()
87+
chrome.storage.local.get()
8888
.then(storageObject => {
8989
const storageKeys = Object.keys(storageObject);
9090
mainElement.dataset.showLimitWarning = storageKeys.length >= 512;
@@ -151,15 +151,15 @@ const onImportInputChanged = async ({ currentTarget }) => {
151151
if (!keysAreValid) throw new Error('Imported data contains invalid keys.');
152152
if (!valuesAreValid) throw new Error('Imported data contains invalid values.');
153153

154-
await browser.storage.local.set(storageObject);
154+
await chrome.storage.local.set(storageObject);
155155
} catch (exception) {
156156
window.alert(exception.toString());
157157
} finally {
158158
currentTarget.value = currentTarget.defaultValue;
159159
}
160160
};
161161

162-
browser.storage.local.get()
162+
chrome.storage.local.get()
163163
.then(storageObject => Object.entries(storageObject).sort(([a], [b]) => a - b).reverse())
164164
.then(items => mainElement.append(...items.map(constructItem)))
165165
.catch(exception => {
@@ -171,7 +171,7 @@ browser.storage.local.get()
171171
})
172172
.finally(() => mainElement.setAttribute('aria-busy', false));
173173

174-
browser.storage.onChanged.addListener(onStorageChanged);
174+
chrome.storage.onChanged.addListener(onStorageChanged);
175175
updateExportDownload();
176176

177177
importInput.addEventListener('change', onImportInputChanged);

0 commit comments

Comments
 (0)
Please sign in to comment.