Skip to content

Commit 5cdb9ec

Browse files
committed
Merge branch 'GPII-4218'
* GPII-4218: GPII-4218: Fixed grammar GPII-4218: Updated the BrowserChannel documentation GPII-4218: Brought UIO+ high contrast transform into line with GPII-4492 GPII-4218: Reinstated the UIO+ "fabulous" inverse transform of 'contrastTheme' GPII-4218: Fixed one more comment GPII-4218: Fixed comments, tests, and examples. GPII-4218: Modifed to send confirmation receipt to the source request GPII-4218: Modified to support UIO+ "changeSettings" requests GPII-4218: Removed UIO+ fabulous inverse transformation of 'contrastTheme' GPII-4218: Fixed lint errors GPII-4218: Added inverse transformations for UIO+
2 parents bd2a063 + 11d4205 commit 5cdb9ec

File tree

8 files changed

+388
-57
lines changed

8 files changed

+388
-57
lines changed

documentation/BrowserChannel.md

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,34 @@ This document describes how the __Browser Channel__ and the __WebSockets__ setti
55
This feature consists on:
66

77
* A route in the Flow Manager that serves as the entry point for clients: `/browserChannel`
8-
* The component behind this route is the _gpii.settingsHandlers.webSockets.component_
8+
* The components behind this route are the _gpii.flowManager.browserChannel.handler_
9+
and the _gpii.settingsHandlers.webSockets.component_
910

1011
## The browser channel
1112

12-
This handler processes every request to `http://localhost:8081/browserChannel` and is responsible for:
13+
This handler processes every request to `ws://localhost:8081/browserChannel` and is responsible for:
1314

1415
* Processing every request and determining whether a client is allowed or not to connect
15-
* Registering and removing the clients as they are connecting or disconnecting
16+
* Registering and removing the clients as they connect or disconnect.
17+
* Processing modifications of settings that are caused by other aspects of the system, e.g. a new user logs in.
18+
19+
The browser channel handler supports the following request messages and sends the
20+
associated responses. When an error occurs, the handler sends an response and
21+
closes the web sockets connection.
22+
23+
* A client sends a connection request. In this example, the client is UIO+:
24+
* request: `{type: "connect", solutionId: "net.gpii.uioPlus"}`
25+
* response: `{type: "connectionSucceeded, "payload": {initial settings values for the solutionId}}`
26+
* Client sends a request to change settings values:
27+
* request: `{type: "changeSettings", "payload": {settings values to change}}`
28+
* response: `{type: "changeSettingsReceived", "payload": {settings values after changing}}`
29+
* Some other component of the system changes a setting relevant to connected clients:
30+
* response: `{type: "onChangeSettings", "payload:" {settings values after changing}}`
31+
* Error response when connecting with an unknown solution:
32+
* response: `{isError: true, message: "Rejecting a connection request from _solutionId_.
33+
The solution id was not found in the solutions registry"}`
34+
* Error response when trying to connect more than once:
35+
* response: `{isError: true, message: "Connection already established - cannot send a second connect message"}`
1636

1737
## The WebSockets settings handler
1838

