Commit aae34baf authored by Kyle Keating's avatar Kyle Keating

Add preStartServer() method to cross-origin-rcp module

When called, allows any incoming rpc request to wait in a queue and be proceeded a short time later when the actual start() method is called. This prevents potential timeouts from incoming RPC requests from LMS (or similar) that arrive after we tipped off the parent frame with a fetchConfig outgoing request but before startServer() is called.

- Rename start() to startServer()
- Use newer module export standard that matches the rest of the app
parent b4953ce6
import warnOnce from '../shared/warn-once';
// Array to keep track of pre-start requests
let preStartQueue = [];
/**
* Return the mapped methods that can be called remotely via this server.
*
......@@ -48,7 +51,18 @@ function isJsonRpcMessage(data) {
function start(store, settings, $window) {
const methods = registeredMethods(store);
$window.addEventListener('message', function receiveMessage(event) {
// Process the pre-start incoming RPC requests
preStartQueue.forEach(event => {
receiveMessage(event);
});
// Clear the queue and remove the preStartMessageListener
preStartQueue = [];
window.removeEventListener('message', preStartMessageListener);
// Start listening to new RPC requests
$window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
let allowedOrigins = settings.rpcAllowedOrigins || [];
if (!isJsonRpcMessage(event.data)) {
......@@ -67,7 +81,7 @@ function start(store, settings, $window) {
let jsonRpcRequest = event.data;
event.source.postMessage(jsonRpcResponse(jsonRpcRequest), event.origin);
});
}
/** Return a JSON-RPC response to the given JSON-RPC request object. */
function jsonRpcResponse(request) {
......@@ -93,8 +107,32 @@ function start(store, settings, $window) {
}
}
export default {
server: {
start: start,
},
/**
* Queues all incoming RPC requests so they can be handled later.
*
* @param {MessageEvent} event - RPC event payload
*/
function preStartMessageListener(event) {
preStartQueue.push(event);
}
/**
* Start listening to incoming RPC requests right away so they don't timeout. These
* requests are saved until the server starts up and then they can be handled accordingly.
*
* Why?
*
* This allows the client to fetch its config from the parent app frame and potentially
* receive new unsolicited incoming requests that the parent app may send before this
* RPC server starts.
*
* @param {Window} window_ - Test seam
*/
function preStart(window_ = window) {
window_.addEventListener('message', preStartMessageListener);
}
module.exports = {
preStartServer: preStart,
startServer: start,
};
......@@ -2,7 +2,10 @@
import { jsonConfigsFrom } from '../shared/settings';
import crossOriginRPC from './cross-origin-rpc.js';
import {
startServer as startRPCServer,
preStartServer as preStartRPCServer,
} from './cross-origin-rpc.js';
import addAnalytics from './ga';
import disableOpenerForExternalLinks from './util/disable-opener-for-external-links';
import { fetchConfig } from './util/fetch-config';
......@@ -294,7 +297,7 @@ function startAngularApp(config) {
.run(sendPageView)
.run(setupApi)
.run(setupRoute)
.run(crossOriginRPC.server.start);
.run(startRPCServer);
// Work around a check in Angular's $sniffer service that causes it to
// incorrectly determine that Firefox extensions are Chrome Packaged Apps which
......@@ -311,6 +314,9 @@ function startAngularApp(config) {
angular.bootstrap(appEl, ['h'], { strictDi: true });
}
// Start capturing RPC requests before we start the RPC server (startRPCServer)
preStartRPCServer();
fetchConfig(appConfig)
.then(config => {
startAngularApp(config);
......
This diff is collapsed.
......@@ -176,7 +176,7 @@ describe('sidebar.util.fetch-config', () => {
});
});
it('makes an RCP request to `requestConfig` ', async () => {
it('makes an RPC request to `requestConfig` ', async () => {
await fetchConfig({}, fakeWindow);
fakeJsonRpc.call.calledWithExactly(
fakeTopWindow,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment