@itwin/ecschema-rpcinterface-tests 5.13.0-dev.15 → 5.13.0-dev.17

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.
@@ -91445,6 +91445,8 @@ const COPYRIGHT_NOTICE = `Copyright © 2017-${new Date().getFullYear()} <a href=
91445
91445
 
91446
91446
 
91447
91447
 
91448
+ /** CSS class name applied to the notice element of a logo card created by [[IModelApp.makeLogoCard]]. */
91449
+ const logoCardNoticeClassName = "logo-cards";
91448
91450
  /**
91449
91451
  * Global singleton that connects the user interface with the iTwin.js services. There can be only one IModelApp active in a session. All
91450
91452
  * members of IModelApp are static, and it serves as a singleton object for gaining access to session information.
@@ -91957,10 +91959,21 @@ class IModelApp {
91957
91959
  }
91958
91960
  if (undefined !== opts.notice) {
91959
91961
  if (typeof opts.notice === "string")
91960
- IModelApp.makeHTMLElement("p", { parent: noticeCell, innerHTML: opts.notice, className: "logo-cards" });
91962
+ IModelApp.makeHTMLElement("p", { parent: noticeCell, innerHTML: opts.notice, className: logoCardNoticeClassName });
91961
91963
  else
91962
91964
  noticeCell.appendChild(opts.notice);
91963
91965
  }
91966
+ else if (undefined !== opts.noticeLines) {
91967
+ // A <p> cannot legally contain flow content, so use a <div> when a line is an element.
91968
+ const containerTag = opts.noticeLines.some((line) => typeof line !== "string") ? "div" : "p";
91969
+ const notice = IModelApp.makeHTMLElement(containerTag, { parent: noticeCell, className: logoCardNoticeClassName });
91970
+ opts.noticeLines.forEach((line, index) => {
91971
+ if (index > 0)
91972
+ notice.appendChild(IModelApp.makeHTMLElement("br"));
91973
+ // Strings are appended as text nodes so they are never parsed as HTML.
91974
+ notice.append(line);
91975
+ });
91976
+ }
91964
91977
  return card;
91965
91978
  }
91966
91979
  /** Make the logo card for the library itself. This card gets placed at the top of the stack.
@@ -93527,7 +93540,9 @@ let iModelJsCss = `
93527
93540
 
93528
93541
  .logo-cards {
93529
93542
  position:relative;
93530
- width:100%
93543
+ width:100%;
93544
+ margin-block-start:1em;
93545
+ margin-block-end:1em
93531
93546
  }
93532
93547
 
93533
93548
  .imodeljs-modal-overlay {
@@ -93571,7 +93586,7 @@ let iModelJsCss = `
93571
93586
  max-width: calc(100% - (2 * var(--width-border))) !important;
93572
93587
  width: unset !important;
93573
93588
  }
93574
- .imodeljs-about .logo-card-message p {
93589
+ .imodeljs-about .logo-card-message p, .imodeljs-about .logo-card-message .logo-cards {
93575
93590
  margin-block-end: 1em;
93576
93591
  }
93577
93592
  .imodeljs-about .logo-cards {
@@ -96217,9 +96232,12 @@ class Google3dTilesProvider {
96217
96232
  // Order by most occurances to least
96218
96233
  // See https://developers.google.com/maps/documentation/tile/create-renderer#display-attributions
96219
96234
  const sortedCopyrights = [...copyrightMap.entries()].sort((a, b) => b[1] - a[1]);
96220
- let copyrightMsg = "Data provided by:<br><ul>";
96221
- copyrightMsg += sortedCopyrights.map(([key]) => `<li>${key}</li>`).join("");
96222
- copyrightMsg += "</ul>";
96235
+ const list = document.createElement("ul");
96236
+ for (const [key] of sortedCopyrights) {
96237
+ const item = document.createElement("li");
96238
+ item.textContent = key;
96239
+ list.appendChild(item);
96240
+ }
96223
96241
  const iconSrc = document.createElement("img");
96224
96242
  iconSrc.src = `${_IModelApp__WEBPACK_IMPORTED_MODULE_8__.IModelApp.publicPath}images/GoogleMaps_Logo_Gray.svg`;
96225
96243
  iconSrc.style.padding = "10px 10px 5px 10px";
@@ -96227,7 +96245,7 @@ class Google3dTilesProvider {
96227
96245
  iconSrc,
96228
96246
  iconWidth: 98,
96229
96247
  heading: "Google Photorealistic 3D Tiles",
96230
- notice: copyrightMsg
96248
+ noticeLines: ["Data provided by:", list],
96231
96249
  }));
96232
96250
  }
96233
96251
  }
@@ -116617,7 +116635,7 @@ class GoogleMapsDecorator {
116617
116635
  const copyrightText = sortedCopyrights.map(([key]) => ` • ${key}`).join("");
116618
116636
  // Create and add element, offset to leave space for i.js and Google logos
116619
116637
  const elem = document.createElement("div");
116620
- elem.innerHTML = copyrightText;
116638
+ elem.textContent = copyrightText;
116621
116639
  elem.style.color = "white";
116622
116640
  elem.style.fontSize = "11px";
116623
116641
  elem.style.textWrap = "wrap";
@@ -153924,7 +153942,11 @@ class OrbitGtTreeReference extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.R
153924
153942
  if (this._name)
153925
153943
  strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_6__.IModelApp.localization.getLocalizedString("iModelJs:TooltipInfo.Name")} ${this._name}`);
153926
153944
  const div = document.createElement("div");
153927
- div.innerHTML = strings.join("<br>");
153945
+ strings.forEach((str, index) => {
153946
+ if (index > 0)
153947
+ div.appendChild(document.createElement("br"));
153948
+ div.appendChild(document.createTextNode(str));
153949
+ });
153928
153950
  return div;
153929
153951
  }
153930
153952
  }
@@ -155688,7 +155710,11 @@ class RealityTreeReference extends RealityModelTileTree.Reference {
155688
155710
  if (-1 === key.indexOf("#")) // Avoid internal cesium
155689
155711
  strings.push(`${key}: ${JSON.stringify(batch[key])}`);
155690
155712
  const div = document.createElement("div");
155691
- div.innerHTML = strings.join("<br>");
155713
+ strings.forEach((str, index) => {
155714
+ if (index > 0)
155715
+ div.appendChild(document.createElement("br"));
155716
+ div.appendChild(document.createTextNode(str));
155717
+ });
155692
155718
  return div;
155693
155719
  }
155694
155720
  /** @deprecated in 5.0 - might be removed in next major version. Use [addAttributions] instead. */
