Hey there!
I've encountered a tricky situation while trying to implement a Google extension. Due to technical limitations, I need to open the extension in a separate window as opposed to a disappearing pop-up, which is causing some issues with the functionality. Unfortunately, I'm facing an error when attempting to capture sound from this separate window:
"Error when capturing a tab. Extension has not been invoked for the current page (see activeTab permission). Chrome pages cannot be captured."
I've gone through various responses on similar topics but haven't been able to find a solution that works or that I can fully grasp. Other extensions like Volume Recorder Online have the capabilities I require, but their code is obfuscated, making it challenging to understand why they work and mine doesn't.
Any assistance would be greatly appreciated. Below is the code I'm working with:
Manifest v3:
{
"update_url": "https://clients2.google.com/service/update2/crx",
"name": "AnyTalk",
"version": "1.0.1",
"manifest_version": 3,
"minimum_chrome_version": "114",
"background": {
"service_worker": "scripts/window.js"
},
"icons": {
"16": "assets/icon-16.png",
"32": "assets/icon-32.png",
"48": "assets/icon-48.png",
"128": "assets/icon-128.png"
},
"action": {
"default_icon": "assets/icon-128.png",
"default_title": "AnyTalk"
},
"permissions": [
"tabCapture",
"downloads",
"storage",
"activeTab",
"system.display",
"tabs"
],
"host_permissions": [
"<all_urls>"
]
}
window.js (background) \ Opens extension window and sends current tabid in query
chrome.action.onClicked.addListener(function(tab) {
var tabId = tab.id;
chrome.windows.create({
url: '../views/recorder.html?tabId=' + tabId,
type: 'popup',
width: 400,
height: 500
});
});
recorder.js
let recordingEnabled = false;
let socket = null;
let recorder = null;
function getQueryParam(param) {
console.log('Executing getQueryParam function');
var urlParams = new URLSearchParams(window.location.search);
return urlParams.get(param);
}
let tabId = parseInt(getQueryParam("tabId"));
document.addEventListener('DOMContentLoaded', function () {
console.log('DOMContentLoaded event listener triggered');
var statusCircle = document.getElementById('status-circle');
statusCircle.addEventListener('click', async function() {
console.log('statusCircle click event listener triggered');
if (recordingEnabled) {
console.log('Recording is enabled. Stopping recording...');
recordingEnabled = false;
statusCircle.style.backgroundColor = 'blue';
stopRecording();
} else {
console.log('Recording is disabled. Starting recording...');
recordingEnabled = true;
statusCircle.style.backgroundColor = 'red';
captureTab(tabId);
}
});
});
function captureTab(tabId) {
console.log('Executing captureTab function');
console.log(typeof(tabId))
chrome.tabs.update(tabId, { active: true }, function(tab) {
if (chrome.runtime.lastError) {
console.error('Error when updating a tab', chrome.runtime.lastError.message);
return;
}
console.log('Tab updated:', tab);
var captureOptions = { audio: true, video: false };
chrome.tabCapture.capture(captureOptions, function(stream) {
console.log('Tab captured:', stream);
if (chrome.runtime.lastError) {
console.error('Error when capturing a tab ', chrome.runtime.lastError.message);
return;
}
Check out the log results here