libsurf-webext.c 2.8 KB

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