@@ -156876,7 +156902,21 @@ class ArcGisUtilities {
156876
156902
  */
156877
156903
  static async validateSource(args) {
156878
156904
  const { source, ignoreCache, capabilitiesFilter } = args;
156879
- const metadata = await this.getServiceJson({ url: source.url, formatId: source.formatId, userName: source.userName, password: source.password, queryParams: source.collectQueryParams(), ignoreCache });
156905
+ let metadata;
156906
+ try {
156907
+ metadata = await this.getServiceJson({ url: source.url, formatId: source.formatId, userName: source.userName, password: source.password, queryParams: source.collectQueryParams(), ignoreCache });
156908
+ }
156909
+ catch (err) {
156910
+ if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError) {
156911
+ let blockedOrigin;
156912
+ try {
156913
+ blockedOrigin = new URL(err.url).origin;
156914
+ }
156915
+ catch { /* non-hierarchical URL */ }
156916
+ return { status: _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
156917
+ }
156918
+ throw err;
156919
+ }
156880
156920
  const json = metadata?.content;
156881
156921
  if (json === undefined) {
156882
156922
  return { status: _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerSourceStatus.InvalidUrl };
@@ -156939,6 +156979,9 @@ class ArcGisUtilities {
156939
156979
  * @param password Password to use for legacy token based security
156940
156980
  * @param ignoreCache Flag to skip cache lookup (i.e. force a new server request)
156941
156981
  * @param requireToken Flag to indicate if a token is required
156982
+ * @throws [[MapLayerUntrustedOriginError]] if an NTLM/Negotiate challenge could not be answered because
156983
+ * the URL's origin is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]);
156984
+ * all other errors are caught and reported by returning `undefined`.
156942
156985
  */
156943
156986
  static async getServiceJson(args) {
156944
156987
  const { url, formatId, userName, password, queryParams, ignoreCache, requireToken } = args;
@@ -156974,8 +157017,17 @@ class ArcGisUtilities {
156974
157017
  }
156975
157018
  let response = await fetch(tmpUrl, { method: "GET" });
156976
157019
  if (response.status === 401 && !requireToken && (0,_request_utils__WEBPACK_IMPORTED_MODULE_3__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
156977
- // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
156978
- response = await fetch(tmpUrl, { method: "GET", credentials: "include" });
157020
+ // fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
157021
+ const challengedUrl = response.url || tmpUrl.toString();
157022
+ if (!_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(challengedUrl))
157023
+ throw new _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError(challengedUrl);
157024
+ _IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(challengedUrl);
157025
+ // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication).
157026
+ response = await fetch(challengedUrl, {
157027
+ method: "GET",
157028
+ credentials: "include",
157029
+ redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
157030
+ });
156979
157031
  }
156980
157032
  // Append security token when corresponding error code is returned by ArcGIS service
156981
157033
  let errorCode = await ArcGisUtilities.checkForResponseErrorCode(response);
@@ -156997,8 +157049,10 @@ class ArcGisUtilities {
156997
157049
  ArcGisUtilities._serviceCache.set(url, (errorCode === undefined ? info : undefined));
156998
157050
  return info; // Always return json, even though it contains an error code.
156999
157051
  }
157000
- catch {
157052
+ catch (err) {
157001
157053
  ArcGisUtilities._serviceCache.set(url, undefined);
157054
+ if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError)
157055
+ throw err; // propagate so callers can report the blocked origin
157002
157056
  return undefined;
157003
157057
  }
157004
157058
  }
@@ -157160,7 +157214,9 @@ class ArcGISImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE_0__.
157160
157214
  try {
157161
157215
  metadata = await _tile_internal__WEBPACK_IMPORTED_MODULE_0__.ArcGisUtilities.getServiceJson({ url: this._settings.url, formatId: this._settings.formatId, userName: this._settings.userName, password: this._settings.password, queryParams: this._settings.collectQueryParams() });
157162
157216
  }
157163
- catch {
157217
+ catch (err) {
157218
+ if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError)
157219
+ this.reportBlockedOrigin(err.url);
157164
157220
  }
157165
157221
  if (metadata && metadata.accessTokenRequired) {
157166
157222
  const accessClient = _IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.mapLayerFormatRegistry.getAccessClient(this._settings.formatId);
@@ -157208,12 +157264,32 @@ class ArcGISImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE_0__.
157208
157264
  await this._firstRequestPromise;
157209
157265
  let response;
157210
157266
  try {
157211
- response = await fetch(urlObj, { ...options, credentials: this._includeUserCredentials ? "include" : undefined });
157267
+ const requestUrl = urlObj.toString();
157268
+ const includeCredentials = this.includeUserCredentials(requestUrl);
157269
+ response = await fetch(urlObj, {
157270
+ ...options,
157271
+ credentials: includeCredentials ? "include" : undefined,
157272
+ redirect: includeCredentials ? this.credentialedRedirect : options?.redirect,
157273
+ });
157274
+ if (includeCredentials)
157275
+ this.checkCredentialedRedirect(requestUrl, response);
157212
157276
  if (response.status === 401 && !this._lastAccessToken && (0,_request_utils__WEBPACK_IMPORTED_MODULE_3__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
157213
- // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
157214
- response = await fetch(urlObj, { ...options, credentials: "include" });
157215
- if (response.status === 200) {
157216
- this._includeUserCredentials = true; // avoid going through 401 challenges over and over
157277
+ // fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
157278
+ const challengedUrl = response.url || requestUrl;
157279
+ if (this.isSsoAllowed(challengedUrl)) {
157280
+ // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication).
157281
+ this.logUntrustedOriginUse(challengedUrl);
157282
+ response = await fetch(challengedUrl, {
157283
+ ...options,
157284
+ credentials: "include",
157285
+ redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
157286
+ });
157287
+ if (response.status === 200) {
157288
+ this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
157289
+ }
157290
+ }
157291
+ else {
157292
+ this.reportBlockedOrigin(challengedUrl);
157217
157293
  }
157218
157294
  }
157219
157295
  if ((this._lastAccessToken && response.status === 400)
@@ -157426,8 +157502,12 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
157426
157502
  }
157427
157503
  async initialize() {
157428
157504
  const metadata = await this.getServiceJson();
157429
- if (metadata?.content === undefined)
157505
+ if (metadata?.content === undefined) {
157506
+ // By returning (i.e., not throwing), we ensure the tile tree gets created and the current provider is preserved to report status.
157507
+ if (this.status === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerImageryProviderStatus.UntrustedOrigin)
157508
+ return;
157430
157509
  throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_0__.ServerError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_5__.IModelStatus.ValidationFailed, "");
157510
+ }
157431
157511
  const json = metadata.content;
157432
157512
  if (json?.error?.code === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.ArcGisErrorCode.TokenRequired
157433
157513
  || json?.error?.code === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.ArcGisErrorCode.InvalidToken
@@ -157512,7 +157592,7 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
157512
157592
  addLogoCards(cards) {
157513
157593
  if (!cards.dataset.arcGisLogoCard) {
157514
157594
  cards.dataset.arcGisLogoCard = "true";
157515
- cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.makeLogoCard({ heading: "ArcGIS", notice: this._copyrightText }));
157595
+ cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.makeLogoCard({ heading: "ArcGIS", noticeLines: [this._copyrightText] }));
157516
157596
  }
157517
157597
  }
157518
157598
  async addAttributions(cards, _vp) {
@@ -157553,7 +157633,7 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
157553
157633
  if (json && Array.isArray(json.results)) {
157554
157634
  for (const result of json.results) {
157555
157635
  if (result.attributes !== undefined && result.attributes[result.displayFieldName] !== undefined) {
157556
- const thisString = `${result.displayFieldName}: ${result.attributes[result.displayFieldName]}`;
157636
+ const thisString = `${(0,_tile_internal__WEBPACK_IMPORTED_MODULE_2__.escapeHtml)(String(result.displayFieldName))}: ${(0,_tile_internal__WEBPACK_IMPORTED_MODULE_2__.escapeHtml)(String(result.attributes[result.displayFieldName]))}`;
157557
157637
  if (!stringSet.has(thisString)) {
157558
157638
  strings.push(thisString);
157559
157639
  stringSet.add(thisString);
@@ -157869,13 +157949,7 @@ class BingMapsImageryLayerProvider extends _tile_internal__WEBPACK_IMPORTED_MODU
157869
157949
  const copyrights = [];
157870
157950
  for (const match of matchingAttributions)
157871
157951
  copyrights.push(match.copyrightMessage);
157872
- let copyrightMsg = "";
157873
- for (let i = 0; i < copyrights.length; ++i) {
157874
- if (i > 0)
157875
- copyrightMsg += "<br>";
157876
- copyrightMsg += copyrights[i];
157877
- }
157878
- cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.makeLogoCard({ iconSrc: `${_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.publicPath}images/bing.svg`, heading: "Microsoft Bing", notice: copyrightMsg }));
157952
+ cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.makeLogoCard({ iconSrc: `${_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.publicPath}images/bing.svg`, heading: "Microsoft Bing", noticeLines: copyrights }));
157879
157953
  }
157880
157954
  async addAttributions(cards, vp) {
157881
157955
  // eslint-disable-next-line @typescript-eslint/no-deprecated
@@ -158484,7 +158558,10 @@ class WmsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE
158484
158558
  // Don't throw error if unauthorized status:
158485
158559
  // We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
158486
158560
  // When credentials will be provided, a new provider will be created, and initialization should be fine.
158487
- if (error?.status === 401) {
158561
+ if (error instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError) {
158562
+ this.reportBlockedOrigin(error.url);
158563
+ }
158564
+ else if (error?.status === 401) {
158488
158565
  this.setStatus(_tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerImageryProviderStatus.RequireAuth);
158489
158566
  }
158490
158567
  else {
@@ -158646,7 +158723,8 @@ class WmtsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODUL
158646
158723
  }
158647
158724
  async initialize() {
158648
158725
  try {
158649
- this._capabilities = await _tile_internal__WEBPACK_IMPORTED_MODULE_2__.WmtsCapabilities.create(this._baseUrl);
158726
+ const credentials = (this._settings.userName && this._settings.password ? { user: this._settings.userName, password: this._settings.password } : undefined);
158727
+ this._capabilities = await _tile_internal__WEBPACK_IMPORTED_MODULE_2__.WmtsCapabilities.create(this._baseUrl, credentials);
158650
158728
  this.initPreferredTileMatrixSet();
158651
158729
  this.initPreferredStyle();
158652
158730
  this.initDisplayedLayer();
@@ -158659,7 +158737,10 @@ class WmtsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODUL
158659
158737
  // Don't throw error if unauthorized status:
158660
158738
  // We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
158661
158739
  // When credentials will be provided, a new provider will be created, and initialization should be fine.
158662
- if (error?.status === 401) {
158740
+ if (error instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerUntrustedOriginError) {
158741
+ this.reportBlockedOrigin(error.url);
158742
+ }
158743
+ else if (error?.status === 401) {
158663
158744
  this.setStatus(_tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerImageryProviderStatus.RequireAuth);
158664
158745
  }
158665
158746
  else {
@@ -159470,14 +159551,18 @@ __webpack_require__.r(__webpack_exports__);
159470
159551
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
159471
159552
  /* harmony export */ WmsUtilities: () => (/* binding */ WmsUtilities)
159472
159553
  /* harmony export */ });
159473
- /* harmony import */ var _request_Request__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../request/Request */ "../../core/frontend/lib/esm/request/Request.js");
159474
- /* harmony import */ var _request_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../request/utils */ "../../core/frontend/lib/esm/request/utils.js");
159554
+ /* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
159555
+ /* harmony import */ var _request_Request__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../request/Request */ "../../core/frontend/lib/esm/request/Request.js");
159556
+ /* harmony import */ var _request_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../request/utils */ "../../core/frontend/lib/esm/request/utils.js");
159557
+ /* harmony import */ var _tile_internal__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../tile/internal */ "../../core/frontend/lib/esm/tile/internal.js");
159475
159558
  /*---------------------------------------------------------------------------------------------
159476
159559
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
159477
159560
  * See LICENSE.md in the project root for license terms and full copyright notice.
159478
159561
  *--------------------------------------------------------------------------------------------*/
159479
159562
 
159480
159563
 
159564
+
159565
+
159481
159566
  /** @packageDocumentation
159482
159567
  * @module Tiles
159483
159568
  */
@@ -159494,16 +159579,35 @@ class WmsUtilities {
159494
159579
  static async fetchXml(url, credentials) {
159495
159580
  let headers;
159496
159581
  if (credentials && credentials.user && credentials.password) {
159497
- headers = new Headers();
159498
- (0,_request_utils__WEBPACK_IMPORTED_MODULE_1__.setBasicAuthorization)(headers, credentials);
159582
+ // Basic credentials are considered settings-derived credentials for this source. When the registry is
159583
+ // enforcing trusted origins, the source URL itself is the only implicitly trusted origin for basic auth;
159584
+ // opaque/custom-protocol URLs have no network origin and must therefore be treated as untrusted.
159585
+ const allowBasicAuth = !_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins
159586
+ || _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, url);
159587
+ if (allowBasicAuth) {
159588
+ headers = new Headers();
159589
+ (0,_request_utils__WEBPACK_IMPORTED_MODULE_2__.setBasicAuthorization)(headers, credentials);
159590
+ }
159499
159591
  }
159500
159592
  let response = await fetch(url, { method: "GET", headers });
159501
- if (!credentials && response.status === 401 && (0,_request_utils__WEBPACK_IMPORTED_MODULE_1__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
159502
- // We got a http 401 challenge, lets try SSO (i.e. Windows Authentication)
159503
- response = await fetch(url, { method: "GET", credentials: "include" });
159593
+ if (!headers && credentials && credentials.user && credentials.password && (response.status === 401 || response.status === 403)) {
159594
+ throw new _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError(url);
159595
+ }
159596
+ if (!credentials && response.status === 401 && (0,_request_utils__WEBPACK_IMPORTED_MODULE_2__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
159597
+ // fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
159598
+ const challengedUrl = response.url || url;
159599
+ if (!_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(challengedUrl))
159600
+ throw new _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError(challengedUrl);
159601
+ _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(challengedUrl);
159602
+ // We got a http 401 challenge, lets try SSO (i.e. Windows Authentication).
159603
+ response = await fetch(challengedUrl, {
159604
+ method: "GET",
159605
+ credentials: "include",
159606
+ redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
159607
+ });
159504
159608
  }
159505
159609
  if (response.status !== 200)
159506
- throw new _request_Request__WEBPACK_IMPORTED_MODULE_0__.HttpResponseError(response.status, await response.text());
159610
+ throw new _request_Request__WEBPACK_IMPORTED_MODULE_1__.HttpResponseError(response.status, await response.text());
159507
159611
  return response.text();
159508
159612
  }
159509
159613
  }
@@ -171917,6 +172021,7 @@ __webpack_require__.r(__webpack_exports__);
171917
172021
  /* harmony export */ MapLayerSourceStatus: () => (/* reexport safe */ _map_MapLayerSources__WEBPACK_IMPORTED_MODULE_86__.MapLayerSourceStatus),
171918
172022
  /* harmony export */ MapLayerSources: () => (/* reexport safe */ _map_MapLayerSources__WEBPACK_IMPORTED_MODULE_86__.MapLayerSources),
171919
172023
  /* harmony export */ MapLayerTileTreeReference: () => (/* reexport safe */ _map_MapLayerTileTreeReference__WEBPACK_IMPORTED_MODULE_64__.MapLayerTileTreeReference),
172024
+ /* harmony export */ MapLayerUntrustedOriginError: () => (/* reexport safe */ _map_MapLayerFormatRegistry__WEBPACK_IMPORTED_MODULE_42__.MapLayerUntrustedOriginError),
171920
172025
  /* harmony export */ MapTile: () => (/* reexport safe */ _map_MapTile__WEBPACK_IMPORTED_MODULE_70__.MapTile),
171921
172026
  /* harmony export */ MapTileLoader: () => (/* reexport safe */ _internal_tile_map_MapTileLoader__WEBPACK_IMPORTED_MODULE_72__.MapTileLoader),
171922
172027
  /* harmony export */ MapTileProjection: () => (/* reexport safe */ _map_MapTile__WEBPACK_IMPORTED_MODULE_70__.MapTileProjection),
@@ -172012,6 +172117,7 @@ __webpack_require__.r(__webpack_exports__);
172012
172117
  /* harmony export */ decodeMeshoptBuffer: () => (/* reexport safe */ _internal_tile_MeshoptCompression__WEBPACK_IMPORTED_MODULE_93__.decodeMeshoptBuffer),
172013
172118
  /* harmony export */ deflateCoordinates: () => (/* reexport safe */ _internal_tile_map_ImageryProviders_CoordinatesUtils__WEBPACK_IMPORTED_MODULE_47__.deflateCoordinates),
172014
172119
  /* harmony export */ disposeTileTreesForGeometricModels: () => (/* reexport safe */ _internal_tile_PrimaryTileTree__WEBPACK_IMPORTED_MODULE_82__.disposeTileTreesForGeometricModels),
172120
+ /* harmony export */ escapeHtml: () => (/* reexport safe */ _map_MapLayerImageryProvider__WEBPACK_IMPORTED_MODULE_49__.escapeHtml),
172015
172121
  /* harmony export */ getCesiumAccessClient: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAccessClient),
172016
172122
  /* harmony export */ getCesiumAccessTokenAndEndpointUrl: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAccessTokenAndEndpointUrl),
172017
172123
  /* harmony export */ getCesiumAssetUrl: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAssetUrl),
@@ -172031,7 +172137,8 @@ __webpack_require__.r(__webpack_exports__);
172031
172137
  /* harmony export */ readImdlContent: () => (/* reexport safe */ _ImdlReader__WEBPACK_IMPORTED_MODULE_35__.readImdlContent),
172032
172138
  /* harmony export */ readPntsColors: () => (/* reexport safe */ _internal_tile_PntsReader__WEBPACK_IMPORTED_MODULE_76__.readPntsColors),
172033
172139
  /* harmony export */ readPointCloudTileContent: () => (/* reexport safe */ _internal_tile_PntsReader__WEBPACK_IMPORTED_MODULE_76__.readPointCloudTileContent),
172034
- /* harmony export */ tileTreeReferenceFromRenderGraphic: () => (/* reexport safe */ _RenderGraphicTileTree__WEBPACK_IMPORTED_MODULE_78__.tileTreeReferenceFromRenderGraphic)
172140
+ /* harmony export */ tileTreeReferenceFromRenderGraphic: () => (/* reexport safe */ _RenderGraphicTileTree__WEBPACK_IMPORTED_MODULE_78__.tileTreeReferenceFromRenderGraphic),
172141
+ /* harmony export */ tryGetOrigin: () => (/* reexport safe */ _map_MapLayerImageryProvider__WEBPACK_IMPORTED_MODULE_49__.tryGetOrigin)
172035
172142
  /* harmony export */ });
172036
172143
  /* harmony import */ var _internal_tile_ViewFlagOverrides__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../internal/tile/ViewFlagOverrides */ "../../core/frontend/lib/esm/internal/tile/ViewFlagOverrides.js");
172037
172144
  /* harmony import */ var _map_MapCartoRectangle__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./map/MapCartoRectangle */ "../../core/frontend/lib/esm/tile/map/MapCartoRectangle.js");
@@ -173730,7 +173837,8 @@ __webpack_require__.r(__webpack_exports__);
173730
173837
  __webpack_require__.r(__webpack_exports__);
173731
173838
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
173732
173839
  /* harmony export */ MapLayerFormat: () => (/* binding */ MapLayerFormat),
173733
- /* harmony export */ MapLayerFormatRegistry: () => (/* binding */ MapLayerFormatRegistry)
173840
+ /* harmony export */ MapLayerFormatRegistry: () => (/* binding */ MapLayerFormatRegistry),
173841
+ /* harmony export */ MapLayerUntrustedOriginError: () => (/* binding */ MapLayerUntrustedOriginError)
173734
173842
  /* harmony export */ });
173735
173843
  /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
173736
173844
  /* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
@@ -173745,7 +173853,7 @@ __webpack_require__.r(__webpack_exports__);
173745
173853
 
173746
173854
 
173747
173855
 
173748
- const loggerCategory = "ArcGISFeatureProvider";
173856
+ const loggerCategory = "MapLayerFormatRegistry";
173749
173857
  /**
173750
173858
  * Class representing a map-layer format.
173751
173859
  * Each format has it's unique 'formatId' string, used to uniquely identify a format in the [[MapLayerFormatRegistry]].
@@ -173794,16 +173902,127 @@ class MapLayerFormat {
173794
173902
  return undefined;
173795
173903
  }
173796
173904
  }
173905
+ /** Error thrown when an NTLM or Negotiate http 401 challenge could not be answered because the request
173906
+ * URL's origin is not listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]]
173907
+ * (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
173908
+ * Thrown by the static map-layer utilities (e.g. capabilities / service-metadata fetches) that have no
173909
+ * provider instance on which to report the blocked origin; callers convert it to
173910
+ * [[MapLayerImageryProviderStatus.UntrustedOrigin]] (provider initialization) or
173911
+ * [[MapLayerSourceStatus.UntrustedOrigin]] (source validation).
173912
+ * @internal
173913
+ */
173914
+ class MapLayerUntrustedOriginError extends Error {
173915
+ /** The URL of the request whose authentication challenge was left unanswered. */
173916
+ url;
173917
+ constructor(url) {
173918
+ super(`Authentication blocked: origin of '${url}' is not listed in MapLayerFormatRegistry.trustedCredentialsOrigins`);
173919
+ this.url = url;
173920
+ }
173921
+ }
173797
173922
  /**
173798
173923
  * A registry of MapLayerFormats identified by their unique format IDs. The registry can be accessed via [[IModelApp.mapLayerFormatRegistry]].
173799
173924
  * @public
173800
173925
  */
173801
173926
  class MapLayerFormatRegistry {
173802
173927
  _configOptions;
173928
+ _trustedCredentialsOrigins = [];
173929
+ /** Opt-in enforcement of origin restrictions on map-layer credentials.
173930
+ * When enabled, map layer providers:
173931
+ * - attach the basic-auth credentials stored in the layer settings only to requests targeting the origin
173932
+ * of the layer's settings URL or an origin listed in [[trustedCredentialsOrigins]];
173933
+ * - retry a request with browser credentials included (i.e. SSO / Windows Authentication) after an NTLM
173934
+ * or Negotiate http 401 challenge only for origins explicitly listed in [[trustedCredentialsOrigins]]
173935
+ * (the settings-URL origin is NOT implicitly trusted for SSO, since map-layer URLs may originate from
173936
+ * untrusted user input while SSO shares the user's ambient identity).
173937
+ * Default is false, preserving the legacy behavior of sending credentials to any request URL.
173938
+ * @beta
173939
+ */
173940
+ restrictCredentialsToTrustedOrigins = false;
173803
173941
  constructor(opts) {
173804
173942
  this._configOptions = opts ?? {};
173805
173943
  _internal__WEBPACK_IMPORTED_MODULE_2__.internalMapLayerImageryFormats.forEach((format) => this.register(format));
173806
173944
  }
173945
+ /** Origins (e.g. "https://tiles.example.com") to which map layer providers may send credentials —
173946
+ * both the basic-auth credentials stored in the layer settings and browser credentials for
173947
+ * SSO (i.e. Windows Authentication) retries after an NTLM or Negotiate http 401 challenge.
173948
+ * Only enforced when [[restrictCredentialsToTrustedOrigins]] is enabled.
173949
+ * For basic-auth, the origin of each map layer's settings URL is always implicitly trusted; for SSO,
173950
+ * origins must be explicitly listed here.
173951
+ * Entries are normalized to their origin (scheme + host + port); only `http:` and `https:` URLs are accepted,
173952
+ * and any other entry is ignored and logged. Opaque schemes such as `file:`, `data:`, `about:` and custom
173953
+ * Electron protocols are rejected because they all share the same serialized origin, so trusting one would
173954
+ * trust every other.
173955
+ * @beta
173956
+ */
173957
+ get trustedCredentialsOrigins() {
173958
+ return this._trustedCredentialsOrigins;
173959
+ }
173960
+ set trustedCredentialsOrigins(origins) {
173961
+ const normalized = [];
173962
+ for (const entry of origins) {
173963
+ const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(entry);
173964
+ if (origin !== undefined)
173965
+ normalized.push(origin);
173966
+ else
173967
+ _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(loggerCategory, `trustedCredentialsOrigins: ignoring '${entry}'; entries must be http or https URLs.`);
173968
+ }
173969
+ this._trustedCredentialsOrigins = normalized;
173970
+ }
173971
+ /** Returns true if a request to the given URL may be retried with browser credentials included
173972
+ * (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
173973
+ * Always true unless [[restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
173974
+ * When enabled, the URL's origin must be explicitly listed in [[trustedCredentialsOrigins]];
173975
+ * unlike basic-auth, the settings-URL origin is NOT implicitly trusted because SSO shares the user's
173976
+ * ambient identity, and map-layer URLs may originate from untrusted user input.
173977
+ * @internal
173978
+ */
173979
+ isSsoAllowed(url) {
173980
+ if (!this.restrictCredentialsToTrustedOrigins)
173981
+ return true;
173982
+ const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url);
173983
+ // Entries are normalized to their origin by the [[trustedCredentialsOrigins]] setter.
173984
+ return origin !== undefined && this._trustedCredentialsOrigins.includes(origin);
173985
+ }
173986
+ /** Returns true if the basic-auth credentials belonging to a map-layer source or settings URL may be
173987
+ * attached to a request to the given URL. Always true unless [[restrictCredentialsToTrustedOrigins]]
173988
+ * is enabled (opt-in). When enabled, the origin of `settingsUrl` is implicitly trusted (the credentials
173989
+ * belong to that server); any other origin must be listed in [[trustedCredentialsOrigins]].
173990
+ * @internal
173991
+ */
173992
+ isCredentialsSharingAllowed(url, settingsUrl) {
173993
+ if (!this.restrictCredentialsToTrustedOrigins)
173994
+ return true;
173995
+ const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url);
173996
+ if (origin === undefined)
173997
+ return false;
173998
+ if (origin === (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(settingsUrl))
173999
+ return true;
174000
+ // Entries are normalized to their origin by the [[trustedCredentialsOrigins]] setter.
174001
+ return this._trustedCredentialsOrigins.includes(origin);
174002
+ }
174003
+ /** Origins for which a "credentials sent to untrusted origin" warning was already logged;
174004
+ * used to log the discovery warning only once per origin.
174005
+ */
174006
+ _untrustedUseLogged = new Set();
174007
+ /** Logs a warning (once per origin) when credentials are sent to an origin that would be blocked
174008
+ * if [[restrictCredentialsToTrustedOrigins]] were enabled.
174009
+ * Helps applications discover the origins they need to whitelist before opting in to the restriction.
174010
+ * If `settingsUrl` is supplied, requests sharing its origin are not logged, since that origin is
174011
+ * implicitly trusted for basic-auth.
174012
+ * @internal
174013
+ */
174014
+ logUntrustedOriginUse(url, settingsUrl) {
174015
+ if (this.restrictCredentialsToTrustedOrigins)
174016
+ return; // restriction active; nothing to preview
174017
+ const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url) ?? url;
174018
+ if (settingsUrl !== undefined && origin === (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(settingsUrl))
174019
+ return; // implicitly trusted for basic-auth
174020
+ if (this._untrustedUseLogged.has(origin) || this._trustedCredentialsOrigins.includes(origin))
174021
+ return;
174022
+ this._untrustedUseLogged.add(origin);
174023
+ _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(loggerCategory, `Credentials sent to origin '${origin}' which is not in MapLayerFormatRegistry.trustedCredentialsOrigins; `
174024
+ + "this request would be blocked if restrictCredentialsToTrustedOrigins were enabled.");
174025
+ }
173807
174026
  _formats = new Map();
173808
174027
  isRegistered(formatId) { return this._formats.get(formatId) !== undefined; }
173809
174028
  register(formatClass) {
@@ -173969,6 +174188,14 @@ class WmsMapLayerFormat extends ImageryMapLayerFormat {
173969
174188
  return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.Valid, subLayers };
173970
174189
  }
173971
174190
  catch (err) {
174191
+ if (err instanceof _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError) {
174192
+ let blockedOrigin;
174193
+ try {
174194
+ blockedOrigin = new URL(err.url).origin;
174195
+ }
174196
+ catch { /* non-hierarchical URL */ }
174197
+ return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
174198
+ }
173972
174199
  let status = _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidUrl;
173973
174200
  if (err?.status === 401) {
173974
174201
  status = ((userName && password) ? _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidCredentials : _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.RequireAuth);
@@ -174034,6 +174261,14 @@ class WmtsMapLayerFormat extends ImageryMapLayerFormat {
174034
174261
  return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.Valid, subLayers };
174035
174262
  }
174036
174263
  catch (err) {
174264
+ if (err instanceof _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError) {
174265
+ let blockedOrigin;
174266
+ try {
174267
+ blockedOrigin = new URL(err.url).origin;
174268
+ }
174269
+ catch { /* non-hierarchical URL */ }
174270
+ return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
174271
+ }
174037
174272
  let status = _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidUrl;
174038
174273
  if (err?.status === 401) {
174039
174274
  status = ((userName && password) ? _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidCredentials : _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.RequireAuth);
@@ -174098,7 +174333,9 @@ const internalMapLayerImageryFormats = [WmsMapLayerFormat, WmtsMapLayerFormat, A
174098
174333
  __webpack_require__.r(__webpack_exports__);
174099
174334
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
174100
174335
  /* harmony export */ MapLayerImageryProvider: () => (/* binding */ MapLayerImageryProvider),
174101
- /* harmony export */ MapLayerImageryProviderStatus: () => (/* binding */ MapLayerImageryProviderStatus)
174336
+ /* harmony export */ MapLayerImageryProviderStatus: () => (/* binding */ MapLayerImageryProviderStatus),
174337
+ /* harmony export */ escapeHtml: () => (/* binding */ escapeHtml),
174338
+ /* harmony export */ tryGetOrigin: () => (/* binding */ tryGetOrigin)
174102
174339
  /* harmony export */ });
174103
174340
  /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
174104
174341
  /* harmony import */ var _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @itwin/core-common */ "../../core/common/lib/esm/core-common.js");
@@ -174125,6 +174362,34 @@ __webpack_require__.r(__webpack_exports__);
174125
174362
  const tileImageSize = 256, untiledImageSize = 256;
174126
174363
  const earthRadius = 6378137;
174127
174364
  const doDebugToolTips = false;
174365
+ /** Escapes HTML metacharacters so the text renders literally when assigned to `innerHTML`.
174366
+ * Use for any server- or user-supplied string that ends up in the map tooltip, which is rendered
174367
+ * as HTML by [[MapLayerTileTreeReference.getToolTip]].
174368
+ * @internal
174369
+ */
174370
+ function escapeHtml(text) {
174371
+ return text.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
174372
+ }
174373
+ /** Returns the origin (scheme + host + port) of the given URL, or undefined if it cannot be parsed or does
174374
+ * not denote a distinct network origin.
174375
+ *
174376
+ * Only `http:` and `https:` URLs yield an origin. Every other scheme is rejected because opaque URLs
174377
+ * — `file:`, `data:`, `about:`, `blob:null`, and the custom protocols Electron hosts commonly register —
174378
+ * all serialize to the literal string `"null"`. Comparing those would make unrelated URLs look same-origin,
174379
+ * so a single trusted entry could unlock all of them. Callers use this for credential-trust decisions, and
174380
+ * returning `undefined` keeps those decisions fail-closed.
174381
+ * @internal
174382
+ */
174383
+ function tryGetOrigin(url) {
174384
+ let parsed;
174385
+ try {
174386
+ parsed = new URL(url);
174387
+ }
174388
+ catch {
174389
+ return undefined;
174390
+ }
174391
+ return (parsed.protocol === "http:" || parsed.protocol === "https:") ? parsed.origin : undefined;
174392
+ }
174128
174393
  /** The status of the map layer imagery provider that lets you know if authentication is needed to request tiles.
174129
174394
  * @public
174130
174395
  */
@@ -174132,6 +174397,12 @@ var MapLayerImageryProviderStatus;
174132
174397
  (function (MapLayerImageryProviderStatus) {
174133
174398
  MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["Valid"] = 0] = "Valid";
174134
174399
  MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["RequireAuth"] = 1] = "RequireAuth";
174400
+ /** A request received an authentication challenge, but credentials were withheld because the request origin
174401
+ * is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
174402
+ * The blocked origins are available via [[MapLayerImageryProvider.blockedOrigins]].
174403
+ * @beta
174404
+ */
174405
+ MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["UntrustedOrigin"] = 2] = "UntrustedOrigin";
174135
174406
  })(MapLayerImageryProviderStatus || (MapLayerImageryProviderStatus = {}));
