177 lines
No EOL
5.9 KiB
JavaScript
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(); |