multi-account-containers/src/js/background/recordManager.js

177 lines
No EOL
5.9 KiB
JavaScript

const recordManager = {
recording: null,
listening: null,
Recording: class {
constructor(tab) {
if (tab) {
this.windowId = tab.windowId;
this.tabId = tab.id;
this.isTabActive = tab.active;
} else {
this.windowId = browser.windows.WINDOW_ID_NONE;
this.tabId = browser.tabs.TAB_ID_NONE;
this.isTabActive = false;
}
}
get valid() {
return this.tabId !== browser.tabs.TAB_ID_NONE;
}
async sendTabMessage() {
return messageHandler.sendTabMessage(this.tabId, this.tabMessage);
}
async stop() {
if (!this.valid) { return; }
recordManager.listening.enabled = false;
// Update GUI
this.tabMessage = { recording: false, popup: false };
const tab = await backgroundLogic.getTabOrNull(this.tabId);
// Don't try to send "stop recording" message to tab if already closed or showing an invalid page
if (tab && tab.url) {
return this.sendTabMessage();
}
}
async start() {
if (!this.valid) { return; }
recordManager.listening.enabled = true;
// Update GUI
const baPopup = messageHandler.browserAction.popup;
const tabPopup = this.isTabActive && (!baPopup || baPopup.windowId !== this.windowId);
this.tabMessage = { recording: true, popup: tabPopup, popupOptions: {tabId: this.tabId} };
const showingPage = browser.tabs.update(this.tabId, { url: browser.runtime.getURL("/recording.html") });
const messagingTab = this.sendTabMessage();
return Promise.all([showingPage, messagingTab]);
}
// Re-show recording state on page load
onTabsUpdated(tabId, changeInfo) {
if (this.tabId === tabId && changeInfo.status === "complete") {
this.sendTabMessage();
}
}
// Show/hide tabPopup on this tab show/hide
onTabsActivated(activeInfo) {
if (this.tabId === activeInfo.tabId) {
this.sendTabMessage();
}
}
// Keep track of tab's windowId
onTabsAttached(tabId, attachInfo) {
if (this.tabId === tabId) {
this.windowId = attachInfo.newWindowId;
}
}
// Stop recording on close
onTabsRemoved(tabId) {
if (this.tabId === tabId) {
recordManager.setTabId(browser.tabs.TAB_ID_NONE);
}
}
// Show/hide tabPopup on hide/show browserActionPopup
onToggleBrowserActionPopup(baPopupVisible, baPopup) {
if (this.windowId === baPopup.windowId && this.isTabActive) {
this.tabMessage.popup = !baPopupVisible;
this.tabMessage.popupOptions = { tabId:this.tabId, width:baPopup.width, height:baPopup.height };
this.sendTabMessage();
}
}
},
Listening: class {
constructor() {
this._enabled = false;
}
get enabled() { return this._enabled; }
set enabled(enabled) {
if (this._enabled === !!enabled) { return; }
this._enabled = !!enabled;
if (enabled) {
browser.tabs.onUpdated.addListener(this.onTabsUpdated, { properties: ["status"] });
browser.tabs.onActivated.addListener(this.onTabsActivated);
browser.tabs.onAttached.addListener(this.onTabsAttached);
browser.tabs.onRemoved.addListener(this.onTabsRemoved);
window.addEventListener("BrowserActionPopupLoad", this.onBrowserActionPopupLoad);
window.addEventListener("BrowserActionPopupUnload", this.onBrowserActionPopupUnload);
} else {
browser.tabs.onUpdated.removeListener(this.onTabsUpdated);
browser.tabs.onActivated.removeListener(this.onTabsActivated);
browser.tabs.onAttached.removeListener(this.onTabsAttached);
browser.tabs.onRemoved.removeListener(this.onTabsRemoved);
window.removeEventListener("BrowserActionPopupLoad", this.onBrowserActionPopupLoad);
window.removeEventListener("BrowserActionPopupUnload", this.onBrowserActionPopupUnload);
}
}
onTabsUpdated(...args) { recordManager.recording.onTabsUpdated(...args); }
onTabsActivated(...args) { recordManager.recording.onTabsActivated(...args); }
onTabsAttached(...args) { recordManager.recording.onTabsAttached(...args); }
onTabsRemoved(...args) { recordManager.recording.onTabsRemoved(...args); }
onBrowserActionPopupLoad() { recordManager.recording.onToggleBrowserActionPopup(true, messageHandler.browserAction.popup); }
onBrowserActionPopupUnload() { recordManager.recording.onToggleBrowserActionPopup(false, messageHandler.browserAction.popup); }
},
init() {
this.recording = new recordManager.Recording();
this.listening = new recordManager.Listening();
},
isRecordingTabId(tabId) {
if (!this.recording.valid) { return false; }
if (this.recording.tabId !== tabId) { return false; }
return true;
},
getTabId() {
return this.recording.tabId;
},
async setTabId(tabId) {
// Ensure tab is recordable
tabId = backgroundLogic.asTabId(tabId);
const tab = await backgroundLogic.getTabOrNull(tabId);
const wantRecordableTab = tabId !== browser.tabs.TAB_ID_NONE;
const isRecordableTab = tab && "cookieStoreId" in tab;
// Invalid tab - stop recording & throw error
if (wantRecordableTab && !isRecordableTab) {
this.setTabId(browser.tabs.TAB_ID_NONE); // Don't wait for stop
throw new Error(`Recording not possible for tab with id ${tabId}`);
}
// Already recording
if (this.recording.tabId === tabId) { return; }
const oldRecording = this.recording;
const newRecording = this.recording = new recordManager.Recording(tab);
// Don't wait for stop
oldRecording.stop();
try {
// But DO wait for start
await newRecording.start();
// If error while starting, immediately stop, but don't wait
} catch (e) {
this.setTabId(browser.tabs.TAB_ID_NONE);
throw e;
}
}
};
recordManager.init();