174136
174407
  /** Abstract class for map layer imagery providers.
174137
174408
  * Map layer imagery providers request and provide tile images and other data. Each map layer from a separate source needs its own imagery provider object.
@@ -174149,7 +174420,41 @@ class MapLayerImageryProvider {
174149
174420
  /** @internal */
174150
174421
  _status = MapLayerImageryProviderStatus.Valid;
174151
174422
  /** @internal */
174152
- _includeUserCredentials = false;
174423
+ _blockedOrigins = new Set();
174424
+ /** Origins of requests for which credentials were withheld because they are not trusted
174425
+ * (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
174426
+ * Populated when [[status]] transitions to [[MapLayerImageryProviderStatus.UntrustedOrigin]];
174427
+ * [[onStatusChanged]] is raised again each time a new origin is added. Cleared by [[resetStatus]].
174428
+ * @beta
174429
+ */
174430
+ get blockedOrigins() { return [...this._blockedOrigins]; }
174431
+ /** Origins for which a previous SSO handshake (i.e. Windows Authentication) succeeded.
174432
+ * Browser credentials are only included for subsequent requests targeting these origins,
174433
+ * so that a successful handshake with one host does not leak credentials to other hosts
174434
+ * this provider may contact.
174435
+ * @internal
174436
+ */
174437
+ _ssoSucceededOrigins = new Set();
174438
+ /** Returns true if browser credentials should be included for the given URL because a previous
174439
+ * SSO handshake succeeded for its origin AND the origin is still allowed by the current policy
174440
+ * (see [[MapLayerFormatRegistry.isSsoAllowed]]). Re-checking the policy ensures a handshake recorded
174441
+ * while enforcement was disabled — or before an origin was removed from
174442
+ * [[MapLayerFormatRegistry.trustedCredentialsOrigins]] — does not keep latching credentials on.
174443
+ * @internal
174444
+ */
174445
+ includeUserCredentials(url) {
174446
+ const origin = tryGetOrigin(url);
174447
+ return origin !== undefined && this._ssoSucceededOrigins.has(origin) && this.isSsoAllowed(url);
174448
+ }
174449
+ /** Records that an SSO handshake succeeded for the given URL's origin, so subsequent requests
174450
+ * to that origin include browser credentials without going through another 401 challenge.
174451
+ * @internal
174452
+ */
174453
+ recordSsoSucceeded(url) {
174454
+ const origin = tryGetOrigin(url);
174455
+ if (origin !== undefined)
174456
+ this._ssoSucceededOrigins.add(origin);
174457
+ }
174153
174458
  /** @internal */