@@ -21,8 +41,7 @@ of the system. The settings handler is an instance of `gpii.settingsHandler.web
2141
in _gpii/node_modules/settingsHandlers/src/WebSocketsComponent.js_.
2242

2343
This component stores the information about clients and keeps a list of settings for every solution that makes use of
24-
this settings handler. Also, this component create notifications for every connected client at any time when the
25-
settings change.
44+
this settings handler. Also, this component notifies connected clients whenever their settings change.
2645

2746
## Usage
2847

@@ -69,30 +88,34 @@ The workflow between the client and server can be summarised as follows:
6988
the *id* of the client, in this instance `net.gpii.uioPlus`.
7089
* The client will be registered if the solution's id can be found of the solutions registry, otherwise, the registration
7190
will be rejected and the system will emit en error, and the client will disconnect.
72-
* When the flow manager emits either the _connectionSucceeded_ (after being registered) or the _onSettingsChanged_
73-
(after a user login/logout) signal to the client, it is delivering the current available settings for the client in
74-
the following way:
75-
91+
* The client can request changes to its settings by sending a _changeSettings_ message type. If successful, the client
92+
is sent a _changeSettingsReceived_ message type.
93+
* When a _connectionSucceeded_, _changeSettingsReceived_, or an _onSettingsChanged_ signal is sent to the client, the
94+
current available settings for the client are sent as well, e.g.:
7695
```json
7796
{
78-
"screenReaderTTS/enabled":false,
79-
"highContrast/enabled":true,
80-
"invertColours":false,
81-
"magnifierEnabled":true,
82-
"magnification":2,
83-
"fontSize":"medium",
84-
"simplifier":false,
85-
"highContrastTheme":"white-black"
97+
"characterSpace":1,
98+
"clickToSelectEnabled":false,
99+
"contrastTheme":"wb",
100+
"fontSize":1.1,
101+
"inputsLargerEnabled":false,
102+
"lineSpace":1,
103+
"selectionTheme":"default",
104+
"selfVoicingEnabled":false,
105+
"simplifiedUiEnabled":false,
106+
"syllabificationEnabled":false,
107+
"tableOfContentsEnabled":false,
108+
"wordSpace":1
86109
}
87110
```
88-
* When a client disconnects, it'll be removed from the list of registered clients
111+
* When a client disconnects, it is removed from the list of registered clients
89112

90113
## Running the sample client
91114

92-
The client has been checked in to [../examples/browserChannelClient](../examples/browserChannelClient). To try it out, first
93-
start the GPII in the CloudBased browserChannel test configuration from the root of universal with
115+
An example client is avaiable at [../examples/browserChannelClient](../examples/browserChannelClient). To try it out, first
116+
start the GPII test configuration from the root of universal with
94117

95-
node gpii.js gpii/configs gpii.config.cloudBased.production
118+
npm start
96119

97120
Then start the client from [../examples/browserChannelClient](../examples/browserChannelClient) with
98121

examples/browserChannelClient/browserChannelClient.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ var ws = require("ws");
2121

2222
var socket = new ws("ws://localhost:8081/browserChannel"); // eslint-disable-line new-cap
2323

24+
var changeSetting = false;
25+
2426
// When the connection is done, the client tells to the flow manager its id
2527

2628
socket.on("open", function () {
27-
console.log("## Socket connected");
29+
console.log("## browserChannelClient: Socket connected");
2830
socket.send(JSON.stringify({
2931
type: "connect",
3032
payload: {
@@ -34,16 +36,36 @@ socket.on("open", function () {
3436
});
3537

3638
socket.on("message", function (data) {
37-
console.log("## Received the following message: " + data);
39+
console.log("## browserChannelClient: Received the following message: " + data);
3840
var message = JSON.parse(data);
3941
// Right after sending the id to the flow manager, the server will return back
4042
// the current settings in the system (if any)
4143
if (message.type === "connectionSucceeded") {
42-
console.log("## Got initial settings ", message.payload, " on connection");
44+
changeSetting = true;
45+
console.log("## browserChannelClient: Got initial settings ", message.payload, " on connection");
4346
}
4447
// By listening to this message type, the client will be notified when the system has
4548
// new settings to be applied on the client side
4649
else if (message.type === "onSettingsChanged") {
47-
console.log("## Got changed settings ", message.payload);
50+
console.log("## browserChannelClient: Got changed settings ", message.payload);
51+
}
52+
// Log acknowledgement that the "changeSettings" message was sent
53+
else if (message.type === "changeSettingsReceived") {
54+
console.log("## browserChannelClient: ChangeSettings was successfully sent ", message.payload);
55+
}
56+
57+
// Change two settings, and be done.
58+
if (changeSetting) {
59+
changeSetting = false;
60+
socket.send(JSON.stringify({
61+
type: "changeSettings",
62+
payload: {
63+
settings: {
64+
characterSpace: 1,
65+
clickToSelectEnabled: false,
66+
contrastTheme: "default"
67+
}
68+
}
69+
}));
4870
}
4971
});

examples/pspChannelClient/pspChannelClientApplyPrefs.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,22 @@ var socket = new ws("ws://localhost:8081/pspChannel"); // eslint-disable-line ne
2424

2525
// When the connection is done, the server will send the initial data of the current session if any
2626
socket.on("open", function () {
27-
console.log("## Socket connected");
27+
console.log("## pspChannelClientApplyPrefs: Socket connected");
2828
});
2929

3030
socket.on("message", function (data) {
3131
var message = JSON.parse(data);
32-
console.log("## Received the following message: " + JSON.stringify(message, null, 4));
32+
console.log("## pspChannelClientApplyPrefs: Received the following message: " + JSON.stringify(message, null, 4));
3333

3434
if (message.type === "preferencesApplied") {
35-
console.log("Preferences have been applied");
35+
console.log("## pspChannelClientApplyPrefs: Preferences have been applied");
3636
socket.close();
3737
return;
38-
};
38+
} else {
39+
console.log("## pspChannelClientApplyPrefs: Message type '" + message.type + "' not 'preferencesApplied'");
40+
}
3941

42+
console.log("## pspChannelClientApplyPrefs: Sending 'modelChanged' request");
4043
socket.send(JSON.stringify(
4144
{
4245
"type": "modelChanged",

examples/pspChannelClient/pspChannelClientReadPrefs.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,29 @@ var readRequestCount = 0;
2525

2626
// When the connection is done, the server will send the initial data of the current session if any
2727
socket.on("open", function () {
28-
console.log("## Socket connected");
28+
console.log("## pspChannelClientReadPrefs: Socket connected");
2929
});
3030

3131
socket.on("message", function (data) {
3232
var message = JSON.parse(data);
33-
console.log("## Received the following message: " + JSON.stringify(message, null, 4));
33+
console.log("## pspChannelClientReadPrefs: Received the following message: " + JSON.stringify(message, null, 4));
3434

3535
if (message.type === "preferenceReadSuccess") {
36-
console.log("Preference has been read");
36+
console.log("## pspChannelClientReadPrefs: Preference has been read");
3737
socket.close();
3838
return;
39-
};
40-
if (message.type === "preferenceReadFail") {
41-
console.log("Preference cannot be read");
39+
} else if (message.type === "preferenceReadFail") {
40+
console.log("## pspChannelClientReadPrefs: Preference cannot be read");
4241
socket.close();
4342
return;
44-
};
43+
} else {
44+
console.log("## pspChannelClientReadPrefs: Message type '" + message.type + "' not reading success/failure");
45+
}
4546

4647
if (readRequestCount === 0) {
4748
readRequestCount++;
4849
// Only send the read request once
50+
console.log("## pspChannelClientReadPrefs: Sending 'pullModel' request");
4951
socket.send(JSON.stringify(
5052
{
5153
"type": "pullModel",

gpii/node_modules/flowManager/src/BrowserChannel.js

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
/*!
2+
GPII BrowserChannel Handler
3+
4+
Copyright 2014, 2015 Emergya
5+
Copyright 2015-2018 Raising the Floor - International
6+
Copyright 2020 OCAD University
7+
8+
Licensed under the New BSD license. You may not use this file except in
9+
compliance with this License.
10+
11+
You may obtain a copy of the License at
12+
https://github.com/gpii/universal/LICENSE.txt
13+
*/
14+
115
"use strict";
216

317
var fluid = require("infusion");
@@ -24,6 +38,11 @@ fluid.defaults("gpii.flowManager.browserChannel.handler", {
2438
}
2539
});
2640

41+
/**
42+
* Send an error response for the request.
43+
* @param {Component} request - An instance of gpii.flowManager.browserChannel.handler.
44+
* @param {String} message - Error message text to include in the response.
45+
*/
2746
gpii.flowManager.browserChannel.sendError = function (request, message) {
2847
fluid.log("Sending browserChannel error ", message);
2948
var error = {
@@ -35,20 +54,62 @@ gpii.flowManager.browserChannel.sendError = function (request, message) {
3554
request.ws.close(1008, "Solution id not authorized");
3655
};
3756

57+
/**
58+
* Handler for all message types:
59+
* - an initial "connect" message type establishes the connection and
60+
* initializes the channel and its relationship with the WebSockets settings
61+
* handler. This includes dynamically attaching the
62+
* gpii.flowManager.browserChannel.receiveChangeSettingsMsg() listener to
63+
* handle "changeSettings" message types after the connection is established.
64+
* - any subsequent "connect" message types are silently ignored,
65+
* - all other message types cause an error response and close the connection
66+
* The one exception is the "changeSettings" message type (see first point).
67+
* @param {Component} that - An instance of gpii.flowManager.browserChannel.handler.
68+
* @param {Object} message - Object containing the message type and its payload.
69+
* @param {Component} solutionsRegistryDataSource - Used to match the solution
70+
* given in the payload.
71+
* @param {Component} platformReporter - Used to determine the platform this
72+
* is running on.
73+
*/
3874
gpii.flowManager.browserChannel.receiveMessage = function (that, message, solutionsRegistryDataSource, platformReporter) {
39-
var solutionId = message.payload.solutionId;
75+
if (message.type !== "connect") {
76+
return;
77+
}
4078
if (that.established) {
4179
gpii.flowManager.browserChannel.sendError(that, "Connection already established - cannot send a second connect message");
4280
}
81+
var solutionId = message.payload.solutionId;
4382
solutionsRegistryDataSource.get({os: platformReporter.reportPlatform().id}, function onSuccess(entries) {
4483
if (!(solutionId in entries)) {
4584
gpii.flowManager.browserChannel.sendError(that, "Rejecting a connection request from '" + solutionId +
4685
"'. The solution id was not found in the solutions registry");
4786
} else {
4887
gpii.settingsHandlers.webSockets.instance.addClient(solutionId, that);
4988
that.established = true;
89+
that.solutionId = solutionId;
5090
}
5191
}, function (error) {
5292
gpii.flowManager.browserChannel.sendError(that, error.message);
5393
});
5494
};
95+
96+
/**
97+
* Listener for the "changeSettings" message type. This is added as a listener
98+
* after the connection has been established. That is, this will not function
99+
* without a previous "connect" message type.
100+
* @param {Component} that - An instance of gpii.flowManager.browserChannel.handler.
101+
* @param {Object} message - Object containing the message type and its payload.
102+
*/
103+
gpii.flowManager.browserChannel.receiveChangeSettingsMsg = function (that, message) {
104+
if (message.type === "changeSettings" && that.established) {
105+
var wsPayload = {};
106+
wsPayload[that.solutionId] = [{
107+
options: {
108+
path: that.solutionId,
109+
source: that
110+
},
111+
settings: message.payload.settings
112+
}];
113+
gpii.settingsHandlers.webSockets.set(wsPayload);
114+
}
115+
};

0 commit comments

Comments
 (0)