@sapui5/sap.ushell_abap 1.145.1 → 1.147.0

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 (62) hide show
  1. package/package.json +4 -4
  2. package/src/main/js/sap/ushell_abap/.library +8 -7
  3. package/src/main/js/sap/ushell_abap/adapters/abap/AdapterContainer.js +4 -5
  4. package/src/main/js/sap/ushell_abap/adapters/abap/AppStateAdapter.js +1 -1
  5. package/src/main/js/sap/ushell_abap/adapters/abap/ClientSideTargetResolutionAdapter.js +143 -69
  6. package/src/main/js/sap/ushell_abap/adapters/abap/CommonDataModelAdapter.js +1 -1
  7. package/src/main/js/sap/ushell_abap/adapters/abap/ConfigurationDefaultsAdapter.js +7 -4
  8. package/src/main/js/sap/ushell_abap/adapters/abap/ContainerAdapter.js +19 -10
  9. package/src/main/js/sap/ushell_abap/adapters/abap/FlpLaunchPageAdapter.js +148 -109
  10. package/src/main/js/sap/ushell_abap/adapters/abap/LaunchPageAdapter.js +1 -1
  11. package/src/main/js/sap/ushell_abap/adapters/abap/NavTargetResolutionAdapter.js +1 -1
  12. package/src/main/js/sap/ushell_abap/adapters/abap/NavTargetResolutionInternalAdapter.js +1 -1
  13. package/src/main/js/sap/ushell_abap/adapters/abap/PageBuildingAdapter.js +1 -1
  14. package/src/main/js/sap/ushell_abap/adapters/abap/PagePersistenceAdapter.js +9 -10
  15. package/src/main/js/sap/ushell_abap/adapters/abap/PersonalizationAdapter.js +1 -1
  16. package/src/main/js/sap/ushell_abap/adapters/abap/PersonalizationV2Adapter.js +1 -1
  17. package/src/main/js/sap/ushell_abap/adapters/abap/SearchAdapter.js +1 -1
  18. package/src/main/js/sap/ushell_abap/adapters/abap/SupportTicketAdapter.js +1 -1
  19. package/src/main/js/sap/ushell_abap/adapters/abap/Ui5ComponentLoaderAdapter.js +1 -1
  20. package/src/main/js/sap/ushell_abap/adapters/hana/ContainerAdapter.js +1 -1
  21. package/src/main/js/sap/ushell_abap/bootstrap/BootTask/PrepareDirectAppStart.js +20 -0
  22. package/src/main/js/sap/ushell_abap/bootstrap/BootTask/RequestGroups.js +51 -0
  23. package/src/main/js/sap/ushell_abap/bootstrap/BootTask/RequestTargetMappings.js +29 -0
  24. package/src/main/js/sap/ushell_abap/bootstrap/BootTask.js +47 -0
  25. package/src/main/js/sap/ushell_abap/bootstrap/ConfigurationProvider.js +87 -0
  26. package/src/main/js/sap/ushell_abap/bootstrap/DirectAppStart.js +231 -0
  27. package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpad/CreateRenderer.js +43 -0
  28. package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpad/InitXhrLogon.js +148 -0
  29. package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpad/RequestPages.js +86 -0
  30. package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpad.js +63 -0
  31. package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpadModule.js +11 -0
  32. package/src/main/js/sap/ushell_abap/bootstrap/PageSetsRequestHandler.js +247 -0
  33. package/src/main/js/sap/ushell_abap/bootstrap/PlatformConfig.js +385 -0
  34. package/src/main/js/sap/ushell_abap/bootstrap/{evo/SAPCompanionConditionSetter.js → SAPCompanionConditionSetter.js} +6 -4
  35. package/src/main/js/sap/ushell_abap/bootstrap/StartupRequestHandler.js +145 -0
  36. package/src/main/js/sap/ushell_abap/bootstrap/ThemeHandler.js +276 -0
  37. package/src/main/js/sap/ushell_abap/bootstrap/XhrFactory.js +69 -0
  38. package/src/main/js/sap/ushell_abap/bootstrap/{evo/XhrLogonEventHandler.js → XhrLogonEventHandler.js} +13 -7
  39. package/src/main/js/sap/ushell_abap/bootstrap/XhrLogonLibLoader.js +51 -0
  40. package/src/main/js/sap/ushell_abap/bootstrap/abap-def-dev.js +20 -0
  41. package/src/main/js/sap/ushell_abap/bootstrap/{evo/abap-def-loader.js → abap-def-loader.js} +2 -2
  42. package/src/main/js/sap/ushell_abap/bootstrap/abap-def.js +22 -0
  43. package/src/main/js/sap/ushell_abap/bootstrap/{evo/abap.constants.js → abapConstants.js} +8 -2
  44. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.js +1 -1
  45. package/src/main/js/sap/ushell_abap/components/TCodeNavigation/MessageCode.js +18 -1
  46. package/src/main/js/sap/ushell_abap/components/TCodeNavigation.js +27 -16
  47. package/src/main/js/sap/ushell_abap/library.js +1 -1
  48. package/src/main/js/sap/ushell_abap/pbServices/ui2/Contracts.js +33 -0
  49. package/ui5.yaml +7 -6
  50. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap-def-dev.js +0 -42
  51. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap-def.js +0 -45
  52. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.bootstrap.utils.js +0 -172
  53. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.configure.theme.js +0 -28
  54. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.configure.ushell.js +0 -176
  55. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.load.launchpad.js +0 -72
  56. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.pageset.js +0 -219
  57. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.startup.js +0 -154
  58. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.theme.handler.js +0 -75
  59. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.xhrlogon.LibLoader.js +0 -21
  60. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.xhrlogon.configure.js +0 -62
  61. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.xhrlogon.handler.js +0 -82
  62. package/src/main/js/sap/ushell_abap/bootstrap/evo/boottask.js +0 -948
