fix: Chrome extension MV3 CSP violations and missing alarms permission

- Add "alarms" permission to manifest — chrome.alarms.create() was
  throwing "Cannot read properties of undefined" because the permission
  was missing; also removed invalid "sockets" permission (not a valid MV3 perm)
- Remove all inline event handlers from popup.html (onclick, ondragover,
  ondragleave, ondrop, onchange) — MV3 CSP blocks inline JS entirely;
  all handlers moved to popup.js addEventListener() calls
- Replace inline onclick="removeFile(i)" on dynamically generated remove
  buttons with data-idx attribute + delegated click listener on the list
  container — same CSP fix for runtime-generated elements

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Zac Gaetano 2026-04-06 21:38:50 -04:00
parent fa206ba21a
commit e588a69a78
3 changed files with 29 additions and 10 deletions

View file

@ -7,7 +7,7 @@
"storage",
"activeTab",
"scripting",
"sockets"
"alarms"
],
"host_permissions": [
"https://*/*",

View file

@ -109,8 +109,8 @@ body{font-family:'Segoe UI',system-ui,sans-serif;background:#06080e;color:#e4e8f
<!-- Upload Mode -->
<div class="mode-row">
<button class="mode-btn active-http" id="btn-http" onclick="setMode('http')">🔗 HTTP<br/><small>Reliable</small></button>
<button class="mode-btn" id="btn-udp" onclick="setMode('udp')">⚡ UDP<br/><small>Fast WAN</small></button>
<button class="mode-btn active-http" id="btn-http">🔗 HTTP<br/><small>Reliable</small></button>
<button class="mode-btn" id="btn-udp">⚡ UDP<br/><small>Fast WAN</small></button>
</div>
<!-- Folder Selector -->
@ -122,18 +122,18 @@ body{font-family:'Segoe UI',system-ui,sans-serif;background:#06080e;color:#e4e8f
</div>
<!-- Drop Zone -->
<div class="drop-zone" id="drop-zone" onclick="document.getElementById('file-input').click()" ondragover="ev.preventDefault();this.classList.add('over')" ondragleave="this.classList.remove('over')" ondrop="onDrop(event)">
<div class="drop-zone" id="drop-zone">
<span class="dz-icon">📂</span>
<div class="dz-label">Drop files or click to browse</div>
<div class="dz-sub">Video, audio, image up to 50 GB</div>
</div>
<input id="file-input" type="file" multiple onchange="onFileInputChange(event)"/>
<input id="file-input" type="file" multiple/>
<!-- File List -->
<div class="file-list" id="file-list"></div>
<!-- Upload Button -->
<button class="upload-btn http" id="upload-btn" onclick="startUpload()" disabled>Upload Files</button>
<button class="upload-btn http" id="upload-btn" disabled>Upload Files</button>
<!-- Status -->
<div class="status-bar" id="status-bar"></div>
@ -155,7 +155,7 @@ body{font-family:'Segoe UI',system-ui,sans-serif;background:#06080e;color:#e4e8f
<label class="setting-label">Password</label>
<input class="setting-input" id="cfg-pass" type="password" placeholder="password"/>
</div>
<button class="save-btn" onclick="saveSettings()">Save &amp; Connect</button>
<button class="save-btn" id="save-btn">Save &amp; Connect</button>
<div class="status-bar" id="settings-status" style="margin-top:.5rem"></div>
</div>

View file

@ -31,11 +31,24 @@ let connected = false;
}
})();
// ==================== EVENT LISTENERS ====================
document.getElementById('settings-toggle').addEventListener('click', () => {
const panel = document.getElementById('settings-panel');
panel.classList.toggle('open');
document.getElementById('settings-panel').classList.toggle('open');
});
document.getElementById('save-btn').addEventListener('click', saveSettings);
document.getElementById('upload-btn').addEventListener('click', startUpload);
document.getElementById('btn-http').addEventListener('click', () => setMode('http'));
document.getElementById('btn-udp').addEventListener('click', () => setMode('udp'));
const dropZone = document.getElementById('drop-zone');
dropZone.addEventListener('click', () => document.getElementById('file-input').click());
dropZone.addEventListener('dragover', (e) => { e.preventDefault(); dropZone.classList.add('over'); });
dropZone.addEventListener('dragleave', () => dropZone.classList.remove('over'));
dropZone.addEventListener('drop', onDrop);
document.getElementById('file-input').addEventListener('change', onFileInputChange);
// ==================== CONNECTION ====================
async function tryConnect() {
setConnStatus('grey', 'Connecting…');
@ -187,12 +200,18 @@ function renderFileList() {
<div class="fi-prog" id="fp-${i}" style="display:none"><div class="fi-prog-bar${uploadMode==='udp'?' udp':''}" id="fpb-${i}" style="width:0%"></div></div>
</div>
<span class="fi-status ${item.status}" id="fs-${i}">${item.status}</span>
<button class="fi-rm" onclick="removeFile(${i})">×</button>
<button class="fi-rm" data-idx="${i}">×</button>
`;
list.appendChild(el);
});
}
// Delegated listener for remove buttons (avoids inline onclick — CSP compliant)
document.getElementById('file-list').addEventListener('click', (e) => {
const btn = e.target.closest('.fi-rm');
if (btn) removeFile(parseInt(btn.dataset.idx, 10));
});
function removeFile(i) { selectedFiles.splice(i, 1); renderFileList(); updateBtn(); }
function updateBtn() {