Skip to content
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
f846454
GPII-228: First steps towards the snapshotter implementation
Feb 14, 2014
000b33c
GPII-228: Temporary save while doing other work
Feb 19, 2014
e36f564
GPII-228: Things are working now. Requires cleanup and tests
Feb 21, 2014
179e705
GPII-228: Cleaned up branch
Feb 21, 2014
eb78e33
GPII-228: Fixed a few more errors
Feb 21, 2014
04f4e0a
GPII-228: Added linux entries for snapshotting
Feb 24, 2014
b45079c
GPII-228 First attempt at merging Kapsers work from 2014
sgithens May 23, 2018
fa8a2fb
GPII-228 Continuing cleanup and refactoring.
sgithens Jun 1, 2018
526d545
GPII-228 Renaming snapshot to capture.
sgithens Jun 1, 2018
25ac4d4
Merge remote-tracking branch 'gpii/master' into gpii-228-2018
sgithens Jun 1, 2018
4516c89
GPII-228 Finished with first iteration of snapshotter revival
sgithens Jun 4, 2018
1764ef9
GPII-228 Removign some spaces that got removed.
sgithens Jun 4, 2018
2ef4b41
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Dec 8, 2018
1c05b52
GPII-228 Updating location of getDeviceContext
sgithens Dec 31, 2018
3c55217
Merge remote-tracking branch 'GPII' into gpii-228-2018
sgithens Dec 31, 2018
29a2708
GPII-228 Another round of Capture/Snapshotting prototyping
sgithens Jan 15, 2019
f30a253
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Mar 14, 2019
cd8127b
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Apr 17, 2019
eba8606
GPII-228 Reverting to current version of NoSettingsHandler
sgithens Apr 19, 2019
179c7e1
GPII-228 Removing http handler endpoints for capturing.
sgithens Apr 19, 2019
b94f137
GPII-228 Minor refactorings and initial tests.
sgithens May 7, 2019
c727f64
GPII-228 Refactoring event->promise based methods needed for capture
sgithens May 7, 2019
4aba301
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Jun 26, 2019
db831bb
GPII-228 Minor change to promise/event signature to match previous args
sgithens Jun 26, 2019
f484faf
GPII-228 Initial unit tests, some cleanup
sgithens Jul 10, 2019
b79d476
GPII-228 Adding Capture Tests back in
sgithens Jul 10, 2019
b26a588
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Jul 10, 2019
38bea00
GPII-228 Continuing impl work
sgithens Jul 14, 2019
8dec2c5
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Aug 14, 2019
eb54bb8
GPII-228 Tests/impl for solutions with multiple settings handlers
sgithens Aug 15, 2019
d594966
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Sep 9, 2019
0131b23
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Sep 26, 2019
f562fe8
GPII-228 Removing duplicate sequences from installed solutions events.
sgithens Sep 26, 2019
17ce607
GPII-228 Added test for capture.getInstalledSolutions
sgithens Sep 26, 2019
ec7cb2f
GPII-228 Removing event based capture in favor of promise based API
sgithens Sep 26, 2019
f32a13d
GPII-228 Fixing up jsdoc on captureSystemSettings
sgithens Sep 26, 2019
e15f44d
GPII-228 Simplifying invoker name.
sgithens Sep 26, 2019
1b636f7
GPII-4146 GPII-228 Adding adjustments for capturing from JAWS default…
sgithens Oct 2, 2019
edd5160
GPII-228 Adding checks and unit tests for error payload that may be i…
sgithens Oct 9, 2019
6b0416d
GPII-228 Temporary workaround for SPI and native windows payloads
sgithens Nov 5, 2019
511e08b
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Nov 21, 2019
adcf338
GPII-228 Refactoring and cleanup
sgithens Nov 28, 2019
0fd86ac
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Dec 7, 2019
49e4a38
GPII-228 Updating test data adjustments
sgithens Dec 9, 2019
dd53284
Merge remote-tracking branch 'GPII/master' into gpii-228-2018
sgithens Jan 24, 2020
3e70229
GPII-228 Removed unused test configuration
sgithens Jan 24, 2020
2017627
GPII-228 Rearranging test runs so simple functions are just called wi…
sgithens Jan 25, 2020
98e56d4
GPII-288 More meaningful messages on errors in operating settings han…
sgithens Jan 25, 2020
2b3f8e9
GPII-228 Cleaning up TODO comments
sgithens Jan 25, 2020
caa6508
GPII-228 Refactoring fetch all solutions loop
sgithens Jan 25, 2020
4b167f8
GPII-228 Adding missing jsdocs
sgithens Jan 26, 2020
146119b
GPII-228 cleanup
sgithens Jan 27, 2020
2eb479f
GPII-228 Cleanup
sgithens Jan 28, 2020
e710078
GPII-228 Using lifecycle managers now identicle settings read functio…
sgithens Jan 28, 2020
382c51f
GPII-228 Scoping argument to lifecycleManager.read invoker
sgithens Jan 28, 2020
41b100d
GPII-228 Fixing tests (OS reported) for CI Pipeline (and running on l…
sgithens Jan 29, 2020
53ae908
GPII-228 Updates from review
sgithens Feb 6, 2020
b71918f
GPII-228 Combined gpii.flowManager getSolutions and getSolutionsPromise
sgithens Feb 6, 2020
97b5f82
GPII-228 Updates from Review
sgithens Feb 6, 2020
5c985d0
GPII-228 Diversifying test data
sgithens Feb 6, 2020
3834082
GPII-228 Minor refactoring of promise chains, documenting invokers
sgithens Feb 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 192 additions & 0 deletions gpii/node_modules/flowManager/src/Capture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/**
* GPII Capture Component
*
* Copyright 2020 Raising the Floor - International
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* You may obtain a copy of the License at
* https://github.com/gpii/universal/LICENSE.txt
*/
"use strict";

var fluid = require("infusion"),
gpii = fluid.registerNamespace("gpii");

fluid.defaults("gpii.flowManager.capture", {
gradeNames: ["fluid.component"],
events: {
// Pseudoevents for transforming promise chains to fetch the solutions on the current device
// and capture the settings for the device.
onSolutionsForCurrentDevice: null,
onCaptureSettingsForCurrentDevice: null
},
listeners: {
// Begin declaration of Promise Chain for onSolutionsForCurrentDevice
"onSolutionsForCurrentDevice.getDeviceContextPromise": {
funcName: "gpii.lifecycleManager.getDeviceContextPromise",
args: ["{flowManager}.deviceReporter"],
priority: "first"
},
"onSolutionsForCurrentDevice.getSolutions": {
funcName: "gpii.flowManager.getSolutions",
args: [ "{flowManager}.solutionsRegistryDataSource", "{arguments}.0"],
priority: "after:getDeviceContextPromise"
},
"onSolutionsForCurrentDevice.solutionsRegistryEntriesToPromise": {
funcName: "fluid.toPromise",
args: ["{arguments}.0.solutionsRegistryEntries"],
priority: "after:getSolutions"
},
// Begin declaration of Promise Chain for onCaptureSettingsForCurrentDevice
"onCaptureSettingsForCurrentDevice.getInstalledSolutionsForCurrentDevice": {
func: "{that}.getInstalledSolutionsForCurrentDevice",
priority: "first"
},
"onCaptureSettingsForCurrentDevice.captureSystemSettings": {
func: "{that}.captureSystemSettings",
args: ["{arguments}.0", "{arguments}.1"],
priority: "after:getInstalledSolutionsForCurrentDevice"
},
"onCaptureSettingsForCurrentDevice.formatRawCapturedSettings": {
func: "gpii.flowManager.capture.formatRawCapturedSettings",
args: ["{arguments}.0"],
priority: "after:captureSystemSettings"
}
},
invokers: {
getInstalledSolutionsForCurrentDevice: {
funcName: "fluid.promise.fireTransformEvent",
args: ["{that}.events.onSolutionsForCurrentDevice"]
},
getSystemSettingsCapture: {
funcName: "fluid.promise.fireTransformEvent",
args: ["{that}.events.onCaptureSettingsForCurrentDevice", {}, "{arguments}.0"] // options
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's confusing to have the second argument as an empty object. BTW, you didn't document it in the jsdoc for this function. I understand you use it as a placeholder for the solution list returned by getInstalledSolutionsForCurrentDevice(). But this gonna to be expressed in a more understandable way. What I can think of is:

  1. remove this argument;
  2. improve the first action onCaptureSettingsForCurrentDevice.getInstalledSolutionsForCurrentDevice in the promise chain to return:
{
    installedSolutions: {},
    options: {}
}
  1. This structure will be the input of the next listener.

Copy link
Contributor

@cindyli cindyli Feb 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, you did have a doc for this empty object although it's inaccurate:
* @param {Object} solutions - Solutions registry entries for solutions available on the current machine.

"solutions available on the current machine" is a value waiting to be calculated within this function rather than an empty object.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so I cleaned things up abit. I also removed another internal invoker that was just for the promise chain and declared it in line. The remaining two invokers are both for external usage, and I added a jsdoc for the first one as well.

I cleaned up the arguments on the other jsdoc... actually it had a couple arguments that were no longer relevant anymore, it only takes the one single options argument. It was still documenting the parameters from the function version rather than the invoker setup.

I changed the transforming promise chain invocation's argument from an empty object to just null, to hopefully make it more clear. It is only there so I can use the 3rd argument from the fire transform api. https://github.com/fluid-project/infusion-docs/blob/master/src/documents/PromisesAPI.md#fluidpromisefiretransformeventevent-payload-options

I'd like to keep the promise chains set up the way they are if possible, and keep the options in the designated 3rd parameter that each of the listeners can optionally except. I think it's pretty nice that each member in the chain takes the previous value and returns the next promise with no extra stuff. It's just that the promise chain doesn't require any payload to start, which is which is why the null is there.

},
captureSystemSettings: {
funcName: "gpii.flowManager.capture.captureSystemSettings",
args: ["{lifecycleManager}.read", "{arguments}.0", "{arguments}.1"] // solutionsRegistryEntries, options
}
}
});

/**
* Invoker `{gpii.flowManager.capture}.getSystemSettingsCapture`
*
* @function
* @name {gpii.flowManager.capture}.getSystemSettingsCapture
*
* This main API entry point for capturing settings from a system or computer. This captures
* the actual settings on the device, so it assumed to be running in a local untrusted flow
* manager.
*
* @param {Event} onCaptureSettingsForCurrentDevice - The transforming promise chain
* @param {Object} options - Options for this chain.
* @param {Array} options.solutionsList - An array of solution IDs to filter by when
* retreiving settings. If this option is not included, all available settings will be
* returned. ex: `["com.microsoft.windows.mouseSettings", "com.freedomscientific.jaws"]`.
* @return {Promise} A promise resolved with the payload of captured system settings.
*/

/**
* Runs through all the solutions currently available on the system, pulls the current
* setting for each supportedSetting and returns them in an object. Primary use case
* is for backing Capture tools that would allow a user to set up their GPII profile
* starting with the current settings for their applications on the local machine.
*
* @param {Function|gpii.lifecycleManager.read} readSettingsFunc - lifecycleManager.read (or suitable implementation),
* that takes solution registry entries, reads their current values on the device, and returns a promise resolved to
* them.
* @param {Object} solutions - Solutions registry entries for solutions available on the current machine.
* @param {Object} options - Extra options for processing.
* @param {Array} options.solutionsList - If provided, only solutions in this list of `solutionsID`s will
* be captured. Example:
*
* '''json
* ["com.microsoft.windows.cursors", "com.freedomscientific.jaws"]
* '''
* @return {fluid.promise} Returns a promise resolving with the entire system settings capture.
*/
gpii.flowManager.capture.captureSystemSettings = function (readSettingsFunc, solutions, options) {
var solutionsToFetch = fluid.copy(solutions);
if (options.solutionsList) {
fluid.remove_if(solutionsToFetch, function (solution, solutionID) {
return !options.solutionsList.includes(solutionID);
});
}

return readSettingsFunc(solutionsToFetch);
};

/**
* The raw return payload from the capture promise sequence looks like:
* '''json
* [
* {
* "fakemag1": [
* {
* "settings": {
* "magnification": 2
* }
* }
* ]
* },
* {
* "fakemag1": [
* {
* "settings": {
* "invert": true
* }
* }
* ]
* },
* {
* "fakemag2": [
* {
* "settings": {
* "magnification": 2,
* "invert": true
* }
* }
* ]
* }
* ]
* '''
*
* and we want:
* '''json
* {
* "fakemag1": {
* "magnification": 2,
* "invert": true
* },
* "fakemag2": {
* "magnification": 2,
* "invert": true
* }
* }
* '''
*
* @param {Object} data - The raw captured data.
* @return {Object} Returns a new payload with collapsed data, and multiple settings handler
* results for the same solution merged together.
*/
gpii.flowManager.capture.formatRawCapturedSettings = function (data) {
var togo = {};
fluid.each(data, function (sequenceItem) {
if (sequenceItem.isError) {
fluid.log("Error capturing settings for: ", sequenceItem);
return;
}
fluid.each(sequenceItem, function (item, key) {
if (!togo[key]) {
togo[key] = {};
}
fluid.each(fluid.get(item, "0.settings"), function (value, settingId) {
togo[key][settingId] = value;
});
});
});
return togo;
};
4 changes: 4 additions & 0 deletions gpii/node_modules/flowManager/src/FlowManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ require("./DefaultSettingsLoader.js");
require("./PSPChannel.js");
require("./SettingsDataSource.js");
require("./UntrustedFlowManager.js");
require("./Capture.js");

require("preferencesServer");
require("lifecycleManager");
Expand Down Expand Up @@ -179,6 +180,9 @@ fluid.defaults("gpii.flowManager.local", {
eventLog: {
type: "gpii.eventLog"
},
capture: {
type: "gpii.flowManager.capture"
},
userListeners: {
type: "gpii.userListeners"
},
Expand Down
39 changes: 28 additions & 11 deletions gpii/node_modules/flowManager/src/MatchMaking.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,28 +77,45 @@
});
};

