Skip to content
Merged
Show file tree
Hide file tree
Changes from 51 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
286 changes: 286 additions & 0 deletions gpii/node_modules/flowManager/src/Capture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
/**
* GPII snapshot Handler
*
* Copyright 2014 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: {
onSolutionsForCurrentDevice: null,
onCaptureSettingsForCurrentDevice: null
},
listeners: {
onSolutionsForCurrentDevice: [
{
funcName: "gpii.lifecycleManager.getDeviceContextPromise",
args: ["{flowManager}.deviceReporter"]
},
{
funcName: "gpii.flowManager.getSolutionsPromise",
args: [ "{flowManager}.solutionsRegistryDataSource", "{arguments}.0"]
},
{
funcName: "fluid.toPromise",
args: ["{arguments}.0.solutionsRegistryEntries"]
}
],
onCaptureSettingsForCurrentDevice: [
{
func: "{that}.getInstalledSolutions"
},
{
func: "{that}.captureSystemSettings",
args: ["{arguments}.0", "{arguments}.1"]
},
{
func: "gpii.flowManager.formatRawCapturedSettings",
args: ["{arguments}.0"]
}
]
},
invokers: {
getInstalledSolutions: {
funcName: "gpii.flowManager.getInstalledSolutions",
args: ["{that}"]
},
getSystemSettingsCapture: {
funcName: "gpii.flowManager.getSystemSettingsCapture",
args: ["{that}.events.onCaptureSettingsForCurrentDevice", "{arguments}.0"] // Options
},
captureSystemSettings: {
funcName: "gpii.flowManager.captureSystemSettings",
args: ["{lifecycleManager}.invokeSettingsHandlerGet", "{lifecycleManager}.variableResolver",
"{arguments}.0", "{arguments}.1"]
}
}
});

gpii.flowManager.getInstalledSolutions = function (that) {
return fluid.promise.fireTransformEvent(that.events.onSolutionsForCurrentDevice);
};

/**
* 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.
*/
gpii.flowManager.getSystemSettingsCapture = function (onCaptureSettingsForCurrentDevice, options) {
return fluid.promise.fireTransformEvent(onCaptureSettingsForCurrentDevice,
{}, options);
};

/**
* This function invokers a settings handler to fetch settings, but wraps the processing and reports
* back any failures in an `isError: true` json block.
*
* @param {Function} invokeSettingsHandlerGet - The get function from the appropriate settings handler.
* @param {String} solutionID - The dotted solution id, ex `com.freedomscientific.jaws`
* @param {Object} handlerSpec - TODO, exactly how much of the solutions entry block is this?
* @return {Object} The returned settings, or an error block with debugging information.
*/
gpii.flowManager.capture.safeHandlerGet = function (invokeSettingsHandlerGet, solutionID, handlerSpec) {
var promiseTogo = fluid.promise();
try {
invokeSettingsHandlerGet(solutionID, handlerSpec).then(function (data) {
promiseTogo.resolve(data);
}, function (err) {
promiseTogo.resolve({
solutionId: solutionID,
handlerSpec: handlerSpec,
isError: true,
message: "Settings Handler Promise Rejection",
err: err
});
});
}
catch (err) {
promiseTogo.resolve({
solutionId: solutionID,
handlerSpec: handlerSpec,
isError: true,
message: "Unexpected Error in operating settings handler.",
Copy link
Member

Choose a reason for hiding this comment

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

Mention the capture workflow in both of these messages. You may find the utility kettle.upgradeError https://github.com/fluid-project/kettle/blob/master/lib/KettleUtils.js#L82 helpful in capturing details of an original error whilst composing further detail

Copy link
Member Author

Choose a reason for hiding this comment

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

I updated these strings to mention the capture workflow, but kept my structure, as I'd some of the data to stay separate for debugging and blackbox investigation if necessary, I don't really want my message and the error concatenated, and would like the other bits to stay in json form.

err: err
});
}
return promiseTogo;
};

