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