Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GPII-4410: Opening BYOB web links in an existing tab. #202

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
8 changes: 8 additions & 0 deletions configs/app.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@
"metrics": {
"record": "gpii.app.metrics",
"target": "{/ gpii.metrics}.options.gradeNames"
},
"linkRedirect": {
"record": {
"linkRedirect": {
"type": "gpii.app.linkRedirect"
}
},
"target": "{/ gpii.flowManager.local}.options.components"
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions siteconfig.json5
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@

alwaysUseChrome: false,

// The redirect url to open links by showing the tab if the link is already open in the browser. The encoded
// destination url is added to the end of this, or replaces `$1`. Normally, this value is
// "http://opensametab.morphic.org/redirect/", but it can be "http://refreshsametab.morphic.org/redirect/"
// to make the tab reload itself.
currentTabRedirect: "http://opensametab.morphic.org/redirect/",

// The template that is used for every label of the language setting's options.
// The "%" followed by a word specifies a variable and there are three possible variables:
// - native - the name of the language in its native form
Expand Down
1 change: 1 addition & 0 deletions src/main/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ require("./storage.js");
require("./tray.js");
require("./userErrorsHandler.js");
require("./metrics.js");
require("./linkRedirect.js");

// enhance the normal require to work with .json5 files
require("json5/lib/register");
Expand Down
74 changes: 74 additions & 0 deletions src/main/linkRedirect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Handles link redirection.
*
* Copyright 2020 Raising the Floor - International
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* The R&D leading to these results received funding from the
* Department of Education - Grant H421A150005 (GPII-APCP). However,
* these results do not necessarily represent the policy of the
* Department of Education, and you should not assume endorsement by the
* Federal Government.
*
* You may obtain a copy of the License at
* https://github.com/GPII/gpii-app/blob/master/LICENSE.txt
*/

"use strict";

var fluid = require("infusion"),
URL = require("url").URL;

var gpii = fluid.registerNamespace("gpii");
fluid.registerNamespace("gpii.app.linkRedirect");

/**
* Handles /redirect, which redirects the browser to the provided url.
* This is a fall-back for the 'open link in existing tab' feature [GPII-4410], where the browser is opened with a
* special link which gets intercepted by a browser extension. The link really points to this handler, so it will
* still work with browsers that don't have the extension installed.
*/
fluid.defaults("gpii.app.linkRedirect", {
gradeNames: ["kettle.app"],
defaultRedirectUrl: "http://opensametab.morphic.org/redirect/$1",
Copy link

Choose a reason for hiding this comment

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

I don't see where the "refreshsametab.morphic.org" urls are redirected. Is that in configuration somewhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

requestHandlers: {
handle: {
type: "gpii.app.linkRedirect.request",
route: "/redirect/:destination(.*)"
}
}
});

fluid.defaults("gpii.app.linkRedirect.request", {
gradeNames: ["kettle.request.http"],
invokers: {
handleRequest: {
funcName: "gpii.app.linkRedirect.handleRequest",
args: [
"{request}",
"{request}.req.params.destination"
]
}
}
});

/**
* Handler for /redirect. Redirects the browser to the given url.
*
* @param {Component} request The request object.
* @param {String} destination The destination URL.
*/
gpii.app.linkRedirect.handleRequest = function (request, destination) {
try {
// Make sure the url is valid before sending it out.
var url = new URL(destination);
request.res.status(301).redirect(url.href);
} catch (e) {
request.handlerPromise.reject({
statusCode: 400,
message: e.message
});
}
};
44 changes: 43 additions & 1 deletion src/main/siteConfigurationHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
*/
"use strict";

var fluid = require("infusion");
var fluid = require("infusion"),
URL = require("url").URL;

var gpii = fluid.registerNamespace("gpii");

Expand Down Expand Up @@ -111,6 +112,27 @@ fluid.defaults("gpii.app.siteConfigurationHandler", {
distributeMetrics: {
record: "{that}.options.siteConfig.metrics",
target: "{/ gpii.app.metrics}.options.siteConfig"
},
distributeQssConfigUrl: {
record: {
// Tweaks the redirect url so it's on the same port as the app.
expander: {
funcName: "gpii.app.siteConfigurationHandler.setUrlPort",
args: [
{
expander: {
funcName: "fluid.firstDefined",
args: [
"{that}.options.siteConfig.qss.currentTabRedirect",
"{gpii.app.linkRedirect}.options.defaultRedirectUrl"
]
}
},
"{kettle.server}.options.port"
]
}
},
target: "{that qssWrapper}.options.siteConfig.currentTabRedirect"
}
},

Expand Down Expand Up @@ -156,3 +178,23 @@ gpii.app.siteConfigurationHandler.requireFirst = function (files) {
}
return togo;
};

/**
* Sets the port value of a url.
* @param {String} url The url to update.
* @param {Number} port The new port number.
* @return {String} The url, with the updated port.
*/
gpii.app.siteConfigurationHandler.setUrlPort = function (url, port) {
var togo;
if (url) {
try {
var u = new URL(url);
u.port = port;
togo = u.href;
} catch (e) {
fluid.log(fluid.logLevel.WARN, "Unable to parse url '" + url + "' ", e.message);
}
}
return togo;
};
20 changes: 16 additions & 4 deletions src/renderer/common/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,28 +92,40 @@
* @param {String} siteUrl - cloud folder's url
* @param {Boolean} alwaysUseChrome - true to use chrome, rather than the default browser.
* @param {Boolean} forceFullScreen - the function requires the browser to be open maximized
* @param {String} redirectUrl - [optional] A url which will wrap `siteUrl`. This can be used to make a redirection
* url. Current use case is to make an extension open an existing tab. `siteUrl` is encoded and added to the end of
* this, or a placeholder of `$1` can be used.
*/
gpii.windows.openUrl = function (siteUrl, alwaysUseChrome, forceFullScreen) {
gpii.windows.openUrl = function (siteUrl, alwaysUseChrome, forceFullScreen, redirectUrl) {
if (fluid.isValue(siteUrl)) {
var finalUrl = siteUrl;

// Wrap the url in the opensametab
if (redirectUrl) {
finalUrl = redirectUrl.replace(/\$1|$/, encodeURIComponent(siteUrl));
}

fluid.log("Opening link", finalUrl);

if (alwaysUseChrome) {
var command =
// Check chrome is installed
"reg query \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe\" /ve"
// If so, run chrome
+ " && start chrome \"" + siteUrl.replace(/"/g, "%22") + "\"";
+ " && start chrome \"" + finalUrl.replace(/"/g, "%22") + "\"";
if (forceFullScreen) {
// adding the full screen option for Chrome as well
command += " --start-fullscreen";
}
child_process.exec(command, function (err) {
if (err) {
// It failed, so use the default browser.
shell.openExternal(siteUrl);
shell.openExternal(finalUrl);
}
});
} else {
// we have the url, opening it in the default browser
shell.openExternal(siteUrl);
shell.openExternal(finalUrl);
}
} else {
// there is no value in the config, sending the warning
Expand Down
9 changes: 9 additions & 0 deletions src/renderer/qss/js/qss.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,15 @@
updateIsKeyedIn: {
changePath: "isKeyedIn",
value: "{arguments}.0"
},
openUrl: {
funcName: "gpii.windows.openUrl",
args: [
"{arguments}.0", // siteUrl
"{arguments}.1", // alwaysUseChrome
"{arguments}.2", // forceFullScreen
"{that}.options.siteConfig.currentTabRedirect" // redirectUrl,
]
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/qss/js/qssServiceButtons.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@
gradeNames: ["gpii.qss.buttonPresenter"],
invokers: {
activate: {
funcName: "gpii.windows.openUrl",
func: "{gpii.qss}.openUrl",
args: [
"{that}.model.item.schema.url", // using the url from the custom button's schema
true, // Override the OS default browser to always use Chrome instead
Expand Down