-
Notifications
You must be signed in to change notification settings - Fork 2
Manifest v3 #54
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
base: main
Are you sure you want to change the base?
Manifest v3 #54
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="utf-8" /> | ||
| <title>RadioWave Audio Player</title> | ||
| </head> | ||
| <body> | ||
| <script src="offscreen.js"></script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,22 @@ | ||||||||||
| "use strict"; | ||||||||||
|
|
||||||||||
| const audio = new Audio(); | ||||||||||
|
|
||||||||||
| chrome.runtime.onMessage.addListener((message) => { | ||||||||||
| switch (message.type) { | ||||||||||
| case 'AUDIO_PLAY': | ||||||||||
| audio.volume = message.volume || 0.3; | ||||||||||
| audio.src = message.url; | ||||||||||
| audio.play().catch(err => console.error('Audio play error:', err)); | ||||||||||
| break; | ||||||||||
|
|
||||||||||
| case 'AUDIO_STOP': | ||||||||||
| audio.pause(); | ||||||||||
| audio.src = ''; | ||||||||||
| break; | ||||||||||
|
|
||||||||||
| case 'AUDIO_VOLUME': | ||||||||||
| audio.volume = message.volume; | ||||||||||
| break; | ||||||||||
|
||||||||||
| break; | |
| break; | |
| default: | |
| console.warn('Unknown message type received:', message.type, message); |
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,89 @@ | ||||||||||||||||||||||||||||||||||||||
| "use strict"; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Import stations list | ||||||||||||||||||||||||||||||||||||||
| importScripts('../shared/stations.js'); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const STREAM_API_URL = "https://europe-southwest1-radio--wave.cloudfunctions.net/getstream-v2"; | ||||||||||||||||||||||||||||||||||||||
| const CLIENT = "client=chrome-extension"; | ||||||||||||||||||||||||||||||||||||||
| const currentVersion = "3.0.0"; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Initialize storage on install | ||||||||||||||||||||||||||||||||||||||
| chrome.runtime.onInstalled.addListener(async () => { | ||||||||||||||||||||||||||||||||||||||
| const data = await chrome.storage.local.get(['version', 'volume', 'station', 'state']); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (!data.version || data.version !== currentVersion) { | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
| if (!data.version || data.version !== currentVersion) { | |
| if (typeof data.version === "undefined") { | |
| // Fresh install: set default values | |
| await chrome.storage.local.set({ | |
| version: currentVersion, | |
| volume: 30, | |
| state: "paused", | |
| station: "TVR.KissFM" | |
| }); | |
| } else if (data.version !== currentVersion) { | |
| // Upgrade: preserve station if it exists in the new station list |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential race condition: chrome.runtime.sendMessage is called without ensuring the offscreen document is fully ready to receive messages. The offscreen document creation is async, but there's no guarantee it has loaded and registered its message listener before this message is sent. Consider adding a small delay or a handshake mechanism to ensure the offscreen document is ready.
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling: chrome.runtime.sendMessage can fail if the offscreen document doesn't exist or isn't ready. These calls should include error handling (e.g., .catch()) to gracefully handle message delivery failures, especially since the STOP and SET_VOLUME cases don't call setupOffscreenDocument() first.
| chrome.runtime.sendMessage({ type: 'AUDIO_STOP' }); | |
| await chrome.storage.local.set({ state: 'paused' }); | |
| sendResponse({ success: true }); | |
| break; | |
| case 'SET_VOLUME': | |
| chrome.runtime.sendMessage({ type: 'AUDIO_VOLUME', volume: message.volume / 100 }); | |
| await chrome.runtime.sendMessage({ type: 'AUDIO_STOP' }).catch((err) => { | |
| console.error('Failed to send AUDIO_STOP message:', err); | |
| }); | |
| await chrome.storage.local.set({ state: 'paused' }); | |
| sendResponse({ success: true }); | |
| break; | |
| case 'SET_VOLUME': | |
| await chrome.runtime.sendMessage({ type: 'AUDIO_VOLUME', volume: message.volume / 100 }).catch((err) => { | |
| console.error('Failed to send AUDIO_VOLUME message:', err); | |
| }); |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Missing default case: The switch statement doesn't handle unknown message types. Add a default case to log or handle unexpected message types, which can help with debugging and prevent silent failures.
| break; | |
| break; | |
| default: | |
| console.warn("Unknown message type received:", message.type, message); | |
| sendResponse({ success: false, error: "Unknown message type" }); | |
| break; |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,22 @@ | ||
| { | ||
| "background": { | ||
| "page": "background/index.html" | ||
| }, | ||
| "browser_action": { | ||
| "default_popup": "popup/index.html" | ||
| }, | ||
| "manifest_version": 3, | ||
| "name": "Radio Wave", | ||
| "version": "3.0.0", | ||
| "description": "A simple application for listening to online radio.", | ||
| "icons": { | ||
| "128": "icons/128.png", | ||
| "16": "icons/16.png", | ||
| "24": "icons/24.png", | ||
| "256": "icons/256.png", | ||
| "32": "icons/32.png", | ||
| "64": "icons/64.png" | ||
| "64": "icons/64.png", | ||
| "128": "icons/128.png", | ||
| "256": "icons/256.png" | ||
| }, | ||
| "permissions": ["https://europe-southwest1-radio--wave.cloudfunctions.net/*"], | ||
| "manifest_version": 2, | ||
| "name": "Radio Wave", | ||
| "version": "2.2.9" | ||
| "action": { | ||
| "default_popup": "popup/index.html" | ||
| }, | ||
| "background": { | ||
| "service_worker": "background/service-worker.js" | ||
| }, | ||
| "permissions": ["storage", "offscreen"], | ||
| "host_permissions": ["https://europe-southwest1-radio--wave.cloudfunctions.net/*"] | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,73 +2,96 @@ | |||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| const getStationId = (group, station) => `${group}.${station}`; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| const backgroundPlayer = chrome.extension.getBackgroundPage().backgroundPlayer; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| const controlPlay = document.getElementById("cnt_play"); | ||||||||||||||||||||||||||||
| const controlVolume = document.getElementById("cnt_volume"); | ||||||||||||||||||||||||||||
| const playList = document.getElementById("play_list"); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| let currentState = { state: "paused", volume: 30, station: "TVR.KissFM" }; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Initialize popup with current state | ||||||||||||||||||||||||||||
| async function initializePopup() { | ||||||||||||||||||||||||||||
| currentState = await chrome.runtime.sendMessage({ type: 'GET_STATE' }); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
| currentState = await chrome.runtime.sendMessage({ type: 'GET_STATE' }); | |
| try { | |
| currentState = await chrome.runtime.sendMessage({ type: 'GET_STATE' }); | |
| } catch (error) { | |
| console.error("Failed to get state from background:", error); | |
| // Optionally, show user feedback in the UI | |
| // For example, display an error message or set a default state | |
| currentState = { state: "paused", volume: 30, station: "TVR.KissFM" }; | |
| // Optionally, display an error message in the popup | |
| if (playList) { | |
| playList.innerHTML = '<li class="error">Failed to load state. Please reload the extension.</li>'; | |
| } | |
| } |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
State synchronization issue: The popup updates currentState.state to "played" or "paused" immediately after sending messages, but if the service worker operation fails, the local state will be out of sync with the actual state. The response from sendMessage should be checked before updating local state, or the state should be re-fetched after the operation.
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling: If the SET_VOLUME message fails, the volume slider and state will be inconsistent. Add error handling to revert the UI on failure.
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling: If the SET_VOLUME message fails, the volume slider will show an incorrect value that doesn't match the actual audio volume. Add error handling to revert the UI state on failure.
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
State synchronization issue: Setting currentState.station and currentState.state before the message operations complete (lines 88-93) can lead to inconsistent state if the operations fail. The local state should only be updated after verifying the operations succeeded.
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling: The message sending operations (lines 88-93) should include error handling. If either SET_STATION or PLAY fails, the UI will be in an inconsistent state showing the station as selected and playing when it may not be.
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling: If initializePopup() fails (e.g., service worker not responding), the popup will not initialize properly and will remain in an unusable state. Wrap the call in a try-catch or add .catch() to provide fallback behavior or user feedback.
| initializePopup(); | |
| initializePopup().catch((err) => { | |
| // Provide fallback behavior or user feedback | |
| // For example, display an error message in the popup | |
| playList.innerHTML = '<li class="error">Failed to initialize popup. Please try again later.</li>'; | |
| console.error("Failed to initialize popup:", err); | |
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incomplete error handling:
audio.play()returns a Promise that can be rejected, but the error is only logged to console. Consider notifying the service worker of playback failures so it can update the state to "paused" and inform the user, rather than leaving the UI in an inconsistent "played" state when audio actually failed.