@blackbaud/sky-addin-client 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/CHANGELOG.md +124 -118
  2. package/README.md +470 -470
  3. package/bundles/sky-addin-client.global-es2015.js +914 -851
  4. package/bundles/sky-addin-client.global-es2015.min.js +1 -1
  5. package/bundles/sky-addin-client.global.js +926 -863
  6. package/bundles/sky-addin-client.global.min.js +1 -1
  7. package/bundles/sky-addin-client.umd-es2015.js +914 -851
  8. package/bundles/sky-addin-client.umd-es2015.min.js +1 -1
  9. package/bundles/sky-addin-client.umd.js +926 -863
  10. package/bundles/sky-addin-client.umd.min.js +1 -1
  11. package/index.d.ts +1 -1
  12. package/index.js +17 -17
  13. package/package.json +67 -67
  14. package/src/addin/addin-client.d.ts +277 -277
  15. package/src/addin/addin-client.js +703 -640
  16. package/src/addin/addin-client.js.map +1 -1
  17. package/src/addin/addin-client.spec.d.ts +1 -1
  18. package/src/addin/addin-client.spec.js +1476 -1414
  19. package/src/addin/addin-client.spec.js.map +1 -1
  20. package/src/addin/client-interfaces/addin-action-button-config.d.ts +10 -10
  21. package/src/addin/client-interfaces/addin-action-button-config.js +2 -2
  22. package/src/addin/client-interfaces/addin-button-config.d.ts +10 -10
  23. package/src/addin/client-interfaces/addin-button-config.js +2 -2
  24. package/src/addin/client-interfaces/addin-button-style.d.ts +6 -6
  25. package/src/addin/client-interfaces/addin-button-style.js +17 -17
  26. package/src/addin/client-interfaces/addin-client-args.d.ts +10 -10
  27. package/src/addin/client-interfaces/addin-client-args.js +2 -2
  28. package/src/addin/client-interfaces/addin-client-callbacks.d.ts +40 -40
  29. package/src/addin/client-interfaces/addin-client-callbacks.js +2 -2
  30. package/src/addin/client-interfaces/addin-client-close-modal-args.d.ts +10 -10
  31. package/src/addin/client-interfaces/addin-client-close-modal-args.js +2 -2
  32. package/src/addin/client-interfaces/addin-client-event-args.d.ts +13 -13
  33. package/src/addin/client-interfaces/addin-client-event-args.js +2 -2
  34. package/src/addin/client-interfaces/addin-client-flyout-permalink.d.ts +14 -14
  35. package/src/addin/client-interfaces/addin-client-flyout-permalink.js +2 -2
  36. package/src/addin/client-interfaces/addin-client-init-args.d.ts +28 -28
  37. package/src/addin/client-interfaces/addin-client-init-args.js +2 -2
  38. package/src/addin/client-interfaces/addin-client-navigate-args.d.ts +9 -9
  39. package/src/addin/client-interfaces/addin-client-navigate-args.js +2 -2
  40. package/src/addin/client-interfaces/addin-client-open-help-args.d.ts +10 -10
  41. package/src/addin/client-interfaces/addin-client-open-help-args.js +2 -2
  42. package/src/addin/client-interfaces/addin-client-ready-args.d.ts +39 -39
  43. package/src/addin/client-interfaces/addin-client-ready-args.js +2 -2
  44. package/src/addin/client-interfaces/addin-client-ready-button-config.d.ts +10 -10
  45. package/src/addin/client-interfaces/addin-client-ready-button-config.js +2 -2
  46. package/src/addin/client-interfaces/addin-client-show-confirm-args.d.ts +19 -19
  47. package/src/addin/client-interfaces/addin-client-show-confirm-args.js +2 -2
  48. package/src/addin/client-interfaces/addin-client-show-error-args.d.ts +18 -18
  49. package/src/addin/client-interfaces/addin-client-show-error-args.js +2 -2
  50. package/src/addin/client-interfaces/addin-client-show-flyout-args.d.ts +46 -46
  51. package/src/addin/client-interfaces/addin-client-show-flyout-args.js +2 -2
  52. package/src/addin/client-interfaces/addin-client-show-flyout-result.d.ts +9 -9
  53. package/src/addin/client-interfaces/addin-client-show-flyout-result.js +2 -2
  54. package/src/addin/client-interfaces/addin-client-show-modal-args.d.ts +14 -14
  55. package/src/addin/client-interfaces/addin-client-show-modal-args.js +2 -2
  56. package/src/addin/client-interfaces/addin-client-show-modal-result.d.ts +10 -10
  57. package/src/addin/client-interfaces/addin-client-show-modal-result.js +2 -2
  58. package/src/addin/client-interfaces/addin-client-show-toast-args.d.ts +15 -15
  59. package/src/addin/client-interfaces/addin-client-show-toast-args.js +2 -2
  60. package/src/addin/client-interfaces/addin-client-theme-settings.d.ts +13 -13
  61. package/src/addin/client-interfaces/addin-client-theme-settings.js +2 -2
  62. package/src/addin/client-interfaces/addin-confirm-button-style.d.ts +8 -8
  63. package/src/addin/client-interfaces/addin-confirm-button-style.js +16 -16
  64. package/src/addin/client-interfaces/addin-confirm-button.d.ts +26 -26
  65. package/src/addin/client-interfaces/addin-confirm-button.js +2 -2
  66. package/src/addin/client-interfaces/addin-modal-config.d.ts +12 -12
  67. package/src/addin/client-interfaces/addin-modal-config.js +2 -2
  68. package/src/addin/client-interfaces/addin-tab-config.d.ts +9 -9
  69. package/src/addin/client-interfaces/addin-tab-config.js +2 -2
  70. package/src/addin/client-interfaces/addin-tab-summary-style.d.ts +4 -4
  71. package/src/addin/client-interfaces/addin-tab-summary-style.js +13 -13
  72. package/src/addin/client-interfaces/addin-tile-config.d.ts +32 -32
  73. package/src/addin/client-interfaces/addin-tile-config.js +2 -2
  74. package/src/addin/client-interfaces/addin-tile-summary-style.d.ts +5 -5
  75. package/src/addin/client-interfaces/addin-tile-summary-style.js +15 -15
  76. package/src/addin/client-interfaces/addin-toast-style.d.ts +6 -6
  77. package/src/addin/client-interfaces/addin-toast-style.js +17 -17
  78. package/src/addin/client-interfaces/index.d.ts +27 -27
  79. package/src/addin/client-interfaces/index.js +43 -43
  80. package/src/addin/host-interfaces/addin-host-message-event-data.d.ts +23 -23
  81. package/src/addin/host-interfaces/addin-host-message-event-data.js +2 -2
  82. package/src/addin/host-interfaces/addin-host-message.d.ts +44 -44
  83. package/src/addin/host-interfaces/addin-host-message.js +2 -2
  84. package/src/addin/host-interfaces/index.d.ts +2 -2
  85. package/src/addin/host-interfaces/index.js +18 -18
  86. package/src/addin/index.d.ts +3 -3
  87. package/src/addin/index.js +19 -19