/*
* Asynchronous function which makes a get call to the solutions registry (1st parameter) to
/**
* Asynchronous/Promise returning function which makes a get call to the solutions registry (1st parameter) to
* retrieve the solutions registry matching what is passed in the `device` parameter.
* This is appended to the matchmaker payload (mmpayload) parameter, which in turn is passed
* as parameter in the event fired.
*
* @solutionsRegistryDataSource (Object) - a solutions registry data source
* @deviceContext (Object) - output from a device reporter. Used to filter solutions registry entries
* @event (Object) - Event to be fired when the solutionsRegistry entry has been retrieved
* @onError (Object) - Event to be fired when an error occurs
* This function can be used with either (or both) asyncronously with an `event` and `onError` handlers
* passed in, or with the returned `fluid.promise`.
*
* @return (undefined) - function is asynchronous and doesn't return anything. Instead the event
* is fired with the modified mmpayload.
* @param {Object} solutionsRegistryDataSource - a solutions registry data source
* @param {Object} deviceContext - output from a device reporter. Used to filter solutions registry entries
* @param {Object} onSuccessEvent - Optional: Event to be fired when the solutionsRegistry entry has been retrieved
* @param {Object} onErrorEvent - Optional: Event to be fired when an error occurs
* @return {fluid.promise} - Returns a promise resolving with the mmpayload. Optionally if provided, the events
* are also fired with the modified mmpayload.
*/
gpii.flowManager.getSolutions = function (solutionsRegistryDataSource, deviceContext, event, onError) {
gpii.flowManager.getSolutions = function (solutionsRegistryDataSource, deviceContext, onSuccessEvent, onErrorEvent) {
var promiseTogo = fluid.promise();

var os = fluid.get(deviceContext, "OS.id");
var promise = solutionsRegistryDataSource.get({});
promise.then(function (solutions) {
var solutionsRegistryEntries = gpii.matchMakerFramework.filterSolutions(solutions[os], deviceContext);
fluid.log("Fetched filtered solutions registry entries: ", gpii.renderMegapayload({solutionsRegistryEntries: solutionsRegistryEntries}));
event.fire(solutionsRegistryEntries, solutions);
}, onError.fire);
promiseTogo.resolve({
solutionsRegistryEntries: solutionsRegistryEntries,
solutions: solutions
});
if (onSuccessEvent) {
onSuccessEvent.fire(solutionsRegistryEntries, solutions);
}
}, function (error) {
promiseTogo.reject(error);
if (onErrorEvent) {
onErrorEvent.fire(error);
}
});

return promiseTogo;
};

// initialPayload contains fields
Expand Down
Loading