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:
Defined in:
components/web_extension.crcomponents/web_extension/IPC.cr
components/web_extension/annotations.cr
Class Method Summary
-
.eval(js : String)
Evaluates js and gets the result back.
-
.uuid
Gets UUID hex string of the
WebView
which loads this extension
Macro Summary
-
function(arg_name)
This macro initializes an anonymous JavaScript function.
-
initialize_extension
Entry point of a Web Extension shared library
-
new(constructor, *args)
JavaScript's
new
operator, returnsJSCPrimative | JSCFunction | JSCObject
-
register_class(type)
Exposes a Crystal's Class so it can be used in JavaScript
-
undefined
JavaScript
undefined
Class Method Detail
Macro Detail
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
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
}
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
.