Initial commit
This repository holds code for a Chrome extension which shows
instructions for manual testing of touch panels, collects
touch events, and sends touch events over a WebSocket.
This is an unchanged copy of software released by Optofidelity OY.
Change-Id: I6a990ef1daca70ef5712941e267156c3dd3204b4
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/optofidelity_chrome_touch_client/+/2023316
Reviewed-by: Harry Cutts <hcutts@chromium.org>
Commit-Queue: Sean O'Brien <seobrien@chromium.org>
Tested-by: Sean O'Brien <seobrien@chromium.org>
diff --git a/README.chromium b/README.chromium
new file mode 100644
index 0000000..e3f8fad
--- /dev/null
+++ b/README.chromium
@@ -0,0 +1,4 @@
+DESCRIPTION="Chrome extension to show manual touch validation instructions"
+LOCAL_GIT_REPO="https://chromium.googlesource/com/chromiumos/third_party/optofidelity_chrome_touch_client
+LOCAL_BUGSDB="https://crbug.com"
+LICENSE="4-clause BSD"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..db48faa
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+### Chrome Extension
+
+To enable in Chrome browser:
+
+1. navigate to chrome://extensions
+2. enable "developer mode"
+3. click "load unpacked" and select chrome_plugin directory
+
+#### To create package:
+
+1. navigate to chrome://extensions
+2. you have to have the Touch Client plugin installed in developer mode
+3. click "Details" in Touch Client plugin
+4. at the top bar click "Pack Extension"
+
+
+#### Usage:
+
+When installed, the chrome plugin will show as a button at the toolbar.
+The button looks like Optofidelity logo; red, green and blue squares.
+
+1. Open settings by right-clicking the button.
+2. Set TPPT server's ip-address, port 50009 and DUT name (default: Dut1)
+3. Make sure that you have started the TPPT server.
+4. Left-click the toolbar button, this should open a new page with "full screen" button on it. This will also open the connection to the TPPT server.
+5. Follow the instructions from the TPPT server.
+
+If the connection is lost, refresh the page. Refreshing the page will create new connection to the server.
+
+
diff --git a/chrome_plugin/application.mjs b/chrome_plugin/application.mjs
new file mode 100644
index 0000000..27caf2d
--- /dev/null
+++ b/chrome_plugin/application.mjs
@@ -0,0 +1,196 @@
+/*
+Copyright (c) 2019, OptoFidelity OY
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY.
+ 4. Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+export function Application( dut_name )
+ {
+ //
+ // Application is the main logic of a websocket client.
+ // Websocket Communicator needs an application instance to run.
+ // Communicator will parse incoming messages and run functions from Application.
+ // Functions take in command name and (json-formatted) parameters, return (json-formatted) response.
+ //
+
+ // register commands (this is the API for the application)
+ this.name = dut_name;
+
+ this.commands = {
+ "touches": this.cmd_touches.bind(this),
+ "draw_image": this.cmd_draw_image.bind(this),
+ "get_info": this.cmd_get_info.bind(this)
+ };
+
+ // register event listeners for touch recording.
+ var t = document.getElementById("infotainment")
+
+ t.ontouchstart = this.mousedown.bind(this);
+ t.ontouchmove = this.mousemove.bind(this);
+ t.ontouchend = this.mouseup.bind(this);
+
+ t.onmousedown = this.mousedown.bind(this);
+ t.onmousemove = this.mousemove.bind(this);
+ t.onmouseup = this.mouseup.bind(this);
+
+ // set up touches array
+ this.touches = [];
+
+ // constants used in cmd_touches response. For each touch, store [touch_type, x, y]
+ this.ACTION_DOWN = 0;
+ this.ACTION_UP = 1;
+ this.ACTION_MOVE = 2;
+ }
+
+Application.prototype.cmd_touches = function(params)
+ {
+ //
+ // touches command
+ //
+ var t = [];
+ for( var i=0; i<this.touches.length; i++ )
+ {
+ var p = this.touches[ i ];
+ t.push( p );
+ }
+ this.touches = [];
+ return {"fields": ["action", "x", "y", "time", "id"], "touches": t};
+ }
+
+Application.prototype.cmd_draw_image = function(params)
+ {
+ //
+ // draw image command
+ //
+ // params : dict {'image_data': base64 encoded image data (jpeg, png, etc.)}
+
+ var image_data = params["image"];
+
+ // resize canvas if needed
+ if( infotainment.width != infotainment.clientWidth )
+ {
+ infotainment.width = infotainment.clientWidth;
+ }
+
+ if( infotainment.height != infotainment.clientHeight )
+ {
+ infotainment.height = infotainment.clientHeight;
+ }
+
+ var img = new Image();
+ img.x0 = 0;
+ img.y0 = 0;
+ img.x1 = infotainment.clientWidth;
+ img.y1 = infotainment.clientHeight;
+ img.onload = this.imageLoaded.bind(this);
+ img.src = "data:image/png;base64," + image_data;
+
+ return ""
+ }
+
+Application.prototype.imageLoaded = function(e)
+ {
+ //
+ // The async part of the draw image command.
+ //
+ var img = e.target;
+ var c = infotainment.getContext( "2d" );
+
+ c.drawImage( img, img.x0, img.y0, img.x1-img.x0, img.y1-img.y0 );
+ }
+
+Application.prototype.cmd_get_info = function(params)
+ {
+ //
+ // Get info command. Return all needed info of the device under test.
+ //
+ var info = {
+ "dut_name": this.name,
+ "width": infotainment.clientWidth,
+ "height": infotainment.clientHeight,
+ "pixel_ratio": devicePixelRatio,
+ "display_resolution": {"width": infotainment.clientWidth, "height": infotainment.clientHeight }
+ };
+ return info;
+ }
+
+Application.prototype.mousedown = function(e)
+ {
+ e.preventDefault();
+
+ var ct = e.changedTouches;
+ if( ct )
+ {
+ // touch events
+ for( var i=0; i<ct.length; i++ )
+ {
+ var t = ct[ i ];
+ this.touches.push([this.ACTION_DOWN, t.pageX, t.pageY, Math.floor(e.timeStamp), t.identifier]);
+ }
+ }
+ else
+ {
+ // mouse events
+ this.touches.push([this.ACTION_DOWN, e.pageX, e.pageY, Math.floor(e.timeStamp), 0]);
+ }
+ }
+
+Application.prototype.mousemove = function(e)
+ {
+ e.preventDefault();
+
+ var ct = e.changedTouches;
+ if( ct )
+ {
+ // touch events
+ for( var i=0; i<ct.length; i++ )
+ {
+ var t = ct[ i ];
+ this.touches.push([this.ACTION_MOVE, t.pageX, t.pageY, Math.floor(e.timeStamp), t.identifier]);
+ }
+ }
+ else
+ {
+ // mouse events
+ this.touches.push([this.ACTION_MOVE, e.pageX, e.pageY, Math.floor(e.timeStamp), 0]);
+ }
+ }
+
+Application.prototype.mouseup = function(e)
+ {
+ e.preventDefault();
+
+ var ct = e.changedTouches;
+ if( ct )
+ {
+ // touch events
+ for( var i=0; i<ct.length; i++ )
+ {
+ var t = ct[ i ];
+ this.touches.push([this.ACTION_UP, t.pageX, t.pageY, Math.floor(e.timeStamp), t.identifier]);
+ }
+ }
+ else
+ {
+ // mouse events
+ this.touches.push([this.ACTION_UP, e.pageX, e.pageY, Math.floor(e.timeStamp), 0]);
+ }
+ }
+
diff --git a/chrome_plugin/background.js b/chrome_plugin/background.js
new file mode 100644
index 0000000..a2c0755
--- /dev/null
+++ b/chrome_plugin/background.js
@@ -0,0 +1,28 @@
+/*
+Copyright (c) 2019, OptoFidelity OY
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY.
+ 4. Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// enable functionality on every tab
+chrome.tabs.onUpdated.addListener(function(id, info, tab)
+ {
+ chrome.pageAction.show(tab.id);
+ });
+
diff --git a/chrome_plugin/communicator.mjs b/chrome_plugin/communicator.mjs
new file mode 100644
index 0000000..fd107f4
--- /dev/null
+++ b/chrome_plugin/communicator.mjs
@@ -0,0 +1,144 @@
+/*
+Copyright (c) 2019, OptoFidelity OY
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY.
+ 4. Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+Websocket Communicator.
+(C) 2019 Optofidelity.
+
+Usage:
+ var host = "127.0.0.1";
+ var port = 50009;
+ var dut_name = "DUT1";
+ var application = new Application( dut_name );
+ var communicator = new Communicator( host, port, application );
+ communicator.start()
+
+Application instance must have dictionary called "commands"
+ commands must have key for every command in API.
+ commands must have functions for every key, taking in (json-originated) parameters.
+ command functions must return a (json-formattable) value.
+*/
+
+export function Communicator( host, port, application )
+ {
+ //
+ // port: Websocket port of the server.
+ // application: Application instance.
+ //
+ console.log("Communicator init");
+ this.host = host;
+ this.port = port;
+ this.application = application;
+ this.buffer = "";
+ this.socket = null;
+ this.commands = {};
+ }
+
+Communicator.prototype.handleCmd = function( cmd )
+ {
+ //
+ // Handle a command
+ // IN: "command_name" + " " + "json-formatted parameters" + "\n"
+ // OUT:
+ // "ok " + json formatted response
+ // "error " + error message string.
+
+ if( cmd == "" ) return;
+
+ var params = [];
+ var p = cmd.indexOf(' ');
+ if( p >= 0 )
+ {
+ params = cmd.substr( p + 1 )
+ cmd = cmd.substr( 0, p );
+ }
+ cmd = cmd.toLowerCase()
+
+ var rv = "";
+
+ try
+ {
+ var command = this.application.commands[ cmd ];
+ if( command )
+ {
+ if( params.length )
+ {
+ params = JSON.parse( params );
+ }
+ var response = command( params );
+ response = JSON.stringify( response );
+ rv = "ok " + response;
+ }
+
+ else
+ {
+ rv = 'error';
+ }
+ }
+ catch( err )
+ {
+ console.log( err );
+ rv = 'error ' + err;
+ }
+ return rv;
+ }
+
+Communicator.prototype.start = function()
+ {
+ var s = new WebSocket("ws://" + this.host + ":" + this.port + "/");
+ s.onopen = function(e)
+ {
+ console.log("opened");
+ this.buffer = "";
+ }
+ s.onclose = function(e) { console.log("closed"); }
+ s.onmessage = this.onmessage.bind( this );
+ this.socket = s;
+ };
+
+Communicator.prototype.onmessage = function(e)
+ {
+ this.buffer += e.data;
+
+ // messages split with newline
+
+ var p = this.buffer.search("\n");
+ if( p < 0 )
+ {
+ return;
+ }
+ var msg = this.buffer.substr( 0, p );
+ this.buffer = this.buffer.substr( p+1 );
+
+ var cmds = msg.trim().split('\n');
+ var rv = "";
+ for( var i=0; i<cmds.length; i++ )
+ {
+ var cmd = cmds[ i ];
+ rv += this.handleCmd( cmd );
+ rv += '\n';
+ }
+
+ // always respond
+ this.socket.send(rv)
+ }
+
diff --git a/chrome_plugin/icons/optofidelity_icon_128.png b/chrome_plugin/icons/optofidelity_icon_128.png
new file mode 100644
index 0000000..7ffab67
--- /dev/null
+++ b/chrome_plugin/icons/optofidelity_icon_128.png
Binary files differ
diff --git a/chrome_plugin/icons/optofidelity_icon_16.png b/chrome_plugin/icons/optofidelity_icon_16.png
new file mode 100644
index 0000000..6f8070a
--- /dev/null
+++ b/chrome_plugin/icons/optofidelity_icon_16.png
Binary files differ
diff --git a/chrome_plugin/icons/optofidelity_icon_32.png b/chrome_plugin/icons/optofidelity_icon_32.png
new file mode 100644
index 0000000..be83fd6
--- /dev/null
+++ b/chrome_plugin/icons/optofidelity_icon_32.png
Binary files differ
diff --git a/chrome_plugin/icons/optofidelity_icon_48.png b/chrome_plugin/icons/optofidelity_icon_48.png
new file mode 100644
index 0000000..80125e7
--- /dev/null
+++ b/chrome_plugin/icons/optofidelity_icon_48.png
Binary files differ
diff --git a/chrome_plugin/manifest.json b/chrome_plugin/manifest.json
new file mode 100644
index 0000000..02eb990
--- /dev/null
+++ b/chrome_plugin/manifest.json
@@ -0,0 +1,42 @@
+ {
+ "name": "Touch Client",
+ "version": "1.0",
+ "description": "TnT compatible touch client",
+ "manifest_version": 2,
+ "options_page": "options.html",
+
+ "background":
+ {
+ "scripts": ["background.js"],
+ "persistent": false
+ },
+
+ "page_action":
+ {
+ "default_popup": "popup.html",
+ "default_icon":
+ {
+ "16": "icons/optofidelity_icon_16.png",
+ "32": "icons/optofidelity_icon_32.png",
+ "48": "icons/optofidelity_icon_48.png",
+ "128": "icons/optofidelity_icon_128.png"
+ }
+ },
+
+ "icons":
+ {
+ "16": "icons/optofidelity_icon_16.png",
+ "32": "icons/optofidelity_icon_32.png",
+ "48": "icons/optofidelity_icon_48.png",
+ "128": "icons/optofidelity_icon_128.png"
+ },
+
+ "permissions":
+ [
+ "storage",
+ "tabs",
+ "notifications",
+ "http://*/",
+ "https://*/"
+ ]
+ }
\ No newline at end of file
diff --git a/chrome_plugin/options.html b/chrome_plugin/options.html
new file mode 100644
index 0000000..16aa385
--- /dev/null
+++ b/chrome_plugin/options.html
@@ -0,0 +1,71 @@
+<!--
+
+Copyright (c) 2019, OptoFidelity OY
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY.
+ 4. Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<!DOCTYPE html>
+ <html>
+ <head>
+ <style>
+ button
+ {
+ height: 30px;
+ width: 30px;
+ outline: none;
+ margin: 10px;
+ }
+
+ .option_label
+ {
+ width: 200px;
+ height: 18px;
+ margin-left: -100px;
+ left: 50%;
+ margin-bottom: 0px;
+ position: relative;
+ text-align: center;
+ margin-top: 10px;
+ }
+
+ .option_input
+ {
+ width: 200px;
+ height: 44px;
+ margin-left: -100px;
+ left: 50%;
+ position: relative;
+ background-color: white;
+ border-radius: 7px;
+ margin-bottom: 10px;
+ text-align: center;
+ }
+
+ </style>
+ </head>
+ <body>
+ <div>
+ <h1><center>Touch Client Settings</center></h1>
+ </div>
+ <div id="buttonDiv"></div>
+ </body>
+ <script src="options.js"></script>
+ </html>
\ No newline at end of file
diff --git a/chrome_plugin/options.js b/chrome_plugin/options.js
new file mode 100644
index 0000000..549ff86
--- /dev/null
+++ b/chrome_plugin/options.js
@@ -0,0 +1,68 @@
+/*
+Copyright (c) 2019, OptoFidelity OY
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY.
+ 4. Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+let page = document.getElementById('buttonDiv');
+
+function constructOptions()
+ {
+ function createOption( label, type, variable_name )
+ {
+ let group = document.createElement( "div" );
+
+ let labelDiv = document.createElement( "div" );
+ labelDiv.innerHTML = label;
+ labelDiv.className = "option_label";
+
+ group.append( labelDiv );
+
+ let inputDiv = document.createElement( "input" );
+ inputDiv.setAttribute( "input-type", type );
+ inputDiv.className = "option_input";
+
+ group.appendChild( inputDiv );
+
+ group.style.background = "linear-gradient(transparent, rgba(0,0,0,0.1))";
+
+ page.appendChild( group );
+
+ chrome.storage.local.get([variable_name], function(result)
+ {
+ console.log( "hoi", result );
+ inputDiv.value = result[variable_name];
+ });
+
+ inputDiv.onchange = function( e )
+ {
+ chrome.storage.local.set({[variable_name]: inputDiv.value}, function()
+ {
+ console.log('Value of ' + variable_name + ' is set to ' + inputDiv.value);
+ });
+ }
+
+ }
+
+ createOption( "Server IP address", "text", "host" );
+ createOption( "Server IP port", "number", "port" );
+ createOption( "DUT name", "text", "name" );
+ }
+constructOptions();
\ No newline at end of file
diff --git a/chrome_plugin/popup.html b/chrome_plugin/popup.html
new file mode 100644
index 0000000..fe5e0ae
--- /dev/null
+++ b/chrome_plugin/popup.html
@@ -0,0 +1,28 @@
+<!--
+
+Copyright (c) 2019, OptoFidelity OY
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY.
+ 4. Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<!DOCTYPE html>
+<html>
+<script src="popup.js"></script>
+</html>
\ No newline at end of file
diff --git a/chrome_plugin/popup.js b/chrome_plugin/popup.js
new file mode 100644
index 0000000..1999f51
--- /dev/null
+++ b/chrome_plugin/popup.js
@@ -0,0 +1,23 @@
+/*
+Copyright (c) 2019, OptoFidelity OY
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY.
+ 4. Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+chrome.tabs.create({"url": "testapp.html"});
diff --git a/chrome_plugin/testapp.html b/chrome_plugin/testapp.html
new file mode 100644
index 0000000..9542c62
--- /dev/null
+++ b/chrome_plugin/testapp.html
@@ -0,0 +1,69 @@
+<!--
+
+Copyright (c) 2019, OptoFidelity OY
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY.
+ 4. Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>testapp</title>
+</head>
+
+
+<style>
+ body
+ {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ }
+
+ .infotainment
+ {
+ width: 100%;
+ height: 100%;
+ position: fixed;
+ left: 0px;
+ top: 0px;
+ }
+
+ .fullscreenbutton
+ {
+ position: fixed;
+ left: 0px;
+ top: 0px;
+ }
+</style>
+
+
+
+<body>
+ <canvas id="infotainment" class="infotainment"></canvas>
+ <button id="fullscreenbutton" class="fullscreenbutton">Full Screen</button>
+</body>
+
+<script src="testapp.js" type="module"></script>
+
+</html>
\ No newline at end of file
diff --git a/chrome_plugin/testapp.js b/chrome_plugin/testapp.js
new file mode 100644
index 0000000..4aeacc2
--- /dev/null
+++ b/chrome_plugin/testapp.js
@@ -0,0 +1,113 @@
+/*
+Copyright (c) 2019, OptoFidelity OY
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY.
+ 4. Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function Start()
+ {
+ var canvas = document.getElementById( "infotainment" );
+ var b = document.getElementById("fullscreenbutton")
+
+ b.onclick = function(e)
+ {
+ document.documentElement.webkitRequestFullscreen();
+ };
+
+ canvas.onmousemove = function( e )
+ {
+ if( e.button == 0 )
+ {
+ if( canvas.width != canvas.clientWidth || canvas.height != canvas.clientHeight )
+ {
+ canvas.width = canvas.clientWidth;
+ canvas.height = canvas.clientHeight;
+ }
+
+ var c = canvas.getContext( "2d" );
+
+
+ var x = e.clientX;
+ var y = e.clientY;
+ c.fillRect( x-2, y-2, 4, 4 );
+ }
+ }
+ }
+
+
+// Start();
+
+import { Application } from './application.mjs';
+import { Communicator } from './communicator.mjs';
+
+
+function DoStart()
+ {
+ function Starter()
+ {
+ this.host = null;
+ this.port = null;
+ this.name = null;
+
+ chrome.storage.local.get(["host"], this.gethost.bind(this));
+ chrome.storage.local.get(["port"], this.getport.bind(this));
+ chrome.storage.local.get(["name"], this.getname.bind(this));
+ }
+
+ Starter.prototype.gethost = function( result )
+ {
+ this.host = result["host"]
+ console.log( "got host " + this.host );
+ this.tryStart();
+ }
+
+ Starter.prototype.getport = function( result )
+ {
+ this.port = result["port"]
+ console.log( "got port " + this.port );
+ this.tryStart();
+ }
+
+ Starter.prototype.getname = function( result )
+ {
+ this.name = result["name"]
+ console.log( "got name " + this.name );
+ this.tryStart();
+ }
+
+ Starter.prototype.tryStart = function()
+ {
+ if( this.host && this.port && this.name )
+ {
+ var testapp_application = new Application(this.name);
+ var testapp_communicator = new Communicator( this.host, this.port, testapp_application );
+ testapp_communicator.start();
+ }
+ }
+
+ var b = document.getElementById("fullscreenbutton")
+ b.onclick = function(e)
+ {
+ document.documentElement.webkitRequestFullscreen();
+ };
+
+ var testapp_starter = new Starter();
+ }
+
+DoStart();
\ No newline at end of file