174154
174459
  onFirstRequestCompleted = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.BeEvent();
174155
174460
  /** @internal */
@@ -174165,7 +174470,17 @@ class MapLayerImageryProvider {
174165
174470
  * @public
174166
174471
  */
174167
174472
  get supportsMapFeatureInfo() { return false; }
174168
- resetStatus() { this.setStatus(MapLayerImageryProviderStatus.Valid); }
174473
+ /** Reset the provider's status to [[MapLayerImageryProviderStatus.Valid]] and clear the list of
174474
+ * [[blockedOrigins]] accumulated while in the [[MapLayerImageryProviderStatus.UntrustedOrigin]] state.
174475
+ * Raises [[onStatusChanged]] if the status actually changes.
174476
+ * Typically called after the user has provided credentials or the application has updated
174477
+ * [[MapLayerFormatRegistry.trustedCredentialsOrigins]], so that subsequent requests are re-attempted.
174478
+ * @beta
174479
+ */
174480
+ resetStatus() {
174481
+ this._blockedOrigins.clear();
174482
+ this.setStatus(MapLayerImageryProviderStatus.Valid);
174483
+ }
174169
174484
  /** @internal */
174170
174485
  get tileSize() { return this._usesCachedTiles ? tileImageSize : untiledImageSize; }
174171
174486
  /** @internal */
@@ -174339,6 +174654,32 @@ class MapLayerImageryProvider {
174339
174654
  (0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.setBasicAuthorization)(headers, this._settings.userName, this._settings.password);
174340
174655
  }
174341
174656
  }
