aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extension/background.js114
-rw-r--r--fs/hello.c113
2 files changed, 170 insertions, 57 deletions
diff --git a/extension/background.js b/extension/background.js
index 8588275..8a1d808 100644
--- a/extension/background.js
+++ b/extension/background.js
@@ -1,25 +1,3 @@
-let ws;
-function tryConnect() {
- ws = new WebSocket("ws://localhost:8888");
- updateToolbarIcon();
- ws.onopen = ws.onclose = updateToolbarIcon;
-}
-
-function updateToolbarIcon() {
- if (ws && ws.readyState == 1) { // OPEN
- chrome.browserAction.setBadgeBackgroundColor({color: 'blue'});
- chrome.browserAction.setBadgeText({text: 'f'});
- } else {
- chrome.browserAction.setBadgeBackgroundColor({color: 'red'});
- chrome.browserAction.setBadgeText({text: '!'});
- }
-}
-
-tryConnect();
-chrome.browserAction.onClicked.addListener(function() {
- tryConnect();
-});
-
const unix = {
EPERM: 1,
ENOENT: 2,
@@ -93,6 +71,13 @@ function pathComponent(path, i) {
const router = {
"tabs": {
+ /* "last-focused": {
+ * // FIXME: symlink to tab by id.
+ * async readlink() {
+ * return "../windows/last-focused/selected-tab"
+ * }
+ * },
+ */
"by-id": {
async readdir() {
const tabs = await queryTabs();
@@ -112,6 +97,21 @@ const router = {
return (tab.title + "\n").substr(offset, size);
}
},
+ "tree": {
+ async open(path) {
+ const debuggee = {tabId: parseInt(pathComponent(path, -2))};
+ await new Promise(resolve => chrome.debugger.attach(debuggee, "1.2", resolve));
+ chrome.debugger.sendCommand(debuggee, "Page.getResourceTree", {}, function(result) {
+ console.log(result);
+ });
+ },
+ async read(path) {
+
+ },
+ async close(path) {
+
+ }
+ }
}
}
}
@@ -148,16 +148,10 @@ async function getattr(path) {
}
}
-async function readdir(path) {
- let route = findRoute(path);
- if (route.readdir) return route.readdir(path);
- return Object.keys(route);
-}
-
async function open(path) {
let route = findRoute(path);
if (route.open) return route.open(path);
- else return 0; // empty fd
+ else return 0; // empty fh
}
async function read(path, fh, size, offset) {
@@ -170,7 +164,23 @@ async function release(path, fh) {
if (route.release) return route.release(path, fh);
}
-ws.onmessage = async function(event) {
+async function opendir(path) {
+ let route = findRoute(path);
+ if (route.opendir) return route.opendir(path);
+ else return 0; // empty fh
+}
+async function readdir(path) {
+ let route = findRoute(path);
+ if (route.readdir) return route.readdir(path);
+ return Object.keys(route);
+}
+async function releasedir(path) {
+ let route = findRoute(path);
+ if (route.releasedir) return route.releasedir(path);
+}
+
+let ws;
+async function onmessage(event) {
const req = JSON.parse(event.data);
let response = { op: req.op, error: unix.EIO };
@@ -190,12 +200,6 @@ ws.onmessage = async function(event) {
fh: await open(req.path)
};
- } else if (req.op === 'readdir') {
- response = {
- op: 'readdir',
- entries: [".", "..", ...(await readdir(req.path))]
- };
-
} else if (req.op === 'read') {
const buf = await read(req.path, req.fh, req.size, req.offset)
response = {
@@ -208,6 +212,22 @@ ws.onmessage = async function(event) {
response = {
op: 'release'
};
+
+ } else if (req.op === 'opendir') {
+ response = {
+ op: 'opendir',
+ fh: await opendir(req.path)
+ };
+
+ } else if (req.op === 'readdir') {
+ response = {
+ op: 'readdir',
+ entries: [".", "..", ...(await readdir(req.path))]
+ };
+
+ } else if (req.op === 'releasedir') {
+ await releasedir(req.path, req.fh);
+ response = { op: 'releasedir' };
}
} catch (e) {
response = {
@@ -220,3 +240,25 @@ ws.onmessage = async function(event) {
response.id = req.id;
ws.send(JSON.stringify(response));
};
+
+function tryConnect() {
+ ws = new WebSocket("ws://localhost:8888");
+ updateToolbarIcon();
+ ws.onopen = ws.onclose = updateToolbarIcon;
+ ws.onmessage = onmessage;
+}
+
+function updateToolbarIcon() {
+ if (ws && ws.readyState == 1) { // OPEN
+ chrome.browserAction.setBadgeBackgroundColor({color: 'blue'});
+ chrome.browserAction.setBadgeText({text: 'f'});
+ } else {
+ chrome.browserAction.setBadgeBackgroundColor({color: 'red'});
+ chrome.browserAction.setBadgeText({text: '!'});
+ }
+}
+
+tryConnect();
+chrome.browserAction.onClicked.addListener(function() {
+ tryConnect();
+});
diff --git a/fs/hello.c b/fs/hello.c
index 66985e2..bb6a7b1 100644
--- a/fs/hello.c
+++ b/fs/hello.c
@@ -63,6 +63,7 @@ static request_id enqueue_request(cJSON *req) {
/* printf("%s\n", queue[id].request); */
+ pthread_cond_signal(&queue_cv);
pthread_mutex_unlock(&queue_mutex);
return id;
@@ -164,32 +165,32 @@ hello_getattr(const char *path, struct stat *stbuf)
}
static int
-hello_open(const char *path, struct fuse_file_info *fi)
+hello_readlink(const char *path, char *buf, size_t size)
{
- MAKE_REQ("open", {
+ MAKE_REQ("readlink", {
cJSON_AddStringToObject(req, "path", path);
- cJSON_AddNumberToObject(req, "flags", fi->flags);
}, {
- cJSON *fh_item = cJSON_GetObjectItemCaseSensitive(resp, "fh");
- if (fh_item) fi->fh = fh_item->valueint;
+ cJSON *resp_buf_item = cJSON_GetObjectItemCaseSensitive(resp, "buf");
+ // FIXME: fix
+ char *resp_buf = cJSON_GetStringValue(resp_buf_item);
+ size_t resp_buf_len = strlen(resp_buf);
+ size = resp_buf_len < size ? resp_buf_len : size;
- ret = 0;
+ memcpy(buf, resp_buf, size);
+
+ ret = size;
});
}
static int
-hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
- off_t offset, struct fuse_file_info *fi)
+hello_open(const char *path, struct fuse_file_info *fi)
{
- // send {op: "readdir", path} to the websocket handler
- MAKE_REQ("readdir", {
+ MAKE_REQ("open", {
cJSON_AddStringToObject(req, "path", path);
+ cJSON_AddNumberToObject(req, "flags", fi->flags);
}, {
- cJSON *entries = cJSON_GetObjectItemCaseSensitive(resp, "entries");
- cJSON *entry;
- cJSON_ArrayForEach(entry, entries) {
- filler(buf, cJSON_GetStringValue(entry), NULL, 0);
- }
+ cJSON *fh_item = cJSON_GetObjectItemCaseSensitive(resp, "fh");
+ if (fh_item) fi->fh = fh_item->valueint;
ret = 0;
});
@@ -208,7 +209,11 @@ hello_read(const char *path, char *buf, size_t size, off_t offset,
cJSON_AddNumberToObject(req, "flags", fi->flags);
}, {
cJSON *resp_buf_item = cJSON_GetObjectItemCaseSensitive(resp, "buf");
+ if (!resp_buf_item) return -EIO;
+
char *resp_buf = cJSON_GetStringValue(resp_buf_item);
+ if (!resp_buf) return -EIO;
+
size_t resp_buf_len = strlen(resp_buf);
size = resp_buf_len < size ? resp_buf_len : size;
@@ -227,12 +232,59 @@ static int hello_release(const char *path, struct fuse_file_info *fi) {
});
}
+static int
+hello_opendir(const char *path, struct fuse_file_info *fi)
+{
+ MAKE_REQ("opendir", {
+ cJSON_AddStringToObject(req, "path", path);
+ cJSON_AddNumberToObject(req, "flags", fi->flags);
+ }, {
+ cJSON *fh_item = cJSON_GetObjectItemCaseSensitive(resp, "fh");
+ if (fh_item) fi->fh = fh_item->valueint;
+
+ ret = 0;
+ });
+}
+
+static int
+hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ // send {op: "readdir", path} to the websocket handler
+ MAKE_REQ("readdir", {
+ cJSON_AddStringToObject(req, "path", path);
+ }, {
+ cJSON *entries = cJSON_GetObjectItemCaseSensitive(resp, "entries");
+ cJSON *entry;
+ cJSON_ArrayForEach(entry, entries) {
+ filler(buf, cJSON_GetStringValue(entry), NULL, 0);
+ }
+
+ ret = 0;
+ });
+}
+
+static int
+hello_releasedir(const char *path, struct fuse_file_info *fi)
+{
+ MAKE_REQ("releasedir", {
+ cJSON_AddStringToObject(req, "path", path);
+ cJSON_AddNumberToObject(req, "fh", fi->fh);
+ }, {
+ ret = 0;
+ });
+}
+
static struct fuse_operations hello_filesystem_operations = {
- .getattr = hello_getattr, /* To provide size, permissions, etc. */
- .open = hello_open, /* To enforce read-only access. */
- .read = hello_read, /* To provide file content. */
- .release = hello_release,
- .readdir = hello_readdir, /* To provide directory listing. */
+ .getattr = hello_getattr, /* To provide size, permissions, etc. */
+ .readlink = hello_readlink,
+ .open = hello_open, /* To enforce read-only access. */
+ .read = hello_read, /* To provide file content. */
+ .release = hello_release,
+
+ .opendir = hello_opendir,
+ .readdir = hello_readdir, /* To provide directory listing. */
+ .releasedir = hello_releasedir
};
static int
@@ -339,6 +391,24 @@ test_log(const char* text)
DEBUG("[debug] %s\n", text);
}
+int check_io_demand() {
+ if (con == NULL) return 1;
+
+ for (request_id id = 0; id < REQUEST_RESPONSE_QUEUE_SIZE; id++) {
+ if (queue[id].state == SEND_REQUEST || queue[id].state == RECEIVE_RESPONSE) {
+ return 1;
+ }
+ }
+ return 0;
+}
+void await_io_demand() {
+ pthread_mutex_lock(&queue_mutex);
+ while (!check_io_demand()) {
+ pthread_cond_wait(&queue_cv, &queue_mutex);
+ }
+ pthread_mutex_unlock(&queue_mutex);
+}
+
void *websocket_main(void *threadid)
{
void *memory = NULL;
@@ -365,6 +435,8 @@ void *websocket_main(void *threadid)
printf("Awaiting WebSocket connection from Chrome extension.\n");
for (;;) {
+ await_io_demand();
+
send_any_enqueued_requests();
wby_update(&server);
@@ -384,5 +456,4 @@ main(int argc, char **argv)
pthread_t websocket_thread;
pthread_create(&websocket_thread, NULL, websocket_main, NULL);
return fuse_main(argc, argv, &hello_filesystem_operations, NULL);
-
}