Commit d60435e3 authored by Robert Knight's avatar Robert Knight

Read sidebar app config asynchronously on startup

In preparation for introducing an optional new postMessage-based method
for the sidebar app to fetch configuration from its embedder, make the
setting fetch flow async.

- Move the Angular app startup logic into a function which receives
  settings as an argument.
- Add a function to merge config rendered into the sidebar app HTML
  page with config fetched asynchronously from a host frame.
parent 87098dd8
......@@ -10,20 +10,15 @@ require('../shared/polyfills');
let raven;
// Read settings rendered into sidebar app HTML by service/extension.
const settings = require('../shared/settings').jsonConfigsFrom(document);
const appConfig = require('../shared/settings').jsonConfigsFrom(document);
if (settings.raven) {
if (appConfig.raven) {
// Initialize Raven. This is required at the top of this file
// so that it happens early in the app's startup flow
raven = require('./raven');
raven.init(settings.raven);
raven.init(appConfig.raven);
}
const hostPageConfig = require('./host-config');
Object.assign(settings, hostPageConfig(window));
settings.apiUrl = getApiUrl(settings);
// Disable Angular features that are not compatible with CSP.
//
// See https://docs.angularjs.org/api/ng/directive/ngCsp
......@@ -42,14 +37,14 @@ const angular = require('angular');
require('autofill-event');
// Setup Angular integration for Raven
if (settings.raven) {
if (appConfig.raven) {
raven.angularModule(angular);
} else {
angular.module('ngRaven', []);
}
if(settings.googleAnalytics){
addAnalytics(settings.googleAnalytics);
if (appConfig.googleAnalytics) {
addAnalytics(appConfig.googleAnalytics);
}
// Fetch external state that the app needs before it can run. This includes the
......@@ -118,29 +113,37 @@ function setupHttp($http, streamer) {
$http.defaults.headers.common['X-Client-Id'] = streamer.clientId;
}
function processAppOpts() {
if (settings.liveReloadServer) {
require('./live-reload-client').connect(settings.liveReloadServer);
}
}
/**
* Merge settings rendered into sidebar app HTML page with
* settings provided by the embedder of Hypothesis.
*/
function fetchConfig(appConfig) {
const hostPageConfig = require('./host-config');
const mergedConfig = Object.assign({}, appConfig, hostPageConfig(window));
module.exports = angular.module('h', [
// Angular addons which export the Angular module name
// via module.exports
require('angular-route'),
require('angular-sanitize'),
require('angular-toastr'),
mergedConfig.apiUrl = getApiUrl(mergedConfig);
// Angular addons which do not export the Angular module
// name via module.exports
['angulartics', require('angulartics')][0],
['angulartics.google.analytics', require('angulartics/src/angulartics-ga')][0],
['ngTagsInput', require('ng-tags-input')][0],
['ui.bootstrap', require('./vendor/ui-bootstrap-custom-tpls-0.13.4')][0],
return Promise.resolve(mergedConfig);
}
// Local addons
'ngRaven',
])
function startAngularApp(config) {
angular.module('h', [
// Angular addons which export the Angular module name
// via module.exports
require('angular-route'),
require('angular-sanitize'),
require('angular-toastr'),
// Angular addons which do not export the Angular module
// name via module.exports
['angulartics', require('angulartics')][0],
['angulartics.google.analytics', require('angulartics/src/angulartics-ga')][0],
['ngTagsInput', require('ng-tags-input')][0],
['ui.bootstrap', require('./vendor/ui-bootstrap-custom-tpls-0.13.4')][0],
// Local addons
'ngRaven',
])
// The root component for the application
.component('hypothesisApp', require('./components/hypothesis-app'))
......@@ -220,7 +223,7 @@ module.exports = angular.module('h', [
.value('random', require('./util/random'))
.value('raven', require('./raven'))
.value('serviceConfig', serviceConfig)
.value('settings', settings)
.value('settings', config)
.value('time', require('./util/time'))
.value('urlEncodeFilter', require('./filter/url').encode)
......@@ -232,18 +235,27 @@ module.exports = angular.module('h', [
.run(setupHttp)
.run(crossOriginRPC.server.start);
processAppOpts();
// Work around a check in Angular's $sniffer service that causes it to
// incorrectly determine that Firefox extensions are Chrome Packaged Apps which
// do not support the HTML 5 History API. This results Angular redirecting the
// browser on startup and thus the app fails to load.
// See https://github.com/angular/angular.js/blob/a03b75c6a812fcc2f616fc05c0f1710e03fca8e9/src/ng/sniffer.js#L30
if (window.chrome && !window.chrome.app) {
window.chrome.app = {
dummyAddedByHypothesisClient: true,
};
if (config.liveReloadServer) {
require('./live-reload-client').connect(config.liveReloadServer);
}
// Work around a check in Angular's $sniffer service that causes it to
// incorrectly determine that Firefox extensions are Chrome Packaged Apps which
// do not support the HTML 5 History API. This results Angular redirecting the
// browser on startup and thus the app fails to load.
// See https://github.com/angular/angular.js/blob/a03b75c6a812fcc2f616fc05c0f1710e03fca8e9/src/ng/sniffer.js#L30
if (window.chrome && !window.chrome.app) {
window.chrome.app = {
dummyAddedByHypothesisClient: true,
};
}
const appEl = document.querySelector('hypothesis-app');
angular.bootstrap(appEl, ['h'], {strictDi: true});
}
const appEl = document.querySelector('hypothesis-app');
angular.bootstrap(appEl, ['h'], {strictDi: true});
fetchConfig(appConfig).then(config => {
startAngularApp(config);
}).catch(err => {
console.error(err);
});
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