@atlassian/atlassian-connect-js 5.3.190

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 (190) hide show
  1. package/.depcheckrc.json +16 -0
  2. package/.editorconfig +9 -0
  3. package/.envrc +5 -0
  4. package/.eslintignore +12 -0
  5. package/.eslintrc +31 -0
  6. package/.husky/pre-commit +11 -0
  7. package/.lintstagedrc.js +6 -0
  8. package/.netrc +1 -0
  9. package/.npmrc-public +4 -0
  10. package/.nvmrc +1 -0
  11. package/LICENSE +3 -0
  12. package/README.md +281 -0
  13. package/bitbucket-pipelines.yml +33 -0
  14. package/build/bin/bin-helper.js +29 -0
  15. package/build/bin/npm-postinstall.js +9 -0
  16. package/build/configs/append-sourcemapping.js +13 -0
  17. package/build/configs/availabletasks.js +15 -0
  18. package/build/configs/clean.js +12 -0
  19. package/build/configs/concat.js +44 -0
  20. package/build/configs/copy.js +32 -0
  21. package/build/configs/index.js +19 -0
  22. package/build/configs/jshint.js +9 -0
  23. package/build/configs/karma.js +11 -0
  24. package/build/configs/replace.js +10 -0
  25. package/build/configs/requirejs.js +187 -0
  26. package/build/configs/saucelabs-launchers.js +30 -0
  27. package/build/configs/shell.js +24 -0
  28. package/build/configs/uglify.js +15 -0
  29. package/build/configs/watch.js +45 -0
  30. package/build/end.frag +13 -0
  31. package/build/start.frag +18 -0
  32. package/bundlesize.config.json +14 -0
  33. package/dist/connect-host.css +225 -0
  34. package/dist/connect-host.js +13908 -0
  35. package/dist/connect-host.min.css +1 -0
  36. package/dist/iframe-fedramp.js +13663 -0
  37. package/dist/iframe.js +13663 -0
  38. package/dist/legacy-text-colors.css +245 -0
  39. package/dist/surfaces.css +11 -0
  40. package/dist/themes/atlaskit-tokens_dark-future.css +6 -0
  41. package/dist/themes/atlaskit-tokens_dark.css +394 -0
  42. package/dist/themes/atlaskit-tokens_legacy-dark.css +394 -0
  43. package/dist/themes/atlaskit-tokens_legacy-light.css +394 -0
  44. package/dist/themes/atlaskit-tokens_light-future.css +6 -0
  45. package/dist/themes/atlaskit-tokens_light.css +394 -0
  46. package/dist/themes/atlaskit-tokens_shape.css +14 -0
  47. package/dist/themes/atlaskit-tokens_spacing.css +26 -0
  48. package/dist/themes/atlaskit-tokens_typography-adg3.css +25 -0
  49. package/dist/themes/atlaskit-tokens_typography-modernized.css +25 -0
  50. package/dist/themes/atlaskit-tokens_typography-refreshed.css +25 -0
  51. package/gulpfile.js +204 -0
  52. package/memleak-check/app.html +10 -0
  53. package/memleak-check/index.html +31 -0
  54. package/memleak-check/index.js +33 -0
  55. package/package.json +102 -0
  56. package/renovate.json +11 -0
  57. package/security-assistant.yml +2 -0
  58. package/spec/.eslintrc +10 -0
  59. package/spec/config/karma.base.conf.js +200 -0
  60. package/spec/config/karma.conf.js +20 -0
  61. package/spec/fixtures/base_dialog_component_tests.js +180 -0
  62. package/spec/mocks/mock_feature_flag.js +23 -0
  63. package/spec/tests/amd_spec.js +122 -0
  64. package/spec/tests/analytics_dispatcher_spec.js +429 -0
  65. package/spec/tests/analytics_performance_spec.js +41 -0
  66. package/spec/tests/button_spec.js +143 -0
  67. package/spec/tests/dialog_extension_spec.js +59 -0
  68. package/spec/tests/dialog_module_provider_spec.js +499 -0
  69. package/spec/tests/dialog_module_spec.js +395 -0
  70. package/spec/tests/dialog_spec.js +296 -0
  71. package/spec/tests/dialog_webitem_spec.js +183 -0
  72. package/spec/tests/dropdown_module_spec.js +77 -0
  73. package/spec/tests/env_module_spec.js +153 -0
  74. package/spec/tests/events_spec.js +77 -0
  75. package/spec/tests/extension_configuration_options_store_spec.js +25 -0
  76. package/spec/tests/flag_module_provider_spec.js +79 -0
  77. package/spec/tests/flag_module_spec.js +118 -0
  78. package/spec/tests/flag_spec.js +243 -0
  79. package/spec/tests/host-api_spec.js +220 -0
  80. package/spec/tests/iframe-create_spec.js +43 -0
  81. package/spec/tests/iframe_container_spec.js +19 -0
  82. package/spec/tests/iframe_spec.js +265 -0
  83. package/spec/tests/inline_dialog_spec.js +41 -0
  84. package/spec/tests/inline_dialog_webitem_spec.js +331 -0
  85. package/spec/tests/loading_indicator_spec.js +48 -0
  86. package/spec/tests/messages_module_spec.js +108 -0
  87. package/spec/tests/meta_spec.js +71 -0
  88. package/spec/tests/module_args_spec.js +52 -0
  89. package/spec/tests/observe_spec.js +73 -0
  90. package/spec/tests/public_events.spec.js +102 -0
  91. package/spec/tests/scroll_position_spec.js +109 -0
  92. package/spec/tests/theming_spec.js +594 -0
  93. package/spec/tests/util_spec.js +55 -0
  94. package/spec/tests/utils/base64_spec.js +20 -0
  95. package/spec/tests/utils/button_spec.js +11 -0
  96. package/spec/tests/utils/cookie_spec.js +19 -0
  97. package/spec/tests/utils/deprecate_spec.js +22 -0
  98. package/spec/tests/utils/dialog_spec.js +297 -0
  99. package/spec/tests/utils/host_util_spec.js +45 -0
  100. package/spec/tests/utils/iframe_spec.js +41 -0
  101. package/spec/tests/utils/jwt_spec.js +135 -0
  102. package/spec/tests/utils/url_spec.js +37 -0
  103. package/spec/tests/utils/waitUntilReadyNextTick.js +5 -0
  104. package/spec/tests/utils/webitem.js +219 -0
  105. package/spec/tests/webitem_spec.js +131 -0
  106. package/src/css/host/dialog.css +144 -0
  107. package/src/css/host/flags.css +5 -0
  108. package/src/css/host/host.css +64 -0
  109. package/src/css/host/messages.css +12 -0
  110. package/src/css/plugin/legacy-text-colors.less +55 -0
  111. package/src/css/plugin/surfaces.css +11 -0
  112. package/src/host/ACJSFrameworkAdaptor.js +44 -0
  113. package/src/host/actions/analytics_action.js +35 -0
  114. package/src/host/actions/button_actions.js +21 -0
  115. package/src/host/actions/dialog_actions.js +27 -0
  116. package/src/host/actions/dialog_extension_actions.js +25 -0
  117. package/src/host/actions/dom_event_actions.js +32 -0
  118. package/src/host/actions/dropdown_actions.js +12 -0
  119. package/src/host/actions/env_actions.js +57 -0
  120. package/src/host/actions/event_actions.js +33 -0
  121. package/src/host/actions/flag_actions.js +22 -0
  122. package/src/host/actions/iframe_actions.js +27 -0
  123. package/src/host/actions/inline_dialog_actions.js +26 -0
  124. package/src/host/actions/inline_dialog_webitem_actions.js +10 -0
  125. package/src/host/actions/jwt_actions.js +51 -0
  126. package/src/host/actions/loading_indicator_actions.js +10 -0
  127. package/src/host/actions/module_actions.js +14 -0
  128. package/src/host/actions/webitem_actions.js +29 -0
  129. package/src/host/components/button.js +112 -0
  130. package/src/host/components/dialog.js +447 -0
  131. package/src/host/components/dialog_extension.js +106 -0
  132. package/src/host/components/dialog_webitem.js +69 -0
  133. package/src/host/components/flag.js +102 -0
  134. package/src/host/components/iframe.js +130 -0
  135. package/src/host/components/iframe_container.js +38 -0
  136. package/src/host/components/inline_dialog.js +108 -0
  137. package/src/host/components/inline_dialog_webitem.js +157 -0
  138. package/src/host/components/loading_indicator.js +110 -0
  139. package/src/host/components/webitem.js +227 -0
  140. package/src/host/deprecate.js +20 -0
  141. package/src/host/dispatchers/analytics_dispatcher.js +512 -0
  142. package/src/host/dispatchers/event_dispatcher.js +46 -0
  143. package/src/host/dollar.js +8 -0
  144. package/src/host/host-api.js +325 -0
  145. package/src/host/iframe-create.js +7 -0
  146. package/src/host/index.js +108 -0
  147. package/src/host/module-providers.js +13 -0
  148. package/src/host/modules/_featureFlag.js +42 -0
  149. package/src/host/modules/_performance.js +54 -0
  150. package/src/host/modules/analytics.js +17 -0
  151. package/src/host/modules/dialog.js +496 -0
  152. package/src/host/modules/dropdown.js +255 -0
  153. package/src/host/modules/env.js +156 -0
  154. package/src/host/modules/events.js +28 -0
  155. package/src/host/modules/flag.js +170 -0
  156. package/src/host/modules/host.js +19 -0
  157. package/src/host/modules/inline-dialog.js +33 -0
  158. package/src/host/modules/messages.js +309 -0
  159. package/src/host/modules/page.js +29 -0
  160. package/src/host/modules/scroll-position.js +102 -0
  161. package/src/host/modules/theming.js +114 -0
  162. package/src/host/stores/extension_configuration_options_store.js +24 -0
  163. package/src/host/util.js +98 -0
  164. package/src/host/utils/access-narrowing-context.js +18 -0
  165. package/src/host/utils/base64.js +22 -0
  166. package/src/host/utils/button.js +10 -0
  167. package/src/host/utils/cookie.js +14 -0
  168. package/src/host/utils/dialog.js +239 -0
  169. package/src/host/utils/feature-flag.js +27 -0
  170. package/src/host/utils/iframe.js +23 -0
  171. package/src/host/utils/jwt.js +60 -0
  172. package/src/host/utils/observe.js +34 -0
  173. package/src/host/utils/removal-observer.js +30 -0
  174. package/src/host/utils/simplexdm.js +58 -0
  175. package/src/host/utils/url.js +23 -0
  176. package/src/host/utils/webitem.js +214 -0
  177. package/src/plugin/amd.js +115 -0
  178. package/src/plugin/analytics.js +84 -0
  179. package/src/plugin/deprecate.js +16 -0
  180. package/src/plugin/dialog.js +197 -0
  181. package/src/plugin/dollar.js +77 -0
  182. package/src/plugin/events-instance.js +2 -0
  183. package/src/plugin/events.js +246 -0
  184. package/src/plugin/extension_configuration_options_store.js +27 -0
  185. package/src/plugin/featureFlag.js +8 -0
  186. package/src/plugin/index.js +118 -0
  187. package/src/plugin/meta.js +14 -0
  188. package/src/plugin/public-events.js +73 -0
  189. package/src/plugin/theming.js +211 -0
  190. package/src/plugin/util.js +104 -0
