about summary refs log tree commit diff
path: root/native
diff options
context:
space:
mode:
Diffstat (limited to 'native')
-rwxr-xr-xnative182
1 files changed, 182 insertions, 0 deletions
diff --git a/native b/native
new file mode 100755
index 0000000..e64bd6e
--- /dev/null
+++ b/native
@@ -0,0 +1,182 @@
+#! /usr/bin/env nix-shell
+#! nix-shell -i ruby -p ruby
+
+require 'json'
+
+PROTOCOL_VERSION = 0
+
+WINDOW_ID_NONE = -1
+WINDOW_ID_CURRENT = -2
+TAB_ID_NONE = -1
+
+module WebExtension
+  class <<self
+    def read()
+      length = $stdin.read(4).unpack1('L')
+      json = $stdin.read(length)
+      JSON.parse(json)
+    end
+
+    def write(obj)
+      json = JSON.generate(obj)
+      raise "tried to send object larger than maximum allowed 1 MiB, was #{json.length/1024/1024} MiB" if json.length > 1024*1024
+      $stdout.write([ json.length ].pack('L'))
+      $stdout.write(json)
+      $stdout.flush()
+    end
+  end
+end
+
+module API
+  class <<self
+    def call(command, *args)
+      WebExtension::write([ command, args ])
+    end
+
+    def console_log(*args)
+      call('console:log', *args)
+    end
+
+    def console_error(*args)
+      call('console:error', *args)
+    end
+  end
+end
+
+# alwaysOnTop: false
+# focused: true
+# height: 1080
+# id: 18
+# incognito: false
+# left: 0
+# state: "fullscreen"
+# title: "Toolbox - Extension / Help, I'm drowning in tabs! — Mozilla Firefox"
+# top: 0
+# type: "normal"
+# width: 1920
+# Window = Struct(
+#   :id,
+#   :type,
+#   :state,
+
+#   :title,
+
+#   :always_on_top?,
+#   :focused?,
+#   :incognito?,
+
+#   :width,
+#   :height,
+#   :top,
+#   :left,
+# )
+
+# active: true
+# attention: false
+# audible: false
+# cookieStoreId: "firefox-default"
+# discarded: false
+# favIconUrl: "chrome://branding/content/icon32.png"
+# height: 1006
+# hidden: false
+# highlighted: true
+# id: 2834
+# incognito: false
+# index: 1228
+# isArticle: false
+# isInReaderMode: false
+# lastAccessed: 1625021510454
+# mutedInfo: Object { muted: false }
+# pinned: false
+# sharingState: Object { camera: false, microphone: false }
+# status: "complete"
+# successorTabId: -1
+# title: "New Tab"
+# url: "about:newtab"
+# width: 1599
+# windowId: 18
+# Tab = Struct(
+#   :id,
+#   :window_id,
+#   :index,
+#   :successor_tab_id,
+#   :last_accessed,
+
+#   :status,
+#   :url,
+#   :icon_url,
+#   :title,
+  
+#   :active?,
+#   :attention?,
+#   :audible?,
+#   :pinned?,
+#   :hidden?,
+#   :discarded?,
+#   :incognito?,
+#   :selected?,
+
+#   :width,
+#   :height,
+
+#   :cookie_store_id,
+#   :article?,
+#   :in_reader_mode?,
+
+#   :muted_info,
+#   :sharing_state,
+# )
+
+# class State
+#   attr_reader :windows, :tabs
+
+#   def initialize(raw)
+#     @tabs = raw.concat_map
+#   end
+# end
+
+if $stdin.tty?
+  $stderr.puts 'TODO'
+  exit 1
+end
+
+WebExtension::write(PROTOCOL_VERSION)
+version = WebExtension::read()
+if version != PROTOCOL_VERSION
+  $stderr.puts "Extension protocol has an incompatible version! Wanted #{PROTOCOL_VERSION}, got #{version}"
+  exit 1
+end
+
+API::console_log('Native application successfully loaded.')
+
+loop do
+  command, data = WebExtension::read()
+
+  case command
+  when 'init:windows' then API::console_log("Initialised #{data.length} windows.")
+  when 'init:tabs' then API::console_log("Initialised #{data.length} tabs.")
+  when 'init:contexts' then API::console_log("Initialised #{data.length} contexts.")
+  
+  when 'window:create' then API::console_log('Window created', data)
+  when 'window:destroy' then API::console_log("Window #{data} destroyed")
+  when 'window:focus'
+    if data == WINDOW_ID_NONE
+      then API::console_log('Browser lost focus')
+      else API::console_log("Window #{data} focused")
+    end
+
+  when 'tab:create' then API::console_log('Tab created', data)
+  when 'tab:destroy' then API::console_log("Tab #{data[0]} destroyed in window #{data[1]}#{", due to the window closing" if data[2]}")
+  when 'tab:update' then API::console_log("Tab #{data[0]} updated", data[1])
+  when 'tab:activate' then API::console_log("Tab #{data[1]} in window #{data[0]} activated#{", previous tab was #{data[2]}" if not data[2].nil?}")
+  when 'tab:select' then API::console_log("Tabs #{data[1]} in window #{data[0]} selected")
+  when 'tab:detach' then API::console_log("Tab #{data[0]} detached from window #{data[1]} at position #{data[2]}")
+  when 'tab:attach' then API::console_log("Tab #{data[0]} attached to window #{data[1]} at position #{data[2]}")
+
+  when 'context:create' then API::console_error('context:create NYI')
+  when 'context:destroy' then API::console_error('context:destroy NYI')
+  when 'context:update' then API::console_error('context:update NYI')
+
+  else API::console_error("Unknown native command #{command}")
+  end
+end