/**
* Fetches all settings for a particular solution, going through all of the solutions settings handlers.
*
* @param {lifecycleManager.invokeSettingsHandlerGet} invokeSettingsHandlerGet - Invoker from the `lifecycleManager`
* necessary for extracting settings from a solution and it's spec.
* @param {Object} solution - The solution registry entry body for this solution.
* @param {String} solutionID - The dotted solution id, example `com.microsoft.windows.cursors`.
* @param {lifecycleManager.variableResolver} resolver - Resolver for looking up handler specifications
* @return {Array} An array of promises resolving to the results from each settings handler the solution uses.
*/
gpii.flowManager.capture.fetchAllSettingsForSolution = function (invokeSettingsHandlerGet, solution, solutionID, resolver) {
var settingsPromisesTogo = [];

var newSolution = gpii.lifecycleManager.transformSolutionSettings(solution, gpii.settingsHandlers.changesToSettings);

// TODO GPII-4146 In progress refactoring back to gpii-windows
// https://issues.gpii.net/browse/GPII-4146
// if (solutionID === "com.freedomscientific.jaws") {
// newSolution = gpii.flowManager.jawsVoiceProfileAdjustment(newSolution, localResolver);
// }

fluid.each(newSolution.settingsHandlers, function (handlerSpec) {
//if applicationSettings is unspecified, dont attempt to get settings
if (!handlerSpec.supportedSettings) {
return;
}
handlerSpec.settings = handlerSpec.supportedSettings;
// TODO There is some in progress refactoring that happened here to update spiSettingsHandler.
// No longer here, but this is a reminder to resolve it when there are acceptance tests for the SPI settings capture.
handlerSpec = resolver.resolve(handlerSpec, {});
settingsPromisesTogo.push(gpii.flowManager.capture.safeHandlerGet(invokeSettingsHandlerGet, solutionID, handlerSpec));
});
return settingsPromisesTogo;
};

/**
* Fetches all the settings for an entire list of solutions.
*
* @param {Object} solutionsToFetch - A keyed object of solutions using the same format as the solutions registry. Keys
* are solutionsIDs, like `com.freedomscientific.jaws` and the entries are the full solution registry entries.
* @param {lifecycleManager.invokeSettingsHandlerGet} invokeSettingsHandlerGet - Invoker from the `lifecycleManager`
* necessary for extracting settings from a solution and it's spec.
* @param {lifecycleManager.variableResolver} resolver - Resolver for looking up handler specifications
* @return {Array} Returns a list of promises that resolve to captured settings for each particular settings handler in
* every solution.
*/
gpii.flowManager.capture.fetchAllSettingsForSolutionsList = function (solutionsToFetch, invokeSettingsHandlerGet, resolver) {
Copy link
Contributor

@cindyli cindyli Jan 27, 2020

Choose a reason for hiding this comment

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

With the recent merge of the new read API, this function and lifecycleManager.read() are pretty much the same. Is it possible to directly use lifecycleManager.read() or at least consolidate the common part into a shared function?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @cindyli , as you mentioned the code between these two features are identical so I was able to remove mine and just use the lifecyclemanager. However, as soon as GPII-3119 is merged in (hopefully today or tomorrow), we can remove the custom SPI settings handling from the lifecycle manager processRead method.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree. Thanks for the heads up.

var handlerGetPromises = [];

fluid.each(solutionsToFetch, function (solution, solutionID) {
var nextPromises = gpii.flowManager.capture.fetchAllSettingsForSolution(invokeSettingsHandlerGet, solution, solutionID, resolver);
handlerGetPromises = handlerGetPromises.concat(nextPromises);
});

return fluid.promise.sequence(handlerGetPromises);
};

/**
* 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 {lifecycleManager.invokeSettingsHandlerGet} invokeSettingsHandlerGet - Invoker from the `lifecycleManager`
* necessary for extracting settings from a solution and it's spec.
* @param {lifecycleManager.variableResolver} resolver - Resolver for looking up handler specifications
* @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 captures. Example:
*
* '''json
* ["com.microsoft.windows.cursors", "com.freedomscientific.jaws"]
* '''
* @return {fluid.promise} Returns a promise resolving with the entire system settings capture.
*/
gpii.flowManager.captureSystemSettings = function (invokeSettingsHandlerGet, resolver, solutions, options) {
var solutionsToFetch = solutions;
if (options.solutionsList) {
solutionsToFetch = {};
fluid.each(solutions, function (solution, solutionID) {
if (options.solutionsList.indexOf(solutionID) >= 0) {
solutionsToFetch[solutionID] = solution;
}
});
}

return gpii.flowManager.capture.fetchAllSettingsForSolutionsList(solutionsToFetch, invokeSettingsHandlerGet, resolver);
};

/**
* 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.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(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
20 changes: 18 additions & 2 deletions gpii/node_modules/flowManager/src/MatchMaking.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,29 @@
* is fired with the modified mmpayload.
*/
gpii.flowManager.getSolutions = function (solutionsRegistryDataSource, deviceContext, event, onError) {
gpii.flowManager.getSolutionsPromise(solutionsRegistryDataSource, deviceContext).then(
function (data) {
event.fire(data.solutionsRegistryEntries, data.solutions);
},
onError.fire
);
};

gpii.flowManager.getSolutionsPromise = function (solutionsRegistryDataSource, deviceContext) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than adding a new getSolutionsPromise function, have you tried to get getSolutions return a promise besides firing events and have the capture component call getSolutions?

Copy link
Member Author

Choose a reason for hiding this comment

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

Neat idea, I updated the function to handle both purposes, and cleaned up it's jsdoc

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
});
}, promiseTogo.reject);

return promiseTogo;
};

// initialPayload contains fields
Expand Down
Loading