module WebExtension

Overview

According to architecture of WebKit2GTK, JavaScript code runs in a separeted process called Render Process. That's why extending JavaScript can not be done in the same process which manages the WebView. Instead WebKit2GTK proposes a new way to extend JavaScript with native code called WebExtension. A WebExtension is a shared library which will be loaded at runtime by Render Process. This module provides some simple macros to reduce redundant works in making a webExtension. The following code shows an simple example which provides a JS function. It reads given file on filesystem.

require "alizarin"
include WebExtension
initialize_extension do
  # code inside this block will be executed when this Web Extension is loaded by Render Process
  func = function params do
    if params.size != 1
      JSCFunction.raise "#{params.size} parameter(s) provided, expect 1"
      undefined
    else
      path = params.first.to_s
      File.read(path) rescue nil # Return content of file at *path*, otherwise return JS's null
    end
  end
  JSCContext.set_value("read_file", func)
end

Builds shared library:

$ crystal build --single-module --link-flags="-shared -fpic" -o <output-path> <source-file>

NOTE The shared library should be placed in the directory provided with WebView#extension_dir=

In main process (which manages an instance of WebView), opens WebInspector's console and types:

read_file("/a-file-located-some-where")

See more:

  1. JSCContext
  2. JSCFunction
  3. JSCPrimative
  4. JSCObject
  5. JSObjectUtils

Defined in:

components/web_extension.cr
components/web_extension/IPC.cr
components/web_extension/annotations.cr

Class Method Summary

Macro Summary

Class Method Detail

def self.eval(js : String) #

Evaluates js and gets the result back.


[View source]
def self.uuid #

Gets UUID hex string of the WebView which loads this extension


[View source]

Macro Detail

macro function(arg_name) #

This macro initializes an anonymous JavaScript function.

func = function p do
  puts typeof(p) # => Array(JSCFunction|JSCObject|JSCPrimative)
  # Developers can return anything as long as it has method to_jsc() : JSC::JSValue
  if p.size != 0
    JSCPrimative.new true
  else
    false
  else
  # return type is (JSCPrimative|Bool), it's ok because both JSCPrimative and Bool have method to_jsc()
end

[View source]
macro initialize_extension #

Entry point of a Web Extension shared library


[View source]
macro new(constructor, *args) #

JavaScript's new operator, returns JSCPrimative | JSCFunction | JSCObject

include WebExtension
promise = JSCContext.get_value("Promise")
new Promise, function p {
  resolve = p.first.as(JSCFunction)
  spawn do
    1000.times{ sleep 0.1 }
    resolve.call true
  end
}

[View source]
macro register_class(type) #

Exposes a Crystal's Class so it can be used in JavaScript

Example:

  • webextension.cr:
class File
  def initialize(p : [] of (JSCFunction | JSCObject | JSCPrimative))
    super(p.first.to_s)
  end

  @[JSCInstanceMethod]
  def content(p)
    self.seek(0)
    self.gets_to_end
  end
end
JSCContext.set_value "File", WebExtension.register_class(File)
  • index.js
var content = new File("./LICENSE").content();

See more at JSCInstanceMethod.


[View source]
macro undefined #

JavaScript undefined


[View source]