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:
parent
fa206ba21a
commit
e588a69a78
3 changed files with 29 additions and 10 deletions
|
|
@ -7,7 +7,7 @@
|
||||||
"storage",
|
"storage",
|
||||||
"activeTab",
|
"activeTab",
|
||||||
"scripting",
|
"scripting",
|
||||||
"sockets"
|
"alarms"
|
||||||
],
|
],
|
||||||
"host_permissions": [
|
"host_permissions": [
|
||||||
"https://*/*",
|
"https://*/*",
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,8 @@ body{font-family:'Segoe UI',system-ui,sans-serif;background:#06080e;color:#e4e8f
|
||||||
|
|
||||||
<!-- Upload Mode -->
|
<!-- Upload Mode -->
|
||||||
<div class="mode-row">
|
<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 active-http" id="btn-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" id="btn-udp">⚡ UDP<br/><small>Fast WAN</small></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Folder Selector -->
|
<!-- Folder Selector -->
|
||||||
|
|
@ -122,18 +122,18 @@ body{font-family:'Segoe UI',system-ui,sans-serif;background:#06080e;color:#e4e8f
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Drop Zone -->
|
<!-- 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>
|
<span class="dz-icon">📂</span>
|
||||||
<div class="dz-label">Drop files or click to browse</div>
|
<div class="dz-label">Drop files or click to browse</div>
|
||||||
<div class="dz-sub">Video, audio, image up to 50 GB</div>
|
<div class="dz-sub">Video, audio, image up to 50 GB</div>
|
||||||
</div>
|
</div>
|
||||||
<input id="file-input" type="file" multiple onchange="onFileInputChange(event)"/>
|
<input id="file-input" type="file" multiple/>
|
||||||
|
|
||||||
<!-- File List -->
|
<!-- File List -->
|
||||||
<div class="file-list" id="file-list"></div>
|
<div class="file-list" id="file-list"></div>
|
||||||
|
|
||||||
<!-- Upload Button -->
|
<!-- 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 -->
|
<!-- Status -->
|
||||||
<div class="status-bar" id="status-bar"></div>
|
<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>
|
<label class="setting-label">Password</label>
|
||||||
<input class="setting-input" id="cfg-pass" type="password" placeholder="password"/>
|
<input class="setting-input" id="cfg-pass" type="password" placeholder="password"/>
|
||||||
</div>
|
</div>
|
||||||
<button class="save-btn" onclick="saveSettings()">Save & Connect</button>
|
<button class="save-btn" id="save-btn">Save & Connect</button>
|
||||||
<div class="status-bar" id="settings-status" style="margin-top:.5rem"></div>
|
<div class="status-bar" id="settings-status" style="margin-top:.5rem"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,24 @@ let connected = false;
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// ==================== EVENT LISTENERS ====================
|
||||||
document.getElementById('settings-toggle').addEventListener('click', () => {
|
document.getElementById('settings-toggle').addEventListener('click', () => {
|
||||||
const panel = document.getElementById('settings-panel');
|
document.getElementById('settings-panel').classList.toggle('open');
|
||||||
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 ====================
|
// ==================== CONNECTION ====================
|
||||||
async function tryConnect() {
|
async function tryConnect() {
|
||||||
setConnStatus('grey', 'Connecting…');
|
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 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>
|
</div>
|
||||||
<span class="fi-status ${item.status}" id="fs-${i}">${item.status}</span>
|
<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);
|
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 removeFile(i) { selectedFiles.splice(i, 1); renderFileList(); updateBtn(); }
|
||||||
|
|
||||||
function updateBtn() {
|
function updateBtn() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue