Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tabs permission overhaul #321

Merged
merged 3 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
# Changelog

## v3.1.11
## v3.1.12

<!--Releasenotes start-->
- Removed "tabs" permission from the extension, enhancing privacy.
<!--Releasenotes end-->

## v3.1.11

- Changed the default settings to not open shuffled videos in a new tab.
- Moved the informative text about remaining YouTube API quota to the advanced settings menu.
- Updated the welcome page for a better experience.
<!--Releasenotes end-->

## v3.1.10

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "random-youtube-video",
"version": "3.1.11",
"version": "3.1.12",
"description": "Customize, shuffle and play random videos from any YouTube channel.",
"scripts": {
"dev": "concurrently \"npm run dev:chromium\" \"npm run dev:firefox\"",
Expand Down
3 changes: 2 additions & 1 deletion src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async function initExtension() {
await setSyncStorageValue("previousVersion", manifestData.version);
const welcomeUrl = chrome.runtime.getURL("html/welcome.html");
await chrome.tabs.create({ url: welcomeUrl });
} else if (isFirefox && !await browser.permissions.contains({ permissions: ["tabs"], origins: ["*://*.youtube.com/*"] })) {
} else if (isFirefox && !await browser.permissions.contains({ origins: ["*://*.youtube.com/*"] })) {
console.log("The extension is running in Firefox and does not have the required permissions.");
const welcomeUrl = chrome.runtime.getURL("html/welcome.html");
await chrome.tabs.create({ url: welcomeUrl });
Expand Down Expand Up @@ -360,6 +360,7 @@ function rot13(message, encrypt) {
}

// Get all tabs whose url is a YouTube page. Content scripts cannot access the chrome.tabs API
// We are allowed to query tabs for which we have host permissions even without the tabs permission
async function getAllYouTubeTabs() {
return await chrome.tabs.query({ url: "*://*.youtube.com/*" });
}
Expand Down
6 changes: 5 additions & 1 deletion src/html/htmlUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,13 @@ function adjustParentContainerHeight(childElement, heightChange) {
}

// ----- Tab interaction -----
// For Chromium, we are not allowed to query our own tabs, so this will always return mustOpenTab = true for Chromium with the current use cases
// This is not a big problem, as we only use it to query if the changelog page is already open, or the shuffling page had an error and should be automatically closed
export async function tryFocusingTab(tabUrl) {
let mustOpenTab = true;
let tabs = await chrome.tabs.query({});
// Only query for the requested URL (pattern), as we have not been granted the tabs permission which would allow querying all tabs
let tabs = await chrome.tabs.query({ url: tabUrl });

for (let i = 0; i <= tabs.length - 1; i++) {
if (tabs[i].url === tabUrl) {
// An instance of the page already exists, so don't create a new one
Expand Down
16 changes: 8 additions & 8 deletions src/html/popup/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,24 +368,24 @@ async function setPopupDomElementEventListeners(domElements) {

// Popup shuffle button
domElements.popupShuffleButton.addEventListener("click", async function () {
const shufflingPage = chrome.runtime.getURL("html/shufflingPage.html");
const shufflingPageUrl = chrome.runtime.getURL("html/shufflingPage.html");

// Get the status of the shufflingPage, if it exists
const shufflingPageIsShuffling = await chrome.runtime.sendMessage({ command: "getShufflingPageShuffleStatus" });
// If the page is not shuffling, close it if it exists, as that means an error was encountered
if (!shufflingPageIsShuffling) {
const tabs = await chrome.tabs.query({});
const tabs = await chrome.tabs.query({ url: shufflingPageUrl });
for (const tab of tabs) {
if (tab.url === shufflingPage) {
if (tab.url === shufflingPageUrl) {
chrome.tabs.remove(tab.id);
break;
}
}
}

let mustOpenTab = await tryFocusingTab(shufflingPage);
let mustOpenTab = await tryFocusingTab(shufflingPageUrl);
if (mustOpenTab) {
await chrome.tabs.create({ url: shufflingPage });
await chrome.tabs.create({ url: shufflingPageUrl });
}

// Close the popup
Expand Down Expand Up @@ -459,11 +459,11 @@ async function setPopupDomElementEventListeners(domElements) {
// When the popup is opened, checks if an overlay should be shown
async function determineOverlayVisibility(domElements) {
// If we are on Firefox and have not been granted permissions, show the overlay and then ask for permissions
if (isFirefox && !await browser.permissions.contains({ permissions: ["tabs"], origins: ["*://*.youtube.com/*"] })) {
if (isFirefox && !await browser.permissions.contains({ origins: ["*://*.youtube.com/*"] })) {
domElements.firefoxPermissionsNeededDiv.classList.remove("hidden");

domElements.firefoxPermissionsNeededButton.addEventListener("click", async function () {
browser.permissions.request({ permissions: ["tabs"], origins: ["*://*.youtube.com/*"] });
browser.permissions.request({ origins: ["*://*.youtube.com/*"] });
window.close();
});
} else {
Expand Down Expand Up @@ -506,7 +506,7 @@ async function updateDomElementsDependentOnChannel(domElements) {
updateChannelSettingsDropdownMenu(domElements);

// ----- Popup shuffle button -----
domElements.popupShuffleButton.innerText = configSync.currentChannelName ? `Shuffle from: ${configSync.currentChannelName}`: "This will be a shuffle button!";
domElements.popupShuffleButton.innerText = configSync.currentChannelName ? `Shuffle from: ${configSync.currentChannelName}` : "This will be a shuffle button!";
}

async function updateChannelSettingsDropdownMenu(domElements) {
Expand Down
6 changes: 3 additions & 3 deletions src/html/shufflingPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ async function setDomElementEventListeners(domElements) {
domElements.viewChangelogButton.addEventListener("click", async function () {
await setSyncStorageValue("lastViewedChangelogVersion", chrome.runtime.getManifest().version);

const tabUrl = chrome.runtime.getURL("html/changelog.html");
let mustOpenTab = await tryFocusingTab(tabUrl);
const changelogUrl = chrome.runtime.getURL("html/changelog.html");
let mustOpenTab = await tryFocusingTab(changelogUrl);
if (mustOpenTab) {
window.open(tabUrl, "_blank");
window.open(changelogUrl, "_blank");
}
});
}
Expand Down
28 changes: 13 additions & 15 deletions src/html/welcome.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,17 @@ const isFirefox = typeof browser !== "undefined";
const domElements = getDomElements();

let mayShowReloadAllYouTubePagesDiv = false;
chrome.tabs.query({}, function (tabs) {
for (let i = 0; i <= tabs.length - 1; i++) {
if (tabs[i].url.split("/")[2]?.includes("youtube")) {
mayShowReloadAllYouTubePagesDiv = true;
// Immediately show if we are not waiting for Firefox permissions
if (!isFirefox) {
domElements.needToReloadYouTubePagesDiv.classList.remove("hidden");
}
break;
let tabs = await chrome.runtime.sendMessage({ command: "getAllYouTubeTabs" }) ?? [];
for (let i = 0; i <= tabs.length - 1; i++) {
if (tabs[i].url.split("/")[2]?.includes("youtube")) {
mayShowReloadAllYouTubePagesDiv = true;
// Immediately show if we are not waiting for Firefox permissions
if (!isFirefox || await browser.permissions.contains({ origins: ["*://*.youtube.com/*"] })) {
domElements.needToReloadYouTubePagesDiv.classList.remove("hidden");
}
break;
}
});
}

// --- Set headers ---
const currentVersion = chrome.runtime.getManifest().version_name ?? chrome.runtime.getManifest().version;
Expand Down Expand Up @@ -66,7 +65,7 @@ function getDomElements() {
// Set event listeners for DOM elements
async function setPopupDomElementEventListeners(domElements) {
// Firefox permissions button
if (isFirefox && !await browser.permissions.contains({ permissions: ["tabs"], origins: ["*://*.youtube.com/*"] })) {
if (isFirefox && !await browser.permissions.contains({ origins: ["*://*.youtube.com/*"] })) {
domElements.firefoxPermissionsDiv.classList.remove("hidden");

// This is so important that we will use a browser alert window to make sure the user sees and acknowledges it
Expand All @@ -76,7 +75,7 @@ async function setPopupDomElementEventListeners(domElements) {
domElements.giveFirefoxPermissionsButton.addEventListener("click", async function () {
await requestFirefoxPermissions();
// If permissions were not granted we must ask again, without them the extension does not work
if (!await browser.permissions.contains({ permissions: ["tabs"], origins: ["*://*.youtube.com/*"] })) {
if (!await browser.permissions.contains({ origins: ["*://*.youtube.com/*"] })) {
alert("You need to grant the extension permission to run on YouTube in order to use it. Please grant permissions.")
} else {
domElements.firefoxPermissionsDiv.classList.add("hidden");
Expand All @@ -89,7 +88,7 @@ async function setPopupDomElementEventListeners(domElements) {

// Reload all YouTube pages button
domElements.reloadAllYouTubePagesButton.addEventListener("click", async function () {
let tabs = await chrome.tabs.query({});
let tabs = await chrome.runtime.sendMessage({ command: "getAllYouTubeTabs" }) ?? [];
for (let i = 0; i <= tabs.length - 1; i++) {
if (tabs[i].url.split("/")[2]?.includes("youtube")) {
chrome.tabs.reload(tabs[i].id);
Expand Down Expand Up @@ -125,8 +124,7 @@ async function setPopupDomElementEventListeners(domElements) {

async function requestFirefoxPermissions() {
const permissionsToRequest = {
permissions: ["tabs"],
origins: ["*://*.youtube.com/*"]
}
await browser.permissions.request(permissionsToRequest);
}
}
3 changes: 0 additions & 3 deletions static/firefox-manifest-extra.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
"id": "RandomYouTubeVideo@NikkelM"
}
},
"optional_permissions": [
"tabs"
],
"options_ui": {
"page": "html/popup.html"
}
Expand Down
10 changes: 6 additions & 4 deletions static/manifest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "Random YouTube Video",
"description": "Customize, shuffle and play random videos from any YouTube channel.",
"version": "3.1.11",
"version_name": "3.1.11",
"version": "3.1.12",
"version_name": "3.1.12",
"manifest_version": 3,
"content_scripts": [
{
Expand All @@ -16,8 +16,10 @@
}
],
"permissions": [
"storage",
"tabs"
"storage"
],
"host_permissions": [
"*://*.youtube.com/*"
],
"action": {
"default_popup": "html/popup.html",
Expand Down
Loading