174657
+ /** Returns true if the given URL has the same origin as this layer's settings URL.
174658
+ * Used to avoid leaking credentials to third-party hosts.
174659
+ * @internal
174660
+ */
174661
+ matchesSettingsUrlOrigin(url) {
174662
+ const origin = tryGetOrigin(url);
174663
+ return origin !== undefined && origin === tryGetOrigin(this._settings.url);
174664
+ }
174665
+ /** Returns true if the basic-auth credentials from the layer settings may be attached to a request to the given URL.
174666
+ * Always true unless [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
174667
+ * When enabled, the origin of this layer's settings URL is implicitly trusted (the credentials belong to that
174668
+ * server); other origins must be listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]].
174669
+ * See [[MapLayerFormatRegistry.isCredentialsSharingAllowed]].
174670
+ * @internal
174671
+ */
174672
+ isCredentialsSharingAllowed(url) {
174673
+ return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, this._settings.url);
174674
+ }
174675
+ /** Returns true if a request to the given URL may be retried with browser credentials included
174676
+ * (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
174677
+ * See [[MapLayerFormatRegistry.isSsoAllowed]].
174678
+ * @internal
174679
+ */
174680
+ isSsoAllowed(url) {
174681
+ return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(url);
174682
+ }
174342
174683
  /** @internal */