@@ -0,0 +1,29 @@
1
+ // Copyright (c) 2009-2026 SAP SE, All Rights Reserved
2
+ sap.ui.define([
3
+ "sap/base/util/ObjectPath",
4
+ "sap/ushell_abap/bootstrap/StartupRequestHandler",
5
+ "sap/ushell/bootstrap/Config"
6
+ ], (
7
+ ObjectPath,
8
+ StartupRequestHandler,
9
+ BootstrapConfig
10
+ ) => {
11
+ "use strict";
12
+
13
+ class RequestTargetMappings {
14
+ async run () {
15
+ const oUshellConfig = BootstrapConfig.get();
16
+
17
+ const pResult = StartupRequestHandler.requestFullTM();
18
+
19
+ ObjectPath.set("services.ClientSideTargetResolution.adapter.config.navTargetDataPromise", pResult, oUshellConfig);
20
+ // Do not issue the separate compact request for the launchpage adapter, as it was done in the earlier FLP versions.
21
+ // Reuse the existing full target mappings request that is sent in any case.
22
+ ObjectPath.set("services.LaunchPage.adapter.config.compactTMPromise", pResult, oUshellConfig);
23
+ ObjectPath.set("services.FlpLaunchPage.adapter.config.compactTMPromise", pResult, oUshellConfig);
24
+ ObjectPath.set("services.VisualizationDataProvider.adapter.config.compactTMPromise", pResult, oUshellConfig);
25
+ }
26
+ }
27
+
28
+ return new RequestTargetMappings();
29
+ });
@@ -0,0 +1,47 @@
1
+ // Copyright (c) 2009-2026 SAP SE, All Rights Reserved
2
+ sap.ui.define([
3
+ "sap/base/Log",
4
+ "sap/ui/performance/trace/initTraces",
5
+ "sap/ushell_abap/bootstrap/BootTask/PrepareDirectAppStart",
6
+ "sap/ushell_abap/bootstrap/BootTask/RequestTargetMappings",
7
+ "sap/ushell_abap/bootstrap/BootTask/RequestGroups"
8
+ ], (
9
+ Log,
10
+ initTraces,
11
+ PrepareDirectAppStart,
12
+ RequestTargetMappings,
13
+ RequestGroups
14
+ ) => {
15
+ "use strict";
16
+
17
+ class BootTask {
18
+ async run (fnCallback, fnErrorCallback) {
19
+ try {
20
+ performance?.mark("FLP - boottask start");
21
+
22
+ // initialize UI5 performance tracing (FESR) before first request is sent, so that this is also instrumented
23
+ initTraces();
24
+
25
+ PrepareDirectAppStart.run().catch((oError) => {
26
+ Log.error("Error during the preparation of direct app start", oError, "sap.ushell_abap.bootstrap.BootTask");
27
+ });
28
+
29
+ RequestGroups.run().catch((oError) => {
30
+ Log.error("Error during request of groups", oError, "sap.ushell_abap.bootstrap.BootTask");
31
+ });
32
+
33
+ RequestTargetMappings.run().catch((oError) => {
34
+ Log.error("Error during request of target mappings", oError, "sap.ushell_abap.bootstrap.BootTask");
35
+ });
36
+
37
+ performance?.mark("FLP - boottask end");
38
+
39
+ fnCallback();
40
+ } catch (oError) {
41
+ fnErrorCallback(oError);
42
+ }
43
+ }
44
+ }
45
+
46
+ return new BootTask();
47
+ });
@@ -0,0 +1,87 @@
1
+ // Copyright (c) 2009-2026 SAP SE, All Rights Reserved
2
+
3
+ /**
4
+ * @fileoverview ABAP bootstrap configuration provider.
5
+ *
6
+ * Coordinates the initialization of BootstrapConfig, PlatformConfig, and
7
+ * the merged UI5 configuration for the ABAP platform. Returns a singleton.
8
+ */
9
+ sap.ui.define([
10
+ "sap/base/util/deepExtend",
11
+ "sap/ushell_abap/bootstrap/abapConstants",
12
+ "sap/ushell_abap/bootstrap/PlatformConfig",
13
+ "sap/ushell/bootstrap/Config"
14
+ ], (
15
+ deepExtend,
16
+ abapConstants,
17
+ PlatformConfig,
18
+ BootstrapConfig
19
+ ) => {
20
+ "use strict";
21
+
22
+ /**
23
+ * @alias sap.ushell_abap.bootstrap.ConfigurationProvider
24
+ * @namespace
25
+ * @description Configuration provider for the ABAP bootstrap.
26
+ *
27
+ * Initializes the ushell configuration with ABAP defaults, applies
28
+ * platform-specific settings, and merges the resulting UI5 configuration.
29
+ *
30
+ * @since 1.147.0
31
+ * @private
32
+ */
33
+ class ConfigurationProvider {
34
+ /** @type {object} The merged UI5 configuration */
35
+ #oUI5Config;
36
+
37
+ constructor () {
38
+ this.#init();
39
+ }
40
+
41
+ /**
42
+ * Runs the initialization sequence: initializes BootstrapConfig with ABAP
43
+ * defaults, configures the ushell via PlatformConfig, merges UI5 configs,
44
+ * and applies module paths.
45
+ *
46
+ * @since 1.147.0
47
+ * @private
48
+ */
49
+ #init () {
50
+ BootstrapConfig.initialize(abapConstants.defaultUshellConfig);
51
+
52
+ // Extend the default config with platform specific config inplace
53
+ PlatformConfig.configureUshell();
54
+
55
+ this.#oUI5Config = deepExtend({}, BootstrapConfig.getUI5Config(), PlatformConfig.getUI5Config());
56
+
57
+ BootstrapConfig.applyModulePaths();
58
+ }
59
+
60
+ /**
61
+ * Returns the value of a UI5 configuration property.
62
+ *
63
+ * @param {string} sCamelizedKey The camelCase key of the UI5 configuration property (e.g. "sapUiTheme", "sapUiLanguage")
64
+ * @returns {any} The value of the requested key, or <code>undefined</code>
65
+ *
66
+ * @since 1.147.0
67
+ * @private
68
+ */
69
+ get (sCamelizedKey) {
70
+ return this.#oUI5Config[sCamelizedKey];
71
+ }
72
+
73
+ /**
74
+ * Only for testing purposes!
75
+ * Resets the configuration and re-runs initialization.
76
+ *
77
+ * @since 1.147.0
78
+ * @private
79
+ */
80
+ reset () {
81
+ BootstrapConfig.reset();
82
+ this.#init();
83
+ }
84
+ }
85
+
86
+ return new ConfigurationProvider();
87
+ });
@@ -0,0 +1,231 @@
1
+ // Copyright (c) 2009-2026 SAP SE, All Rights Reserved
2
+ sap.ui.define([
3
+ "sap/base/Log",
4
+ "sap/base/util/ObjectPath",
5
+ "sap/ushell_abap/bootstrap/StartupRequestHandler",
6
+ "sap/ushell/bootstrap/Config",
7
+ "sap/ushell/base/promisify",
8
+ "sap/ushell/base/requireAsync",
9
+ "sap/ushell/base/UrlParsing"
10
+ ], (
11
+ Log,
12
+ ObjectPath,
13
+ StartupRequestHandler,
14
+ BootstrapConfig,
15
+ promisify,
16
+ requireAsync,
17
+ UrlParsing
18
+ ) => {
19
+ "use strict";
20
+
21
+ class DirectAppStart {
22
+ #aInternTargets = [
23
+ "#Shell-home",
24
+ "#Launchpad-openFLPPage",
25
+ "#Shell-appfinder",
26
+ "#Shell-catalog",
27
+ "#shell-catalog",
28
+ "#Action-search"
29
+ ];
30
+
31
+ #isRelevant () {
32
+ const sHash = this.#getFullHash();
33
+
34
+ return sHash !== "#" && !this.#aInternTargets.some((sTarget) => sHash.startsWith(sTarget));
35
+ }
36
+
37
+ async prepare () {
38
+ const oUshellConfig = BootstrapConfig.get();
39
+
40
+ if (!this.#isRelevant()) {
41
+ ObjectPath.set("services.ClientSideTargetResolution.adapter.config.initialSegmentPromise", Promise.resolve(null), oUshellConfig);
42
+ ObjectPath.set("services.AppState.config.initialAppStatesPromise", Promise.resolve({}), oUshellConfig);
43
+ return;
44
+ }
45
+
46
+ const oParsedHash = UrlParsing.parseShellHash(this.#getFullHash(), true);
47
+ const oInitialKeys = {
48
+ "sap-xapp-state": oParsedHash.params?.["sap-xapp-state"]?.[0],
49
+ "sap-intent-param": oParsedHash.params?.["sap-intent-param"]?.[0],
50
+ "sap-system": oParsedHash.params?.["sap-system"]?.[0],
51
+ "sap-iapp-state": oParsedHash.params?.["sap-iapp-state"]?.[0]
52
+ };
53
+
54
+ // consider iapp-state also from appSpecificRoute
55
+ if (!oInitialKeys["sap-iapp-state"] && oParsedHash.appSpecificRoute?.includes("sap-iapp-state")) {
56
+ const rRegex = /(\?|&|[/])(sap-iapp-state=[A-Z0-9]+)/;
57
+ const aMatch = oParsedHash.appSpecificRoute.match(rRegex);
58
+ if (aMatch?.[2]) {
59
+ oInitialKeys["sap-iapp-state"] = aMatch[2].split("=")[1];
60
+ }
61
+ }
62
+
63
+ // remove all undefined values, as they would cause issues in the query
64
+ Object.keys(oInitialKeys).forEach((sKey) => {
65
+ if (oInitialKeys[sKey] === undefined) {
66
+ delete oInitialKeys[sKey];
67
+ }
68
+ });
69
+
70
+ const oSegment = {
71
+ semanticObject: oParsedHash.semanticObject,
72
+ action: oParsedHash.action
73
+ };
74
+
75
+ const pTargetMappings = StartupRequestHandler.requestDirectStart(oSegment, oInitialKeys);
76
+
77
+ const pInitialSegmentPromise = pTargetMappings.then((oResult) => {
78
+ if (!oResult.targetMappings) {
79
+ return null;
80
+ }
81
+ return [
82
+ [oSegment],
83
+ oResult.targetMappings,
84
+ oResult.systemAliases,
85
+ oResult.urlTemplates
86
+ ];
87
+ });
88
+ ObjectPath.set("services.ClientSideTargetResolution.adapter.config.initialSegmentPromise", pInitialSegmentPromise, oUshellConfig);
89
+
90
+ const pInitialAppStatesPromise = pTargetMappings.then((oResult) => {
91
+ const oInitialAppStates = [
92
+ { key: "sap-intent-param", startUpKey: "iparState" },
93
+ { key: "sap-iapp-state", startUpKey: "iappState" },
94
+ { key: "sap-xapp-state", startUpKey: "xappState" }
95
+ ].reduce((oAppStates, { key, startUpKey }) => {
96
+ const sAppStateKey = oInitialKeys[key];
97
+
98
+ if (sAppStateKey && oResult[startUpKey]) {
99
+ oAppStates[sAppStateKey] = oResult[startUpKey];
100
+ }
101
+
102
+ return oAppStates;
103
+ }, {});
104
+
105
+ ObjectPath.set("services.AppState.config.initialAppStates", oInitialAppStates, oUshellConfig);
106
+ });
107
+ ObjectPath.set("services.AppState.config.initialAppStatesPromise", pInitialAppStatesPromise, oUshellConfig);
108
+
109
+ return Promise.all([
110
+ pTargetMappings,
111
+ pInitialSegmentPromise,
112
+ pInitialAppStatesPromise
113
+ ]);
114
+ }
115
+
116
+ async startApp () {
117
+ if (!this.#isRelevant()) {
118
+ return;
119
+ }
120
+
121
+ window["sap-ushell-async-libs-promise-directstart"] = this.#startApp();
122
+
123
+ await window["sap-ushell-async-libs-promise-directstart"];
124
+ }
125
+
126
+ async #startApp () {
127
+ let sHash = this.#getFullHash();
128
+ if (sHash.includes("sap-ssb-eval-id")) {
129
+ sHash = await this.#resolveEvalId(sHash);
130
+ }
131
+
132
+ const [Container] = await requireAsync(["sap/ushell/Container"]);
133
+ const NavTargetResolutionInternal = await Container.getServiceAsync("NavTargetResolutionInternal");
134
+ const oDeferred = NavTargetResolutionInternal.resolveHashFragment(UrlParsing.ensureLeadingHash(sHash));
135
+
136
+ const oResolvedHashFragment = await promisify(oDeferred);
137
+
138
+ const [AppConfiguration] = await requireAsync(["sap/ushell/services/AppConfiguration"]);
139
+
140
+ AppConfiguration.setCurrentApplication(oResolvedHashFragment);
141
+
142
+ if (oResolvedHashFragment?.ui5ComponentName) {
143
+ // create UI5 component early
144
+ const Ui5ComponentLoader = await Container.getServiceAsync("Ui5ComponentLoader");
145
+
146
+ const oResolvedHashFragmentWithComponentHandle = await Ui5ComponentLoader.createComponent(
147
+ oResolvedHashFragment,
148
+ [this.#createWaitForRendererCreatedPromise(Container)],
149
+ "Application"
150
+ );
151
+
152
+ return {
153
+ resolvedHashFragment: oResolvedHashFragmentWithComponentHandle,
154
+ dependenciesLoaded: true
155
+ };
156
+ }
157
+
158
+ // non-ui5 app
159
+ return {
160
+ resolvedHashFragment: oResolvedHashFragment,
161
+ dependenciesLoaded: false
162
+ };
163
+ }
164
+
165
+ /**
166
+ * For a Smart Business direct start the parameter sap-ssb-eval-id has to be
167
+ * resolved by Smart Business early so that the resolved parameters are already
168
+ * passed to the app component during the early component creation.
169
+ * @param {string} sHash the current hash
170
+ */
171
+ async #resolveEvalId (sHash) {
172
+ const [SmartBusiness] = await requireAsync(["sap/ushell/utils/SmartBusiness"]);
173
+
174
+ // At this early point in time the Smart Business library has not been loaded yet.
175
+ // Load it to avoid single file requests.
176
+ // On ABAP, the path where the library is loaded from differs from the
177
+ // common namespace so it has to be mapped.
178
+ await SmartBusiness.loadSmartBusinessLibrary("/sap/bc/ui5_ui5/sap/ssbtileslibs1");
179
+
180
+ let oParsedShellHash = UrlParsing.parseShellHash(sHash);
181
+ oParsedShellHash = await SmartBusiness.resolveEvaluationId(oParsedShellHash, true);
182
+ return UrlParsing.constructShellHash(oParsedShellHash);
183
+ }
184
+
185
+ /**
186
+ * Creates an ECMA6 Promise which resolves after the shell renderer has been created. This
187
+ * is necessary to delay the component creation in direct start case, so that the shell renderer
188
+ * had time to initialize (e.g. init shell navigation service).
189
+ *
190
+ * This method must only be called after the shell bootstrap!
191
+ * @param {sap.ushell.Container} Container The shell container instance
192
+ * @returns {Promise} A promise to chain following steps.
193
+ * @private
194
+ */
195
+ async #createWaitForRendererCreatedPromise (Container) {
196
+ const [EventHub] = await requireAsync(["sap/ushell/EventHub"]);
197
+ const oDeferred = Promise.withResolvers();
198
+
199
+ function fnOnRendererCreated () {
200
+ Log.info("Direct application start: resolving component waitFor promise after shell renderer created event fired.");
201
+ Container.detachRendererCreatedInternal(fnOnRendererCreated);
202
+ oDeferred.resolve();
203
+ }
204
+
205
+ EventHub.once("ShellNavigationInitialized").do(() => {
206
+ if (Container.getRendererInternal()) {
207
+ Log.info("Direct application start: resolving component waitFor promise immediately (shell renderer already created).");
208
+ oDeferred.resolve();
209
+ } else {
210
+ // the renderer should be created when the shell navigation is initialized, just to but be robust
211
+ Container.attachRendererCreatedInternal(fnOnRendererCreated);
212
+ }
213
+ });
214
+
215
+ return oDeferred.promise;
216
+ }
217
+
218
+ #getFullHash () {
219
+ const sHash = this.getLocationHash();
220
+ const sSanitizedHash = sHash.startsWith("#") ? sHash : `#${sHash}`;
221
+ // decode hash: identical behavior to ShellNavigationInternal.hrefForExternal
222
+ return decodeURI(sSanitizedHash);
223
+ }
224
+
225
+ getLocationHash () {
226
+ return window.location.hash;
227
+ }
228
+ }
229
+
230
+ return new DirectAppStart();
231
+ });
@@ -0,0 +1,43 @@
1
+ // Copyright (c) 2009-2026 SAP SE, All Rights Reserved
2
+ sap.ui.define([
3
+ "sap/ushell/Container",
4
+ "sap/ushell/state/StateManager",
5
+ "sap/ushell/renderer/ShellLayout",
6
+ "sap/ushell/ui/shell/SysInfoBar"
7
+ ], (
8
+ Container,
9
+ StateManager,
10
+ ShellLayout,
11
+ SysInfoBar
12
+ ) => {
13
+ "use strict";
14
+
15
+ // shortcut for sap.ushell.state.StateManager.ShellMode
16
+ const ShellMode = StateManager.ShellMode;
17
+
18
+ class CreateRenderer {
19
+ async run () {
20
+ const oRenderer = await Container.createRendererInternal("fiori2");
21
+ oRenderer.placeAt("canvas", "only");
22
+ const oSystem = Container.getLogonSystem();
23
+ const sCurrentShellMode = StateManager.getShellMode();
24
+
25
+ if (!oSystem.getSysInfoBar() || sCurrentShellMode === ShellMode.Headerless) {
26
+ return;
27
+ }
28
+
29
+ const sSystemInfoHtml = "<div id='systemInfo-shellArea'></div>";
30
+ const oShellHeaderShellArea = document.getElementById(ShellLayout.ShellArea.ShellHeader);
31
+ oShellHeaderShellArea.insertAdjacentHTML("beforebegin", sSystemInfoHtml);
32
+
33
+ new SysInfoBar({
34
+ icon: oSystem.getSysInfoBarIcon(),
35
+ text: oSystem.getSysInfoBarMainText(),
36
+ subText: oSystem.getSysInfoBarSecondaryText(),
37
+ color: oSystem.getSysInfoBarColor()
38
+ }).placeAt("systemInfo-shellArea");
39
+ }
40
+ }
41
+
42
+ return new CreateRenderer();
43
+ });
@@ -0,0 +1,148 @@
1
+ // Copyright (c) 2009-2026 SAP SE, All Rights Reserved
2
+ sap.ui.define([
3
+ "sap/ushell_abap/bootstrap/XhrLogonLibLoader", // triggers loading of the XHR logon lib, once required
4
+ "sap/ushell_abap/bootstrap/XhrLogonEventHandler",
5
+ "sap/ushell/bootstrap/Config",
6
+ "sap/base/Log",
7
+ "sap/ushell/Container"
8
+ ], (
9
+ XhrLogonLibLoader,
10
+ XhrLogonEventHandler,
11
+ BootstrapConfig,
12
+ Log,
13
+ Container
14
+ ) => {
15
+ "use strict";
16
+
17
+ class InitXhrLogon {
18
+ async run () {
19
+ await Promise.all([
20
+ this.#initXhrLogon(),
21
+ this.#initFrameLogonManager()
22
+ ]);
23
+ }
24
+
25
+ /**
26
+ * Determines the XHR logon mode based on the bootstrap configuration
27
+ * and the URL parameters sap-ushell-xhrLogon-mode and saml2.
28
+ * @returns {string} the logon mode
29
+ */
30
+ #getLogonMode () {
31
+ const oUshellConfig = BootstrapConfig.get();
32
+ const sSearch = this.getWindowLocationSearch();
33
+ const oUrlParameters = new URLSearchParams(sSearch);
34
+
35
+ return oUrlParameters.get("sap-ushell-xhrLogon-mode")
36
+ || (oUrlParameters.get("saml2")?.toLowerCase() === "disabled" ? "logoffAndRedirect" : undefined)
37
+ || oUshellConfig?.xhrLogon?.mode
38
+ || "frame";
39
+ }
40
+
41
+ /**
42
+ * Initializes and starts XHR logon lib based on a given configuration.
43
+ * <p>
44
+ *
45
+ * @private
46
+ */
47
+ async #initXhrLogon () {
48
+ const oXhrLogonLib = await XhrLogonLibLoader.getLib();
49
+
50
+ const sLogonMode = this.#getLogonMode();
51
+ const oXhrLogonEventHandler = this.createXhrLogonEventHandler(window, sLogonMode);
52
+ const oLogonManager = oXhrLogonLib.LogonManager.getInstance();
53
+ const oXHRLogonManager = oXhrLogonLib.XHRLogonManager.getInstance();
54
+ const oXhrLibConfig = {
55
+ explicitMatchOnCORS: true // avoids to send XHRLib HTTP headers to thirdparty services
56
+ };
57
+
58
+ oXhrLogonLib.start(oXhrLibConfig);
59
+
60
+ if (sLogonMode === "reload" || sLogonMode === "logoffAndRedirect") {
61
+ oLogonManager.unregisterAllHandlers();
62
+ oLogonManager.registerAuthHandler("*", (oEvent) => {
63
+ oXhrLogonEventHandler.handleEvent(oEvent);
64
+ });
65
+ } else if (sLogonMode !== "frame") {
66
+ Log.warning(`Unknown setting for xhrLogonMode: '${sLogonMode}'. Using default mode 'frame'.`, null, "sap.ushell_abap.bootstrap.XhrLogon");
67
+ }
68
+
69
+ oXhrLogonLib.Log.set(this.#createUi5ConnectedXhrLogger());
70
+ this.#initXhrLogonIgnoreList(oXHRLogonManager);
71
+ }
72
+
73
+ async #initFrameLogonManager () {
74
+ const oXhrLogonLib = await XhrLogonLibLoader.getLib();
75
+ const oFrameLogonManager = oXhrLogonLib.FrameLogonManager.getInstance();
76
+ Container.oFrameLogonManager = oFrameLogonManager;
77
+ }
78
+
79
+ /**
80
+ * Creates a logger for XMLHttpRequest(s) that logs errors, warnings, info
81
+ * and debug messages via Log.
82
+ *
83
+ * @returns {object}
84
+ * A logger that can be assigned to XMLHttpRequest.
85
+ *
86
+ * @private
87
+ */
88
+ #createUi5ConnectedXhrLogger () {
89
+ return ["error", "warning", "info", "debug"].reduce((oXhrLogger, sLevel) => {
90
+ oXhrLogger[sLevel] = function (sMsg) {
91
+ return Log[sLevel](sMsg);
92
+ };
93
+ return oXhrLogger;
94
+ }, {});
95
+ }
96
+
97
+ /**
98
+ * Initializes the ignore list of the XHR logon manager.
99
+ * <p>
100
+ * If the UI5 resources (including the own bootstrap script) are loaded from an absolute URL
101
+ * (in case CDN is activated),
102
+ * this URL is added to the ignore list to prevent CORS preflight requests due to the X headers.
103
+ * We expect that all resources can be loaded without authentication in this case.
104
+ *
105
+ * @param {object} oXHRLogonManager
106
+ * the logon frame manager instance to use
107
+ *
108
+ * @private
109
+ */
110
+ #initXhrLogonIgnoreList (oXHRLogonManager) {
111
+ const sOrigin = this.getLocationOrigin();
112
+ const sUi5ResourceRootUrl = sap.ui.require.toUrl("");
113
+
114
+ // add "/" to origin, as otherwise the following use case will match:
115
+ // sUi5ResourceRootUrl: http://sap.com:123
116
+ // sOrigin: http://sap.com
117
+ if (sUi5ResourceRootUrl && sUi5ResourceRootUrl.indexOf(`${sOrigin}/`) === -1) {
118
+ // In case UI5 is loaded from a different domain (CDN / AKAMAI), that URL
119
+ // needs to be ignored for the XHR logon, as we expect that the resources
120
+ // are not protected.
121
+ oXHRLogonManager.ignore.add(sUi5ResourceRootUrl);
122
+ }
123
+ }
124
+
125
+ /**
126
+ * We expose a factory method for the tests and allow to pass a test double for the window object
127
+ *
128
+ * @param {object} oWindow the window object
129
+ * @param {string} sXhrLogonMode logon mode
130
+ * @returns {XhrLogonEventHandler} a new XhrLogonEventHandler
131
+ *
132
+ * @private
133
+ */
134
+ createXhrLogonEventHandler (oWindow, sXhrLogonMode) {
135
+ return new XhrLogonEventHandler(oWindow, sXhrLogonMode);
136
+ }
137
+
138
+ getWindowLocationSearch () {
139
+ return window.location.search;
140
+ }
141
+
142
+ getLocationOrigin () {
143
+ return window.location.origin;
144
+ }
145
+ }
146
+
147
+ return new InitXhrLogon();
148
+ });
@@ -0,0 +1,86 @@
1
+ // Copyright (c) 2009-2026 SAP SE, All Rights Reserved
2
+ sap.ui.define([
3
+ "sap/base/util/ObjectPath",
4
+ "sap/ushell/bootstrap/Config",
5
+ "sap/ushell/Container",
6
+ "sap/ushell/components/pages/controller/PagesAndSpaceId",
7
+ "sap/ushell/resources"
8
+ ], (
9
+ ObjectPath,
10
+ BootstrapConfig,
11
+ Container,
12
+ PagesAndSpaceId,
13
+ ushellResources
14
+ ) => {
15
+ "use strict";
16
+
17
+ class RequestPages {
18
+ #aInternTargets = [
19
+ "Shell-home",
20
+ "Launchpad-openFLPPage"
21
+ ];
22
+
23
+ #isRelevant () {
24
+ const oUshellConfig = BootstrapConfig.get();
25
+ if (!ObjectPath.get("ushell.spaces.enabled", oUshellConfig)) {
26
+ return false;
27
+ }
28
+
29
+ let sHash = this.getLocationHash();
30
+ sHash = sHash.startsWith("#") ? sHash.slice(1) : sHash;
31
+
32
+ return !sHash || this.#aInternTargets.some((sTarget) => sHash.startsWith(sTarget));
33
+ }
34
+
35
+ async run () {
36
+ if (!this.#isRelevant()) {
37
+ return;
38
+ }
39
+
40
+ await Promise.all([
41
+ this.#requestPagesPersonalization(),
42
+ this.#requestPagesContent()
43
+ ]);
44
+ }
45
+
46
+ async #requestPagesPersonalization () {
47
+ const PersonalizationV2 = await Container.getServiceAsync("PersonalizationV2");
48
+ const oPersId = {
49
+ container: "sap.ushell.cdm3-1.personalization",
50
+ item: "data"
51
+ };
52
+
53
+ const oScope = {
54
+ validity: "Infinity",
55
+ keyCategory: PersonalizationV2.KeyCategory.GENERATED_KEY,
56
+ writeFrequency: PersonalizationV2.WriteFrequency.HIGH,
57
+ clientStorageAllowed: false
58
+ };
59
+ const oPersonalizer = await PersonalizationV2.getPersonalizer(oPersId, oScope);
60
+ return oPersonalizer.getPersData();
61
+ }
62
+
63
+ async #requestPagesContent () {
64
+ await ushellResources.awaitResourceBundle();
65
+
66
+ const pId = PagesAndSpaceId.getPageAndSpaceId(this.getLocationHash());
67
+ const pPagePersistenceService = Container.getServiceAsync("PagePersistence");
68
+
69
+ const [
70
+ oIds,
71
+ PagePersistence
72
+ ] = await Promise.all([
73
+ pId,
74
+ pPagePersistenceService
75
+ ]);
76
+
77
+ await PagePersistence.getPage(oIds.pageId);
78
+ }
79
+
80
+ getLocationHash () {
81
+ return window.location.hash;
82
+ }
83
+ }
84
+
85
+ return new RequestPages();
86
+ });