@@ -0,0 +1,22 @@
1
+ import { toByteArray, fromByteArray } from 'base64-js';
2
+
3
+ export function encode(string) {
4
+ return fromByteArray(
5
+ new TextEncoder().encode(string)
6
+ );
7
+ }
8
+
9
+ export function decode(string) {
10
+ var padding = 4 - string.length % 4;
11
+ if (padding === 1) {
12
+ string += '=';
13
+ } else if (padding === 2) {
14
+ string += '==';
15
+ }
16
+ return new TextDecoder().decode(toByteArray(string));
17
+ }
18
+
19
+ export default {
20
+ encode,
21
+ decode
22
+ }
@@ -0,0 +1,10 @@
1
+ class ButtonUtils {
2
+ // button identifier for XDM. NOT an id attribute
3
+ randomIdentifier(){
4
+ return Math.random().toString(16).substring(7);
5
+ }
6
+ }
7
+
8
+ var buttonUtilsInstance = new ButtonUtils();
9
+
10
+ export default buttonUtilsInstance;
@@ -0,0 +1,14 @@
1
+ function prefixCookie (addonKey, name){
2
+ if (!addonKey || addonKey.length === 0) {
3
+ throw new Error('addon key must be defined on cookies');
4
+ }
5
+
6
+ if (!name || name.length === 0) {
7
+ throw new Error('Name must be defined');
8
+ }
9
+ return addonKey + '$$' + name;
10
+ }
11
+
12
+ export default {
13
+ prefixCookie
14
+ };
@@ -0,0 +1,239 @@
1
+ import util from '../util';
2
+ import buttonUtils from './button';
3
+ import $ from '../dollar';
4
+ import AnalyticsDispatcher from '../dispatchers/analytics_dispatcher';
5
+
6
+ class DialogUtils {
7
+ _maxDimension(val, maxPxVal){
8
+ var parsed = util.stringToDimension(val);
9
+ var parsedInt = parseInt(parsed, 10);
10
+ var parsedMaxPxVal = parseInt(maxPxVal, 10);
11
+
12
+ if ((parsed.indexOf('%') > -1 && parsedInt >= 100) // %
13
+ || (parsedInt > parsedMaxPxVal)) { // px
14
+ return '100%';
15
+ }
16
+ return parsed;
17
+ }
18
+
19
+ _closeOnEscape (options){
20
+ if (options.closeOnEscape === false) {
21
+ return false;
22
+ } else {
23
+ return true;
24
+ }
25
+ }
26
+
27
+ _size (options){
28
+ var size = options.size;
29
+ if (options.size === 'x-large') {
30
+ size = 'xlarge';
31
+ }
32
+ if (options.size !== 'maximum' && options.width === '100%' && options.height === '100%') {
33
+ size = 'fullscreen';
34
+ }
35
+ return size;
36
+ }
37
+
38
+ _header(text){
39
+ var headerText = '';
40
+ switch(typeof text) {
41
+ case 'string':
42
+ headerText = text;
43
+ break;
44
+
45
+ case 'object':
46
+ headerText = text.value;
47
+ break;
48
+ }
49
+
50
+ return headerText;
51
+ }
52
+
53
+ _hint(text){
54
+ if(typeof text === 'string'){
55
+ return text;
56
+ }
57
+ return '';
58
+ }
59
+
60
+ _chrome(options){
61
+ var returnval = false;
62
+ if (typeof options.chrome === 'boolean') {
63
+ returnval = options.chrome;
64
+ }
65
+ if(options.size === 'fullscreen') {
66
+ returnval = true;
67
+ }
68
+ if(options.size === 'maximum') {
69
+ returnval = false;
70
+ }
71
+ return returnval;
72
+ }
73
+
74
+ _width(options){
75
+ if(options.size) {
76
+ return undefined;
77
+ }
78
+ if(options.width) {
79
+ return this._maxDimension(options.width, $(window).width());
80
+ }
81
+ return '50%';
82
+ }
83
+
84
+ _height(options){
85
+ if(options.size) {
86
+ return undefined;
87
+ }
88
+ if(options.height) {
89
+ return this._maxDimension(options.height, $(window).height());
90
+ }
91
+ return '50%';
92
+ }
93
+
94
+ _actions(options){
95
+ var sanitizedActions = [];
96
+ options = options || {};
97
+ if (!options.actions) {
98
+
99
+ sanitizedActions = [
100
+ {
101
+ name: 'submit',
102
+ identifier: 'submit',
103
+ text: options.submitText || 'Submit',
104
+ type: 'primary',
105
+ disabled: true // disable submit button by default (until the dialog has loaded).
106
+ },
107
+ {
108
+ name: 'cancel',
109
+ identifier: 'cancel',
110
+ text: options.cancelText || 'Cancel',
111
+ type: 'link',
112
+ immutable: true
113
+ }
114
+ ];
115
+ }
116
+
117
+ if(options.buttons) {
118
+ sanitizedActions = sanitizedActions.concat(this._buttons(options));
119
+ }
120
+
121
+ return sanitizedActions;
122
+
123
+ }
124
+
125
+ _id(str){
126
+ if(typeof str !== 'string'){
127
+ str = Math.random().toString(36).substring(2, 8);
128
+ }
129
+ return str;
130
+ }
131
+ // user defined action buttons
132
+ _buttons(options) {
133
+ var buttons = [];
134
+ if(options.buttons && Array.isArray(options.buttons)) {
135
+ options.buttons.forEach((button) => {
136
+ var text;
137
+ var identifier;
138
+ var disabled = false;
139
+ if(button.text && typeof button.text === 'string') {
140
+ text = button.text;
141
+ }
142
+ if(button.identifier && typeof button.identifier === 'string') {
143
+ identifier = button.identifier;
144
+ } else {
145
+ identifier = buttonUtils.randomIdentifier();
146
+ }
147
+ if(button.disabled && button.disabled === true) {
148
+ disabled = true;
149
+ }
150
+
151
+ buttons.push({
152
+ text: text,
153
+ identifier: identifier,
154
+ type: 'secondary',
155
+ custom: true,
156
+ disabled: disabled
157
+ });
158
+ });
159
+ }
160
+ return buttons;
161
+ }
162
+
163
+ _onHide(options) {
164
+ var noop = function () {};
165
+ if (typeof options.onHide === 'function') {
166
+ return options.onHide;
167
+ } else {
168
+ return noop;
169
+ }
170
+ }
171
+
172
+ sanitizeOptions(options){
173
+ options = options || {};
174
+ var sanitized = {
175
+ chrome: this._chrome(options),
176
+ header: this._header(options.header),
177
+ hint: this._hint(options.hint),
178
+ width: this._width(options),
179
+ height: this._height(options),
180
+ $content: options.$content,
181
+ extension: options.extension,
182
+ actions: this._actions(options),
183
+ id: this._id(options.id),
184
+ size: options.size,
185
+ closeOnEscape: this._closeOnEscape(options),
186
+ onHide: this._onHide(options),
187
+ };
188
+ sanitized.size = this._size(sanitized);
189
+
190
+ return sanitized;
191
+ }
192
+ // such a bad idea! this entire concept needs rewriting in the p2 plugin.
193
+ moduleOptionsFromGlobal(addon_key, key) {
194
+ var defaultOptions = {
195
+ chrome: true,
196
+ hostFrameOffset: 1
197
+ };
198
+
199
+ if(window._AP
200
+ && window._AP.dialogModules
201
+ && window._AP.dialogModules[addon_key]
202
+ && window._AP.dialogModules[addon_key][key]) {
203
+ return util.extend({}, defaultOptions, window._AP.dialogModules[addon_key][key].options);
204
+ }
205
+ return false;
206
+ }
207
+
208
+ // determines information about dialogs that are about to open and are already open
209
+ trackMultipleDialogOpening(dialogExtension, options) {
210
+ // check for dialogs that are already open
211
+ let trackingDescription;
212
+ let size = this._size(options);
213
+ if($('.ap-aui-dialog2:visible').length) {
214
+ // am i in the confluence editor? first check for macro dialogs opened through macro browser, second is editing an existing macro
215
+ if($('#macro-browser-dialog').length || (AJS.Confluence && AJS.Confluence.Editor && AJS.Confluence.Editor.currentEditMode)) {
216
+ if (size === 'fullscreen') {
217
+ trackingDescription = 'connect-macro-multiple-fullscreen';
218
+ } else {
219
+ trackingDescription = 'connect-macro-multiple';
220
+ }
221
+ } else {
222
+ trackingDescription = 'connect-multiple';
223
+ }
224
+ AnalyticsDispatcher.trackGasV3MultipleDialogOpening(trackingDescription, dialogExtension);
225
+ }
226
+ }
227
+
228
+ // abstracts and handles a failure to find active dialog
229
+ assertActiveDialogOrThrow(dialogProvider, addon_key) {
230
+ if (!dialogProvider.isActiveDialog(addon_key)) {
231
+ throw new Error('Failed to find an active dialog for: ' + addon_key);
232
+ }
233
+ }
234
+
235
+ }
236
+
237
+ var dialogUtilsInstance = new DialogUtils();
238
+
239
+ export default dialogUtilsInstance;
@@ -0,0 +1,27 @@
1
+ import FeatureGates from '@atlaskit/feature-gate-js-client';
2
+ import AnalyticsDispatcher from '../dispatchers/analytics_dispatcher';
3
+
4
+ function getBooleanFeatureFlagStatsig(flagName) {
5
+ if (FeatureGates.initializeCompleted()) {
6
+ return FeatureGates.checkGate(flagName);
7
+ }
8
+ AnalyticsDispatcher.trackGasV3FeatureFlagDefaultFalse(flagName);
9
+ console.error(`[ACJS] Feature flag service is not initialised. Default flag '${flagName}' to false`);
10
+ return false;
11
+ }
12
+
13
+
14
+ /**
15
+ * For all new feature flags, please create them in Statsig
16
+ * https://hello.atlassian.net/wiki/spaces/ECO/pages/3707522428
17
+ *
18
+ * @param {string} flagName Feature flag name
19
+ * @returns {boolean}
20
+ */
21
+ export default function getBooleanFeatureFlag(flagName) {
22
+ return getBooleanFeatureFlagStatsig(flagName);
23
+ }
24
+
25
+ export const Flags = {
26
+ getBooleanFeatureFlag,
27
+ }
@@ -0,0 +1,23 @@
1
+ import util from '../util';
2
+
3
+ export default {
4
+ optionsToAttributes: function(options){
5
+ var sanitized = {};
6
+ if(options && typeof options ==='object'){
7
+ if(options.width){
8
+ sanitized.width = util.stringToDimension(options.width);
9
+ }
10
+ if(options.height){
11
+ sanitized.height = util.stringToDimension(options.height);
12
+ }
13
+ if (typeof options.sandbox === 'string'){
14
+ var domElem = document.createElement('iframe');
15
+ sanitized.sandbox = options.sandbox
16
+ .split(' ')
17
+ .filter(value => util.isSupported(domElem, 'sandbox', value, true))
18
+ .join(' ');
19
+ }
20
+ }
21
+ return sanitized;
22
+ }
23
+ };
@@ -0,0 +1,60 @@
1
+ import { decode } from './base64';
2
+ import EventDispatcher from '../dispatchers/event_dispatcher';
3
+ var JWT_SKEW = 60; // in seconds.
4
+
5
+ function parseJwtIssuer(jwt) {
6
+ return parseJwtClaims(jwt)['iss'];
7
+ }
8
+
9
+ function parseJwtClaims(jwt) {
10
+
11
+ if (null === jwt || '' === jwt) {
12
+ throw('Invalid JWT: must be neither null nor empty-string.');
13
+ }
14
+
15
+ var firstPeriodIndex = jwt.indexOf('.');
16
+ var secondPeriodIndex = jwt.indexOf('.', firstPeriodIndex + 1);
17
+
18
+ if (firstPeriodIndex < 0 || secondPeriodIndex <= firstPeriodIndex) {
19
+ throw('Invalid JWT: must contain 2 period (".") characters.');
20
+ }
21
+
22
+ var encodedClaims = jwt.substring(firstPeriodIndex + 1, secondPeriodIndex);
23
+
24
+ if (null === encodedClaims || '' === encodedClaims) {
25
+ throw('Invalid JWT: encoded claims must be neither null nor empty-string.');
26
+ }
27
+
28
+ var claimsString = decode.call(window, encodedClaims);
29
+ return JSON.parse(claimsString);
30
+ }
31
+
32
+ function isJwtExpired(jwtString, skew) {
33
+ if (skew === undefined) {
34
+ skew = JWT_SKEW;
35
+ }
36
+ var claims = parseJwtClaims(jwtString);
37
+ var expires = 0;
38
+ var now = Math.floor(Date.now() / 1000); // UTC timestamp now
39
+ if (claims && claims.exp) {
40
+ expires = claims.exp;
41
+ }
42
+
43
+ if ((expires - skew) < now){
44
+ return true;
45
+ }
46
+
47
+ return false;
48
+
49
+ }
50
+
51
+ EventDispatcher.register('jwt-skew-set', function(data){
52
+ JWT_SKEW = data.skew;
53
+ });
54
+
55
+
56
+ export default {
57
+ parseJwtIssuer,
58
+ parseJwtClaims,
59
+ isJwtExpired
60
+ }
@@ -0,0 +1,34 @@
1
+ const threshold = 0.25;
2
+ let targets = [];
3
+ let observe;
4
+
5
+ const observed = target => {
6
+ targets = targets.filter(({ element, callback }) => {
7
+ if (element === target) {
8
+ callback();
9
+ return false;
10
+ }
11
+ return true;
12
+ });
13
+ }
14
+
15
+ if ('IntersectionObserver' in window &&
16
+ 'IntersectionObserverEntry' in window) {
17
+ const observer = new IntersectionObserver(entries => {
18
+ entries.forEach(({ intersectionRatio, target }) => {
19
+ if (intersectionRatio > 0) {
20
+ observer.unobserve(target);
21
+ observed(target);
22
+ }
23
+ });
24
+ }, { threshold });
25
+ observe = observer.observe.bind(observer);
26
+ }
27
+
28
+ export default (element, callback) => {
29
+ if (typeof callback === 'function'
30
+ && element instanceof Element) {
31
+ targets.push({ element, callback });
32
+ observe(element);
33
+ }
34
+ };
@@ -0,0 +1,30 @@
1
+ import HostApi from '../host-api';
2
+
3
+ export function observeIframeRemoval() {
4
+ const scopedObserver = new MutationObserver((mutationsList) => {
5
+ mutationsList.forEach((mutation) => {
6
+ if (mutation.type === 'childList') {
7
+ mutation.removedNodes.forEach((node) => {
8
+ if (node.nodeType !== Node.ELEMENT_NODE) {
9
+ return;
10
+ }
11
+ const onDisconnect = (node) => {
12
+ HostApi.destroy(node.id);
13
+ };
14
+ // Check if the node itself is an iframe
15
+ if (node.tagName === 'IFRAME' && node.id) {
16
+ onDisconnect(node);
17
+ } else {
18
+ // Check if any iframes exist within the removed node's subtree
19
+ node.querySelectorAll('iframe[id]').forEach((childNode) => {
20
+ onDisconnect(childNode);
21
+ });
22
+ }
23
+ });
24
+ }
25
+ });
26
+ });
27
+
28
+ scopedObserver.observe(document.body, { childList: true, subtree: true });
29
+ return scopedObserver;
30
+ }
@@ -0,0 +1,58 @@
1
+ import iframeUtils from './iframe';
2
+ import simpleXDM from 'simple-xdm/host';
3
+ import IframeActions from '../actions/iframe_actions';
4
+ import util from '../util';
5
+ import $ from '../dollar';
6
+ import ExtensionConfigurationOptionStore from '../stores/extension_configuration_options_store';
7
+ import getBooleanFeatureFlag from './feature-flag';
8
+ import definePerformanceModule, {ADDON_KEY_CODEBARREL} from '../modules/_performance';
9
+ import defineFeatureFlagModule from '../modules/_featureFlag';
10
+
11
+ // nowhere better to put this. Wires an extension for oldschool and new enviroments
12
+ function createSimpleXdmExtension(extension){
13
+ const extensionConfig = extensionConfigSanitizer(extension);
14
+ const systemExtensionConfigOptions = ExtensionConfigurationOptionStore.get();
15
+ extension.options = extensionConfig.options = util.extend({}, extensionConfig.options);
16
+ extension.options.globalOptions = systemExtensionConfigOptions;
17
+ loadConditionalModules(extension.addon_key);
18
+ const iframeAttributes = simpleXDM.create(extensionConfig, () => {
19
+ if(!extension.options.noDOM){
20
+ extension.$el = $(document.getElementById(extension.id));
21
+ }
22
+ IframeActions.notifyBridgeEstablished(extension.$el, extension);
23
+ }, () => {
24
+ IframeActions.notifyUnloaded(extension.$el, extension);
25
+ });
26
+ // HostApi destroy is relying on previous behaviour of the
27
+ // iframe component wherein it would call simpleXDM.create(extension)
28
+ // and then mutate the extension object with the id returned from the
29
+ // iframeAttributes see changes made in ACJS-760 and ACJS-807
30
+ extensionConfig.id = iframeAttributes.id;
31
+ extension.id = iframeAttributes.id;
32
+ util.extend(iframeAttributes, iframeUtils.optionsToAttributes(extension.options));
33
+ return {
34
+ iframeAttributes,
35
+ extension
36
+ }
37
+ }
38
+
39
+ function extensionConfigSanitizer(extension) {
40
+ return {
41
+ addon_key: extension.addon_key,
42
+ key: extension.key,
43
+ url: extension.url,
44
+ options: extension.options,
45
+ };
46
+ }
47
+
48
+ function loadConditionalModules(addonKey) {
49
+ if (addonKey === ADDON_KEY_CODEBARREL) {
50
+ definePerformanceModule();
51
+ }
52
+ defineFeatureFlagModule();
53
+ }
54
+
55
+ export default {
56
+ createSimpleXdmExtension,
57
+ extensionConfigSanitizer
58
+ }
@@ -0,0 +1,23 @@
1
+ import qs from 'query-string';
2
+ import jwtUtil from './jwt';
3
+
4
+ function isJwtExpired(urlStr) {
5
+ var jwtStr = _getJwt(urlStr);
6
+ return jwtUtil.isJwtExpired(jwtStr);
7
+ }
8
+
9
+ function _getJwt(urlStr) {
10
+ var query = qs.parse(qs.extract(urlStr));
11
+ return query['jwt'];
12
+ }
13
+
14
+ function hasJwt(url) {
15
+ var jwt = _getJwt(url);
16
+ return (jwt && _getJwt(url).length !== 0);
17
+
18
+ }
19
+
20
+ export default {
21
+ hasJwt,
22
+ isJwtExpired
23
+ }