@@ -1,641 +1,704 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AddinClient = void 0;
4
- /**
5
- * Collection of regexs for our whitelist of host origins.
6
- */
7
- var allowedOrigins = [
8
- /^https\:\/\/[\w\-\.]+\.blackbaud\.com$/,
9
- /^https\:\/\/[\w\-\.]+\.blackbaud\-dev\.com$/,
10
- /^http\:\/\/[\w\-\.]+\.blackbaud\-dev\.com$/,
11
- /^https\:\/\/[\w\-\.]+\.blackbaudhosting\.com$/,
12
- /^https\:\/\/[\w\-\.]+\.bbcloudservices\.com$/,
13
- /^https\:\/\/localhost(\:[0-9]+)?$/,
14
- /^https\:\/\/secure[2|3|8]\.convio\.net$/,
15
- /^https\:\/\/testweb\.convio\.com$/,
16
- /^https\:\/\/[\w\-\.]+\.conviocloud\.com$/,
17
- /^https\:\/\/[\w\-\.]+\.blackbaudcloud\.com$/,
18
- /^https\:\/\/[\w\-\.]+\.blackbaudfaith\.com$/,
19
- /^https\:\/\/[\w\-\.]+\.blackbaudportal\.com$/,
20
- /^https\:\/\/[\w\-\.]+\.bbk12\.com$/,
21
- /^https\:\/\/[\w\-\.]+\.mycampus\-app\.com$/,
22
- /^https\:\/\/[\w\-\.]+\.myschoolapp\.com$/,
23
- /^https\:\/\/[\w\-\.]+\.myschoolautomation\.com$/,
24
- /^https\:\/\/[\w\-\.]+\.myschooldemo\.com$/,
25
- /^https\:\/\/[\w\-\.]+\.myschooltraining\.com$/
26
- ];
27
- /**
28
- * Client for interacting with the parent page hosting the add-in.
29
- */
30
- var AddinClient = /** @class */ (function () {
31
- function AddinClient(args) {
32
- var _this = this;
33
- this.args = args;
34
- /**
35
- * Tracks pending request to reeceive an auth-token from the host.
36
- */
37
- this.authTokenRequests = [];
38
- /**
39
- * Counter to provide unique ids for each auth token request.
40
- */
41
- this.lastAuthTokenRequestId = 0;
42
- /**
43
- * Tracks modal add-ins that have been launched from this add-in.
44
- */
45
- this.modalRequests = [];
46
- /**
47
- * Counter to provide unique ids for each modal request.
48
- */
49
- this.lastModalRequestId = 0;
50
- /**
51
- * Stores the registered add-in events.
52
- * Key - the event type.
53
- * Value - The callback function to be executed when the event type occurs.
54
- */
55
- this.registeredAddinEvents = {};
56
- /**
57
- * Stores the add-in events that have been sent to the host page.
58
- * Key - the event request ID.
59
- * Value - The Promise resolve function to be executed when the event is received by the host.
60
- */
61
- this.sentEvents = {};
62
- /**
63
- * Stores the pending add-in events that are queued to be sent to the host page after 200
64
- * milliseconds have expired.
65
- * Key - the event type.
66
- * Value - The Promise reject function to be executed if the event fails to be sent to the host page.
67
- */
68
- this.pendingSentEvents = {};
69
- /**
70
- * The event request ID counter.
71
- * The ID is incremented and assigned to each event that is sent.
72
- */
73
- this.eventRequestId = 0;
74
- /**
75
- * An array of event types that are supported by the host page.
76
- * The add-in client will throw an error if an event is attempted but not one the supported types.
77
- */
78
- this.supportedEventTypes = [];
79
- this.windowMessageHandler = function (event) {
80
- _this.handleMessage(event);
81
- };
82
- // Listen to messages from the host page.
83
- window.addEventListener('message', this.windowMessageHandler);
84
- // Inform the host page that the add-in is loaded and listening for messages.
85
- this.raiseAddinReadyMessage();
86
- }
87
- /* istanbul ignore next */
88
- /**
89
- * @returns {string} Returns the current query string path for the window, prefixed with ?.
90
- */
91
- AddinClient.getQueryString = function () {
92
- return window.location.search;
93
- };
94
- /**
95
- * Cleans up the AddinClient, releasing all resources.
96
- */
97
- AddinClient.prototype.destroy = function () {
98
- window.removeEventListener('message', this.windowMessageHandler);
99
- if (this.heightChangeIntervalId) {
100
- clearInterval(this.heightChangeIntervalId);
101
- }
102
- };
103
- /**
104
- * Requests the host page to navigate.
105
- * @param args Arguments describing the navigation request.
106
- */
107
- AddinClient.prototype.navigate = function (args) {
108
- this.postMessageToHostPage({
109
- message: {
110
- url: args.url
111
- },
112
- messageType: 'navigate'
113
- });
114
- };
115
- /**
116
- * Requests an authentication token for the current user.
117
- * @deprecated Use getUserIdentityToken() instead.
118
- * @returns {Promise<any>} Returns a promise which will resolve with the token value.
119
- */
120
- AddinClient.prototype.getAuthToken = function () {
121
- return this.getUserIdentityToken();
122
- };
123
- /**
124
- * Requests a user identity token for the current user.
125
- * @returns {Promise<any>} Returns a promise which will resolve with the token value.
126
- */
127
- AddinClient.prototype.getUserIdentityToken = function () {
128
- var _this = this;
129
- return new Promise(function (resolve, reject) {
130
- var authTokenRequestId = ++_this.lastAuthTokenRequestId;
131
- _this.authTokenRequests[authTokenRequestId] = {
132
- reject: reject,
133
- resolve: resolve
134
- };
135
- _this.postMessageToHostPage({
136
- message: {
137
- authTokenRequestId: authTokenRequestId
138
- },
139
- messageType: 'get-auth-token'
140
- });
141
- });
142
- };
143
- /**
144
- * Requests the host page to launch a modal add-in.
145
- * @param args Arguments for launching the modal.
146
- * @returns {Promise<any>} Returns a promise that will be resolved when the modal add-in is closed.
147
- * Promise will resolve with context data passed by from the modal add-in's closeModal call.
148
- */
149
- AddinClient.prototype.showModal = function (args) {
150
- var _this = this;
151
- return {
152
- modalClosed: new Promise(function (resolve, reject) {
153
- var modalRequestId = ++_this.lastModalRequestId;
154
- _this.modalRequests[modalRequestId] = {
155
- reject: reject,
156
- resolve: resolve
157
- };
158
- _this.postMessageToHostPage({
159
- message: {
160
- args: args,
161
- modalRequestId: modalRequestId
162
- },
163
- messageType: 'show-modal'
164
- });
165
- })
166
- };
167
- };
168
- /**
169
- * Informs the host to close this modal add-in.
170
- * Should only be used from within the modal add-in and not the parent add-in.
171
- * @param args Arguments to provide a context object back to the parent add-in.
172
- */
173
- AddinClient.prototype.closeModal = function (args) {
174
- this.postMessageToHostPage({
175
- message: args,
176
- messageType: 'close-modal'
177
- });
178
- };
179
- /**
180
- * Informs the host to open the help tab with the specified help key.
181
- * @param args Arguments for launching the help tab.
182
- */
183
- AddinClient.prototype.openHelp = function (args) {
184
- this.postMessageToHostPage({
185
- message: {
186
- helpKey: args.helpKey
187
- },
188
- messageType: 'open-help'
189
- });
190
- };
191
- /**
192
- * Informs the host to show a toast message.
193
- * @param args Arguments for showing a toast.
194
- */
195
- AddinClient.prototype.showToast = function (args) {
196
- this.postMessageToHostPage({
197
- message: args,
198
- messageType: 'show-toast'
199
- });
200
- };
201
- /**
202
- * Requests the host page to launch a flyout add-in.
203
- * @param args Arguments for launching the flyout.
204
- * @returns {Promise<any>} Returns a promise that will be resolved when the flyout add-in is closed.
205
- */
206
- AddinClient.prototype.showFlyout = function (args) {
207
- var _this = this;
208
- return {
209
- flyoutClosed: new Promise(function (resolve, reject) {
210
- // host page will apply default values when not provided
211
- args.defaultWidth = args.defaultWidth;
212
- args.maxWidth = args.maxWidth;
213
- args.minWidth = args.minWidth;
214
- _this.flyoutRequest = {
215
- reject: reject,
216
- resolve: resolve
217
- };
218
- _this.postMessageToHostPage({
219
- message: args,
220
- messageType: 'show-flyout'
221
- });
222
- })
223
- };
224
- };
225
- /**
226
- * Requests the host page to close the flyout add-in.
227
- */
228
- AddinClient.prototype.closeFlyout = function () {
229
- this.postMessageToHostPage({
230
- messageType: 'close-flyout'
231
- });
232
- };
233
- /**
234
- * Requests the host page to show a confirm dialog.
235
- * @param args Arguments for showing a confirm dialog.
236
- * @returns {Promise<string>} Returns a promise that will resolve with the
237
- * confirm action when the dialog is closed.
238
- */
239
- AddinClient.prototype.showConfirm = function (args) {
240
- var _this = this;
241
- return new Promise(function (resolve, reject) {
242
- _this.confirmRequest = {
243
- reject: reject,
244
- resolve: resolve
245
- };
246
- _this.postMessageToHostPage({
247
- message: args,
248
- messageType: 'show-confirm'
249
- });
250
- });
251
- };
252
- /**
253
- * Informs the host to show an error dialog.
254
- * @param args Arguments for showing an error dialog.
255
- */
256
- AddinClient.prototype.showError = function (args) {
257
- this.postMessageToHostPage({
258
- message: args,
259
- messageType: 'show-error'
260
- });
261
- };
262
- /**
263
- * Requests the host page to show the page blocking wait indicator.
264
- */
265
- AddinClient.prototype.showWait = function () {
266
- this.postMessageToHostPage({
267
- messageType: 'show-wait'
268
- });
269
- };
270
- /**
271
- * Requests the host page to hide the page blocking wait indicator.
272
- */
273
- AddinClient.prototype.hideWait = function () {
274
- this.postMessageToHostPage({
275
- messageType: 'hide-wait'
276
- });
277
- };
278
- /**
279
- * Registers a callback to be executed when the specified event type occurs.
280
- * @param eventType The event type to process.
281
- * @param callback The callback to execute when the event occurs.
282
- */
283
- AddinClient.prototype.addEventHandler = function (eventType, callback) {
284
- this.registeredAddinEvents[eventType] = callback;
285
- };
286
- /**
287
- * Sends an event to be handled by the host page.
288
- * @returns {Promise<void>} Returns a Promise which will resolve when the add-in host page receives the message, or
289
- * rejects if a subsequent event occurs, for the same event type, within 200 milliseconds.
290
- * The Promise also rejects if an event type is not one of the supported types from the host page.
291
- * @see AddinClientInitArgs#supportedEventTypes
292
- */
293
- AddinClient.prototype.sendEvent = function (args) {
294
- var _this = this;
295
- return new Promise(function (resolve, reject) {
296
- var eventType = args.type;
297
- if (!_this.supportedEventTypes.includes(eventType)) {
298
- reject('Event type not supported');
299
- }
300
- var pendingEvent = _this.pendingSentEvents[eventType];
301
- if (pendingEvent) {
302
- // cancel and reject pending event
303
- clearTimeout(pendingEvent.timeoutId);
304
- pendingEvent.reject('Event cancelled');
305
- }
306
- var timeoutId = setTimeout(function () {
307
- delete _this.pendingSentEvents[eventType];
308
- _this.postMessageToHostPage({
309
- message: {
310
- event: args,
311
- eventRequestId: _this.eventRequestId
312
- },
313
- messageType: 'client-event'
314
- });
315
- _this.sentEvents[_this.eventRequestId] = resolve;
316
- _this.eventRequestId++;
317
- }, 200);
318
- _this.pendingSentEvents[eventType] = {
319
- reject: reject,
320
- timeoutId: timeoutId
321
- };
322
- });
323
- };
324
- /**
325
- * Post a message to the host page informing it that the add-in is
326
- * now started and listening for messages from the host.
327
- */
328
- AddinClient.prototype.raiseAddinReadyMessage = function () {
329
- // No sensitive data should be provided with this message! This is the initial
330
- // message posted to the host page to establish whether the host origin is a
331
- // trusted origin and therefore will post to any host, trusted or untrusted.
332
- // The host should respond with a host-ready message which will include the origin
333
- // and will be validated against a whitelist of allowed origins so that subsequent
334
- // messages can be posted only to that trusted origin.
335
- this.postMessageToHostPage({
336
- messageType: 'ready'
337
- }, '*');
338
- };
339
- /**
340
- * Handles the modal-closed message from the host.
341
- * This is emitted to add-ins which have previously launched a modal, which is now
342
- * closing.
343
- * @param message The message data, which includes a context object from the closing modal, which should be passed
344
- * to the calling modal in the showModal promise.
345
- */
346
- AddinClient.prototype.handleModalClosedMessage = function (message) {
347
- var modalRequests = this.modalRequests;
348
- var modalRequestId = message.modalRequestId;
349
- var modalRequest = modalRequests[modalRequestId];
350
- modalRequest.resolve(message.context);
351
- modalRequests[modalRequestId] = undefined;
352
- };
353
- /**
354
- * Handles host message responses to a get-auth-token request.
355
- * @param data The message.
356
- */
357
- AddinClient.prototype.handleAuthTokenMessage = function (data) {
358
- var authTokenRequests = this.authTokenRequests;
359
- var authTokenRequestId = data.message.authTokenRequestId;
360
- var authTokenRequest = authTokenRequests[authTokenRequestId];
361
- /* tslint:disable-next-line switch-default */
362
- switch (data.messageType) {
363
- case 'auth-token':
364
- var authToken = data.message.authToken;
365
- authTokenRequest.resolve(authToken);
366
- break;
367
- case 'auth-token-fail':
368
- authTokenRequest.reject(data.message.reason);
369
- break;
370
- }
371
- authTokenRequests[authTokenRequestId] = undefined;
372
- };
373
- /**
374
- * Handles message events received from the add-in host page.
375
- * @param event The event posted from the host.
376
- */
377
- AddinClient.prototype.handleMessage = function (event) {
378
- var _this = this;
379
- var data = event.data;
380
- if (data && data.source === 'bb-addin-host') {
381
- if (data.messageType === 'host-ready') {
382
- // The 'host-ready' message is the only message that's not validated against
383
- // the host origin since that is what's being established in the message.
384
- // This MUST be the first message posted by the host page or all further
385
- // communications with the host page will be blocked.
386
- this.setKnownAllowedHostOrigin(event.origin);
387
- this.trackHeightChangesOfAddinContent();
388
- // set the supported event types
389
- this.supportedEventTypes = data.message.supportedEventTypes;
390
- // Pass key data to the add-in for it to initiailze.
391
- this.args.callbacks.init({
392
- context: data.message.context,
393
- envId: data.message.envId,
394
- ready: function (args) {
395
- // Do an immediate height check since the add-in may render something
396
- // due to the context provided. No need to wait a full second to reflect.
397
- _this.checkForHeightChangesOfAddinContent();
398
- _this.postMessageToHostPage({
399
- message: args,
400
- messageType: 'addin-ready'
401
- });
402
- },
403
- supportedEventTypes: data.message.supportedEventTypes,
404
- themeSettings: data.message.themeSettings
405
- });
406
- }
407
- else if (this.isFromValidOrigin(event)) {
408
- /* tslint:disable-next-line switch-default */
409
- switch (data.messageType) {
410
- case 'auth-token':
411
- case 'auth-token-fail':
412
- this.handleAuthTokenMessage(data);
413
- break;
414
- case 'modal-closed':
415
- this.handleModalClosedMessage(data.message);
416
- break;
417
- case 'button-click':
418
- if (this.args.callbacks.buttonClick) {
419
- this.args.callbacks.buttonClick();
420
- }
421
- break;
422
- case 'update-context':
423
- if (this.args.callbacks.updateContext) {
424
- this.args.callbacks.updateContext(data.message);
425
- }
426
- break;
427
- case 'confirm-closed':
428
- if (this.confirmRequest) {
429
- this.confirmRequest.resolve(data.message.reason);
430
- this.confirmRequest = undefined;
431
- }
432
- break;
433
- case 'flyout-closed':
434
- if (this.flyoutRequest) {
435
- this.flyoutRequest.resolve();
436
- this.flyoutRequest = undefined;
437
- }
438
- break;
439
- case 'flyout-next-click':
440
- if (this.args.callbacks.flyoutNextClick) {
441
- this.args.callbacks.flyoutNextClick();
442
- }
443
- break;
444
- case 'flyout-previous-click':
445
- if (this.args.callbacks.flyoutPreviousClick) {
446
- this.args.callbacks.flyoutPreviousClick();
447
- }
448
- break;
449
- // TODO remove support for this message type when help support is removed in next major release
450
- case 'help-click':
451
- if (this.args.callbacks.helpClick) {
452
- this.args.callbacks.helpClick();
453
- }
454
- break;
455
- case 'settings-click':
456
- if (this.args.callbacks.settingsClick) {
457
- this.args.callbacks.settingsClick();
458
- }
459
- break;
460
- case 'theme-change':
461
- if (this.args.callbacks.themeChange) {
462
- this.args.callbacks.themeChange(data.message.themeSettings);
463
- }
464
- break;
465
- case 'host-event':
466
- this.processHostEvent(data.message);
467
- break;
468
- case 'event-received':
469
- this.resolveClientEvent(data.message);
470
- break;
471
- }
472
- }
473
- else {
474
- this.warnInvalidOrigin();
475
- }
476
- }
477
- };
478
- /**
479
- * Validates and registers a value as the origin of the parent page hosting the add-in.
480
- * If the provided origin matches against our trusted whitelist, then it will be saved.
481
- * Post messages will implicitly go to this origin and received messages will be filtered
482
- * to just messages from this origin.
483
- * @param hostOrigin
484
- */
485
- AddinClient.prototype.setKnownAllowedHostOrigin = function (hostOrigin) {
486
- for (var _i = 0, allowedOrigins_1 = allowedOrigins; _i < allowedOrigins_1.length; _i++) {
487
- var allowedOrigin = allowedOrigins_1[_i];
488
- if (allowedOrigin.test(hostOrigin)) {
489
- this.trustedOrigin = hostOrigin;
490
- return;
491
- }
492
- }
493
- };
494
- /**
495
- * Checks if the height of the iFrame has changed since it was last
496
- * posted to the host page (or if it hasn't been posted yet) and initiates
497
- * a new post if so.
498
- */
499
- AddinClient.prototype.checkForHeightChangesOfAddinContent = function () {
500
- // after some discussion and experimentation, using offsetHeight appears to be sufficient
501
- var newHeight = document.documentElement.offsetHeight;
502
- if (newHeight !== this.lastPostedIframeHeight) {
503
- this.lastPostedIframeHeight = newHeight;
504
- this.postMessageToHostPage({
505
- message: {
506
- height: newHeight + 'px'
507
- },
508
- messageType: 'height-change'
509
- });
510
- }
511
- };
512
- /**
513
- * Starts a timeout interval to watch for height changes
514
- * of the iframe content.
515
- */
516
- AddinClient.prototype.trackHeightChangesOfAddinContent = function () {
517
- var _this = this;
518
- this.heightChangeIntervalId = setInterval(function () {
519
- _this.checkForHeightChangesOfAddinContent();
520
- }, 1000);
521
- };
522
- /**
523
- * Posts a message to the parent window.
524
- * @param message The message content to post.
525
- * @param targetOrigin Optional. If provided, then the message will be posted to this origin.
526
- * If not, then it will post to the pre-determined host page origin.
527
- */
528
- AddinClient.prototype.postMessageToHostPage = function (message, targetOrigin) {
529
- message.source = 'bb-addin-client';
530
- message.addinId = this.getQueryVariable('addinId');
531
- targetOrigin = targetOrigin || this.trustedOrigin;
532
- if (targetOrigin) {
533
- window.parent.postMessage(message, targetOrigin);
534
- }
535
- else {
536
- this.warnInvalidOrigin();
537
- }
538
- };
539
- /**
540
- * Processes an add-in event that occurs from the host and responds
541
- * back to the host with an 'event-received' message.
542
- * @param message The message to process by looking up executing the registered callback
543
- * that matches the event type.
544
- */
545
- AddinClient.prototype.processHostEvent = function (message) {
546
- var _this = this;
547
- var eventArgs = message.context;
548
- var callback = this.registeredAddinEvents[eventArgs.type];
549
- var promise;
550
- if (callback) {
551
- if (this.isBlockingEventType(eventArgs.type)) {
552
- promise = new Promise(function (resolve) {
553
- callback(eventArgs.context, function () {
554
- resolve();
555
- });
556
- });
557
- }
558
- else {
559
- promise = new Promise(function (resolve) {
560
- callback(eventArgs.context);
561
- resolve();
562
- });
563
- }
564
- }
565
- else {
566
- promise = Promise.resolve();
567
- }
568
- promise.then(function () { return _this.postEventReceivedMessage(message.eventRequestId); });
569
- };
570
- /**
571
- * Checks whether an event type is blocking and requires a response from the client
572
- * before responding to the host.
573
- * @param type The event type.
574
- */
575
- AddinClient.prototype.isBlockingEventType = function (type) {
576
- switch (type) {
577
- case 'form-save':
578
- case 'form-cancel':
579
- return true;
580
- default: break;
581
- }
582
- return false;
583
- };
584
- /**
585
- * Posts a message to the host page to indicate that a certain event has been received.
586
- * @param eventRequestId The ID of the event request that was received.
587
- */
588
- AddinClient.prototype.postEventReceivedMessage = function (eventRequestId) {
589
- this.postMessageToHostPage({
590
- message: {
591
- eventRequestId: eventRequestId
592
- },
593
- messageType: 'event-received'
594
- });
595
- };
596
- /**
597
- * Attemps to resolve the Promise for a client event that has been received by the host page.
598
- * @param message Message data that includes the ID of the event that was received.
599
- */
600
- AddinClient.prototype.resolveClientEvent = function (message) {
601
- var requestId = message.eventRequestId;
602
- var promiseResolve = this.sentEvents[requestId];
603
- if (promiseResolve) {
604
- promiseResolve();
605
- delete this.sentEvents[requestId];
606
- }
607
- };
608
- /**
609
- * Checks whether a MessageEvent is from the execetd host origin.
610
- * @param event
611
- */
612
- AddinClient.prototype.isFromValidOrigin = function (event) {
613
- return event.origin === this.trustedOrigin;
614
- };
615
- /**
616
- * Log that a message was received with an invalid origin.
617
- */
618
- AddinClient.prototype.warnInvalidOrigin = function () {
619
- console.warn('The origin is not trusted because the host-ready message has not been ' +
620
- 'sent or because the host origin is not a whitelisted origin.');
621
- };
622
- /**
623
- * Reads a query string value from the current window location.
624
- * @param variable Name of the query string parameter to ready.
625
- * @returns The value of the query string parameter.
626
- */
627
- AddinClient.prototype.getQueryVariable = function (variable) {
628
- var query = AddinClient.getQueryString().substring(1);
629
- var vars = query.split('&');
630
- for (var _i = 0, vars_1 = vars; _i < vars_1.length; _i++) {
631
- var v = vars_1[_i];
632
- var pair = v.split('=');
633
- if (decodeURIComponent(pair[0]) === variable) {
634
- return decodeURIComponent(pair[1]);
635
- }
636
- }
637
- };
638
- return AddinClient;
639
- }());
640
- exports.AddinClient = AddinClient;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AddinClient = void 0;
4
+ /**
5
+ * Collection of regexs for our whitelist of host origins.
6
+ */
7
+ var allowedOrigins = [
8
+ /^https\:\/\/[\w\-\.]+\.blackbaud\.com$/,
9
+ /^https\:\/\/[\w\-\.]+\.blackbaud\-dev\.com$/,
10
+ /^http\:\/\/[\w\-\.]+\.blackbaud\-dev\.com$/,
11
+ /^https\:\/\/[\w\-\.]+\.blackbaudhosting\.com$/,
12
+ /^https\:\/\/[\w\-\.]+\.bbcloudservices\.com$/,
13
+ /^https\:\/\/localhost(\:[0-9]+)?$/,
14
+ /^https\:\/\/secure[2|3|8]\.convio\.net$/,
15
+ /^https\:\/\/testweb\.convio\.com$/,
16
+ /^https\:\/\/[\w\-\.]+\.conviocloud\.com$/,
17
+ /^https\:\/\/[\w\-\.]+\.blackbaudcloud\.com$/,
18
+ /^https\:\/\/[\w\-\.]+\.blackbaudfaith\.com$/,
19
+ /^https\:\/\/[\w\-\.]+\.blackbaudportal\.com$/,
20
+ /^https\:\/\/[\w\-\.]+\.bbk12\.com$/,
21
+ /^https\:\/\/[\w\-\.]+\.mycampus\-app\.com$/,
22
+ /^https\:\/\/[\w\-\.]+\.myschoolapp\.com$/,
23
+ /^https\:\/\/[\w\-\.]+\.myschoolautomation\.com$/,
24
+ /^https\:\/\/[\w\-\.]+\.myschooldemo\.com$/,
25
+ /^https\:\/\/[\w\-\.]+\.myschooltraining\.com$/,
26
+ /^https\:\/\/[\w\-\.]+\.blackbaudwp\.com$/,
27
+ /^https\:\/\/[\w\-\.]+\.carrytheload\.org$/,
28
+ /^https\:\/\/[\w\-\.]+\.ummsfoundation\.org$/,
29
+ /^http\:\/\/[\w\-\.]+\.lcrf\.org$/,
30
+ /^https\:\/\/[\w\-\.]+\.go2\.org$/,
31
+ /^https\:\/\/[\w\-\.]+\.nationwidechildrens\.org$/,
32
+ /^https\:\/\/[\w\-\.]+\.lupus\.org$/,
33
+ /^https\:\/\/[\w\-\.]+\.operationsmile\.ca$/,
34
+ /^https\:\/\/[\w\-\.]+\.convio\.net$/,
35
+ /^https\:\/\/[\w\-\.]+\.ontariospca\.ca$/,
36
+ /^https\:\/\/[\w\-\.]+\.brighamandwomens\.org$/,
37
+ /^https\:\/\/[\w\-\.]+\.northernlighthealth\.org$/,
38
+ /^http\:\/\/[\w\-\.]+\.convio\.net$/,
39
+ /^https\:\/\/[\w\-\.]+\.alpha1\.org$/,
40
+ /^https\:\/\/[\w\-\.]+\.pscpartners\.org$/,
41
+ /^https\:\/\/[\w\-\.]+\.mercyforanimals\.org$/,
42
+ /^https\:\/\/[\w\-\.]+\.braintumor\.org$/,
43
+ /^https\:\/\/[\w\-\.]+\.cancer\.ca$/,
44
+ /^https\:\/\/[\w\-\.]+\.phoenixchildrensfoundation\.org$/,
45
+ /^https\:\/\/[\w\-\.]+\.ocmc\.org$/,
46
+ /^https\:\/\/[\w\-\.]+\.stlouischildrens\.org$/,
47
+ /^https\:\/\/[\w\-\.]+\.choa\.org$/,
48
+ /^https\:\/\/[\w\-\.]+\.acsevents\.org$/,
49
+ /^https\:\/\/[\w\-\.]+\.operationsmile\.org$/,
50
+ /^https\:\/\/[\w\-\.]+\.mdmercy\.com$/,
51
+ /^https\:\/\/[\w\-\.]+\.cookchildrens\.org$/,
52
+ /^https\:\/\/[\w\-\.]+\.chla\.org$/,
53
+ /^https\:\/\/[\w\-\.]+\.nleomf\.org$/,
54
+ /^https\:\/\/[\w\-\.]+\.pwatoronto\.org$/,
55
+ /^https\:\/\/[\w\-\.]+\.jfsla\.org$/,
56
+ /^https\:\/\/[\w\-\.]+\.roswellpark\.org$/,
57
+ /^https\:\/\/[\w\-\.]+\.alsagoldenwest\.org$/,
58
+ /^https\:\/\/[\w\-\.]+\.cancercarefoundation\.ca$/,
59
+ /^https\:\/\/[\w\-\.]+\.alsnc\.org$/,
60
+ /^https\:\/\/[\w\-\.]+\.alsanm\.org$/,
61
+ /^https\:\/\/[\w\-\.]+\.waysidewaifs\.org$/,
62
+ /^https\:\/\/[\w\-\.]+\.bladdercancercanada\.org$/,
63
+ /^https\:\/\/[\w\-\.]+\.jimmyfund\.org$/,
64
+ /^https\:\/\/[\w\-\.]+\.info\-komen\.org$/,
65
+ /^https\:\/\/[\w\-\.]+\.mountsinai\.org$/,
66
+ /^https\:\/\/[\w\-\.]+\.walkforpd\.ca$/,
67
+ /^https\:\/\/[\w\-\.]+\.alsoregon\.org$/,
68
+ /^https\:\/\/[\w\-\.]+\.feedhopenow\.org$/,
69
+ /^https\:\/\/[\w\-\.]+\.trilliumgiving\.ca$/,
70
+ /^https\:\/\/[\w\-\.]+\.swimacrossamerica\.org$/,
71
+ /^https\:\/\/ovariancanada\.org$/,
72
+ /^https\:\/\/[\w\-\.]+\.ovariancanada\.org$/,
73
+ /^https\:\/\/[\w\-\.]+\.alsunitedchicago\.org$/,
74
+ /^https\:\/\/[\w\-\.]+\.fredhutch\.org$/,
75
+ /^https\:\/\/[\w\-\.]+\.hss\.edu$/,
76
+ /^https\:\/\/[\w\-\.]+\.nyghfoundation\.ca$/,
77
+ /^https\:\/\/[\w\-\.]+\.natureconservancy\.ca$/,
78
+ /^https\:\/\/[\w\-\.]+\.llscanada\.org$/,
79
+ /^https\:\/\/[\w\-\.]+\.als\-ny\.org$/,
80
+ /^https\:\/\/[\w\-\.]+\.zerocancer\.org$/,
81
+ /^https\:\/\/[\w\-\.]+\.alsmidatlantic\.org$/,
82
+ /^https\:\/\/[\w\-\.]+\.habitat\.ca$/,
83
+ /^https\:\/\/[\w\-\.]+\.stamfordhospitalfoundation\.org$/,
84
+ /^https\:\/\/[\w\-\.]+\.alsohio\.org$/,
85
+ /^https\:\/\/[\w\-\.]+\.cancercarefdn\.mb\.ca$/,
86
+ /^https\:\/\/[\w\-\.]+\.baycrestfoundation\.org$/,
87
+ /^https\:\/\/[\w\-\.]+\.southlake\.ca$/,
88
+ /^https\:\/\/[\w\-\.]+\.parkinson\.ca$/,
89
+ ];
90
+ /**
91
+ * Client for interacting with the parent page hosting the add-in.
92
+ */
93
+ var AddinClient = /** @class */ (function () {
94
+ function AddinClient(args) {
95
+ var _this = this;
96
+ this.args = args;
97
+ /**
98
+ * Tracks pending request to reeceive an auth-token from the host.
99
+ */
100
+ this.authTokenRequests = [];
101
+ /**
102
+ * Counter to provide unique ids for each auth token request.
103
+ */
104
+ this.lastAuthTokenRequestId = 0;
105
+ /**
106
+ * Tracks modal add-ins that have been launched from this add-in.
107
+ */
108
+ this.modalRequests = [];
109
+ /**
110
+ * Counter to provide unique ids for each modal request.
111
+ */
112
+ this.lastModalRequestId = 0;
113
+ /**
114
+ * Stores the registered add-in events.
115
+ * Key - the event type.
116
+ * Value - The callback function to be executed when the event type occurs.
117
+ */
118
+ this.registeredAddinEvents = {};
119
+ /**
120
+ * Stores the add-in events that have been sent to the host page.
121
+ * Key - the event request ID.
122
+ * Value - The Promise resolve function to be executed when the event is received by the host.
123
+ */
124
+ this.sentEvents = {};
125
+ /**
126
+ * Stores the pending add-in events that are queued to be sent to the host page after 200
127
+ * milliseconds have expired.
128
+ * Key - the event type.
129
+ * Value - The Promise reject function to be executed if the event fails to be sent to the host page.
130
+ */
131
+ this.pendingSentEvents = {};
132
+ /**
133
+ * The event request ID counter.
134
+ * The ID is incremented and assigned to each event that is sent.
135
+ */
136
+ this.eventRequestId = 0;
137
+ /**
138
+ * An array of event types that are supported by the host page.
139
+ * The add-in client will throw an error if an event is attempted but not one the supported types.
140
+ */
141
+ this.supportedEventTypes = [];
142
+ this.windowMessageHandler = function (event) {
143
+ _this.handleMessage(event);
144
+ };
145
+ // Listen to messages from the host page.
146
+ window.addEventListener('message', this.windowMessageHandler);
147
+ // Inform the host page that the add-in is loaded and listening for messages.
148
+ this.raiseAddinReadyMessage();
149
+ }
150
+ /* istanbul ignore next */
151
+ /**
152
+ * @returns {string} Returns the current query string path for the window, prefixed with ?.
153
+ */
154
+ AddinClient.getQueryString = function () {
155
+ return window.location.search;
156
+ };
157
+ /**
158
+ * Cleans up the AddinClient, releasing all resources.
159
+ */
160
+ AddinClient.prototype.destroy = function () {
161
+ window.removeEventListener('message', this.windowMessageHandler);
162
+ if (this.heightChangeIntervalId) {
163
+ clearInterval(this.heightChangeIntervalId);
164
+ }
165
+ };
166
+ /**
167
+ * Requests the host page to navigate.
168
+ * @param args Arguments describing the navigation request.
169
+ */
170
+ AddinClient.prototype.navigate = function (args) {
171
+ this.postMessageToHostPage({
172
+ message: {
173
+ url: args.url
174
+ },
175
+ messageType: 'navigate'
176
+ });
177
+ };
178
+ /**
179
+ * Requests an authentication token for the current user.
180
+ * @deprecated Use getUserIdentityToken() instead.
181
+ * @returns {Promise<any>} Returns a promise which will resolve with the token value.
182
+ */
183
+ AddinClient.prototype.getAuthToken = function () {
184
+ return this.getUserIdentityToken();
185
+ };
186
+ /**
187
+ * Requests a user identity token for the current user.
188
+ * @returns {Promise<any>} Returns a promise which will resolve with the token value.
189
+ */
190
+ AddinClient.prototype.getUserIdentityToken = function () {
191
+ var _this = this;
192
+ return new Promise(function (resolve, reject) {
193
+ var authTokenRequestId = ++_this.lastAuthTokenRequestId;
194
+ _this.authTokenRequests[authTokenRequestId] = {
195
+ reject: reject,
196
+ resolve: resolve
197
+ };
198
+ _this.postMessageToHostPage({
199
+ message: {
200
+ authTokenRequestId: authTokenRequestId
201
+ },
202
+ messageType: 'get-auth-token'
203
+ });
204
+ });
205
+ };
206
+ /**
207
+ * Requests the host page to launch a modal add-in.
208
+ * @param args Arguments for launching the modal.
209
+ * @returns {Promise<any>} Returns a promise that will be resolved when the modal add-in is closed.
210
+ * Promise will resolve with context data passed by from the modal add-in's closeModal call.
211
+ */
212
+ AddinClient.prototype.showModal = function (args) {
213
+ var _this = this;
214
+ return {
215
+ modalClosed: new Promise(function (resolve, reject) {
216
+ var modalRequestId = ++_this.lastModalRequestId;
217
+ _this.modalRequests[modalRequestId] = {
218
+ reject: reject,
219
+ resolve: resolve
220
+ };
221
+ _this.postMessageToHostPage({
222
+ message: {
223
+ args: args,
224
+ modalRequestId: modalRequestId
225
+ },
226
+ messageType: 'show-modal'
227
+ });
228
+ })
229
+ };
230
+ };
231
+ /**
232
+ * Informs the host to close this modal add-in.
233
+ * Should only be used from within the modal add-in and not the parent add-in.
234
+ * @param args Arguments to provide a context object back to the parent add-in.
235
+ */
236
+ AddinClient.prototype.closeModal = function (args) {
237
+ this.postMessageToHostPage({
238
+ message: args,
239
+ messageType: 'close-modal'
240
+ });
241
+ };
242
+ /**
243
+ * Informs the host to open the help tab with the specified help key.
244
+ * @param args Arguments for launching the help tab.
245
+ */
246
+ AddinClient.prototype.openHelp = function (args) {
247
+ this.postMessageToHostPage({
248
+ message: {
249
+ helpKey: args.helpKey
250
+ },
251
+ messageType: 'open-help'
252
+ });
253
+ };
254
+ /**
255
+ * Informs the host to show a toast message.
256
+ * @param args Arguments for showing a toast.
257
+ */
258
+ AddinClient.prototype.showToast = function (args) {
259
+ this.postMessageToHostPage({
260
+ message: args,
261
+ messageType: 'show-toast'
262
+ });
263
+ };
264
+ /**
265
+ * Requests the host page to launch a flyout add-in.
266
+ * @param args Arguments for launching the flyout.
267
+ * @returns {Promise<any>} Returns a promise that will be resolved when the flyout add-in is closed.
268
+ */
269
+ AddinClient.prototype.showFlyout = function (args) {
270
+ var _this = this;
271
+ return {
272
+ flyoutClosed: new Promise(function (resolve, reject) {
273
+ // host page will apply default values when not provided
274
+ args.defaultWidth = args.defaultWidth;
275
+ args.maxWidth = args.maxWidth;
276
+ args.minWidth = args.minWidth;
277
+ _this.flyoutRequest = {
278
+ reject: reject,
279
+ resolve: resolve
280
+ };
281
+ _this.postMessageToHostPage({
282
+ message: args,
283
+ messageType: 'show-flyout'
284
+ });
285
+ })
286
+ };
287
+ };
288
+ /**
289
+ * Requests the host page to close the flyout add-in.
290
+ */
291
+ AddinClient.prototype.closeFlyout = function () {
292
+ this.postMessageToHostPage({
293
+ messageType: 'close-flyout'
294
+ });
295
+ };
296
+ /**
297
+ * Requests the host page to show a confirm dialog.
298
+ * @param args Arguments for showing a confirm dialog.
299
+ * @returns {Promise<string>} Returns a promise that will resolve with the
300
+ * confirm action when the dialog is closed.
301
+ */
302
+ AddinClient.prototype.showConfirm = function (args) {
303
+ var _this = this;
304
+ return new Promise(function (resolve, reject) {
305
+ _this.confirmRequest = {
306
+ reject: reject,
307
+ resolve: resolve
308
+ };
309
+ _this.postMessageToHostPage({
310
+ message: args,
311
+ messageType: 'show-confirm'
312
+ });
313
+ });
314
+ };
315
+ /**
316
+ * Informs the host to show an error dialog.
317
+ * @param args Arguments for showing an error dialog.
318
+ */
319
+ AddinClient.prototype.showError = function (args) {
320
+ this.postMessageToHostPage({
321
+ message: args,
322
+ messageType: 'show-error'
323
+ });
324
+ };
325
+ /**
326
+ * Requests the host page to show the page blocking wait indicator.
327
+ */
328
+ AddinClient.prototype.showWait = function () {
329
+ this.postMessageToHostPage({
330
+ messageType: 'show-wait'
331
+ });
332
+ };
333
+ /**
334
+ * Requests the host page to hide the page blocking wait indicator.
335
+ */
336
+ AddinClient.prototype.hideWait = function () {
337
+ this.postMessageToHostPage({
338
+ messageType: 'hide-wait'
339
+ });
340
+ };
341
+ /**
342
+ * Registers a callback to be executed when the specified event type occurs.
343
+ * @param eventType The event type to process.
344
+ * @param callback The callback to execute when the event occurs.
345
+ */
346
+ AddinClient.prototype.addEventHandler = function (eventType, callback) {
347
+ this.registeredAddinEvents[eventType] = callback;
348
+ };
349
+ /**
350
+ * Sends an event to be handled by the host page.
351
+ * @returns {Promise<void>} Returns a Promise which will resolve when the add-in host page receives the message, or
352
+ * rejects if a subsequent event occurs, for the same event type, within 200 milliseconds.
353
+ * The Promise also rejects if an event type is not one of the supported types from the host page.
354
+ * @see AddinClientInitArgs#supportedEventTypes
355
+ */
356
+ AddinClient.prototype.sendEvent = function (args) {
357
+ var _this = this;
358
+ return new Promise(function (resolve, reject) {
359
+ var eventType = args.type;
360
+ if (!_this.supportedEventTypes.includes(eventType)) {
361
+ reject('Event type not supported');
362
+ }
363
+ var pendingEvent = _this.pendingSentEvents[eventType];
364
+ if (pendingEvent) {
365
+ // cancel and reject pending event
366
+ clearTimeout(pendingEvent.timeoutId);
367
+ pendingEvent.reject('Event cancelled');
368
+ }
369
+ var timeoutId = setTimeout(function () {
370
+ delete _this.pendingSentEvents[eventType];
371
+ _this.postMessageToHostPage({
372
+ message: {
373
+ event: args,
374
+ eventRequestId: _this.eventRequestId
375
+ },
376
+ messageType: 'client-event'
377
+ });
378
+ _this.sentEvents[_this.eventRequestId] = resolve;
379
+ _this.eventRequestId++;
380
+ }, 200);
381
+ _this.pendingSentEvents[eventType] = {
382
+ reject: reject,
383
+ timeoutId: timeoutId
384
+ };
385
+ });
386
+ };
387
+ /**
388
+ * Post a message to the host page informing it that the add-in is
389
+ * now started and listening for messages from the host.
390
+ */
391
+ AddinClient.prototype.raiseAddinReadyMessage = function () {
392
+ // No sensitive data should be provided with this message! This is the initial
393
+ // message posted to the host page to establish whether the host origin is a
394
+ // trusted origin and therefore will post to any host, trusted or untrusted.
395
+ // The host should respond with a host-ready message which will include the origin
396
+ // and will be validated against a whitelist of allowed origins so that subsequent
397
+ // messages can be posted only to that trusted origin.
398
+ this.postMessageToHostPage({
399
+ messageType: 'ready'
400
+ }, '*');
401
+ };
402
+ /**
403
+ * Handles the modal-closed message from the host.
404
+ * This is emitted to add-ins which have previously launched a modal, which is now
405
+ * closing.
406
+ * @param message The message data, which includes a context object from the closing modal, which should be passed
407
+ * to the calling modal in the showModal promise.
408
+ */
409
+ AddinClient.prototype.handleModalClosedMessage = function (message) {
410
+ var modalRequests = this.modalRequests;
411
+ var modalRequestId = message.modalRequestId;
412
+ var modalRequest = modalRequests[modalRequestId];
413
+ modalRequest.resolve(message.context);
414
+ modalRequests[modalRequestId] = undefined;
415
+ };
416
+ /**
417
+ * Handles host message responses to a get-auth-token request.
418
+ * @param data The message.
419
+ */
420
+ AddinClient.prototype.handleAuthTokenMessage = function (data) {
421
+ var authTokenRequests = this.authTokenRequests;
422
+ var authTokenRequestId = data.message.authTokenRequestId;
423
+ var authTokenRequest = authTokenRequests[authTokenRequestId];
424
+ /* tslint:disable-next-line switch-default */
425
+ switch (data.messageType) {
426
+ case 'auth-token':
427
+ var authToken = data.message.authToken;
428
+ authTokenRequest.resolve(authToken);
429
+ break;
430
+ case 'auth-token-fail':
431
+ authTokenRequest.reject(data.message.reason);
432
+ break;
433
+ }
434
+ authTokenRequests[authTokenRequestId] = undefined;
435
+ };
436
+ /**
437
+ * Handles message events received from the add-in host page.
438
+ * @param event The event posted from the host.
439
+ */
440
+ AddinClient.prototype.handleMessage = function (event) {
441
+ var _this = this;
442
+ var data = event.data;
443
+ if (data && data.source === 'bb-addin-host') {
444
+ if (data.messageType === 'host-ready') {
445
+ // The 'host-ready' message is the only message that's not validated against
446
+ // the host origin since that is what's being established in the message.
447
+ // This MUST be the first message posted by the host page or all further
448
+ // communications with the host page will be blocked.
449
+ this.setKnownAllowedHostOrigin(event.origin);
450
+ this.trackHeightChangesOfAddinContent();
451
+ // set the supported event types
452
+ this.supportedEventTypes = data.message.supportedEventTypes;
453
+ // Pass key data to the add-in for it to initiailze.
454
+ this.args.callbacks.init({
455
+ context: data.message.context,
456
+ envId: data.message.envId,
457
+ ready: function (args) {
458
+ // Do an immediate height check since the add-in may render something
459
+ // due to the context provided. No need to wait a full second to reflect.
460
+ _this.checkForHeightChangesOfAddinContent();
461
+ _this.postMessageToHostPage({
462
+ message: args,
463
+ messageType: 'addin-ready'
464
+ });
465
+ },
466
+ supportedEventTypes: data.message.supportedEventTypes,
467
+ themeSettings: data.message.themeSettings
468
+ });
469
+ }
470
+ else if (this.isFromValidOrigin(event)) {
471
+ /* tslint:disable-next-line switch-default */
472
+ switch (data.messageType) {
473
+ case 'auth-token':
474
+ case 'auth-token-fail':
475
+ this.handleAuthTokenMessage(data);
476
+ break;
477
+ case 'modal-closed':
478
+ this.handleModalClosedMessage(data.message);
479
+ break;
480
+ case 'button-click':
481
+ if (this.args.callbacks.buttonClick) {
482
+ this.args.callbacks.buttonClick();
483
+ }
484
+ break;
485
+ case 'update-context':
486
+ if (this.args.callbacks.updateContext) {
487
+ this.args.callbacks.updateContext(data.message);
488
+ }
489
+ break;
490
+ case 'confirm-closed':
491
+ if (this.confirmRequest) {
492
+ this.confirmRequest.resolve(data.message.reason);
493
+ this.confirmRequest = undefined;
494
+ }
495
+ break;
496
+ case 'flyout-closed':
497
+ if (this.flyoutRequest) {
498
+ this.flyoutRequest.resolve();
499
+ this.flyoutRequest = undefined;
500
+ }
501
+ break;
502
+ case 'flyout-next-click':
503
+ if (this.args.callbacks.flyoutNextClick) {
504
+ this.args.callbacks.flyoutNextClick();
505
+ }
506
+ break;
507
+ case 'flyout-previous-click':
508
+ if (this.args.callbacks.flyoutPreviousClick) {
509
+ this.args.callbacks.flyoutPreviousClick();
510
+ }
511
+ break;
512
+ // TODO remove support for this message type when help support is removed in next major release
513
+ case 'help-click':
514
+ if (this.args.callbacks.helpClick) {
515
+ this.args.callbacks.helpClick();
516
+ }
517
+ break;
518
+ case 'settings-click':
519
+ if (this.args.callbacks.settingsClick) {
520
+ this.args.callbacks.settingsClick();
521
+ }
522
+ break;
523
+ case 'theme-change':
524
+ if (this.args.callbacks.themeChange) {
525
+ this.args.callbacks.themeChange(data.message.themeSettings);
526
+ }
527
+ break;
528
+ case 'host-event':
529
+ this.processHostEvent(data.message);
530
+ break;
531
+ case 'event-received':
532
+ this.resolveClientEvent(data.message);
533
+ break;
534
+ }
535
+ }
536
+ else {
537
+ this.warnInvalidOrigin();
538
+ }
539
+ }
540
+ };
541
+ /**
542
+ * Validates and registers a value as the origin of the parent page hosting the add-in.
543
+ * If the provided origin matches against our trusted whitelist, then it will be saved.
544
+ * Post messages will implicitly go to this origin and received messages will be filtered
545
+ * to just messages from this origin.
546
+ * @param hostOrigin
547
+ */
548
+ AddinClient.prototype.setKnownAllowedHostOrigin = function (hostOrigin) {
549
+ for (var _i = 0, allowedOrigins_1 = allowedOrigins; _i < allowedOrigins_1.length; _i++) {
550
+ var allowedOrigin = allowedOrigins_1[_i];
551
+ if (allowedOrigin.test(hostOrigin)) {
552
+ this.trustedOrigin = hostOrigin;
553
+ return;
554
+ }
555
+ }
556
+ };
557
+ /**
558
+ * Checks if the height of the iFrame has changed since it was last
559
+ * posted to the host page (or if it hasn't been posted yet) and initiates
560
+ * a new post if so.
561
+ */
562
+ AddinClient.prototype.checkForHeightChangesOfAddinContent = function () {
563
+ // after some discussion and experimentation, using offsetHeight appears to be sufficient
564
+ var newHeight = document.documentElement.offsetHeight;
565
+ if (newHeight !== this.lastPostedIframeHeight) {
566
+ this.lastPostedIframeHeight = newHeight;
567
+ this.postMessageToHostPage({
568
+ message: {
569
+ height: newHeight + 'px'
570
+ },
571
+ messageType: 'height-change'
572
+ });
573
+ }
574
+ };
575
+ /**
576
+ * Starts a timeout interval to watch for height changes
577
+ * of the iframe content.
578
+ */
579
+ AddinClient.prototype.trackHeightChangesOfAddinContent = function () {
580
+ var _this = this;
581
+ this.heightChangeIntervalId = setInterval(function () {
582
+ _this.checkForHeightChangesOfAddinContent();
583
+ }, 1000);
584
+ };
585
+ /**
586
+ * Posts a message to the parent window.
587
+ * @param message The message content to post.
588
+ * @param targetOrigin Optional. If provided, then the message will be posted to this origin.
589
+ * If not, then it will post to the pre-determined host page origin.
590
+ */
591
+ AddinClient.prototype.postMessageToHostPage = function (message, targetOrigin) {
592
+ message.source = 'bb-addin-client';
593
+ message.addinId = this.getQueryVariable('addinId');
594
+ targetOrigin = targetOrigin || this.trustedOrigin;
595
+ if (targetOrigin) {
596
+ window.parent.postMessage(message, targetOrigin);
597
+ }
598
+ else {
599
+ this.warnInvalidOrigin();
600
+ }
601
+ };
602
+ /**
603
+ * Processes an add-in event that occurs from the host and responds
604
+ * back to the host with an 'event-received' message.
605
+ * @param message The message to process by looking up executing the registered callback
606
+ * that matches the event type.
607
+ */
608
+ AddinClient.prototype.processHostEvent = function (message) {
609
+ var _this = this;
610
+ var eventArgs = message.context;
611
+ var callback = this.registeredAddinEvents[eventArgs.type];
612
+ var promise;
613
+ if (callback) {
614
+ if (this.isBlockingEventType(eventArgs.type)) {
615
+ promise = new Promise(function (resolve) {
616
+ callback(eventArgs.context, function () {
617
+ resolve();
618
+ });
619
+ });
620
+ }
621
+ else {
622
+ promise = new Promise(function (resolve) {
623
+ callback(eventArgs.context);
624
+ resolve();
625
+ });
626
+ }
627
+ }
628
+ else {
629
+ promise = Promise.resolve();
630
+ }
631
+ promise.then(function () { return _this.postEventReceivedMessage(message.eventRequestId); });
632
+ };
633
+ /**
634
+ * Checks whether an event type is blocking and requires a response from the client
635
+ * before responding to the host.
636
+ * @param type The event type.
637
+ */
638
+ AddinClient.prototype.isBlockingEventType = function (type) {
639
+ switch (type) {
640
+ case 'form-save':
641
+ case 'form-cancel':
642
+ return true;
643
+ default: break;
644
+ }
645
+ return false;
646
+ };
647
+ /**
648
+ * Posts a message to the host page to indicate that a certain event has been received.
649
+ * @param eventRequestId The ID of the event request that was received.
650
+ */
651
+ AddinClient.prototype.postEventReceivedMessage = function (eventRequestId) {
652
+ this.postMessageToHostPage({
653
+ message: {
654
+ eventRequestId: eventRequestId
655
+ },
656
+ messageType: 'event-received'
657
+ });
658
+ };
659
+ /**
660
+ * Attemps to resolve the Promise for a client event that has been received by the host page.
661
+ * @param message Message data that includes the ID of the event that was received.
662
+ */
663
+ AddinClient.prototype.resolveClientEvent = function (message) {
664
+ var requestId = message.eventRequestId;
665
+ var promiseResolve = this.sentEvents[requestId];
666
+ if (promiseResolve) {
667
+ promiseResolve();
668
+ delete this.sentEvents[requestId];
669
+ }
670
+ };
671
+ /**
672
+ * Checks whether a MessageEvent is from the execetd host origin.
673
+ * @param event
674
+ */
675
+ AddinClient.prototype.isFromValidOrigin = function (event) {
676
+ return event.origin === this.trustedOrigin;
677
+ };
678
+ /**
679
+ * Log that a message was received with an invalid origin.
680
+ */
681
+ AddinClient.prototype.warnInvalidOrigin = function () {
682
+ console.warn('The origin is not trusted because the host-ready message has not been ' +
683
+ 'sent or because the host origin is not a whitelisted origin.');
684
+ };
685
+ /**
686
+ * Reads a query string value from the current window location.
687
+ * @param variable Name of the query string parameter to ready.
688
+ * @returns The value of the query string parameter.
689
+ */
690
+ AddinClient.prototype.getQueryVariable = function (variable) {
691
+ var query = AddinClient.getQueryString().substring(1);
692
+ var vars = query.split('&');
693
+ for (var _i = 0, vars_1 = vars; _i < vars_1.length; _i++) {
694
+ var v = vars_1[_i];
695
+ var pair = v.split('=');
696
+ if (decodeURIComponent(pair[0]) === variable) {
697
+ return decodeURIComponent(pair[1]);
698
+ }
699
+ }
700
+ };
701
+ return AddinClient;
702
+ }());
703
+ exports.AddinClient = AddinClient;
641
704
  //# sourceMappingURL=addin-client.js.map