Fixed CORS issue
Cette révision appartient à :
@@ -1,5 +1,11 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 1.0.3 - 2025-11-01
|
||||
|
||||
- **Added**: Runtime optional host permission flow so users can authorize their own YTPTube servers without manual manifest edits.
|
||||
- **Improved**: Options page now normalizes instance URLs, records granted origins, and cleans up old host permissions when the server changes.
|
||||
- **Fixed**: Background requests to user-managed servers no longer hit CORS/address-space blocks after permissions are granted.
|
||||
|
||||
## 1.0.2 - 2025-08-12
|
||||
|
||||
- **Fixed**: Selected preset was not being sent to YTPTube API - now properly includes preset in requests
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
]
|
||||
},
|
||||
"name": "YTPTube Extension",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"description": "Add URLs to YTPTube instance",
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
@@ -15,6 +15,10 @@
|
||||
"storage",
|
||||
"notifications"
|
||||
],
|
||||
"optional_host_permissions": [
|
||||
"http://*/*",
|
||||
"https://*/*"
|
||||
],
|
||||
"homepage_url": "https://github.com/arabcoders/ytptube-extension",
|
||||
"icons": {
|
||||
"16": "icons/icon-16.png",
|
||||
|
||||
+66
-3
@@ -1,6 +1,7 @@
|
||||
// noinspection JSUnresolvedReference
|
||||
|
||||
const str_keys = ["instance_url", "preset", "template", "folder", "username", "password"]
|
||||
let storedOriginPattern = null;
|
||||
|
||||
if (typeof chrome === 'undefined') {
|
||||
let chrome = browser
|
||||
@@ -19,11 +20,46 @@ const notify = (message, no_inline) => {
|
||||
});
|
||||
}
|
||||
|
||||
const buildOriginPattern = (instanceUrl) => {
|
||||
try {
|
||||
const url = new URL(instanceUrl);
|
||||
return `${url.protocol}//${url.host}/*`;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const ensureOriginPermission = async (originPattern) => {
|
||||
if (!originPattern) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const hasPermission = await chrome.permissions.contains({origins: [originPattern]});
|
||||
if (hasPermission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return await chrome.permissions.request({origins: [originPattern]});
|
||||
};
|
||||
|
||||
const removeOriginPermission = async (originPattern) => {
|
||||
if (!originPattern) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasPermission = await chrome.permissions.contains({origins: [originPattern]});
|
||||
if (!hasPermission) {
|
||||
return;
|
||||
}
|
||||
|
||||
await chrome.permissions.remove({origins: [originPattern]});
|
||||
};
|
||||
|
||||
const testConfig = async () => {
|
||||
|
||||
document.querySelector('#error_msg').innerText = "";
|
||||
|
||||
let instance_url = document.querySelector("#instance_url").value;
|
||||
let instance_url = document.querySelector("#instance_url").value.trim();
|
||||
if (!instance_url) {
|
||||
notify("Please enter a valid YTPTube instance URL.");
|
||||
return false;
|
||||
@@ -33,6 +69,20 @@ const testConfig = async () => {
|
||||
instance_url = instance_url.slice(0, -1);
|
||||
}
|
||||
|
||||
document.querySelector("#instance_url").value = instance_url;
|
||||
|
||||
const originPattern = buildOriginPattern(instance_url);
|
||||
if (!originPattern) {
|
||||
notify("Please enter a valid YTPTube instance URL.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const granted = await ensureOriginPermission(originPattern);
|
||||
if (!granted) {
|
||||
notify("Permission to access the YTPTube instance was denied.");
|
||||
return false;
|
||||
}
|
||||
|
||||
let username = document.querySelector("#username").value;
|
||||
let password = document.querySelector("#password").value;
|
||||
|
||||
@@ -69,7 +119,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
chrome.storage.sync.get(k).then(r => document.querySelector(`#${k}`).value = r[k] || "", onError);
|
||||
});
|
||||
|
||||
chrome.storage.sync.get("showContextMenu").then(r => document.querySelector("#showContextMenu").checked = r.showContextMenu || false);
|
||||
chrome.storage.sync.get(["showContextMenu", "instance_origin"]).then(r => {
|
||||
document.querySelector("#showContextMenu").checked = r.showContextMenu || false;
|
||||
storedOriginPattern = r.instance_origin || null;
|
||||
}, onError);
|
||||
});
|
||||
|
||||
document.getElementById("ytptube_options").addEventListener("submit", async e => {
|
||||
@@ -84,7 +137,16 @@ document.getElementById("ytptube_options").addEventListener("submit", async e =>
|
||||
let data = {presets: {presets: ['default'], last_updated: 0}}
|
||||
|
||||
str_keys.forEach(key => data[key] = document.querySelector(`#${key}`).value)
|
||||
data["showContextMenu"] = showContextMenu
|
||||
data["showContextMenu"] = showContextMenu;
|
||||
|
||||
const newOriginPattern = buildOriginPattern(data.instance_url);
|
||||
if (storedOriginPattern && storedOriginPattern !== newOriginPattern) {
|
||||
await removeOriginPermission(storedOriginPattern);
|
||||
}
|
||||
|
||||
data.instance_origin = newOriginPattern;
|
||||
storedOriginPattern = newOriginPattern;
|
||||
|
||||
chrome.storage.sync.set(data);
|
||||
chrome.contextMenus.update("send-to-ytptube", {visible: showContextMenu});
|
||||
|
||||
@@ -102,3 +164,4 @@ document.getElementById("test_config").addEventListener("click", async e => {
|
||||
e.preventDefault();
|
||||
await testConfig();
|
||||
});
|
||||
|
||||
|
||||
Référencer dans un nouveau ticket
Bloquer un utilisateur