webext-surf.c (2861B)
1 #include <sys/stat.h> 2 #include <fcntl.h> 3 #include <limits.h> 4 #include <stdlib.h> 5 6 #include <gio/gio.h> 7 #include <webkit2/webkit-web-extension.h> 8 #include <webkitdom/webkitdom.h> 9 #include <webkitdom/WebKitDOMDOMWindowUnstable.h> 10 11 #include "common.h" 12 13 #define LENGTH(x) (sizeof(x) / sizeof(x[0])) 14 15 typedef struct Page { 16 guint64 id; 17 WebKitWebPage *webpage; 18 struct Page *next; 19 } Page; 20 21 static int pipein, pipeout; 22 static Page *pages; 23 24 Page * 25 newpage(WebKitWebPage *page) 26 { 27 Page *p; 28 29 if (!(p = calloc(1, sizeof(Page)))) { 30 fputs("Cannot malloc!\n", stderr); 31 exit(1); 32 } 33 34 p->next = pages; 35 pages = p; 36 37 p->id = webkit_web_page_get_id(page); 38 p->webpage = page; 39 40 return p; 41 } 42 43 static void 44 msgsurf(Page *p, const char *s) 45 { 46 static char msg[MSGBUFSZ]; 47 size_t sln = strlen(s); 48 int ret; 49 50 if ((ret = snprintf(msg, sizeof(msg), "%c%c%s", 51 2 + sln, p ? p->id : 0, s)) 52 >= sizeof(msg)) { 53 fprintf(stderr, "webext: message too long: %d\n", ret); 54 return; 55 } 56 57 if (pipeout && write(pipeout, msg, sizeof(msg)) < 0) 58 fprintf(stderr, "webext: error sending: %.*s\n", ret-2, msg+2); 59 } 60 61 static gboolean 62 readpipe(GIOChannel *s, GIOCondition c, gpointer unused) 63 { 64 static char msg[MSGBUFSZ], msgsz; 65 WebKitDOMDOMWindow *view; 66 GError *gerr = NULL; 67 glong wh, ww; 68 Page *p; 69 70 if (g_io_channel_read_chars(s, msg, LENGTH(msg), NULL, &gerr) != 71 G_IO_STATUS_NORMAL) { 72 fprintf(stderr, "webext: error reading pipe: %s\n", 73 gerr->message); 74 g_error_free(gerr); 75 return TRUE; 76 } 77 if ((msgsz = msg[0]) < 3) { 78 fprintf(stderr, "webext: message too short: %d\n", msgsz); 79 return TRUE; 80 } 81 82 for (p = pages; p; p = p->next) { 83 if (p->id == msg[1]) 84 break; 85 } 86 if (!p || !(view = webkit_dom_document_get_default_view( 87 webkit_web_page_get_dom_document(p->webpage)))) 88 return TRUE; 89 90 switch (msg[2]) { 91 case 'h': 92 if (msgsz != 4) 93 return TRUE; 94 ww = webkit_dom_dom_window_get_inner_width(view); 95 webkit_dom_dom_window_scroll_by(view, 96 (ww / 100) * msg[3], 0); 97 break; 98 case 'v': 99 if (msgsz != 4) 100 return TRUE; 101 wh = webkit_dom_dom_window_get_inner_height(view); 102 webkit_dom_dom_window_scroll_by(view, 103 0, (wh / 100) * msg[3]); 104 break; 105 } 106 107 return TRUE; 108 } 109 110 static void 111 webpagecreated(WebKitWebExtension *e, WebKitWebPage *wp, gpointer unused) 112 { 113 Page *p = newpage(wp); 114 } 115 116 G_MODULE_EXPORT void 117 webkit_web_extension_initialize_with_user_data(WebKitWebExtension *e, GVariant *gv) 118 { 119 GIOChannel *gchanpipe; 120 121 g_signal_connect(e, "page-created", G_CALLBACK(webpagecreated), NULL); 122 123 g_variant_get(gv, "(ii)", &pipein, &pipeout); 124 msgsurf(NULL, "i"); 125 126 gchanpipe = g_io_channel_unix_new(pipein); 127 g_io_channel_set_encoding(gchanpipe, NULL, NULL); 128 g_io_channel_set_close_on_unref(gchanpipe, TRUE); 129 g_io_add_watch(gchanpipe, G_IO_IN, readpipe, NULL); 130 }