174343
174684
  async makeTileRequest(url, timeoutMs, authorization) {
174344
174685
  // We want to complete the first request before letting other requests go;
@@ -174358,41 +174699,133 @@ class MapLayerImageryProvider {
174358
174699
  throw new Error("fetch call failed");
174359
174700
  return response;
174360
174701
  }
174702
+ /** Records the given URL's origin and transitions the status to [[MapLayerImageryProviderStatus.UntrustedOrigin]].
174703
+ * Called when a request received an authentication challenge that could not be answered because the origin
174704
+ * is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
174705
+ * Raises [[onStatusChanged]] on the status transition, and again whenever a new origin is added.
174706
+ * @internal
174707
+ */
174708
+ reportBlockedOrigin(url) {
174709
+ const origin = tryGetOrigin(url) ?? url;
174710
+ const isNewOrigin = !this._blockedOrigins.has(origin);
174711
+ this._blockedOrigins.add(origin);
174712
+ if (this._status !== MapLayerImageryProviderStatus.UntrustedOrigin)
174713
+ this.setStatus(MapLayerImageryProviderStatus.UntrustedOrigin);
174714
+ else if (isNewOrigin)
174715
+ this.onStatusChanged.raiseEvent(this); // status unchanged, but a new origin was blocked
174716
+ }
174717
+ /** Logs a warning (once per origin, app-wide) when credentials are sent to an origin that would be blocked
174718
+ * if [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] were enabled.
174719
+ * Helps applications discover the origins they need to whitelist before opting in to the restriction.
174720
+ * See [[MapLayerFormatRegistry.logUntrustedOriginUse]].
174721
+ * @internal
174722
+ */
174723
+ logUntrustedOriginUse(url) {
174724
+ _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(url);
174725
+ }
174726
+ /** The redirect policy to apply to a request that carries browser credentials (see [[includeUserCredentials]]).
174727
+ *
174728
+ * When [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled, redirects are refused
174729
+ * outright (`"error"`). `fetch` cannot be asked to follow only same-origin redirects, and by the time a
174730
+ * followed redirect can be inspected the credentials have already been delivered to the destination — so
174731
+ * refusing is the only way to honour the guarantee that credentials reach none but the origins listed in
174732
+ * [[MapLayerFormatRegistry.trustedCredentialsOrigins]]. Legitimate same-origin redirects fail as a result;
174733
+ * that is the cost of the opt-in restriction.
174734
+ *
174735
+ * When the restriction is disabled (the default), redirects are followed as before and
174736
+ * [[checkCredentialedRedirect]] reports the destination after the fact.
174737
+ * @internal
174738
+ */
174739
+ get credentialedRedirect() {
174740
+ return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
174741
+ }
174742
+ /** Detects that a request carrying browser credentials (see [[includeUserCredentials]]) was transparently
174743
+ * redirected to a different origin, and reports or logs that origin.
174744
+ *
174745
+ * This is a **best-effort, after-the-fact** signal used only while
174746
+ * [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is disabled, where credentialed requests
174747
+ * still follow redirects (see [[credentialedRedirect]]). It cannot prevent the exposure — the credentials
174748
+ * have already been sent — and it does not fire at all when the destination denies CORS, because `fetch`
174749
+ * then rejects instead of returning a `Response`. The destination origin is never latched as SSO-succeeded,
174750
+ * so credentials do not keep flowing to it.
174751
+ * @internal
174752
+ */
174753
+ checkCredentialedRedirect(requestedUrl, response) {
174754
+ const finalOrigin = tryGetOrigin(response.url);
174755
+ if (!response.url || finalOrigin === undefined || finalOrigin === tryGetOrigin(requestedUrl))
174756
+ return;
174757
+ if (!this.isSsoAllowed(response.url))
174758
+ this.reportBlockedOrigin(response.url);
174759
+ else
174760
+ this.logUntrustedOriginUse(response.url); // no-op when the restriction is enabled
174761
+ }
174361
174762
  /** @internal */
174362
174763
  async makeRequest(url, timeoutMs, authorization) {
174363
174764
  let response;
174364
174765
  let headers;
174365
174766
  let hasCreds = false;
174767
+ // Whether this request had basic-auth credentials of its own to offer. Requests carrying a caller-supplied
174768
+ // `authorization` are excluded: those bypass the origin policy entirely.
174769
+ const hasSettingsCreds = !authorization && !!this._settings.userName && !!this._settings.password;
174366
174770
  if (authorization) {
174367
174771
  headers = new Headers();
174368
174772
  headers.set("Authorization", authorization);
174369
174773
  }
174370
- else if (this._settings.userName && this._settings.password) {
174371
- hasCreds = true;
174372
- headers = new Headers();
174373
- this.setRequestAuthorization(headers);
174774
+ else if (hasSettingsCreds) {
174775
+ if (this.isCredentialsSharingAllowed(url)) {
174776
+ hasCreds = true;
174777
+ headers = new Headers();
174778
+ this.setRequestAuthorization(headers);
174779
+ if (!this.matchesSettingsUrlOrigin(url))
174780
+ this.logUntrustedOriginUse(url);
174781
+ }
174374
174782
  }
174783
+ const includeCredentials = this.includeUserCredentials(url);
174375
174784
  const opts = {
174376
174785
  method: "GET",
174377
174786
  headers,
174378
- credentials: this._includeUserCredentials ? "include" : undefined,
174787
+ credentials: includeCredentials ? "include" : undefined,
174788
+ redirect: includeCredentials ? this.credentialedRedirect : undefined,
174379
174789
  };
174380
174790
  if (timeoutMs !== undefined)
174381
174791
  (0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.setRequestTimeout)(opts, timeoutMs);
174382
174792
  response = await fetch(url, opts);
174793
+ if (includeCredentials)
174794
+ this.checkCredentialedRedirect(url, response);
174795
+ // fetch follows redirects transparently, so all trust decisions below target the final
174796
+ // (post-redirect) URL reported by the response, not the URL we asked for.
174797
+ const challengedUrl = response.url || url;
174383
174798
  if (response.status === 401
174384
174799
  && (0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])
174385
- && !this._includeUserCredentials
174800
+ && !includeCredentials
174386
174801
  && !hasCreds) {
174387
- // Removed the previous headers and make sure "include" credentials is set
174388
- opts.headers = undefined;
174389
- opts.credentials = "include";
174390
- // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
174391
- response = await fetch(url, opts);
174392
- if (response.status === 200) {
174393
- this._includeUserCredentials = true; // avoid going through 401 challenges over and over
174802
+ if (this.isSsoAllowed(challengedUrl)) {
174803
+ // Removed the previous headers and make sure "include" credentials is set
174804
+ opts.headers = undefined;
174805
+ opts.credentials = "include";
174806
+ // A Negotiate/NTLM handshake is normally a same-URL 401 round-trip, but in legacy mode we preserve
174807
+ // the previous behavior and allow the browser to follow redirects after the authenticated retry.
174808
+ opts.redirect = _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
174809
+ this.logUntrustedOriginUse(challengedUrl);
174810
+ // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
174811
+ response = await fetch(challengedUrl, opts);
174812
+ if (response.status === 200) {
174813
+ this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
174814
+ }
174815
+ }
174816
+ else {
174817
+ this.reportBlockedOrigin(challengedUrl);
174394
174818
  }
174395
174819
  }
174820
+ else if ((response.status === 401 || response.status === 403) && hasSettingsCreds && !this.isCredentialsSharingAllowed(challengedUrl)) {
174821
+ // Some servers answer an unauthenticated request with 403 (Forbidden) rather than a 401 challenge;
174822
+ // since this request could not present its credentials to the challenging origin, either status most
174823
+ // likely results from that. The permission is recomputed for the challenged URL rather than reusing the
174824
+ // decision made for the requested one: `fetch` strips the Authorization header when it follows a
174825
+ // cross-origin redirect, so a trusted request can still arrive unauthenticated at an untrusted origin,
174826
+ // and conversely a request that started out untrusted may end up at an origin that is trusted.
174827
+ this.reportBlockedOrigin(challengedUrl);
174828
+ }
174396
174829
  return response;
174397
174830
  }
174398
174831
  /** Returns a map layer tile at the specified settings. */
@@ -174423,16 +174856,28 @@ class MapLayerImageryProvider {
174423
174856
  }
174424
174857
  /** @internal */
174425
174858
  async toolTipFromUrl(strings, url) {
174426
- const headers = new Headers();
174427
- this.setRequestAuthorization(headers);
174859
+ let headers;
174860
+ if (this.isCredentialsSharingAllowed(url)) {
174861
+ headers = new Headers();
174862
+ this.setRequestAuthorization(headers);
174863
+ }
174428
174864
  try {
174865
+ const includeCredentials = this.includeUserCredentials(url);
174429
174866
  const response = await fetch(url, {
174430
174867
  method: "GET",
174431
174868
  headers,
174432
- credentials: this._includeUserCredentials ? "include" : undefined,
174869
+ credentials: includeCredentials ? "include" : undefined,
174870
+ redirect: includeCredentials ? this.credentialedRedirect : undefined,
174433
174871
  });
174434
- const text = await response.text();
174435
- if (undefined !== text) {
174872
+ if (includeCredentials)
174873
+ this.checkCredentialedRedirect(url, response);
174874
+ let text = await response.text();
174875
+ if (text) {
174876
+ // Tooltip content (e.g. WMS GetFeatureInfo responses) is rendered as HTML downstream and may
174877
+ // deliberately contain markup; text from origins not trusted for credentials is escaped.
174878
+ // fetch follows redirects transparently, so the text may come from a different origin than requested.
174879
+ if (!this.isCredentialsSharingAllowed(response.url || url))
174880
+ text = escapeHtml(text);
174436
174881
  strings.push(text);
174437
174882
  }
174438
174883
  }
@@ -174612,6 +175057,12 @@ var MapLayerSourceStatus;
174612
175057
  /** Format is not compatible with the URL provided.
174613
175058
  */
174614
175059
  MapLayerSourceStatus[MapLayerSourceStatus["IncompatibleFormat"] = 7] = "IncompatibleFormat";
175060
+ /** Authentication could not be attempted because the source's origin is not trusted
175061
+ * (see [MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]($frontend)). Add the origin to
175062
+ * [MapLayerFormatRegistry.trustedCredentialsOrigins]($frontend) rather than prompting for credentials.
175063
+ * @beta
175064
+ */
175065
+ MapLayerSourceStatus[MapLayerSourceStatus["UntrustedOrigin"] = 8] = "UntrustedOrigin";
174615
175066
  })(MapLayerSourceStatus || (MapLayerSourceStatus = {}));
174616
175067
  /** A source for map layers. These may be catalogued for convenient use by users or applications.
174617
175068
  * @public
@@ -174899,10 +175350,8 @@ class MapLayerTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_3__.T
174899
175350
  const tree = this.treeOwner.tileTree;
174900
175351
  if (undefined === tree || hit.iModel !== tree.iModel || tree.modelId !== hit.sourceId)
174901
175352
  return undefined;
174902
- const strings = [];
174903
- strings.push(`Map Layer: ${this._layerSettings.name}`);
174904
175353
  const div = document.createElement("div");
174905
- div.innerHTML = strings.join("<br>");
175354
+ div.textContent = `Map Layer: ${this._layerSettings.name}`;
174906
175355
  return div;
174907
175356
  }
174908
175357
  decorate(_context) {
@@ -176611,7 +177060,9 @@ class MapTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_7__.TileTr
176611
177060
  let carto;
176612
177061
  const strings = [];
176613
177062
  const getTooltipFunc = async (imageryTreeRef, quadId, cartoGraphic, imageryTree) => {
176614
- strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_4__.IModelApp.localization.getLocalizedString("iModelJs:MapLayers.ImageryLayer")}: ${imageryTreeRef.layerSettings.name}`);
177063
+ // innerHTML is used below because imageryLoader.getToolTip may deliberately supply markup.
177064
+ const layerName = (0,_internal__WEBPACK_IMPORTED_MODULE_7__.escapeHtml)(imageryTreeRef.layerSettings.name);
177065
+ strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_4__.IModelApp.localization.getLocalizedString("iModelJs:MapLayers.ImageryLayer")}: ${layerName}`);
176615
177066
  carto = cartoGraphic;
176616
177067
  await imageryTree.imageryLoader.getToolTip(strings, quadId, cartoGraphic, imageryTree);
176617
177068
  };
@@ -334493,7 +334944,7 @@ var loadLanguages = instance.loadLanguages;
334493
334944
  (module) {
334494
334945
 
334495
334946
  "use strict";
334496
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.13.0-dev.15","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s build:workers && npm run -s copy:draco","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2022 --outDir lib/esm","clean":"rimraf -g lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:draco":"cpx \\"./node_modules/@loaders.gl/draco/dist/libs/*\\" ./lib/public/scripts","docs":"betools docs --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts && npm run -s extract","extract":"betools extract --fileExt=ts --extractFrom=./src/test/example-code --recursive --out=../../generated-docs/extract","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-inline-config -c extraction.eslint.config.js \\"./src/**/*.ts\\" 1>&2","lint":"eslint \\"./src/**/*.ts\\" 1>&2","lint-fix":"eslint --fix -f visualstudio \\"./src/**/*.ts\\" 1>&2","lint-deprecation":"eslint --fix -f visualstudio --no-inline-config -c ../../common/config/eslint/eslint.config.deprecation-policy.js \\"./src/**/*.ts\\"","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run build:test-worker && vitest --run","cover":"npm run build:test-worker && vitest --run","build:test-worker":"vite build --config ./src/test/worker/vite.config.mts 1>&2","build:workers":"rimraf lib/workers/webpack && vite build --config ./src/workers/ImdlParser/vite.config.mts 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@bentley/aec-units-schema":"^1.0.3","@bentley/formats-schema":"^1.0.0","@bentley/units-schema":"^1.0.11","@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*","@itwin/object-storage-core":"^3.0.4","@itwin/eslint-plugin":"^6.0.0","@types/node":"~20.17.0","@types/sinon":"^17.0.2","@vitest/browser-playwright":"^4.1.10","@vitest/coverage-v8":"^4.1.10","cpx2":"^8.0.0","eslint":"^9.31.0","playwright":"~1.56.1","rimraf":"^6.0.1","sinon":"^17.0.2","typescript":"~5.6.2","vite":"^6.4.3","vitest":"^4.1.10","vite-plugin-static-copy":"2.2.0"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"~4.3.4","@loaders.gl/draco":"~4.3.4","fuse.js":"^3.3.0","wms-capabilities":"0.4.0"}}');
334947
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.13.0-dev.17","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s build:workers && npm run -s copy:draco","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2022 --outDir lib/esm","clean":"rimraf -g lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:draco":"cpx \\"./node_modules/@loaders.gl/draco/dist/libs/*\\" ./lib/public/scripts","docs":"betools docs --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts && npm run -s extract","extract":"betools extract --fileExt=ts --extractFrom=./src/test/example-code --recursive --out=../../generated-docs/extract","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-inline-config -c extraction.eslint.config.js \\"./src/**/*.ts\\" 1>&2","lint":"eslint \\"./src/**/*.ts\\" 1>&2","lint-fix":"eslint --fix -f visualstudio \\"./src/**/*.ts\\" 1>&2","lint-deprecation":"eslint --fix -f visualstudio --no-inline-config -c ../../common/config/eslint/eslint.config.deprecation-policy.js \\"./src/**/*.ts\\"","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run build:test-worker && vitest --run","cover":"npm run build:test-worker && vitest --run","build:test-worker":"vite build --config ./src/test/worker/vite.config.mts 1>&2","build:workers":"rimraf lib/workers/webpack && vite build --config ./src/workers/ImdlParser/vite.config.mts 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@bentley/aec-units-schema":"^1.0.3","@bentley/formats-schema":"^1.0.0","@bentley/units-schema":"^1.0.11","@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*","@itwin/object-storage-core":"^3.0.4","@itwin/eslint-plugin":"^6.0.0","@types/node":"~20.17.0","@types/sinon":"^17.0.2","@vitest/browser-playwright":"^4.1.10","@vitest/coverage-v8":"^4.1.10","cpx2":"^8.0.0","eslint":"^9.31.0","playwright":"~1.56.1","rimraf":"^6.0.1","sinon":"^17.0.2","typescript":"~5.6.2","vite":"^6.4.3","vitest":"^4.1.10","vite-plugin-static-copy":"2.2.0"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"~4.3.4","@loaders.gl/draco":"~4.3.4","fuse.js":"^3.3.0","wms-capabilities":"0.4.0"}}');
334497
334948
 
334498
334949
  /***/ }
334499
334950