aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extension/background.js106
1 files changed, 64 insertions, 42 deletions
diff --git a/extension/background.js b/extension/background.js
index e44fb9d..d2ef8cf 100644
--- a/extension/background.js
+++ b/extension/background.js
@@ -79,40 +79,53 @@ function stringSize(str) {
return s + 1;
}
-const debugging = {};
-async function debugTab(tabId) {
- if (debugging[tabId]) {
- debugging[tabId] += 1;
-
- } else {
- await new Promise((resolve, reject) => chrome.debugger.attach({tabId}, "1.3", function callback() {
- if (chrome.runtime.lastError) {
- if (chrome.runtime.lastError.message.indexOf('Another debugger is already attached') !== -1) {
- chrome.debugger.detach({tabId}, callback);
- } else {
- reject(chrome.runtime.lastError);
+const TabManager = {
+ tabState: {},
+
+ debugTab: async function(tabId) {
+ this.tabState[tabId] = this.tabState[tabId] || {};
+ if (this.tabState[tabId].debugging) {
+ this.tabState[tabId].debugging += 1;
+
+ } else {
+ await new Promise((resolve, reject) => chrome.debugger.attach({tabId}, "1.3", async () => {
+ if (chrome.runtime.lastError) {
+ if (chrome.runtime.lastError.message.indexOf('Another debugger is already attached') !== -1) {
+ chrome.debugger.detach({tabId}, () => {this.debugTab(tabId)});
+ } else {
+ reject(chrome.runtime.lastError); return;
+ }
+ return;
}
- } else {
- debugging[tabId] = 1;
- resolve();
- }
- }));
+ this.tabState[tabId].debugging = 1; resolve();
+ }));
+ }
+ },
+ enableDomainForTab: async function(tabId, domain) {
+ this.tabState[tabId] = this.tabState[tabId] || {};
+ if (this.tabState[tabId][domain]) { this.tabState[tabId][domain] += 1;
+ } else {
+ await sendDebuggerCommand(tabId, `${domain}.enable`, {});
+ this.tabState[tabId][domain] = 1;
+ }
}
-}
+};
+
function sendDebuggerCommand(tabId, method, commandParams) {
return new Promise((resolve, reject) =>
chrome.debugger.sendCommand({tabId}, method, commandParams, result => {
- console.log(method, result);
if (result) { resolve(result); } else { reject(chrome.runtime.lastError); }
})
);
}
-let lastFocusedWindowId;
-browser.windows.getLastFocused().then(window => { lastFocusedWindowId = window.id; });
-browser.windows.onFocusChanged.addListener(windowId => {
- if (windowId !== -1) lastFocusedWindowId = windowId;
-});
+const BrowserState = { lastFocusedWindowId: null };
+(function() {
+ browser.windows.getLastFocused().then(window => { BrowserState.lastFocusedWindowId = window.id; });
+ browser.windows.onFocusChanged.addListener(windowId => {
+ if (windowId !== -1) BrowserState.lastFocusedWindowId = windowId;
+ });
+})();
/* if I could specify a custom editor interface for all the routing
below ... I would highlight the route names in blocks of some color
@@ -154,6 +167,18 @@ function fromScript(code) {
}
};
}
+const Cache = {
+ // used when you open a file to cache the content we got from the browser
+ // until you close that file.
+ store: {}, nextHandle: 0,
+ storeObject(object) {
+ const handle = ++this.nextHandle;
+ this.store[handle] = object;
+ return handle;
+ },
+ getObjectForHandle(handle) { return this.store[handle]; },
+ removeObjectForHandle(handle) { delete this.store[handle]; }
+};
router["/tabs/by-id"] = {
async readdir() {
@@ -165,21 +190,24 @@ router["/tabs/by-id/*/url"] = withTab(tab => tab.url + "\n");
router["/tabs/by-id/*/title"] = withTab(tab => tab.title + "\n");
router["/tabs/by-id/*/text"] = fromScript(`document.body.innerText`);
router["/tabs/by-id/*/screenshot.png"] = {
- async read({path, fh, size, offset}) {
+ async open({path}) {
const tabId = parseInt(pathComponent(path, -2));
- await debugTab(tabId);
- await sendDebuggerCommand(tabId, "Page.enable", {});
+ await TabManager.debugTab(tabId); await TabManager.enableDomainForTab(tabId, "Page");
+ // FIXME: cache.
const {data} = await sendDebuggerCommand(tabId, "Page.captureScreenshot");
- const arr = Uint8Array.from(atob(data), c => c.charCodeAt(0));
- const slice = arr.slice(offset, offset + size);
+ return { fh: Cache.storeObject(Uint8Array.from(atob(data), c => c.charCodeAt(0))) };
+ },
+ async read({path, fh, size, offset}) {
+ const slice = Cache.getObjectForHandle(fh).slice(offset, offset + size);
return { buf: String.fromCharCode(...slice) };
- }
+ },
+ async close({fh}) { Cache.removeObjectForHandle(fh); }
};
router["/tabs/by-id/*/resources"] = {
async opendir({path}) {
const tabId = parseInt(pathComponent(path, -2));
- await debugTab(tabId);
+ await TabManager.debugTab(tabId);
return { fh: 0 };
},
async readdir({path}) {
@@ -194,9 +222,7 @@ router["/tabs/by-id/*/resources/*"] = {
const tabId = parseInt(pathComponent(path, -3));
const suffix = pathComponent(path, -1);
- await debugTab(tabId);
-
- await sendDebuggerCommand(tabId, "Page.enable", {});
+ await TabManager.debugTab(tabId); await TabManager.enableDomainForTab(tabId, "Page");
const {frameTree} = await sendDebuggerCommand(tabId, "Page.getResourceTree", {});
for (let resource of frameTree.resources) {
@@ -218,20 +244,16 @@ router["/tabs/by-id/*/resources/*"] = {
}
},
async open({path}) {
- // FIXME: cache the file
+ // FIXME: cache the file.
const tabId = parseInt(pathComponent(path, -3));
- await debugTab(tabId);
+ await TabManager.debugTab(tabId); await TabManager.enableDomainForTab(tabId, "Page");
return {fh: 3};
},
async read({path, fh, size, offset}) {
const tabId = parseInt(pathComponent(path, -3));
const suffix = pathComponent(path, -1);
- if (!debugging[tabId]) throw new UnixError(unix.EIO);
-
- await sendDebuggerCommand(tabId, "Page.enable", {});
-
- const {frameTree} = await sendDebuggerCommand(tabId, "Page.getResourceTree", {});
+ const {frameTree} = await sendDebuggerCommand(tabId, "Page.getResourceTree", {}); // FIXME: cache this
for (let resource of frameTree.resources) {
const resourceSuffix = sanitize(String(resource.url).slice(0, 200));
if (resourceSuffix === suffix) {
@@ -285,7 +307,7 @@ router["/tabs/by-title/*"] = {
router["/tabs/last-focused"] = {
// a symbolic link to /tabs/by-id/[id for this tab]
async readlink({path}) {
- const id = (await browser.tabs.query({ active: true, windowId: lastFocusedWindowId }))[0].id;
+ const id = (await browser.tabs.query({ active: true, windowId: BrowserState.lastFocusedWindowId }))[0].id;
return { buf: "by-id/" + id };
}
}