summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore10
-rw-r--r--Makefile.am101
-rw-r--r--configure.ac41
-rw-r--r--docs/reference/webhelper/Makefile.am.inc31
-rw-r--r--docs/reference/webhelper/eos.css46
-rw-r--r--jasmine.json10
-rw-r--r--test/Makefile.am.inc18
-rw-r--r--test/smoke-tests/webhelper/webview.js160
-rw-r--r--test/smoke-tests/webhelper/webview2.js147
-rw-r--r--test/webhelper/testLocal.js59
-rw-r--r--test/webhelper/testTranslate.js102
-rw-r--r--test/webhelper/testTranslate2.js214
-rw-r--r--test/webhelper/testUpdateFontSize.js97
-rw-r--r--test/webhelper/testWebActions.js141
-rw-r--r--test/webhelper/testWebActions2.js121
-rw-r--r--webhelper/lib/wh2private.c36
-rw-r--r--webhelper/lib/wh2private.h20
-rw-r--r--webhelper/webextensions/wh2extension.c588
-rw-r--r--webhelper/webextensions/wh2jscutil.c65
-rw-r--r--webhelper/webextensions/wh2jscutil.h25
-rw-r--r--webhelper/webhelper.js290
-rw-r--r--webhelper/webhelper2.js529
-rw-r--r--webhelper/webhelper_private/config.js.in1
23 files changed, 6 insertions, 2846 deletions
diff --git a/.gitignore b/.gitignore
index 274e0ae..6847fc3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,14 +6,11 @@ test/smoke-tests/hello
test/smoke-tests/images/credits.gresource
Endless-0.gir
Endless-0.typelib
-WebHelper2Private-1.0.gir
-WebHelper2Private-1.0.typelib
endless/eosresource.c
endless/eosresource-private.h
endless/eosversion.h
tools/eos-application-manifest/eos-application-manifest
tools/eos-json-extractor/eos-json-extractor
-webhelper/webhelper_private/config.js
*.py[cod]
@@ -129,10 +126,3 @@ run_coverage.coverage
# Editor stuff
*~
*.swp
-
-# NaturalDocs project files
-/docs/reference/webhelper/Data/
-/docs/reference/webhelper/Languages.txt
-/docs/reference/webhelper/Menu.txt
-/docs/reference/webhelper/Topics.txt
-/docs/reference/webhelper/html/
diff --git a/Makefile.am b/Makefile.am
index 1491997..9e30ce8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -29,8 +29,6 @@ AM_CFLAGS = @STRICT_CFLAGS@
AM_DISTCHECK_CONFIGURE_FLAGS = \
--enable-gtk-doc \
--enable-gir-doc \
- --enable-js-doc \
- --enable-webhelper \
$(NULL)
if EOS_ENABLE_COVERAGE
AM_DISTCHECK_CONFIGURE_FLAGS += --enable-coverage --with-coverage-dir=@EOS_COVERAGE_DIR@
@@ -51,36 +49,12 @@ dist-hook::
else
dist-hook::
@echo "***"
- @echo "*** You must configure with --enable-gtk-doc, --enable-gir-doc, and"
- @echo "*** --enable-js-doc to run make dist or make distcheck."
+ @echo "*** You must configure with --enable-gtk-doc and --enable-gir-doc"
+ @echo "*** to run make dist or make distcheck."
@echo "***"
@false
endif
-# # # SUBSTITUTED FILES # # #
-# These files need to be filled in with make variables
-
-subst = $(SED) \
- -e 's,%libexecdir%,$(libexecdir),g' \
- $(NULL)
-
-subst_files =
-if ENABLE_WEBHELPER
-subst_files += \
- webhelper/webhelper_private/config.js \
- $(NULL)
-endif ENABLE_WEBHELPER
-
-$(subst_files): %: %.in Makefile
- $(AM_V_GEN)$(MKDIR_P) $(@D) && \
- rm -f $@ $@.tmp && \
- $(subst) $< > $@.tmp && \
- chmod a-w $@.tmp && \
- mv $@.tmp $@
-
-CLEANFILES += $(subst_files)
-EXTRA_DIST += $(patsubst %,%.in,$(subst_files))
-
# # # LIBRARY # # #
# Main Open Endless SDK library
@@ -97,52 +71,6 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = @EOS_SDK_API_NAME@.pc
DISTCLEANFILES += @EOS_SDK_API_NAME@.pc
-# # # WEBHELPER LIBRARY # # #
-
-if ENABLE_WEBHELPER
-
-webhelper_sources = \
- webhelper/webhelper.js \
- webhelper/webhelper2.js \
- $(NULL)
-
-gjsmodulesdir = $(datadir)/gjs-1.0
-webhelperdir = $(gjsmodulesdir)
-webhelper_privatedir = $(webhelperdir)/webhelper_private
-dist_webhelper_DATA = \
- $(webhelper_sources) \
- $(NULL)
-dist_webhelper_private_DATA = \
- webhelper/webhelper_private/config.js \
- $(NULL)
-
-EOS_JS_COVERAGE_FILES += $(webhelper_sources)
-
-## Workaround for https://bugs.webkit.org/show_bug.cgi?id=116672
-## When that is solved, we can eliminate this private library and go back to
-## using pure Javascript in WebHelper.
-lib_LTLIBRARIES += libwebhelper2private.la
-libwebhelper2private_la_SOURCES = \
- webhelper/lib/wh2private.c \
- webhelper/lib/wh2private.h \
- $(NULL)
-libwebhelper2private_la_CPPFLAGS = @WEBHELPER2_PRIVATE_CFLAGS@
-libwebhelper2private_la_LIBADD = @WEBHELPER2_PRIVATE_LIBS@
-libwebhelper2private_la_LDFLAGS = -avoid-version
-
-webhelper2extensionsdir = $(libexecdir)/webhelper2
-webhelper2extensions_LTLIBRARIES = wh2extension.la
-wh2extension_la_SOURCES = \
- webhelper/webextensions/wh2extension.c \
- webhelper/webextensions/wh2jscutil.c \
- webhelper/webextensions/wh2jscutil.h \
- $(NULL)
-wh2extension_la_CPPFLAGS = @WEBHELPER2_EXTENSION_CFLAGS@
-wh2extension_la_LIBADD = @WEBHELPER2_EXTENSION_LIBS@
-wh2extension_la_LDFLAGS = -module -avoid-version -no-undefined
-
-endif ENABLE_WEBHELPER
-
# # # INTROSPECTION FILES # # #
-include $(INTROSPECTION_MAKEFILE)
@@ -169,20 +97,6 @@ Endless_@EOS_SDK_API_VERSION@_gir_FILES = $(introspection_sources)
Endless_@EOS_SDK_API_VERSION@_gir_EXPORT_PACKAGES = @EOS_SDK_API_NAME@
INTROSPECTION_GIRS += Endless-@EOS_SDK_API_VERSION@.gir
-if ENABLE_WEBHELPER
-
-WebHelper2Private-1.0.gir: libwebhelper2private.la
-WebHelper2Private_1_0_gir_INCLUDES = GObject-2.0 GLib-2.0 WebKit2-4.0
-WebHelper2Private_1_0_gir_SCANNERFLAGS = \
- --identifier-prefix=Wh2 \
- --symbol-prefix=wh2 \
- $(NULL)
-WebHelper2Private_1_0_gir_LIBS = libwebhelper2private.la
-WebHelper2Private_1_0_gir_FILES = $(libwebhelper2private_la_SOURCES)
-INTROSPECTION_GIRS += WebHelper2Private-1.0.gir
-
-endif ENABLE_WEBHELPER
-
girdir = $(datadir)/gir-1.0
gir_DATA = $(INTROSPECTION_GIRS)
@@ -365,12 +279,6 @@ nobase_dist_licenses_DATA = licenses/creativecommons/C/CC-BY-2.0.html \
licenses/includes/zero.css \
$(NULL)
-# # # PURE JAVASCRIPT MODULE DOCUMENTATION # # #
-
-if ENABLE_WEBHELPER
-include $(top_srcdir)/docs/reference/webhelper/Makefile.am.inc
-endif ENABLE_WEBHELPER
-
# # # GJS OVERRIDES # # #
include $(top_srcdir)/overrides/Makefile.am.inc
@@ -400,9 +308,4 @@ AM_JS_LOG_FLAGS += @EOS_JS_COVERAGE_LOG_FLAGS@
AM_CFLAGS += @EOS_C_COVERAGE_CFLAGS@
AM_LDFLAGS = @EOS_C_COVERAGE_LDFLAGS@
-if ENABLE_WEBHELPER
-libwebhelper2private_la_LDFLAGS += @EOS_C_COVERAGE_LDFLAGS@
-wh2extension_la_LDFLAGS += @EOS_C_COVERAGE_LDFLAGS@
-endif ENABLE_WEBHELPER
-
clean-local:: clean-coverage
diff --git a/configure.ac b/configure.ac
index 77389a9..7001a30 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,7 +81,6 @@ GOBJECT_REQUIREMENT="gobject-2.0"
GIO_REQUIREMENT="gio-2.0"
GTK_REQUIREMENT="gtk+-3.0 >= 3.20"
JSON_GLIB_REQUIREMENT="json-glib-1.0 >= 0.12"
-WEBKIT2_REQUIREMENT="webkit2gtk-4.0"
EOSMETRICS_REQUIREMENT="eosmetrics-0"
# These go into the pkg-config file as Requires: and Requires.private:
# (Generally, use Requires.private: instead of Requires:)
@@ -122,8 +121,6 @@ AC_PATH_PROG([GIRDOCTOOL], [g-ir-doc-tool], [notfound])
AC_ARG_VAR([GIRDOCTOOL], [Path to g-ir-doc-tool])
AC_PATH_PROG([YELPBUILD], [yelp-build], [notfound])
AC_ARG_VAR([YELPBUILD], [Path to yelp-build])
-AC_PATH_PROG([NATURALDOCS], [naturaldocs], [notfound])
-AC_ARG_VAR([NATURALDOCS], [Path to naturaldocs])
GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0`
AC_SUBST(GLIB_COMPILE_RESOURCES)
@@ -180,12 +177,6 @@ AS_IF([test "x$enable_metrics" != "xno"], [
AC_DEFINE([USE_METRICS])
EOS_REQUIRED_MODULES_PRIVATE="$EOS_REQUIRED_MODULES_PRIVATE $EOSMETRICS_REQUIREMENT"])
-# --disable-webhelper: Don't build WebHelper. Use this if you just want a quick
-# Endless SDK without the webkit dependency.
-AC_ARG_ENABLE([webhelper], [AS_HELP_STRING([--disable-webhelper],
- [WebHelper requires WebKit dependency @<:@default=yes@:>@])])
-AM_CONDITIONAL([ENABLE_WEBHELPER], [test "x$enable_webhelper" != "xno"])
-
# --enable-gir-doc: Build GIR documentation for Javascript. Done automatically
# during 'make distcheck'.
AC_ARG_ENABLE([gir-doc],
@@ -198,22 +189,12 @@ AS_IF([test "x$enable_gir_doc" = "xyes"], [
[AC_MSG_ERROR([yelp-build must be installed for --enable-gir-doc])])])
AM_CONDITIONAL([ENABLE_GIR_DOC], [test "x$enable_gir_doc" = "xyes"])
-# --enable-js-doc: Build pure Javascript module documentation.
-AC_ARG_ENABLE([js-doc],
- [AS_HELP_STRING([--enable-js-doc],
- [Build documentation for pure Javascript modules @<:@default=no@:>@])])
-AS_IF([test "x$enable_js_doc" = "xyes"], [
- AS_IF([test "x$NATURALDOCS" = "xnotfound"],
- [AC_MSG_ERROR([NaturalDocs must be installed for --enable-js-doc])])])
-AM_CONDITIONAL([ENABLE_JS_DOC], [test "x$enable_js_doc" = "xyes"])
-
-# For 'make dist' or 'make distcheck', all three of --enable-gtk-doc,
-# --enable-gir-doc, and --enable-js-doc are required
+# For 'make dist' or 'make distcheck', both of --enable-gtk-doc and
+# --enable-gir-doc are required
AC_MSG_CHECKING([whether this configuration allows building distributions])
can_make_dist=yes
AM_COND_IF([ENABLE_GTK_DOC], [], [can_make_dist=no])
AM_COND_IF([ENABLE_GIR_DOC], [], [can_make_dist=no])
-AM_COND_IF([ENABLE_JS_DOC], [], [can_make_dist=no])
AM_CONDITIONAL([CAN_MAKE_DIST], [test "x$can_make_dist" = "xyes"])
AC_MSG_RESULT([$can_make_dist])
@@ -233,21 +214,6 @@ PKG_CHECK_MODULES([EOS_SDK], [
$EOS_REQUIRED_MODULES
$EOS_REQUIRED_MODULES_PRIVATE])
-AS_IF([test "x$enable_webhelper" != "xno"], [
- PKG_CHECK_MODULES([WEBHELPER2_EXTENSION], [
- $GLIB_REQUIREMENT
- $GOBJECT_REQUIREMENT
- $WEBKIT2_REQUIREMENT])
- PKG_CHECK_MODULES([WEBHELPER2_PRIVATE], [
- $GLIB_REQUIREMENT
- $WEBKIT2_REQUIREMENT])
-
- # Check installed GIRs for webhelper JS module
- EOS_CHECK_GJS_GIR([GLib], [2.0])
- EOS_CHECK_GJS_GIR([WebKit], [3.0])
- EOS_CHECK_GJS_GIR([WebKit2], [4.0])
-])
-
# Code coverage reports support
EOS_COVERAGE_REPORT([c js])
@@ -266,9 +232,6 @@ AC_CONFIG_FILES([
tools/eos-json-extractor/eos-json-extractor
])
AC_CONFIG_HEADERS([config.h]) dnl Header with system-dependent #defines
-# Make docs/reference/webhelper/eos.css available in the build tree as well as
-# the source tree
-AC_CONFIG_LINKS([docs/reference/webhelper/eos.css:docs/reference/webhelper/eos.css])
# Do the output
AC_OUTPUT
diff --git a/docs/reference/webhelper/Makefile.am.inc b/docs/reference/webhelper/Makefile.am.inc
deleted file mode 100644
index 55caccf..0000000
--- a/docs/reference/webhelper/Makefile.am.inc
+++ /dev/null
@@ -1,31 +0,0 @@
-if ENABLE_JS_DOC
-
-build_naturaldocs_verbose = $(build_naturaldocs_verbose_@AM_V@)
-build_naturaldocs_verbose_ = $(build_naturaldocs_verbose_@AM_DEFAULT_V@)
-build_naturaldocs_verbose_0 = @echo ' DOC Building WebHelper docs';
-
-docs/reference/webhelper/doc-build.stamp: webhelper/webhelper.js docs/reference/webhelper/eos.css
- $(build_naturaldocs_verbose)$(MKDIR_P) $(@D)/html && \
- naturaldocs -i $(<D) -o HTML $(@D)/html -p $(@D) -s Default eos -hl All
-
-all-local: docs/reference/webhelper/doc-build.stamp
-
-webhelper_extra_clean_files = \
- docs/reference/webhelper/Data/*.nd \
- docs/reference/webhelper/Menu.txt \
- docs/reference/webhelper/Topics.txt \
- docs/reference/webhelper/Languages.txt \
- $(NULL)
-EXTRA_DIST += docs/reference/webhelper/eos.css
-DISTCLEANFILES += \
- $(webhelper_extra_clean_files) \
- $(NULL)
-
-distclean-local:
- @rm -rf docs/reference/webhelper/html
-
-dist-hook::
- @mkdir -p $(distdir)/docs/reference/webhelper/html
- @cp -r docs/reference/webhelper/html/* $(distdir)/docs/reference/webhelper/html
-
-endif
diff --git a/docs/reference/webhelper/eos.css b/docs/reference/webhelper/eos.css
deleted file mode 100644
index 0bed010..0000000
--- a/docs/reference/webhelper/eos.css
+++ /dev/null
@@ -1,46 +0,0 @@
-* {
- font-family: "Lato";
-}
-
-p {
- font-size: 15pt;
- text-indent: 0;
- margin-bottom: 1em;
-}
-
-.STitle,
-.CTitle,
-.CGroup .CTitle {
- font-size: 17pt;
-}
-
-.CHeading {
- font-size: 13pt;
-}
-
-.SMain td,
-.SClass td,
-.STable,
-.CDLEntry,
-.CDLDescription {
- font-size: 11pt;
-}
-
-.ContentPage #Content,
-.IndexPage #Index {
- margin-left: 55ex;
-}
-
-.ContentPage #Menu,
-.IndexPage #Menu {
- font-size: 11pt;
- width: 41ex;
-}
-
-.Prototype *,
-.prettyprint *,
-.CBody pre,
-.CDLEntry {
- font-family: "DejaVu Sans Mono", Menlo, monospace;
- font-size: 12pt;
-} \ No newline at end of file
diff --git a/jasmine.json b/jasmine.json
index 440dca1..f6eecfd 100644
--- a/jasmine.json
+++ b/jasmine.json
@@ -1,23 +1,15 @@
{
- "include_paths": ["webhelper", "."],
+ "include_paths": ["."],
"options": "--verbose",
"spec_files": [
"test/endless",
- "test/webhelper/testTranslate2.js",
- "test/webhelper",
"test/tools/eos-application-manifest",
"test/tools/testHtmlExtractor.js"
],
- "exclude": [
- "test/webhelper/testTranslate.js",
- "test/webhelper/testUpdateFontSize.js",
- "test/webhelper/testWebActions.js"
- ],
"environment": {
"GI_TYPELIB_PATH": ".",
"LD_LIBRARY_PATH": ".libs",
"TOP_SRCDIR": ".",
- "WEBHELPER_UNINSTALLED_EXTENSION_DIR": ".libs",
"XDG_CONFIG_HOME": "/tmp"
}
}
diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc
index 0d74647..98ec69e 100644
--- a/test/Makefile.am.inc
+++ b/test/Makefile.am.inc
@@ -56,17 +56,6 @@ EXTRA_DIST += \
test/utils.js \
$(NULL)
-if ENABLE_WEBHELPER
-javascript_tests += \
- test/webhelper/testLocal.js \
- test/webhelper/testTranslate.js \
- test/webhelper/testTranslate2.js \
- test/webhelper/testWebActions.js \
- test/webhelper/testWebActions2.js \
- test/webhelper/testUpdateFontSize.js \
- $(NULL)
-endif ENABLE_WEBHELPER
-
# Run tests when running 'make check'
TESTS = \
test/endless/run-tests \
@@ -86,16 +75,12 @@ AM_JS_LOG_FLAGS = \
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh
LOG_COMPILER = $(top_srcdir)/test/tap-test.sh
EXTRA_DIST += \
- test/tap-test.sh
+ test/tap-test.sh \
test/run-with-dbus \
test/test-bus.conf \
$(NULL)
CLEANFILES += stderr.log
-if ENABLE_WEBHELPER
-AM_JS_LOG_FLAGS += --include-path=$(top_srcdir)/webhelper
-endif ENABLE_WEBHELPER
-
# Use locally built versions of Endless-0.gir and libraries; this may need to be
# changed to AM_TESTS_ENVIRONMENT in a future version of Automake
# Set XDG_CONFIG_HOME so as to avoid cluttering the user's actual config
@@ -105,7 +90,6 @@ TESTS_ENVIRONMENT = \
export GI_TYPELIB_PATH="$(top_builddir)$${GI_TYPELIB_PATH:+:$$GI_TYPELIB_PATH}"; \
export LD_LIBRARY_PATH="$(top_builddir)/.libs$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH}"; \
export XDG_CONFIG_HOME=`mktemp -d $${TMPDIR:-/tmp}/sdktestconfig.XXXXXXXX`; \
- export WEBHELPER_UNINSTALLED_EXTENSION_DIR="$(top_builddir)/.libs"; \
export TOP_SRCDIR="$(abs_top_srcdir)"; \
export BUILDDIR="."; \
$(NULL)
diff --git a/test/smoke-tests/webhelper/webview.js b/test/smoke-tests/webhelper/webview.js
deleted file mode 100644
index a1dba65..0000000
--- a/test/smoke-tests/webhelper/webview.js
+++ /dev/null
@@ -1,160 +0,0 @@
-//Copyright 2013 Endless Mobile, Inc.
-
-const Endless = imports.gi.Endless;
-const GLib = imports.gi.GLib;
-const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
-const WebHelper = imports.webhelper;
-const WebKit = imports.gi.WebKit;
-
-const TEST_APPLICATION_ID = 'com.endlessm.example.test-webview';
-
-const TEST_HTML = '\
-<html> \
-<head> \
-<title>First page</title> \
-<style> \
-p, form { \
- width: 50%; \
- padding: 1em; \
- background: #FFFFFF; \
-} \
-body { \
- background: #EEEEEE; \
-} \
-</style> \
-</head> \
-\
-<body> \
-<h1>First page</h1> \
-\
-<p><a href="endless://moveToPage?name=page2">Move to page 2</a></p> \
-\
-<p><a \
-href="endless://showMessageFromParameter?msg=This%20is%20a%20message%20from%20the%20URL%20parameter">Show \
-message from parameter in this URL</a></p> \
-\
-<form action="endless://showMessageFromParameter"> \
-<input name="msg" value="I am in a form!"/> \
-<input type="submit" value="Show message using a form"/> \
-</form> \
-\
-<p> \
-<input id="inputformessage" value="my ID is inputformessage"/> \
-<a href="endless://showMessageFromInputField?id=inputformessage">Show message \
-using the &lt;input&gt;\'s ID</a> \
-</p> \
-\
-<p><a href="http://wikipedia.org">Regular link to a Web site</a></p> \
-\
-<p><a href="endless://addStars?id=starspan">I want \
-stars!</a> <span id="starspan"/></p> \
-\
-<p>This is text that will be italicized: <span name="translatable">Hello, \
-world!</span></p> \
-\
-</body> \
-</html>';
-
-const TestApplication = new Lang.Class({
- Name: 'TestApplication',
- Extends: WebHelper.Application,
-
- /* *** ACTIONS AVAILABLE FROM THE WEB VIEW *** */
-
- /* dict['name'] is the name of the page to move to */
- moveToPage: function(dict) {
- this._pm.visible_child_name = dict['name'];
- },
-
- /* dict['msg'] is the message to display */
- showMessageFromParameter: function(dict) {
- let dialog = new Gtk.MessageDialog({
- buttons: Gtk.ButtonsType.CLOSE,
- message_type: Gtk.MessageType.INFO,
- text: dict['msg']
- });
- dialog.set_transient_for(this._window);
- dialog.run();
- dialog.destroy();
- },
-
- /* dict['id'] is the ID of the input field to use */
- showMessageFromInputField: function(dict) {
- let input = this._getElementById(this._webview, dict['id']);
-
- // WebKitDOMHTMLInputElement
- let msg = input.get_value();
-
- let dialog = new Gtk.MessageDialog({
- buttons: Gtk.ButtonsType.CLOSE,
- message_type: Gtk.MessageType.INFO,
- text: msg
- });
- dialog.set_transient_for(this._window);
- dialog.run();
- dialog.destroy();
- },
-
- /* dict['id'] is the ID of the element to use */
- addStars: function(dict) {
- let e = this._getElementById(this._webview, dict['id']);
- e.inner_text += '★ ';
- },
-
- /* *************************** */
-
- vfunc_startup: function() {
- this.parent();
-
- this.set_translation_function(function(string) {
- return string.italics();
- });
- this.define_web_actions({
- moveToPage: this.moveToPage,
- showMessageFromParameter: this.showMessageFromParameter,
- showMessageFromInputField: this.showMessageFromInputField,
- addStars: this.addStars
- });
-
- this._webview = new WebKit.WebView();
- this._webview.load_string(TEST_HTML, 'text/html', 'UTF-8', 'file://');
- this._webview.connect('notify::load-status',
- Lang.bind(this, function (webview) {
- if (webview.load_status == WebKit.LoadStatus.FINISHED)
- this.translate_html(webview);
- }));
-
- this._webview.connect('navigation-policy-decision-requested',
- Lang.bind(this, this.web_actions_handler));
-
- this._page1 = new Gtk.ScrolledWindow();
- this._page1.add(this._webview);
-
- this._page2 = new Gtk.Grid();
- let back_button = new Gtk.Button({ label:"Go back to page 1" });
- back_button.connect('clicked', Lang.bind(this, function() {
- this._pm.visible_child_name = 'page1';
- }));
- this._page2.add(back_button);
-
- this._window = new Endless.Window({
- application: this,
- border_width: 16
- });
-
- this._pm = this._window.page_manager;
- this._pm.set_transition_type(Gtk.StackTransitionType.CROSSFADE);
- this._pm.add(this._page1, { name: 'page1' });
- this._pm.add(this._page2, { name: 'page2' });
- this._pm.visible_child = this._page1;
-
- this._window.show_all();
- }
-});
-
-let app = new TestApplication({
- application_id: TEST_APPLICATION_ID,
- flags: 0
-});
-app.run(ARGV);
diff --git a/test/smoke-tests/webhelper/webview2.js b/test/smoke-tests/webhelper/webview2.js
deleted file mode 100644
index f50c42d..0000000
--- a/test/smoke-tests/webhelper/webview2.js
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2015 Endless Mobile, Inc.
-
-const Endless = imports.gi.Endless;
-const Gettext = imports.gettext;
-const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
-const WebHelper2 = imports.webhelper2;
-const WebKit2 = imports.gi.WebKit2;
-
-const TEST_APPLICATION_ID = 'com.endlessm.example.test-webview2';
-const TEST_HTML = '\
-<html> \
-<head> \
-<title>First page</title> \
-<style> \
-p, form { \
- width: 50%; \
- padding: 1em; \
- background: #FFFFFF; \
-} \
-body { \
- background: #EEEEEE; \
-} \
-</style> \
-</head> \
-\
-<body> \
-<script type="text/javascript"> \
- window.ngettextButton = (function () { \
- var times = 0; \
- return function () { \
- times++; \
- var message = ngettext("You have clicked me __ time", "You have clicked me __ times", times); \
- alert(message.replace("__", times.toString())); \
- }; \
- })(); \
-</script> \
-<h1>First page</h1> \
-\
-<p><a href="webhelper://moveToPage?name=page2">Move to page 2</a></p> \
-\
-<p><a \
-href="webhelper://showMessageFromParameter?msg=This%20is%20a%20message%20from%20the%20URL%20parameter">Show \
-message from parameter in this URL</a></p> \
-\
-<form action="webhelper://showMessageFromParameter"> \
-<input name="msg" value="I am in a form!"/> \
-<input type="submit" value="Show message using a form"/> \
-</form> \
-\
-<p><a href="http://wikipedia.org">Regular link to a Web site</a></p> \
-\
-<p>This is text that will be italicized: <span name="translatable">Hello, \
-world!</span></p> \
-\
-<p> \
- <button onclick="alert(gettext(\'I came from gettext\'));"> \
- Click me to use gettext \
- </button> \
- <button onclick="ngettextButton();">Click me to use ngettext</button> \
-</p> \
-\
-</body> \
-</html>';
-
-const TestApplication = new Lang.Class({
- Name: 'TestApplication',
- Extends: Endless.Application,
-
- vfunc_dbus_register: function (connection, object_path) {
- this._webhelper = new WebHelper2.WebHelper({
- well_known_name: this.application_id,
- connection: connection,
- });
- return this.parent(connection, object_path);
- },
-
- vfunc_startup: function () {
- this.parent();
-
- this._webhelper.set_gettext((s) => s.italics());
- this._webhelper.set_ngettext((s, p, n) =>
- '** ' + (n == 1 ? s : p) + ' **');
- this._webhelper.define_web_actions({
- moveToPage: this.moveToPage.bind(this),
- showMessageFromParameter: this.showMessageFromParameter.bind(this),
- });
-
- this._webview = new WebKit2.WebView();
- this._webview.connect('load-changed', (webview, event) => {
- if (event === WebKit2.LoadEvent.FINISHED)
- this._webhelper.translate_html(webview, null, (obj, res) => {
- this._webhelper.translate_html_finish(res);
- });
- });
- this._webview.load_html(TEST_HTML, null);
-
- this._page2 = new Gtk.Grid();
- let back_button = new Gtk.Button({ label: 'Go back to page 1' });
- back_button.connect('clicked', () => {
- this._pm.visible_child_name = 'page1';
- });
- this._page2.add(back_button);
-
- this._window = new Endless.Window({
- application: this,
- border_width: 16,
- });
-
- this._pm = this._window.page_manager;
- this._pm.set_transition_type(Gtk.StackTransitionType.CROSSFADE);
- this._pm.add(this._webview, { name: 'page1' });
- this._pm.add(this._page2, { name: 'page2' });
- this._pm.visible_child_name = 'page1';
-
- this._window.show_all();
- },
-
- vfunc_dbus_unregister: function (connection, object_path) {
- this.parent(connection, object_path);
- this._webhelper.unregister();
- },
-
- // WEB ACTIONS
-
- // dict['name'] is the name of the page to move to
- moveToPage: function (dict) {
- this._pm.visible_child_name = dict['name'];
- },
-
- // dict['msg'] is the message to display
- showMessageFromParameter: function (dict) {
- let dialog = new Gtk.MessageDialog({
- buttons: Gtk.ButtonsType.CLOSE,
- message_type: Gtk.MessageType.INFO,
- text: dict['msg'],
- transient_for: this._window,
- });
- dialog.run();
- dialog.destroy();
- },
-});
-
-let app = new TestApplication({
- application_id: TEST_APPLICATION_ID,
-});
-app.run(ARGV);
diff --git a/test/webhelper/testLocal.js b/test/webhelper/testLocal.js
deleted file mode 100644
index d65e6c7..0000000
--- a/test/webhelper/testLocal.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2015 Endless Mobile, Inc.
-
-const Gio = imports.gi.Gio;
-const GLib = imports.gi.GLib;
-const Gtk = imports.gi.Gtk;
-const WebHelper2 = imports.webhelper2;
-const WebKit2 = imports.gi.WebKit2;
-
-const WELL_KNOWN_NAME = 'com.endlessm.WebHelper.testLocal';
-
-Gtk.init(null);
-
-describe('Local URI scheme', function () {
- let owner_id, connection, webview, webhelper;
-
- beforeAll(function (done) {
- owner_id = Gio.DBus.own_name(Gio.BusType.SESSION, WELL_KNOWN_NAME,
- Gio.BusNameOwnerFlags.NONE,
- null, // bus acquired
- (con, name) => { // name acquired
- connection = con;
- done();
- },
- null); // name lost
- });
-
- afterAll(function () {
- Gio.DBus.unown_name(owner_id);
- });
-
- beforeEach(function () {
- webhelper = new WebHelper2.WebHelper({
- well_known_name: WELL_KNOWN_NAME,
- connection: connection,
- });
- webview = new WebKit2.WebView();
- });
-
- afterEach(function () {
- webhelper.unregister();
- });
-
- it('loads a local file', function (done) {
- let path = GLib.build_filenamev([GLib.getenv('TOP_SRCDIR'), 'test',
- 'tools', 'test.html']);
- let test_file = Gio.File.new_for_path(path);
-
- let error_spy = jasmine.createSpy('error_spy');
- webview.connect('load-failed', error_spy);
- let id = webview.connect('load-changed', (webview, event) => {
- if (event === WebKit2.LoadEvent.FINISHED) {
- webview.disconnect(id);
- expect(error_spy).not.toHaveBeenCalled();
- done();
- }
- });
- webview.load_uri(test_file.get_uri().replace(/^file:/, 'local:'));
- });
-});
diff --git a/test/webhelper/testTranslate.js b/test/webhelper/testTranslate.js
deleted file mode 100644
index da8c77a..0000000
--- a/test/webhelper/testTranslate.js
+++ /dev/null
@@ -1,102 +0,0 @@
-const Endless = imports.gi.Endless;
-const GLib = imports.gi.GLib;
-const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
-const WebHelper = imports.webhelper;
-const WebKit = imports.gi.WebKit;
-
-const WebHelperApplicationWithTranslatableText = new Lang.Class({
- Name: 'WebHelperApplicationWithTranslatableText',
- Extends: WebHelper.Application,
-
- get_translation_string: function() {
- return 'Translate Me';
- },
-
- vfunc_startup: function() {
- this.parent();
- this.webview = new WebKit.WebView();
- let string = '<html><body><p name="translatable">' +
- this.get_translation_string() +
- '</p></body></html>';
- this.webview.load_string(string, 'text/html', 'UTF-8', 'file://');
- this.win = new Endless.Window({
- application: this
- });
- this.scrolled = new Gtk.ScrolledWindow();
- this.scrolled.add(this.webview);
- this.win.page_manager.add(this.scrolled);
-
- this.webview.connect('notify::load-status', Lang.bind(this, function() {
- if(this.webview.load_status === WebKit.LoadStatus.FINISHED) {
- this.translate_html(this.webview);
- this.quit();
- }
- }));
- }
-});
-
-describe("Translation strategy", function() {
- let app;
-
- beforeEach(function() {
- // FIXME In this version of GJS there is no Posix module, so fake the PID
- let id_string = 'com.endlessm.webhelper.test' + GLib.get_real_time() + fake_pid;
- // Generate a unique ID for each app instance that we test
- let fake_pid = GLib.random_int();
- app = new WebHelperApplicationWithTranslatableText({
- application_id: id_string
- });
- });
-
- describe("translation function", function() {
- let translationFunctionSpy;
- beforeEach(function() {
- translationFunctionSpy = jasmine.createSpy('translate').and.returnValue('Translated');
- });
- it("gets called with string to translate on run", function() {
- app.set_translation_function(translationFunctionSpy);
- app.run([]);
- expect(translationFunctionSpy).toHaveBeenCalledWith(app.get_translation_string());
- });
- });
-
- it("throws when an incompatible type is set as the translation function", function() {
- expect(function() {
- app.set_translation_function({});
- }).toThrow();
- });
-
- // Can't test this right now as there is no support for propagating exceptions across
- // GI interfaces
- xit("throws when there isn't a translation function set", function() {
- expect(function() {
- app.run([]);
- }).toThrow();
- });
-
- it("has a null translation function by default", function() {
- expect(app.get_translation_function()).toBe(null);
- });
-
- it("stores the expected translation function", function() {
- let translation = function(str) {
- return str;
- };
-
- app.set_translation_function(translation);
- expect(app.get_translation_function()).toBe(translation);
- });
-
- it("allows us to store a null translation function", function() {
- let nonNullTranslation = function(str) {
- return str;
- }
-
- // set a non-null translation function first so that we get
- // the non-default behaviour for get_translation_function
- app.set_translation_function(nonNullTranslation);
- app.set_translation_function(null);
- expect(app.get_translation_function()).toBe(null);
- });
-});
diff --git a/test/webhelper/testTranslate2.js b/test/webhelper/testTranslate2.js
deleted file mode 100644
index 6ce4776..0000000
--- a/test/webhelper/testTranslate2.js
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright 2015 Endless Mobile, Inc.
-
-const Gio = imports.gi.Gio;
-const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
-const Mainloop = imports.mainloop;
-const WebHelper2 = imports.webhelper2;
-const WebKit2 = imports.gi.WebKit2;
-
-const WELL_KNOWN_NAME = 'com.endlessm.WebHelper.testTranslate2';
-
-/* CAUTION:
- * All tests trying to use the translation functionality of WebHelper2 must be
- * run in this file, and this file must be run before any other WebHelper2
- * tests in the same process.
- * That is because we can only tell the default web context to load web
- * extensions with user data once per process. WebHelper doesn't support web
- * contexts other than the default one.
- */
-
-Gtk.init(null);
-
-describe('WebHelper2 translator', function () {
- let webhelper, owner_id, connection;
-
- beforeAll(function (done) {
- owner_id = Gio.DBus.own_name(Gio.BusType.SESSION, WELL_KNOWN_NAME,
- Gio.BusNameOwnerFlags.NONE,
- null, // bus acquired
- (con, name) => { // name acquired
- connection = con;
- done();
- },
- null); // name lost
- });
-
- afterAll(function () {
- Gio.DBus.unown_name(owner_id);
- });
-
- beforeEach(function () {
- webhelper = new WebHelper2.WebHelper({
- well_known_name: WELL_KNOWN_NAME,
- connection: connection,
- });
- });
-
- afterEach(function () {
- webhelper.unregister();
- });
-
- it('complains about a bad gettext function', function () {
- expect(function () {
- webhelper.set_gettext('I am not a function');
- }).toThrow();
- });
-
- it('gets and sets the gettext function', function () {
- let translation_function = (s) => s;
- webhelper.set_gettext(translation_function);
- expect(webhelper.get_gettext()).toBe(translation_function);
- });
-
- it('has a null gettext function by default', function () {
- expect(webhelper.get_gettext()).toBeNull();
- });
-
- it('can remove the gettext function by setting null', function () {
- webhelper.set_gettext((s) => s);
- expect(webhelper.get_gettext()).not.toBeNull();
- webhelper.set_gettext(null);
- expect(webhelper.get_gettext()).toBeNull();
- });
-
- it('complains about a bad ngettext function', function () {
- expect(function () {
- webhelper.set_ngettext('I am not a function');
- }).toThrow();
- });
-
- it('gets and sets the ngettext function', function () {
- let translation_function = (s, p, n) => n == 1 ? s : p;
- webhelper.set_ngettext(translation_function);
- expect(webhelper.get_ngettext()).toBe(translation_function);
- });
-
- it('has a null ngettext function by default', function () {
- expect(webhelper.get_ngettext()).toBeNull();
- });
-
- it('can remove the ngettext function by setting null', function () {
- webhelper.set_ngettext((s, p, n) => n == 1 ? s : p);
- expect(webhelper.get_ngettext()).not.toBeNull();
- webhelper.set_ngettext(null);
- expect(webhelper.get_ngettext()).toBeNull();
- });
-
- describe('translating a page', function () {
- let webview, gettext_spy;
- const MINIMAL_HTML = '<p name="translatable">Translate Me</p>';
-
- function run_loop(html=MINIMAL_HTML) {
- let error_spy = jasmine.createSpy('error_spy');
- webview.connect('load-failed', error_spy);
- let id = webview.connect('load-changed', (webview, event) => {
- if (event === WebKit2.LoadEvent.FINISHED) {
- webhelper.translate_html(webview, null, (obj, res) => {
- expect(function () {
- webhelper.translate_html_finish(res);
- }).not.toThrow();
- webview.disconnect(id);
- expect(error_spy).not.toHaveBeenCalled();
- Mainloop.quit('webhelper2');
- });
- }
- });
- webview.load_html('<html><body>' + html + '</body></html>', null);
- Mainloop.run('webhelper2');
- }
-
- beforeEach(function () {
- webview = new WebKit2.WebView();
- gettext_spy = jasmine.createSpy('gettext_spy').and.callFake((s) => s);
- webhelper.set_gettext(gettext_spy);
- });
-
- it('translates a string', function () {
- run_loop();
- expect(gettext_spy).toHaveBeenCalledWith('Translate Me');
- });
-
- // The following test is disabled because GJS cannot catch exceptions
- // across FFI interfaces (e.g. in GObject callbacks.)
- xit('complains about a gettext function not being set', function () {
- expect(function () {
- run_loop();
- }).toThrow();
- });
-
- it('can cancel the translation operation', function (done) {
- webhelper.set_gettext((s) => s);
- let error_spy = jasmine.createSpy('error_spy');
- webview.connect('load-failed', error_spy);
- let id = webview.connect('load-changed', (webview, event) => {
- if (event === WebKit2.LoadEvent.FINISHED) {
- let cancellable = new Gio.Cancellable();
- cancellable.cancel();
- webhelper.translate_html(webview, cancellable, (obj, res) => {
- expect(function () {
- webhelper.translate_html_finish(res);
- }).toThrow();
- webview.disconnect(id);
- expect(error_spy).not.toHaveBeenCalled();
- done();
- });
- }
- });
- webview.load_html('<html><body></body></html>', null);
- });
-
- it('normalizes a string before translating it', function () {
- run_loop('<p name="translatable">\n\
- Translate Me\n\
- </p>');
- expect(gettext_spy).toHaveBeenCalledWith('Translate Me');
- });
-
- it('handles quotes correctly', function () {
- run_loop('<p name="translatable">String with "quotes"</p>');
- expect(gettext_spy).toHaveBeenCalledWith('String with "quotes"');
- });
-
- it('handles embedded tags correctly', function () {
- run_loop('<p name="translatable">Embedded<br><b>tags</b></p>');
- expect(gettext_spy).toHaveBeenCalledWith('Embedded<br><b>tags</b>');
- });
- });
-
- describe('used from client-side Javascript', function () {
- let webview;
-
- beforeEach(function () {
- webview = new WebKit2.WebView();
- });
-
- function load_script(view, script) {
- view.load_html('<html><body><script type="text/javascript">' +
- script + '</script></body></html>', null);
- Mainloop.run('webhelper2');
- }
-
- it('translates a string with gettext()', function (done) {
- let gettext_spy = jasmine.createSpy('gettext_spy').and.callFake((s) => {
- Mainloop.quit('webhelper2');
- return s;
- });
- webhelper.set_gettext(gettext_spy);
- load_script(webview, 'gettext("Translate Me");');
- expect(gettext_spy).toHaveBeenCalledWith('Translate Me');
- done();
- });
-
- it('translates a string with ngettext()', function (done) {
- let ngettext_spy = jasmine.createSpy('ngettext_spy').and.callFake((s, p, n) => {
- Mainloop.quit('webhelper2');
- return n == 1 ? s : p;
- });
- webhelper.set_ngettext(ngettext_spy);
- load_script(webview, 'ngettext("File", "Files", 3);');
- expect(ngettext_spy).toHaveBeenCalledWith('File', 'Files', 3);
- done();
- });
- });
-});
diff --git a/test/webhelper/testUpdateFontSize.js b/test/webhelper/testUpdateFontSize.js
deleted file mode 100644
index dd45d6f..0000000
--- a/test/webhelper/testUpdateFontSize.js
+++ /dev/null
@@ -1,97 +0,0 @@
-const Endless = imports.gi.Endless;
-const Gio = imports.gi.Gio;
-const GLib = imports.gi.GLib;
-const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
-const WebHelper = imports.webhelper;
-const WebKit = imports.gi.WebKit;
-
-const WebUpdateFontSizeTestApplication = new Lang.Class({
- Name: 'WebUpdateFontSizeTestApplication',
- Extends: WebHelper.Application,
-
- vfunc_startup: function () {
- this.parent();
-
- this.webview = new WebKit.WebView();
- this.websettings = this.webview.get_settings();
- this.webview.set_settings(this.websettings);
- this.win = new Endless.Window({
- application: this,
- font_scaling_active: true
- });
-
- /* Typically logic in tests is bad. In this case, we need to inject these
- * callbacks to test specific cases that only occur during the runtime main
- * loop of the test application. */
- if (this.set_font_resizable_callback !== null) {
- this.set_font_resizable_callback(this.win, this.websettings);
- this.websettings.connect('notify::default-font-size', Lang.bind(this, function () {
- this.default_font_size_changed_callback(this.win, this.websettings);
- }));
- }
-
- if (this.accept_callback !== null)
- this.accept_callback(this.win, this.websettings.default_font_size);
- },
-
- accept_callback: null,
-
- set_font_resizable_callback: null,
-
- default_font_size_changed_callback: null
-});
-
-// TODO: These tests depend on a running X Server and Window Manager. That means
-// that they are not runnable in a continuous-integration server
-describe("Web Helper Font Sizes", function () {
- let app;
-
- beforeEach(function () {
- // Generate a unique ID for each app instance that we test
- let fake_pid = GLib.random_int();
- // FIXME In this version of GJS there is no Posix module, so fake the PID
- let id_string = 'com.endlessm.webhelper.test' + GLib.get_real_time() + fake_pid;
-
- app = new WebUpdateFontSizeTestApplication({
- application_id: id_string
- });
- });
-
- it("does not have the default font scale for a tiny window", function () {
- let test_initial_font_size = function (my_win, default_font_size) {
- my_win.font_scaling_default_window_size = 200; // Force a ridiculous value
- // Window's font scaling is a double, web settings' is an integer
- expect(my_win.font_scaling_calculated_font_size).not.toBeCloseTo(default_font_size, 0);
-
- /* This does not immediately quit the application. It sets a flag for termination
- * which will cause the application to be disposed on the next main loop iteration. */
- app.quit();
- };
-
- app.accept_callback = test_initial_font_size;
-
- spyOn(app, 'accept_callback').and.callThrough();
- app.run([]);
- expect(app.accept_callback).toHaveBeenCalled();
- });
-
- it("takes the provided settings default font size on setting resizable", function () {
- app.set_font_resizable_callback = app.set_web_settings_font_resizable;
-
- let test_font_sizing = function (my_win, my_websettings) {
- // Window's font scaling is a double, web settings' is an integer
- expect(my_win.font_scaling_calculated_font_size).toBeCloseTo(my_websettings.default_font_size, 0);
-
- /* This does not immediately quit the application. It sets a flag for termination
- * which will cause the application to be disposed on the next main loop iteration. */
- app.quit();
- };
-
- app.default_font_size_changed_callback = test_font_sizing;
-
- spyOn(app, 'default_font_size_changed_callback').and.callThrough();
- app.run([]);
- expect(app.default_font_size_changed_callback).toHaveBeenCalled();
- });
-});
diff --git a/test/webhelper/testWebActions.js b/test/webhelper/testWebActions.js
deleted file mode 100644
index e937fb6..0000000
--- a/test/webhelper/testWebActions.js
+++ /dev/null
@@ -1,141 +0,0 @@
-const Endless = imports.gi.Endless;
-const Gio = imports.gi.Gio;
-const GLib = imports.gi.GLib;
-const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
-const WebHelper = imports.webhelper;
-const WebKit = imports.gi.WebKit;
-
-const WebActionTestApplication = new Lang.Class({
- Name: 'WebActionTestApplication',
- Extends: WebHelper.Application,
-
- vfunc_startup: function() {
- this.parent();
- this.webview = new WebKit.WebView();
- this.webview.connect('navigation-policy-decision-requested',
- Lang.bind(this, this.web_actions_handler));
- let string = ('<html><head><meta http-equiv="refresh" content="0;url=' +
- this.webActionToTest + '"></head><body></body></html>');
- this.webview.load_string(string, 'text/html', 'UTF-8', 'file://');
- this.win = new Endless.Window({
- application: this
- });
- this.scrolled = new Gtk.ScrolledWindow();
- this.scrolled.add(this.webview);
- this.win.page_manager.add(this.scrolled);
- }
-});
-
-// TODO: These tests depend on a running X Server and Window Manager. That means
-// that they are not runnable in a continuous-integration server
-describe("Web Actions Bindings", function() {
- let app;
- let webActionSpy;
-
- beforeEach(function() {
- // Generate a unique ID for each app instance that we test
- let fake_pid = GLib.random_int();
- // FIXME In this version of GJS there is no Posix module, so fake the PID
- let id_string = 'com.endlessm.webhelper.test' + GLib.get_real_time() + fake_pid;
- app = new WebActionTestApplication({
- application_id: id_string
- });
- webActionSpy = jasmine.createSpy('quitAction').and.callFake(function() {
- // Calls destroy on the applications window, which decrements the hold count on the
- // application and implicitly causes the application to close.
- app.win.destroy();
- });
- });
-
- let RunApplicationWithWebAction = function(app, action) {
- app.webActionToTest = action;
- app.run([]);
- }
- it("has a working quitApplication uri upon defining quitApplication as a string", function() {
- app.define_web_action('quitApplication', webActionSpy);
- RunApplicationWithWebAction(app, 'endless://quitApplication');
-
- expect(webActionSpy).toHaveBeenCalled();
- });
-
- it("is called with a parameter", function() {
- app.define_web_action('getParameterAndQuit', webActionSpy);
- RunApplicationWithWebAction(app, 'endless://getParameterAndQuit?param=value');
-
- expect(webActionSpy).toHaveBeenCalledWith(new jasmine.ObjectContaining({ param: 'value' }));
- });
-
- it("can be called with many parameters", function() {
- app.define_web_action('getParametersAndQuit', webActionSpy);
- RunApplicationWithWebAction(app, 'endless://getParametersAndQuit?first=thefirst&second=thesecond&third=thethird');
-
- expect(webActionSpy).toHaveBeenCalledWith(new jasmine.ObjectContaining({
- first: 'thefirst',
- second: 'thesecond',
- third: 'thethird'
- }));
- });
-
- it("decodes parameter URI names", function() {
- app.define_web_action('getUriDecodedParameterAndQuit', webActionSpy);
- RunApplicationWithWebAction(app, 'endless://getUriDecodedParameterAndQuit?p%C3%A4r%C3%A4m%F0%9F%92%A9=value');
-
- expect(webActionSpy).toHaveBeenCalledWith(new jasmine.ObjectContaining({
- 'päräm💩' : 'value'
- }));
- });
-
- it("decodes parameter URI values", function() {
- app.define_web_action('getUriDecodedParameterValueAndQuit', webActionSpy);
- RunApplicationWithWebAction(app, 'endless://getUriDecodedParameterValueAndQuit?param=v%C3%A1lu%C3%A9%F0%9F%92%A9');
-
- expect(webActionSpy).toHaveBeenCalledWith(new jasmine.ObjectContaining({
- param : 'válué💩'
- }));
- });
-
- // We currently can't catch exceptions across GObject-Introspection callbacks
- xit('bad action is not called', function() {
- expect(function() { RunApplicationWithWebAction(app, 'endless://nonexistentWebAction') }).toThrow();
- });
-
- describe("with blank parameters", function() {
- beforeEach(function() {
- app.define_web_action('getBlankValueAndQuit', webActionSpy);
- RunApplicationWithWebAction(app, 'endless://getBlankValueAndQuit?param=');
- });
-
- it("can be called", function() {
- expect(webActionSpy).toHaveBeenCalled();
- });
-
- it("is called with a paramater that is an empty string", function() {
- expect(webActionSpy).toHaveBeenCalledWith(new jasmine.ObjectContaining({
- 'param' : ''
- }));
- });
- });
-
- it("URI decodes the action", function() {
- app.define_web_action('äction💩Quit', webActionSpy);
- RunApplicationWithWebAction(app, 'endless://%C3%A4ction%F0%9F%92%A9Quit');
- expect(webActionSpy).toHaveBeenCalled();
- });
-
- it("allows web actions to be defined as object properties", function() {
- app.define_web_actions({
- quitApplication: webActionSpy
- });
-
- RunApplicationWithWebAction(app, 'endless://quitApplication');
-
- expect(webActionSpy).toHaveBeenCalled();
- });
-
- it("throws an error when trying to define an action that is not a function", function() {
- expect(function() {
- app.define_web_action('action', {});
- }).toThrow();
- });
-});
diff --git a/test/webhelper/testWebActions2.js b/test/webhelper/testWebActions2.js
deleted file mode 100644
index 5af5e2b..0000000
--- a/test/webhelper/testWebActions2.js
+++ /dev/null
@@ -1,121 +0,0 @@
-const Gio = imports.gi.Gio;
-const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
-const Mainloop = imports.mainloop;
-const WebHelper2 = imports.webhelper2;
-const WebKit2 = imports.gi.WebKit2;
-
-const WELL_KNOWN_NAME = 'com.endlessm.WebHelper.testWebActions2';
-
-Gtk.init(null);
-
-describe('WebKit2 actions bindings', function () {
- let owner_id, connection, webview, webhelper, web_action_spy;
-
- beforeAll(function (done) {
- owner_id = Gio.DBus.own_name(Gio.BusType.SESSION, WELL_KNOWN_NAME,
- Gio.BusNameOwnerFlags.NONE,
- null, // bus acquired
- (con, name) => { // name acquired
- connection = con;
- done();
- },
- null); // name lost
- });
-
- afterAll(function () {
- Gio.DBus.unown_name(owner_id);
- });
-
- function run_loop(action_to_test) {
- let string = '<html><head><meta http-equiv="refresh" content="0;url=' +
- action_to_test + '"></head><body></body></html>';
- webview.load_html(string, null);
- Mainloop.run('webhelper2');
- }
-
- beforeEach(function () {
- webhelper = new WebHelper2.WebHelper({
- well_known_name: WELL_KNOWN_NAME,
- connection: connection,
- });
- webview = new WebKit2.WebView();
- web_action_spy = jasmine.createSpy('web_action_spy').and.callFake(() =>
- Mainloop.quit('webhelper2'));
- webhelper.define_web_action('action', web_action_spy);
- });
-
- afterEach(function () {
- webhelper.unregister();
- });
-
- it('calls a web action', function () {
- run_loop('webhelper://action');
- expect(web_action_spy).toHaveBeenCalled();
- });
-
- it('calls a web action with a parameter', function () {
- run_loop('webhelper://action?param=value');
- expect(web_action_spy).toHaveBeenCalledWith(jasmine.objectContaining({
- param: 'value',
- }));
- });
-
- it('calls a web action with many parameters', function () {
- run_loop('webhelper://action?first=thefirst&second=thesecond&third=thethird');
- expect(web_action_spy).toHaveBeenCalledWith(jasmine.objectContaining({
- first: 'thefirst',
- second: 'thesecond',
- third: 'thethird',
- }));
- });
-
- it('uri-decodes parameter names', function () {
- run_loop('webhelper://action?p%C3%A4r%C3%A4m%F0%9F%92%A9=value');
- expect(web_action_spy).toHaveBeenCalledWith(jasmine.objectContaining({
- 'päräm💩': 'value',
- }));
- });
-
- it('uri-decodes parameter values', function () {
- run_loop('webhelper://action?param=v%C3%A1lu%C3%A9%F0%9F%92%A9');
- expect(web_action_spy).toHaveBeenCalledWith(jasmine.objectContaining({
- param: 'válué💩',
- }));
- });
-
- // This is commented out because GJS cannot catch exceptions across FFI
- // interfaces (e.g. in GObject callbacks.)
- xit('raises an exception on a nonexistent action instead of calling it', function () {
- expect(function () {
- run_loop('webhelper://nonexistentAction?param=value');
- }).toThrow();
- });
-
- it('calls a web action with a blank parameter', function () {
- run_loop('webhelper://action?param=');
- expect(web_action_spy).toHaveBeenCalledWith(jasmine.objectContaining({
- param: '',
- }));
- });
-
- it('uri-decodes web action names', function () {
- webhelper.define_web_action('äction💩Quit', web_action_spy);
- run_loop('webhelper://%C3%A4ction%F0%9F%92%A9Quit');
- expect(web_action_spy).toHaveBeenCalled();
- });
-
- it('can define more than one action with define_web_actions()', function () {
- webhelper.define_web_actions({
- action2: web_action_spy,
- });
- run_loop('webhelper://action2');
- expect(web_action_spy).toBeTruthy();
- });
-
- it('complains when defining an action that is not a function', function () {
- expect(function () {
- webhelper.define_web_action('badAction', 'not a function');
- }).toThrow();
- });
-});
diff --git a/webhelper/lib/wh2private.c b/webhelper/lib/wh2private.c
deleted file mode 100644
index 04a7710..0000000
--- a/webhelper/lib/wh2private.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Copyright 2015 Endless Mobile, Inc. */
-
-#include <glib.h>
-#include <webkit2/webkit2.h>
-
-#include "wh2private.h"
-
-/**
- * wh2_private_register_global_uri_scheme:
- * @scheme: the network scheme to register
- * @callback: a #WebKitURISchemeRequestCallback.
- * @user_data: (closure): user data for the @callback
- * @notify: destroy notify function for the @callback
- *
- * Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=729611
- *
- * Registers a URI scheme handler with the default WebContext. Does not pass the
- * GDestroyNotifyFunc, which GJS uses to shim a destructor for @callback, along
- * to the the web context.
- *
- * The default web context is a global object which does not get destroyed
- * until a atexit handler after the javascript runtime has been torn down.
- * Calling into the GJS function destructor at that point would be a
- * mistake.
- */
-void
-wh2_register_uri_scheme (const gchar *scheme,
- WebKitURISchemeRequestCallback callback,
- gpointer user_data,
- GDestroyNotify notify)
-{
- WebKitWebContext *context = webkit_web_context_get_default ();
- webkit_web_context_register_uri_scheme (context, scheme, callback, NULL, NULL);
-}
diff --git a/webhelper/lib/wh2private.h b/webhelper/lib/wh2private.h
deleted file mode 100644
index a20fe87..0000000
--- a/webhelper/lib/wh2private.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Copyright 2015 Endless Mobile, Inc. */
-
-#ifndef WH2_PRIVATE_H
-#define WH2_PRIVATE_H
-
-#include <glib.h>
-#include <webkit2/webkit2.h>
-
-G_BEGIN_DECLS
-
-void wh2_register_uri_scheme (const gchar *scheme,
- WebKitURISchemeRequestCallback callback,
- gpointer user_data,
- GDestroyNotify notify);
-
-G_END_DECLS
-
-#endif /* WH2_PRIVATE_H */
diff --git a/webhelper/webextensions/wh2extension.c b/webhelper/webextensions/wh2extension.c
deleted file mode 100644
index 8dd738b..0000000
--- a/webhelper/webextensions/wh2extension.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Copyright 2015 Endless Mobile, Inc. */
-
-#include <math.h>
-#include <string.h>
-
-#include <glib.h>
-#include <JavaScriptCore/JavaScript.h>
-#include <webkit2/webkit-web-extension.h>
-#include <webkitdom/webkitdom.h>
-
-#include "wh2jscutil.h"
-
-#define PRIVATE_NAME "_webhelper_private"
-#define WH2_DBUS_INTERFACE_NAME "com.endlessm.WebHelper2.Translation"
-#define MAIN_PROGRAM_OBJECT_PATH "/com/endlessm/gettext"
-#define MAIN_PROGRAM_INTERFACE_NAME "com.endlessm.WebHelper2.Gettext"
-
-/* Declaration of externally visible symbol */
-void webkit_web_extension_initialize_with_user_data (WebKitWebExtension *, const GVariant *);
-
-typedef struct {
- WebKitWebExtension *extension; /* unowned */
- GDBusConnection *connection; /* unowned */
- GDBusNodeInfo *node; /* owned */
- GDBusInterfaceInfo *interface; /* owned by node */
- GSList *bus_ids; /* GSList<guint>; owned */
- GArray *unregistered_pages; /* GArray<guint64>; owned */
- gchar *main_program_name; /* owned; well-known-name of main program */
-} Context;
-
-typedef struct {
- Context *ctxt; /* unowned */
- guint64 page_id;
-} PageContext;
-
-static const gchar introspection_xml[] =
- "<node>"
- "<interface name='" WH2_DBUS_INTERFACE_NAME "'>"
- "<method name='Translate'/>"
- "</interface>"
- "</node>";
-
-static void
-context_free (Context *ctxt)
-{
- g_clear_pointer (&ctxt->node, g_dbus_node_info_unref);
- g_clear_pointer (&ctxt->bus_ids, g_slist_free);
- if (ctxt->unregistered_pages != NULL)
- g_array_free (ctxt->unregistered_pages, TRUE);
- ctxt->unregistered_pages = NULL;
- g_clear_pointer (&ctxt->main_program_name, g_free);
- g_free (ctxt);
-}
-
-/* Spins the main loop until the DBus connection comes up. We need this since we
-define functions in JS, that JS code can potentially call before there is a
-connection. */
-static void
-wait_for_connection_sync (Context *ctxt)
-{
- g_return_if_fail (ctxt->connection == NULL);
-
- GMainContext *main = g_main_context_get_thread_default ();
- while (ctxt->connection == NULL)
- g_main_context_iteration (main, TRUE /* may block */);
-
- g_assert (ctxt->connection);
-}
-
-static gchar *
-translation_function (const gchar *message,
- Context *ctxt)
-{
- GError *error = NULL;
-
- if (ctxt->connection == NULL)
- wait_for_connection_sync (ctxt);
-
- GVariant *result =
- g_dbus_connection_call_sync (ctxt->connection, ctxt->main_program_name,
- MAIN_PROGRAM_OBJECT_PATH,
- MAIN_PROGRAM_INTERFACE_NAME, "Gettext",
- g_variant_new ("(s)", message),
- (GVariantType *) "(s)",
- G_DBUS_CALL_FLAGS_NO_AUTO_START,
- -1 /* timeout */, NULL /* cancellable */,
- &error);
- if (result == NULL)
- {
- g_warning ("No return value from gettext: %s", error->message);
- g_clear_error (&error);
- return g_strdup (message);
- }
-
- gchar *retval;
- g_variant_get (result, "(s)", &retval);
- g_variant_unref (result);
- return retval;
-}
-
-static gchar *
-ngettext_translation_function (const gchar *singular,
- const gchar *plural,
- guint64 number,
- Context *ctxt)
-{
- GError *error = NULL;
-
- if (ctxt->connection == NULL)
- wait_for_connection_sync (ctxt);
-
- GVariant *result =
- g_dbus_connection_call_sync (ctxt->connection, ctxt->main_program_name,
- MAIN_PROGRAM_OBJECT_PATH,
- MAIN_PROGRAM_INTERFACE_NAME, "NGettext",
- g_variant_new ("(sst)", singular, plural,
- number),
- (GVariantType *) "(s)",
- G_DBUS_CALL_FLAGS_NO_AUTO_START,
- -1 /* timeout */, NULL /* cancellable */,
- &error);
- if (result == NULL)
- {
- g_warning ("No return value from ngettext: %s", error->message);
- g_clear_error (&error);
- return g_strdup (number == 1 ? singular : plural);
- }
-
- gchar *retval;
- g_variant_get (result, "(s)", &retval);
- g_variant_unref (result);
- return retval;
-}
-
-static JSValueRef
-gettext_shim (JSContextRef js,
- JSObjectRef function,
- JSObjectRef this_object,
- size_t n_args,
- const JSValueRef args[],
- JSValueRef *exception)
-{
- if (n_args != 1)
- {
- gchar *errmsg = g_strdup_printf ("Expected one argument to gettext(),"
- "but got %"G_GSIZE_FORMAT".", n_args);
- *exception = throw_exception (js, errmsg);
- g_free (errmsg);
- return NULL;
- }
- if (!JSValueIsString (js, args[0]))
- {
- *exception = throw_exception (js,
- "Expected a string argument to gettext().");
- return NULL;
- }
-
- JSObjectRef window = JSContextGetGlobalObject (js);
- JSStringRef private_name = JSStringCreateWithUTF8CString (PRIVATE_NAME);
- JSValueRef private_data = JSObjectGetProperty (js, window, private_name,
- exception);
- if (JSValueIsUndefined (js, private_data))
- return NULL; /* propagate exception */
- Context *ctxt = (Context *) JSObjectGetPrivate ((JSObjectRef) private_data);
-
- JSStringRef message_ref = JSValueToStringCopy (js, args[0], exception);
- if (message_ref == NULL)
- return NULL; /* propagate exception */
- gchar *message = string_ref_to_string (message_ref);
- JSStringRelease (message_ref);
-
- gchar *translation = translation_function (message, ctxt);
- g_free (message);
-
- JSValueRef retval = string_to_value_ref (js, translation);
- g_free (translation);
- return retval;
-}
-
-static JSValueRef
-ngettext_shim (JSContextRef js,
- JSObjectRef function,
- JSObjectRef this_object,
- size_t n_args,
- const JSValueRef args[],
- JSValueRef *exception)
-{
- if (n_args != 3)
- {
- gchar *errmsg = g_strdup_printf ("Expected three arguments to ngettext(),"
- "but got %"G_GSIZE_FORMAT".", n_args);
- *exception = throw_exception (js, errmsg);
- g_free (errmsg);
- return NULL;
- }
- if (!JSValueIsString (js, args[0]))
- {
- *exception = throw_exception (js, "The first argument to ngettext() "
- "must be a string.");
- return NULL;
- }
- if (!JSValueIsString (js, args[1]))
- {
- *exception = throw_exception (js, "The second argument to ngettext() "
- "must be a string.");
- return NULL;
- }
- if (!JSValueIsNumber (js, args[2]))
- {
- *exception = throw_exception (js, "The third argument to ngettext() "
- "must be a number.");
- return NULL;
- }
-
- JSObjectRef window = JSContextGetGlobalObject (js);
- JSStringRef private_name = JSStringCreateWithUTF8CString (PRIVATE_NAME);
- JSValueRef private_data = JSObjectGetProperty (js, window, private_name,
- exception);
- if (JSValueIsUndefined (js, private_data))
- return NULL; /* propagate exception */
- Context *ctxt = (Context *) JSObjectGetPrivate ((JSObjectRef) private_data);
-
- JSStringRef singular_ref = JSValueToStringCopy (js, args[0], exception);
- if (singular_ref == NULL)
- return NULL; /* propagate exception */
- gchar *singular_msg = string_ref_to_string (singular_ref);
- JSStringRelease (singular_ref);
-
- JSStringRef plural_ref = JSValueToStringCopy (js, args[1], exception);
- if (plural_ref == NULL)
- {
- g_free (singular_msg);
- return NULL; /* propagate exception */
- }
- gchar *plural_msg = string_ref_to_string (plural_ref);
- JSStringRelease (plural_ref);
-
- double number = JSValueToNumber (js, args[2], exception);
- if (isnan (number))
- {
- g_free (singular_msg);
- g_free (plural_msg);
- return NULL; /* propagate exception */
- }
-
- gchar *translation = ngettext_translation_function (singular_msg, plural_msg,
- (guint64) number, ctxt);
- g_free (singular_msg);
- g_free (plural_msg);
-
- JSValueRef retval = string_to_value_ref (js, translation);
- g_free (translation);
- return retval;
-}
-
-static gchar *
-normalize_string (const gchar *string)
-{
- static GRegex *whitespace = NULL;
-
- if (g_once_init_enter (&whitespace))
- {
- GError *regex_error = NULL;
- GRegex *new_regex = g_regex_new ("\\s+", G_REGEX_OPTIMIZE, 0,
- &regex_error);
- // Don't free; will persist until exit
- if (new_regex == NULL)
- {
- g_critical ("Trouble creating regex: %s\n", regex_error->message);
- g_clear_error (&regex_error);
- }
-
- g_once_init_leave (&whitespace, new_regex);
- }
-
- GError *error = NULL;
- gchar *copy = g_strstrip (g_strdup (string));
- gchar *retval = g_regex_replace_literal (whitespace, copy, -1, 0, " ", 0, &error);
- if (retval == NULL)
- {
- g_critical ("Trouble normalizing string: %s\n", error->message);
- g_clear_error (&error);
- return copy;
- }
- g_free (copy);
- return retval;
-}
-
-static void
-translate_html (WebKitDOMDocument *dom,
- Context *ctxt)
-{
- WebKitDOMNodeList *translatable;
- GError *error = NULL;
-
- translatable = webkit_dom_document_get_elements_by_name (dom, "translatable");
-
- gulong index, length = webkit_dom_node_list_get_length (translatable);
- for (index = 0; index < length; index++)
- {
- WebKitDOMNode *element = webkit_dom_node_list_item (translatable, index);
-
- /* Translate the text */
- if (WEBKIT_DOM_IS_HTML_ELEMENT (element))
- {
- WebKitDOMHTMLElement *el_html = WEBKIT_DOM_HTML_ELEMENT (element);
- gchar *inner_html = webkit_dom_html_element_get_inner_html (el_html);
- gchar *normalized = normalize_string (inner_html);
- gchar *translated_html = translation_function (normalized, ctxt);
- webkit_dom_html_element_set_inner_html (el_html, translated_html,
- &error);
- if (error != NULL)
- {
- g_warning ("There was a problem translating '%s' to '%s': %s",
- inner_html, translated_html, error->message);
- g_clear_error (&error);
- }
-
- g_free (translated_html);
- g_free (inner_html);
- g_free (normalized);
- }
- else
- {
- gchar *text = webkit_dom_node_get_text_content (element);
- gchar *normalized = normalize_string (text);
- gchar *translated_text = translation_function (normalized, ctxt);
- webkit_dom_node_set_text_content (element, translated_text, &error);
- if (error != NULL)
- {
- g_warning ("There was a problem translating '%s' to '%s': %s",
- text, translated_text, error->message);
- g_clear_error (&error);
- }
-
- g_free (translated_text);
- g_free (text);
- g_free (normalized);
- }
- }
-
- g_object_unref (translatable);
-}
-
-static void
-on_wh2_method_call (GDBusConnection *connection,
- const gchar *sender,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *method_name,
- GVariant *parameters,
- GDBusMethodInvocation *invocation,
- PageContext *pctxt)
-{
- if (strcmp (method_name, "Translate") != 0)
- {
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
- G_DBUS_ERROR_UNKNOWN_METHOD,
- "Unknown method %s invoked on interface %s",
- method_name, interface_name);
- return;
- }
-
- WebKitWebPage *page = webkit_web_extension_get_page (pctxt->ctxt->extension,
- pctxt->page_id);
- if (page == NULL)
- return;
- /* The page may have been destroyed, but WebKit doesn't let us find out. */
-
- WebKitDOMDocument *document = webkit_web_page_get_dom_document (page);
- if (document == NULL)
- {
- g_dbus_method_invocation_return_error_literal (invocation, G_IO_ERROR,
- G_IO_ERROR_NOT_INITIALIZED,
- "The web page has not loaded a document yet");
- return;
- }
-
- translate_html (document, pctxt->ctxt);
-
- g_dbus_method_invocation_return_value (invocation, NULL);
-}
-
-static GDBusInterfaceVTable dbus_impl_vtable = {
- (GDBusInterfaceMethodCallFunc) on_wh2_method_call,
- NULL, /* get property */
- NULL /* set property */
-};
-
-static void
-register_object (guint64 page_id,
- Context *ctxt)
-{
- GError *error = NULL;
-
- g_assert (ctxt->connection != NULL);
-
- gchar *object_path = g_strdup_printf("/com/endlessm/webview/%"
- G_GUINT64_FORMAT, page_id);
-
- /* This struct is owned by the registered DBus object */
- PageContext *pctxt = g_new0 (PageContext, 1);
- pctxt->ctxt = ctxt;
- pctxt->page_id = page_id;
-
- guint bus_id =
- g_dbus_connection_register_object (ctxt->connection, object_path,
- ctxt->interface, &dbus_impl_vtable,
- pctxt, (GDestroyNotify) g_free, &error);
- g_free (object_path);
- if (bus_id == 0)
- {
- g_critical ("Failed to export webview object on bus: %s", error->message);
- g_clear_error (&error);
- goto fail;
- }
-
- ctxt->bus_ids = g_slist_prepend (ctxt->bus_ids, GUINT_TO_POINTER (bus_id));
- return;
-
-fail:
- g_free (pctxt);
-}
-
-static void
-on_page_created (WebKitWebExtension *extension,
- WebKitWebPage *page,
- Context *ctxt)
-{
- /* The ID is known to the main process and the web process. So we can address
- a specific web page over DBus. */
- guint64 id = webkit_web_page_get_id (page);
-
- if (ctxt->connection == NULL)
- {
- /* The connection is not ready yet. Save the page ID in a list of pages
- for which we need to register objects later. */
- g_array_append_val (ctxt->unregistered_pages, id);
- return;
- }
-
- register_object (id, ctxt);
-}
-
-/* window-object-cleared is the best time to define properties on the page's
-window object, according to the documentation. */
-static void
-on_window_object_cleared (WebKitScriptWorld *script_world,
- WebKitWebPage *page,
- WebKitFrame *frame,
- Context *ctxt)
-{
- JSGlobalContextRef js =
- webkit_frame_get_javascript_context_for_script_world (frame, script_world);
- JSObjectRef window = JSContextGetGlobalObject (js);
-
- /* First we need to create a custom class for a private data object to store
- our context in, because you can't pass callback data to JavaScriptCore
- callbacks. You also can't set private data on a Javascript object if it's not
- of a custom class, because the built-in classes don't allocate space for a
- private pointer. */
- JSClassDefinition class_def = {
- .className = "PrivateContextObject"
- };
- JSClassRef klass = JSClassCreate (&class_def);
- JSObjectRef private_data = JSObjectMake (js, klass, ctxt);
- JSClassRelease (klass);
-
- if (!set_object_property (js, window, PRIVATE_NAME, (JSValueRef) private_data,
- kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete))
- return;
-
- JSObjectRef gettext_func =
- JSObjectMakeFunctionWithCallback (js, NULL, gettext_shim);
- if (!set_object_property (js, window, "gettext", (JSValueRef) gettext_func,
- kJSPropertyAttributeNone))
- return;
-
- JSObjectRef ngettext_func =
- JSObjectMakeFunctionWithCallback (js, NULL, ngettext_shim);
- if (!set_object_property (js, window, "ngettext", (JSValueRef) ngettext_func,
- kJSPropertyAttributeNone))
- return;
-}
-
-static void
-on_bus_acquired (GDBusConnection *connection,
- const gchar *name,
- Context *ctxt)
-{
- GError *error = NULL;
-
- ctxt->connection = connection;
-
- /* Export our interface on the bus */
- ctxt->node = g_dbus_node_info_new_for_xml (introspection_xml, &error);
- if (ctxt->node == NULL)
- goto fail;
- ctxt->interface = g_dbus_node_info_lookup_interface (ctxt->node,
- WH2_DBUS_INTERFACE_NAME);
- if (ctxt->interface == NULL)
- goto fail;
-
- /* Register DBus objects for any pages that were created before we got here */
- guint ix;
- for (ix = 0; ix < ctxt->unregistered_pages->len; ix++)
- {
- guint64 id = g_array_index (ctxt->unregistered_pages, guint64, ix);
- register_object (id, ctxt);
- }
- g_array_remove_range (ctxt->unregistered_pages, 0,
- ctxt->unregistered_pages->len);
-
- return;
-
-fail:
- if (error != NULL)
- {
- g_critical ("Error hooking up web extension DBus interface: %s",
- error->message);
- g_clear_error (&error);
- }
- else
- {
- g_critical ("Unknown error hooking up web extension DBus interface");
- }
-}
-
-static void
-unregister_object (gpointer data,
- GDBusConnection *connection)
-{
- guint bus_id = GPOINTER_TO_UINT (data);
- if (!g_dbus_connection_unregister_object (connection, bus_id))
- g_critical ("Trouble unregistering object");
-}
-
-static void
-on_name_lost (GDBusConnection *connection,
- const gchar *name,
- Context *ctxt)
-{
- if (connection == NULL)
- {
- g_warning ("Could not initialize DBus interface for WebHelper2 "
- "extension; the name %s was lost.", name);
- return;
- }
-
- g_slist_foreach (ctxt->bus_ids, (GFunc) unregister_object, connection);
-}
-
-/* Receives the main program's unique DBus name as user data. */
-G_MODULE_EXPORT void
-webkit_web_extension_initialize_with_user_data (WebKitWebExtension *extension,
- const GVariant *data_from_app)
-{
- const gchar *name = g_variant_get_string ((GVariant *) data_from_app, NULL);
-
- Context *ctxt = g_new0 (Context, 1);
- ctxt->extension = extension;
- ctxt->unregistered_pages = g_array_new (FALSE, FALSE, sizeof (guint64));
- ctxt->main_program_name = g_strdup (name);
- gchar *well_known_name = g_strconcat (name, ".webhelper", NULL);
-
- g_signal_connect (extension, "page-created",
- G_CALLBACK (on_page_created), ctxt);
-
- g_bus_own_name (G_BUS_TYPE_SESSION, well_known_name,
- G_BUS_NAME_OWNER_FLAGS_NONE,
- (GBusAcquiredCallback) on_bus_acquired,
- NULL, /* name acquired callback */
- (GBusNameLostCallback) on_name_lost,
- ctxt, (GDestroyNotify) context_free);
-
- g_free (well_known_name);
-
- /* Get a notification when Javascript is ready. In this callback it's possible
- that the DBus connection has not been acquired yet, so we have sync waits
- later if JS tries to call DBus. However, connecting to this signal later
- doesn't work because it will often already have been fired before the DBus
- connection is acquired. */
- WebKitScriptWorld *script_world = webkit_script_world_get_default ();
- g_signal_connect (script_world, "window-object-cleared",
- G_CALLBACK (on_window_object_cleared), ctxt);
-}
diff --git a/webhelper/webextensions/wh2jscutil.c b/webhelper/webextensions/wh2jscutil.c
deleted file mode 100644
index 34f325f..0000000
--- a/webhelper/webextensions/wh2jscutil.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Copyright 2015 Endless Mobile, Inc. */
-
-#include <glib.h>
-#include <JavaScriptCore/JavaScript.h>
-
-#include "wh2jscutil.h"
-
-G_GNUC_INTERNAL
-gboolean
-set_object_property (JSContextRef js,
- JSObjectRef object,
- const gchar *property_name,
- JSValueRef property_value,
- JSPropertyAttributes flags)
-{
- JSValueRef exception = NULL;
- JSStringRef property_name_ref = JSStringCreateWithUTF8CString (property_name);
- JSObjectSetProperty (js, object, property_name_ref, property_value, flags,
- &exception);
- JSStringRelease (property_name_ref);
- if (exception != NULL)
- {
- g_critical ("There was a problem setting the property '%s'.",
- property_name);
- return FALSE;
- }
- return TRUE;
-}
-
-/* Returns a newly allocated string. */
-G_GNUC_INTERNAL
-gchar *
-string_ref_to_string (JSStringRef string_ref)
-{
- size_t bufsize = JSStringGetMaximumUTF8CStringSize (string_ref);
- gchar *string = g_new0 (gchar, bufsize);
- JSStringGetUTF8CString (string_ref, string, bufsize);
- return string;
-}
-
-G_GNUC_INTERNAL
-JSValueRef
-string_to_value_ref (JSContextRef js,
- const gchar *string)
-{
- JSStringRef string_ref = JSStringCreateWithUTF8CString (string);
- JSValueRef value_ref = JSValueMakeString (js, string_ref);
- /* value_ref owns string_ref now */
- return value_ref;
-}
-
-G_GNUC_INTERNAL
-JSValueRef
-throw_exception (JSContextRef js,
- const gchar *message)
-{
- JSValueRef msgval = string_to_value_ref (js, message);
- JSValueRef inner_error = NULL;
- JSObjectRef exception = JSObjectMakeError (js, 1, &msgval, &inner_error);
- if (inner_error != NULL)
- return inner_error;
- return (JSValueRef) exception;
-}
diff --git a/webhelper/webextensions/wh2jscutil.h b/webhelper/webextensions/wh2jscutil.h
deleted file mode 100644
index af800e5..0000000
--- a/webhelper/webextensions/wh2jscutil.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Copyright 2015 Endless Mobile, Inc. */
-
-#ifndef WH2_JSC_UTIL_H
-#define WH2_JSC_UTIL_H
-
-#include <glib.h>
-#include <JavaScriptCore/JavaScript.h>
-
-gboolean set_object_property (JSContextRef js,
- JSObjectRef object,
- const gchar *property_name,
- JSValueRef property_value,
- JSPropertyAttributes flags);
-
-gchar *string_ref_to_string (JSStringRef string_ref);
-
-JSValueRef string_to_value_ref (JSContextRef js,
- const gchar *string);
-
-JSValueRef throw_exception (JSContextRef js,
- const gchar *message);
-
-#endif /* WH2_JSC_UTIL_H */
diff --git a/webhelper/webhelper.js b/webhelper/webhelper.js
deleted file mode 100644
index d4f6811..0000000
--- a/webhelper/webhelper.js
+++ /dev/null
@@ -1,290 +0,0 @@
-const Endless = imports.gi.Endless;
-const Format = imports.format;
-const GLib = imports.gi.GLib;
-const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
-const WebKit = imports.gi.WebKit;
-
-String.prototype.format = Format.format;
-
-const EOS_URI_SCHEME = 'endless://';
-
-/**
- * Namespace: WebHelper
- * Convenience library for running web applications
- *
- * WebHelper is a convenience library for displaying web applications inside a
- * GTK container running WebKitGTK (currently WebKit 1, not 2.)
- * Although WebKit provides an easy way of communicating from GTK code to
- * the in-browser Javascript, through the execute_script() method, it is not so
- * easy to communicate the other way around.
- *
- * WebHelper solves that problem by detecting when the web page navigates to a
- * custom action URI.
- * The custom URI corresponds to a function that you define using
- * <Application.define_web_action()>, and you can pass parameters to the
- * function.
- *
- * Another often-encountered problem is localizing text through the same API as
- * your main GTK program.
- * WebHelper solves this problem by allowing you to mark strings in your HTML
- * page and translating them through a function of your choice when you run
- * <Application.translate_html()>.
- */
-
-/**
- * Class: Application
- * Main application class for a WebHelper application
- *
- * The application class in GJS for your web application should extend
- * WebHelper.Application.
- *
- * You should set up any WebViews that you create, by connecting
- * <web_actions_handler()>, so that they can handle custom action URIs.
- */
-const Application = new Lang.Class({
- Name: 'WebApplication',
- Extends: Endless.Application,
-
- _init: function(props) {
- this._webActions = {};
- this._translationFunction = null;
- this.parent(props);
- },
-
- /**
- * Method: define_web_action
- * Define an action that may be invoked from a WebView
- *
- * Parameters:
- * name - a string, which must be a valid URI location.
- * implementation - a function (see Callback Parameters below.)
- *
- * Callback Parameters:
- * dict - object containing properties corresponding to the query
- * parameters that the web action was called with
- *
- * Sets up an action that may be invoked from an HTML document inside a
- * WebView, or from the in-browser Javascript environment inside a WebView.
- * If you set up an action "setVolume" as follows:
- * > app.define_web_action('setVolume', function(dict) { ... });
- * Then you can invoke the action inside the HTML document, e.g. as the
- * target of a link, as follows:
- * > <a href="endless://setVolume?volume=11">This one goes to 11</a>
- * Or from the in-browser Javascript, by navigating to the action URI, as
- * follows:
- * > window.location.href = 'endless://setVolume?volume=11';
- *
- * In both cases, the function would then be called with the _dict_
- * parameter equal to
- * > { "volume": "11" }
- *
- * If an action called _name_ is already defined, the new _implementation_
- * replaces the old one.
- */
- define_web_action: function(name, implementation) {
- if(typeof implementation != 'function') {
- throw new Error('The implementation of a web action must be a ' +
- 'function.');
- }
- this._webActions[name] = implementation;
- },
-
- /**
- * Method: define_web_actions
- * Define several web actions at once
- *
- * Parameters:
- * dict - an object, with web action names as property names, and their
- * implementations as values
- *
- * Convenience method to define more than one web action at once.
- * Calls <define_web_action()> on each property of _dict_.
- *
- * *Note* This API is Javascript-only. It will not be implemented in C.
- */
- define_web_actions: function(dict) {
- for(let key in dict) {
- if(dict.hasOwnProperty(key)) {
- this.define_web_action(key, dict[key]);
- }
- }
- },
-
- /**
- * Callback: web_actions_handler
- * Navigation callback which routes the custom URIs to actions
- *
- * When you create a web view in which you want to run a web application
- * that uses custom action URIs, remember to set it up by connecting this
- * callback to its "navigation-policy-decision-requested" signal. The
- * following code will do this:
- *
- * > webview.connect('navigation-policy-decision-requested',
- * > Lang.bind(app, app.web_actions_handler));
- *
- * where 'webview' is the web view, and 'app' is the WebHelper.Application
- * instance.
- */
- web_actions_handler: function(webview, frame, request, action, policy_decision) {
- let uri = request.get_uri();
-
- if(uri.indexOf(EOS_URI_SCHEME) !== 0) {
- // this is a regular URL, just navigate there
- return false;
- }
-
- // get the name and parameters for the desired function
- let f_call = uri.substring(EOS_URI_SCHEME.length, uri.length).split('?');
- var function_name = decodeURI(f_call[0]);
- var parameters = {};
-
- if(f_call[1]) {
- // there are parameters
- let params = f_call[1].split('&');
- params.forEach(function(entry) {
- let param = entry.split('=');
-
- if(param.length == 2) {
- param[0] = decodeURIComponent(param[0]);
- param[1] = decodeURIComponent(param[1]);
- // and now we add it...
- parameters[param[0]] = param[1];
- }
- });
- }
-
- if(this._webActions[function_name])
- Lang.bind(this, this._webActions[function_name])(parameters);
- else
- throw new Error("Undefined WebHelper action '%s'. Did you define " +
- "it with WebHelper.Application.define_web_action()?".format(
- function_name));
-
- policy_decision.ignore();
- return true;
- },
-
- // convenience function
-
- _getElementById: function(webview, id) {
- // WebKit.DOMDocument
- let dom = webview.get_dom_document();
-
- // WebKit.DOMElement
- return dom.get_element_by_id(id);
- },
-
- /**
- * Method: set_translation_function
- * Define function which transforms all translatable text
- *
- * Parameters:
- * translation_function - a function, or null
- *
- * When you plan to use the <translate_html()> function to translate text in
- * your web application, set this property to the translation function.
- * The function must take one parameter, a string, and also return a
- * string.
- * The canonical example is gettext().
- *
- * Pass null for _translation_function_ to unset the translation function.
- *
- * If this function has not been called, or has most recently been called
- * with null, then it is illegal to call <translate_html()>.
- */
- set_translation_function: function(translation_function) {
- if(translation_function !== null
- && typeof translation_function !== 'function') {
- throw new Error('The translation function must be a function, or ' +
- 'null.');
- }
- this._translationFunction = translation_function;
- },
-
- /**
- * Method: get_translation_function
- * Retrieve the currently set translation function
- *
- * Returns:
- * the translation function previously set with
- * <set_translation_function()>, or null if none is currently set.
- */
- get_translation_function: function() {
- return this._translationFunction;
- },
-
- /**
- * Method: translate_html
- * Translate all translatable text currently showing in a web view
- *
- * Parameters:
- * webview - the WebView containing the text to translate.
- *
- * Another problem with running web applications inside a GTK container is
- * keeping all the localization data in the same place.
- * For example, the most obvious way to do localization in a GTK application
- * is to use gettext(), but that does not work so easily inside a web view.
- *
- * In a <WebHelper.Application>, you can mark strings in your HTML for
- * translation by enclosing them in
- * > <span name="translatable">String to be translated</span>
- * or just putting the "translatable" name directly on the element
- * containing the string, e.g. <p> or <h1>.
- *
- * Then after the web view has finished loading, call <translate_html()> on
- * it, and each of the marked strings will be passed to the function that
- * you specify using <set_translation_function()> property.
- * The return value from the translation function will be substituted into
- * the HTML instead of the original string.
- *
- * Example:
- * > app.set_translation_function(_);
- * > webview.connect('notify::load-status',
- * > Lang.bind(app, function(webview) {
- * > if(webview.load_status == WebKit.LoadStatus.FINISHED)
- * > this.translate_html(webview);
- * > }));
- */
- translate_html: function(webview) {
- let dom = webview.get_dom_document();
-
- // WebKit.DOMNodeList
- let translatable = dom.get_elements_by_name('translatable');
-
- for (var i = 0 ; i < translatable.get_length() ; i++) {
- // WebKit.DOMNode
- let element = translatable.item(i);
-
- // Translate the text
- if(typeof this._translationFunction !== 'function')
- throw new Error("No suitable translation function was found. " +
- "Did you forget to call 'set_translation_function()' on " +
- "your app?");
- element.inner_html = this._translationFunction(element.inner_text);
- }
- },
-
- /**
- * Method: set_web_settings_font_resizable
- * Set an eos_window to update font size of web_settings
- *
- * Parameters:
- * eos_windw - an <Endless.Window>
- * web_settings - a <WebKit.WebSettings>
- *
- * The <Endless.Window> will be connected on its "size-allocate" signal
- * to the given <WebKit.WebSettings>. The <Endless.Window> will update the
- * "default-font-size" property of the <WebKit.WebSettings> calculated font size
- * to the <Endless.Window>'s calculated font size.
- */
- set_web_settings_font_resizable: function (eos_window, web_settings) {
- eos_window.connect('size-allocate',
- Lang.bind(this, function (widget, allocation) {
- if (eos_window.font_scaling_active) {
- web_settings.default_font_size = eos_window.font_scaling_calculated_font_size;
- }
- }
- ));
- }
-});
diff --git a/webhelper/webhelper2.js b/webhelper/webhelper2.js
deleted file mode 100644
index ea25bc1..0000000
--- a/webhelper/webhelper2.js
+++ /dev/null
@@ -1,529 +0,0 @@
-// Copyright 2015 Endless Mobile, Inc.
-
-imports.gi.versions.WebKit2 = '4.0';
-
-const Format = imports.format;
-const Gio = imports.gi.Gio;
-const GLib = imports.gi.GLib;
-const GObject = imports.gi.GObject;
-const Lang = imports.lang;
-const WebHelper2Private = imports.gi.WebHelper2Private;
-const WebKit2 = imports.gi.WebKit2;
-const LIBEXEC_SUBDIR = 'webhelper2';
-
-const Config = imports.webhelper_private.config;
-
-String.prototype.format = Format.format;
-
-const WH2_URI_SCHEME = 'webhelper';
-const WH2_LOCAL_FILE_SCHEME = 'local';
-const DBUS_WEBVIEW_EXPORT_PATH = '/com/endlessm/webview/';
-const WH2_DBUS_EXTENSION_INTERFACE = '\
- <node> \
- <interface name="com.endlessm.WebHelper2.Translation"> \
- <method name="Translate"/> \
- </interface> \
- </node>';
-const WH2_DBUS_MAIN_PROGRAM_INTERFACE = '\
- <node> \
- <interface name="com.endlessm.WebHelper2.Gettext"> \
- <method name="Gettext"> \
- <arg name="message" type="s" direction="in"/> \
- <arg name="translation" type="s" direction="out"/> \
- </method> \
- <method name="NGettext"> \
- <arg name="message_singular" type="s" direction="in"/> \
- <arg name="message_plural" type="s" direction="in"/> \
- <arg name="number" type="t" direction="in"/> \
- <arg name="translation" type="s" direction="out"/> \
- </method> \
- </interface> \
- </node>';
-
-/**
- * Namespace: WebHelper2
- * Convenience library for running web applications
- *
- * WebHelper is a convenience library for displaying web applications inside a
- * GTK container running WebKitGTK.
- * WebHelper2 is the WebKit2 version.
- *
- * Although WebKit provides an easy way of communicating from GTK code to
- * the in-browser Javascript, through the execute_script() method, it is not so
- * easy to communicate the other way around.
- *
- * WebHelper solves that problem by detecting when the web page navigates to a
- * custom action URI.
- * The custom URI corresponds to a function that you define using
- * <WebHelper.define_web_action()>, and you can pass parameters to the
- * function.
- *
- * Another often-encountered problem is localizing text through the same API as
- * your main GTK program.
- * WebHelper solves this problem by allowing you to mark strings in your HTML
- * page and translating them through a function of your choice when you run
- * <WebHelper.translate_html()>.
- * It also exposes a *gettext()* function in the client-side Javascript.
- *
- * For cases where you need to load local files for your web applications,
- * WebHelper also provides the local:// URI scheme.
- * For this to work, you must also load your main page via the local:// URI
- * scheme.
- */
-
-/**
- * Class: WebHelper
- * Helper object for a WebKit2 web application
- *
- * Constructor parameters:
- * props - a dictionary of construction properties and values (default {})
- *
- * The application class for your web application should create <WebHelper> after
- * registering itself in the session bus (i.e. not inside *vfunc_dbus_register()*),
- * with appropriate <well-known-name> and <connection> parameters.
- * A good place to do this would be in your *vfunc_startup()* implementation, where
- * you can also do further setup on it, such as defining web actions.
- *
- * There is no need to set up specially any web views that you create, unlike
- * WebKit1 where you must set up <Application.web_actions_handler()>.
- *
- * Example:
- * > const TestApplication = new Lang.Class({
- * > Name: 'TestApplication',
- * > Extends: Gtk.Application,
- * >
- * > vfunc_dbus_register: function (connection, object_path) {
- * > this._webhelper = new WebHelper2.WebHelper({
- * > well_known_name: this.application_id,
- * > connection: connection,
- * > });
- * > return this.parent(connection, object_path);
- * > },
- * >
- * > vfunc_startup: function () {
- * > this.parent();
- * >
- * > this._webhelper.set_gettext(Gettext.dgettext.bind(null,
- * > GETTEXT_DOMAIN));
- * >
- * > let window = new Gtk.Window();
- * > let webview = new WebKit2.WebView();
- * > webview.connect('load-changed', (webview, event) => {
- * > if (event === WebKit2.LoadEvent.FINISHED)
- * > this._webhelper.translate_html(webview, null, (obj, res) => {
- * > this._webhelper.translate_html_finish(res);
- * > window.show_all();
- * > });
- * > });
- * > window.add(webview);
- * > webview.load_uri('file:///path/to/my/page.html');
- * > },
- * >
- * > vfunc_dbus_unregister: function (connection, object_path) {
- * > this.parent(connection, object_path);
- * > this._webhelper.unregister();
- * > },
- * >});
- * >
- * >let app = new TestApplication({
- * > application_id: 'com.example.SmokeGrinder',
- * >});
- * >app.run(ARGV);
- */
-const WebHelper = new Lang.Class({
- Name: 'WebHelper',
- GTypeName: 'Wh2WebHelper',
- Extends: GObject.Object,
- Properties: {
- /**
- * Property: well-known-name
- * Well-known bus name owned by the calling program
- *
- * Type:
- * string
- *
- * This property is required at construction time.
- * It must conform to <the rules for well-known bus names at
- * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names>.
- *
- * This must be a well-known bus name that your program owns.
- * The easiest way to ensure that is to use your application's ID, since
- * every application class registers its ID as a bus name.
- */
- 'well-known-name': GObject.ParamSpec.string('well-known-name',
- 'Well-known name',
- 'Well-known bus name owned by the calling program',
- GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
- ''),
- /**
- * Property: connection
- * DBus connection owned by the calling program
- *
- * Type:
- * *Gio.DBusConnection*
- *
- * This property is required at construction time.
- *
- * This must be a DBus connection object that your program owns.
- * The easiest way to ensure that is to use the connection object passed
- * in to your application's *vfunc_dbus_register()* function.
- */
- 'connection': GObject.ParamSpec.object('connection', 'Connection',
- 'DBus connection owned by the calling program',
- GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
- Gio.DBusConnection.$gtype),
- },
-
- _init: function (props={}) {
- this._web_actions = {};
- this._gettext = null;
- this._ngettext = null;
- this._ProxyConstructor =
- Gio.DBusProxy.makeProxyWrapper(WH2_DBUS_EXTENSION_INTERFACE);
- this.parent(props);
-
- if (this.well_known_name === '')
- throw new Error('The "well-known-name" parameter is required.');
- this._extension_name = this.well_known_name + '.webhelper';
-
- // Set up Webkit to load our web extension
- let context = WebKit2.WebContext.get_default();
- context.connect('initialize-web-extensions', () => {
- let libexec = Gio.File.new_for_path(Config.LIBEXECDIR);
- let path = libexec.get_child(LIBEXEC_SUBDIR).get_path();
-
- let localpath = GLib.getenv('WEBHELPER_UNINSTALLED_EXTENSION_DIR');
- if (localpath)
- path = localpath;
-
- context.set_web_extensions_directory(path);
- context.set_web_extensions_initialization_user_data(new GLib.Variant('s',
- this.well_known_name));
- });
-
- // Export our own DBus interface
- this._dbus_impl =
- Gio.DBusExportedObject.wrapJSObject(WH2_DBUS_MAIN_PROGRAM_INTERFACE,
- this);
- this._dbus_impl.export(this.connection, '/com/endlessm/gettext');
-
- // Set up handling for custom URIs
- WebHelper2Private.register_uri_scheme(WH2_URI_SCHEME,
- this._on_endless_uri_request.bind(this));
- WebHelper2Private.register_uri_scheme(WH2_LOCAL_FILE_SCHEME,
- this._on_local_file_request.bind(this));
- },
-
- _on_endless_uri_request: function (request) {
- let uri = request.get_uri();
-
- // get the name and parameters for the desired function
- let f_call = uri.substr((WH2_URI_SCHEME + '://').length).split('?');
- let function_name = decodeURI(f_call[0]);
-
- if (!this._web_actions.hasOwnProperty(function_name))
- throw new Error(('Undefined WebHelper action "%s". Did you define it with ' +
- 'WebHelper.Application.define_web_action()?').format(function_name));
-
- let parameters = {};
- if (f_call[1]) {
- // there are parameters
- let params = f_call[1].split('&');
- params.forEach(function (entry) {
- let param = entry.split('=');
-
- if (param.length == 2) {
- param[0] = decodeURIComponent(param[0]);
- param[1] = decodeURIComponent(param[1]);
- // and now we add it...
- parameters[param[0]] = param[1];
- }
- });
- }
-
- (this._web_actions[function_name].bind(this))(parameters);
-
- // Don't call request.finish(), because we don't want to finish the
- // action, which would involve loading a new page. The request dies
- // if we return from this function without calling ref() or finish()
- // on it.
- },
-
- _on_local_file_request: function (request) {
- let path = request.get_path();
- let file = Gio.File.new_for_path(path);
- let [content_type, certain] = Gio.content_type_guess(path, null);
- try {
- let stream = file.read(null);
- request.finish(stream, -1, content_type);
- } catch (error) {
- request.finish_error(error);
- }
- },
-
- // DBus implementations
-
- Gettext: function (string) {
- return this._gettext(string);
- },
-
- NGettext: function (singular, plural, number) {
- return this._ngettext(singular, plural, number);
- },
-
- // Public API
-
- /**
- * Method: set_gettext
- * Define function which translates text
- *
- * Parameters:
- * gettext_func - a function, or null
- *
- * When you plan to translate text in your web application, set this
- * property to the translation function.
- * The function must take one parameter, a string, and also return a
- * string.
- * The canonical example is gettext().
- *
- * This function will be called with each string to translate when you call
- * <translate_html()>.
- * The function is also made available directly to the browser-side
- * Javascript as *gettext()*, a property of the global object.
- *
- * Pass null for _gettext_func_ to unset the translation function.
- *
- * If this function has not been called, or has most recently been called
- * with null, then it is illegal to call <translate_html()>.
- *
- * Example:
- * > const Gettext = imports.gettext;
- * > const GETTEXT_DOMAIN = 'smoke-grinder';
- * >
- * > webhelper.set_gettext(Gettext.dgettext.bind(null, GETTEXT_DOMAIN));
- */
- set_gettext: function (gettext_func) {
- if (gettext_func !== null && typeof gettext_func !== 'function')
- throw new Error('The translation function must be a function, or ' +
- 'null.');
- this._gettext = gettext_func;
- },
-
- /**
- * Method: get_gettext
- * Retrieve the currently set translation function
- *
- * Returns:
- * the translation function previously set with <set_gettext()>, or null
- * if none is currently set.
- */
- get_gettext: function () {
- return this._gettext;
- },
-
- /**
- * Method: set_ngettext
- * Define function which translates singular/plural text
- *
- * Parameters:
- * ngettext_func - a function, or null
- *
- * When you plan to translate text in your web application, set this
- * property to the translation function.
- * The function must take three parameters: a string singular message, a
- * string plural message, and a number for which to generate the message.
- * The function must return a string.
- * The canonical example is ngettext().
- *
- * This function is made available directly to the browser-side Javascript
- * as *ngettext()*, a property of the global object.
- *
- * Pass null for _ngettext_func_ to unset the translation function.
- *
- * If this function has not been called, or has most recently been called
- * with null, then it is illegal to call *ngettext()* in the client-side
- * Javascript.
- *
- * Example:
- * > const WebHelper2 = imports.webhelper2;
- * > const Gettext = imports.gettext;
- * > const GETTEXT_DOMAIN = 'smoke-grinder';
- * >
- * > let webhelper = new WebHelper2.WebHelper('com.example.SmokeGrinder');
- * > webhelper.set_gettext(Gettext.dngettext.bind(null, GETTEXT_DOMAIN));
- */
- set_ngettext: function (ngettext_func) {
- if (ngettext_func !== null && typeof ngettext_func !== 'function')
- throw new Error('The translation function must be a function, or ' +
- 'null.');
- this._ngettext = ngettext_func;
- },
-
- /**
- * Method: get_ngettext
- * Retrieve the currently set singular/plural translation function
- *
- * Returns:
- * the translation function previously set with <set_ngettext()>, or null
- * if none is currently set.
- */
- get_ngettext: function () {
- return this._ngettext;
- },
-
- /**
- * Method: translate_html
- * Translate the HTML page in a webview asynchronously
- *
- * Parameters:
- * webview - a *WebKit2.WebView* with HTML loaded
- * cancellable - a *Gio.Cancellable*, or null
- * callback - a function that takes two parameters: this <WebHelper>
- * object, and a result object; or null if you don't want a callback
- *
- * Perform translation on all HTML elements marked with name="translatable"
- * in the HTML document displaying in _webview_.
- * The translation will be performed using the function you have set using
- * <set_gettext()>.
- *
- * When the translation is finished, _callback_ will be called.
- * You can get the result of the operation by calling
- * <translate_html_finish()> with the _result_ object passed to _callback_.
- *
- * You can optionally pass _cancellable_ if you want to be able to cancel
- * the operation.
- *
- * Example:
- * > webview.connect('load-changed', (webview, event) => {
- * > if (event === WebKit2.LoadEvent.FINISHED)
- * > webhelper.translate_html(webview, null, (obj, res) => {
- * > webhelper.translate_html_finish(res);
- * > // Translation done, show the page
- * > webview.show_all();
- * > });
- * > });
- */
- translate_html: function (webview, cancellable, callback) {
- let task = { callback: callback };
- // Wait for the DBus interface to appear on the bus
- task.watch_id = Gio.DBus.watch_name(Gio.BusType.SESSION,
- this._extension_name, Gio.BusNameWatcherFlags.NONE,
- (connection) => {
- // name appeared
- let webview_object_path = DBUS_WEBVIEW_EXPORT_PATH +
- webview.get_page_id();
- // Warning: this._ProxyConstructor will do a synchronous
- // operation unless you pass in a callback
- new this._ProxyConstructor(connection, this._extension_name,
- webview_object_path, (proxy, error) =>
- {
- if (error) {
- this._translate_callback(task, null, error);
- return;
- }
- if (cancellable)
- proxy.TranslateRemote(cancellable,
- this._translate_callback.bind(this, task));
- else
- proxy.TranslateRemote(this._translate_callback.bind(this,
- task));
- }, cancellable);
- },
- null); // do nothing when name vanishes
- return task;
- },
-
- _translate_callback: function (task, result, error) {
- Gio.DBus.unwatch_name(task.watch_id);
- if (error)
- task.error = error;
- if (task.callback)
- task.callback(this, task);
- },
-
- /**
- * Method: translate_html_finish
- * Get the result of <translate_html()>
- *
- * Parameters:
- * res - result object passed to your callback
- *
- * Finishes an operation started by <translate_html()>.
- * If the operation ended in an error, this function will throw that error.
- */
- translate_html_finish: function (res) {
- if (res.error)
- throw res.error;
- },
-
- /**
- * Method: define_web_action
- * Define an action that may be invoked from a WebView
- *
- * Parameters:
- * name - a string, which must be a valid URI location.
- * implementation - a function (see Callback Parameters below.)
- *
- * Callback Parameters:
- * dict - object containing properties corresponding to the query
- * parameters that the web action was called with
- *
- * Sets up an action that may be invoked from an HTML document inside a
- * WebView, or from the in-browser Javascript environment inside a WebView.
- * If you set up an action "setVolume" as follows:
- * > webhelper.define_web_action('setVolume', function (dict) { ... });
- * Then you can invoke the action inside the HTML document, e.g. as the
- * target of a link, as follows:
- * > <a href="webhelper://setVolume?volume=11">This one goes to 11</a>
- * Or from the in-browser Javascript, by navigating to the action URI, as
- * follows:
- * > window.location.href = 'webhelper://setVolume?volume=11';
- *
- * In both cases, the function would then be called with the _dict_
- * parameter equal to
- * > { "volume": "11" }
- *
- * If an action called _name_ is already defined, the new _implementation_
- * replaces the old one.
- */
- define_web_action: function (name, implementation) {
- if (typeof implementation !== 'function') {
- throw new Error('The implementation of a web action must be a ' +
- 'function.');
- }
- this._web_actions[name] = implementation;
- },
-
- /**
- * Method: define_web_actions
- * Define several web actions at once
- *
- * Parameters:
- * dict - an object, with web action names as property names, and their
- * implementations as values
- *
- * Convenience method to define more than one web action at once.
- * Calls <define_web_action()> on each property of _dict_.
- *
- * *Note* This API is Javascript-only. It will not be implemented in C.
- */
- define_web_actions: function (dict) {
- Object.keys(dict).forEach((key) =>
- this.define_web_action(key, dict[key]));
- },
-
- /**
- * Method: unregister
- * Break the connection to WebKit
- *
- * Breaks the connection to all webviews and removes all DBus objects.
- * You should call this in your application's *vfunc_dbus_unregister()*
- * implementation.
- *
- * After this function has been called, no WebHelper functionality will
- * work.
- */
- unregister: function () {
- this._dbus_impl.unexport_from_connection(this.connection);
- },
-});
diff --git a/webhelper/webhelper_private/config.js.in b/webhelper/webhelper_private/config.js.in
deleted file mode 100644
index f9d87cb..0000000
--- a/webhelper/webhelper_private/config.js.in
+++ /dev/null
@@ -1 +0,0 @@
-const LIBEXECDIR = '%libexecdir%';