@itwin/rpcinterface-full-stack-tests 5.13.0-dev.16 → 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.
@@ -111451,6 +111451,8 @@ const COPYRIGHT_NOTICE = `Copyright © 2017-${new Date().getFullYear()} <a href=
111451
111451
 
111452
111452
 
111453
111453
 
111454
+ /** CSS class name applied to the notice element of a logo card created by [[IModelApp.makeLogoCard]]. */
111455
+ const logoCardNoticeClassName = "logo-cards";
111454
111456
  /**
111455
111457
  * Global singleton that connects the user interface with the iTwin.js services. There can be only one IModelApp active in a session. All
111456
111458
  * members of IModelApp are static, and it serves as a singleton object for gaining access to session information.
@@ -111963,10 +111965,21 @@ class IModelApp {
111963
111965
  }
111964
111966
  if (undefined !== opts.notice) {
111965
111967
  if (typeof opts.notice === "string")
111966
- IModelApp.makeHTMLElement("p", { parent: noticeCell, innerHTML: opts.notice, className: "logo-cards" });
111968
+ IModelApp.makeHTMLElement("p", { parent: noticeCell, innerHTML: opts.notice, className: logoCardNoticeClassName });
111967
111969
  else
111968
111970
  noticeCell.appendChild(opts.notice);
111969
111971
  }
111972
+ else if (undefined !== opts.noticeLines) {
111973
+ // A <p> cannot legally contain flow content, so use a <div> when a line is an element.
111974
+ const containerTag = opts.noticeLines.some((line) => typeof line !== "string") ? "div" : "p";
111975
+ const notice = IModelApp.makeHTMLElement(containerTag, { parent: noticeCell, className: logoCardNoticeClassName });
111976
+ opts.noticeLines.forEach((line, index) => {
111977
+ if (index > 0)
111978
+ notice.appendChild(IModelApp.makeHTMLElement("br"));
111979
+ // Strings are appended as text nodes so they are never parsed as HTML.
111980
+ notice.append(line);
111981
+ });
111982
+ }
111970
111983
  return card;
111971
111984
  }
111972
111985
  /** Make the logo card for the library itself. This card gets placed at the top of the stack.
@@ -113533,7 +113546,9 @@ let iModelJsCss = `
113533
113546
 
113534
113547
  .logo-cards {
113535
113548
  position:relative;
113536
- width:100%
113549
+ width:100%;
113550
+ margin-block-start:1em;
113551
+ margin-block-end:1em
113537
113552
  }
113538
113553
 
113539
113554
  .imodeljs-modal-overlay {
@@ -113577,7 +113592,7 @@ let iModelJsCss = `
113577
113592
  max-width: calc(100% - (2 * var(--width-border))) !important;
113578
113593
  width: unset !important;
113579
113594
  }
113580
- .imodeljs-about .logo-card-message p {
113595
+ .imodeljs-about .logo-card-message p, .imodeljs-about .logo-card-message .logo-cards {
113581
113596
  margin-block-end: 1em;
113582
113597
  }
113583
113598
  .imodeljs-about .logo-cards {
@@ -116223,9 +116238,12 @@ class Google3dTilesProvider {
116223
116238
  // Order by most occurances to least
116224
116239
  // See https://developers.google.com/maps/documentation/tile/create-renderer#display-attributions
116225
116240
  const sortedCopyrights = [...copyrightMap.entries()].sort((a, b) => b[1] - a[1]);
116226
- let copyrightMsg = "Data provided by:<br><ul>";
116227
- copyrightMsg += sortedCopyrights.map(([key]) => `<li>${key}</li>`).join("");
116228
- copyrightMsg += "</ul>";
116241
+ const list = document.createElement("ul");
116242
+ for (const [key] of sortedCopyrights) {
116243
+ const item = document.createElement("li");
116244
+ item.textContent = key;
116245
+ list.appendChild(item);
116246
+ }
116229
116247
  const iconSrc = document.createElement("img");
116230
116248
  iconSrc.src = `${_IModelApp__WEBPACK_IMPORTED_MODULE_8__.IModelApp.publicPath}images/GoogleMaps_Logo_Gray.svg`;
116231
116249
  iconSrc.style.padding = "10px 10px 5px 10px";
@@ -116233,7 +116251,7 @@ class Google3dTilesProvider {
116233
116251
  iconSrc,
116234
116252
  iconWidth: 98,
116235
116253
  heading: "Google Photorealistic 3D Tiles",
116236
- notice: copyrightMsg
116254
+ noticeLines: ["Data provided by:", list],
116237
116255
  }));
116238
116256
  }
116239
116257
  }
@@ -136623,7 +136641,7 @@ class GoogleMapsDecorator {
136623
136641
  const copyrightText = sortedCopyrights.map(([key]) => ` • ${key}`).join("");
136624
136642
  // Create and add element, offset to leave space for i.js and Google logos
136625
136643
  const elem = document.createElement("div");
136626
- elem.innerHTML = copyrightText;
136644
+ elem.textContent = copyrightText;
136627
136645
  elem.style.color = "white";
136628
136646
  elem.style.fontSize = "11px";
136629
136647
  elem.style.textWrap = "wrap";
@@ -173930,7 +173948,11 @@ class OrbitGtTreeReference extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.R
173930
173948
  if (this._name)
173931
173949
  strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_6__.IModelApp.localization.getLocalizedString("iModelJs:TooltipInfo.Name")} ${this._name}`);
173932
173950
  const div = document.createElement("div");
173933
- div.innerHTML = strings.join("<br>");
173951
+ strings.forEach((str, index) => {
173952
+ if (index > 0)
173953
+ div.appendChild(document.createElement("br"));
173954
+ div.appendChild(document.createTextNode(str));
173955
+ });
173934
173956
  return div;
173935
173957
  }
173936
173958
  }
@@ -175694,7 +175716,11 @@ class RealityTreeReference extends RealityModelTileTree.Reference {
175694
175716
  if (-1 === key.indexOf("#")) // Avoid internal cesium
175695
175717
  strings.push(`${key}: ${JSON.stringify(batch[key])}`);
175696
175718
  const div = document.createElement("div");
175697
- div.innerHTML = strings.join("<br>");
175719
+ strings.forEach((str, index) => {
175720
+ if (index > 0)
175721
+ div.appendChild(document.createElement("br"));
175722
+ div.appendChild(document.createTextNode(str));
175723
+ });
175698
175724
  return div;
175699
175725
  }
175700
175726
  /** @deprecated in 5.0 - might be removed in next major version. Use [addAttributions] instead. */
@@ -176882,7 +176908,21 @@ class ArcGisUtilities {
176882
176908
  */
176883
176909
  static async validateSource(args) {
176884
176910
  const { source, ignoreCache, capabilitiesFilter } = args;
176885
- const metadata = await this.getServiceJson({ url: source.url, formatId: source.formatId, userName: source.userName, password: source.password, queryParams: source.collectQueryParams(), ignoreCache });
176911
+ let metadata;
176912
+ try {
176913
+ metadata = await this.getServiceJson({ url: source.url, formatId: source.formatId, userName: source.userName, password: source.password, queryParams: source.collectQueryParams(), ignoreCache });
176914
+ }
176915
+ catch (err) {
176916
+ if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError) {
176917
+ let blockedOrigin;
176918
+ try {
176919
+ blockedOrigin = new URL(err.url).origin;
176920
+ }
176921
+ catch { /* non-hierarchical URL */ }
176922
+ return { status: _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
176923
+ }
176924
+ throw err;
176925
+ }
176886
176926
  const json = metadata?.content;
176887
176927
  if (json === undefined) {
176888
176928
  return { status: _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerSourceStatus.InvalidUrl };
@@ -176945,6 +176985,9 @@ class ArcGisUtilities {
176945
176985
  * @param password Password to use for legacy token based security
176946
176986
  * @param ignoreCache Flag to skip cache lookup (i.e. force a new server request)
176947
176987
  * @param requireToken Flag to indicate if a token is required
176988
+ * @throws [[MapLayerUntrustedOriginError]] if an NTLM/Negotiate challenge could not be answered because
176989
+ * the URL's origin is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]);
176990
+ * all other errors are caught and reported by returning `undefined`.
176948
176991
  */
176949
176992
  static async getServiceJson(args) {
176950
176993
  const { url, formatId, userName, password, queryParams, ignoreCache, requireToken } = args;
@@ -176980,8 +177023,17 @@ class ArcGisUtilities {
176980
177023
  }
176981
177024
  let response = await fetch(tmpUrl, { method: "GET" });
176982
177025
  if (response.status === 401 && !requireToken && (0,_request_utils__WEBPACK_IMPORTED_MODULE_3__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
176983
- // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
176984
- response = await fetch(tmpUrl, { method: "GET", credentials: "include" });
177026
+ // fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
177027
+ const challengedUrl = response.url || tmpUrl.toString();
177028
+ if (!_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(challengedUrl))
177029
+ throw new _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError(challengedUrl);
177030
+ _IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(challengedUrl);
177031
+ // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication).
177032
+ response = await fetch(challengedUrl, {
177033
+ method: "GET",
177034
+ credentials: "include",
177035
+ redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
177036
+ });
176985
177037
  }
176986
177038
  // Append security token when corresponding error code is returned by ArcGIS service
176987
177039
  let errorCode = await ArcGisUtilities.checkForResponseErrorCode(response);
@@ -177003,8 +177055,10 @@ class ArcGisUtilities {
177003
177055
  ArcGisUtilities._serviceCache.set(url, (errorCode === undefined ? info : undefined));
177004
177056
  return info; // Always return json, even though it contains an error code.
177005
177057
  }
177006
- catch {
177058
+ catch (err) {
177007
177059
  ArcGisUtilities._serviceCache.set(url, undefined);
177060
+ if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError)
177061
+ throw err; // propagate so callers can report the blocked origin
177008
177062
  return undefined;
177009
177063
  }
177010
177064
  }
@@ -177166,7 +177220,9 @@ class ArcGISImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE_0__.
177166
177220
  try {
177167
177221
  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() });
177168
177222
  }
177169
- catch {
177223
+ catch (err) {
177224
+ if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError)
177225
+ this.reportBlockedOrigin(err.url);
177170
177226
  }
177171
177227
  if (metadata && metadata.accessTokenRequired) {
177172
177228
  const accessClient = _IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.mapLayerFormatRegistry.getAccessClient(this._settings.formatId);
@@ -177214,12 +177270,32 @@ class ArcGISImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE_0__.
177214
177270
  await this._firstRequestPromise;
177215
177271
  let response;
177216
177272
  try {
177217
- response = await fetch(urlObj, { ...options, credentials: this._includeUserCredentials ? "include" : undefined });
177273
+ const requestUrl = urlObj.toString();
177274
+ const includeCredentials = this.includeUserCredentials(requestUrl);
177275
+ response = await fetch(urlObj, {
177276
+ ...options,
177277
+ credentials: includeCredentials ? "include" : undefined,
177278
+ redirect: includeCredentials ? this.credentialedRedirect : options?.redirect,
177279
+ });
177280
+ if (includeCredentials)
177281
+ this.checkCredentialedRedirect(requestUrl, response);
177218
177282
  if (response.status === 401 && !this._lastAccessToken && (0,_request_utils__WEBPACK_IMPORTED_MODULE_3__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
177219
- // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
177220
- response = await fetch(urlObj, { ...options, credentials: "include" });
177221
- if (response.status === 200) {
177222
- this._includeUserCredentials = true; // avoid going through 401 challenges over and over
177283
+ // fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
177284
+ const challengedUrl = response.url || requestUrl;
177285
+ if (this.isSsoAllowed(challengedUrl)) {
177286
+ // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication).
177287
+ this.logUntrustedOriginUse(challengedUrl);
177288
+ response = await fetch(challengedUrl, {
177289
+ ...options,
177290
+ credentials: "include",
177291
+ redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
177292
+ });
177293
+ if (response.status === 200) {
177294
+ this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
177295
+ }
177296
+ }
177297
+ else {
177298
+ this.reportBlockedOrigin(challengedUrl);
177223
177299
  }
177224
177300
  }
177225
177301
  if ((this._lastAccessToken && response.status === 400)
@@ -177432,8 +177508,12 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
177432
177508
  }
177433
177509
  async initialize() {
177434
177510
  const metadata = await this.getServiceJson();
177435
- if (metadata?.content === undefined)
177511
+ if (metadata?.content === undefined) {
177512
+ // By returning (i.e., not throwing), we ensure the tile tree gets created and the current provider is preserved to report status.
177513
+ if (this.status === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerImageryProviderStatus.UntrustedOrigin)
177514
+ return;
177436
177515
  throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_0__.ServerError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_5__.IModelStatus.ValidationFailed, "");
177516
+ }
177437
177517
  const json = metadata.content;
177438
177518
  if (json?.error?.code === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.ArcGisErrorCode.TokenRequired
177439
177519
  || json?.error?.code === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.ArcGisErrorCode.InvalidToken
@@ -177518,7 +177598,7 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
177518
177598
  addLogoCards(cards) {
177519
177599
  if (!cards.dataset.arcGisLogoCard) {
177520
177600
  cards.dataset.arcGisLogoCard = "true";
177521
- cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.makeLogoCard({ heading: "ArcGIS", notice: this._copyrightText }));
177601
+ cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.makeLogoCard({ heading: "ArcGIS", noticeLines: [this._copyrightText] }));
177522
177602
  }
177523
177603
  }
177524
177604
  async addAttributions(cards, _vp) {
@@ -177559,7 +177639,7 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
177559
177639
  if (json && Array.isArray(json.results)) {
177560
177640
  for (const result of json.results) {
177561
177641
  if (result.attributes !== undefined && result.attributes[result.displayFieldName] !== undefined) {
177562
- const thisString = `${result.displayFieldName}: ${result.attributes[result.displayFieldName]}`;
177642
+ 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]))}`;
177563
177643
  if (!stringSet.has(thisString)) {
177564
177644
  strings.push(thisString);
177565
177645
  stringSet.add(thisString);
@@ -177875,13 +177955,7 @@ class BingMapsImageryLayerProvider extends _tile_internal__WEBPACK_IMPORTED_MODU
177875
177955
  const copyrights = [];
177876
177956
  for (const match of matchingAttributions)
177877
177957
  copyrights.push(match.copyrightMessage);
177878
- let copyrightMsg = "";
177879
- for (let i = 0; i < copyrights.length; ++i) {
177880
- if (i > 0)
177881
- copyrightMsg += "<br>";
177882
- copyrightMsg += copyrights[i];
177883
- }
177884
- 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 }));
177958
+ 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 }));
177885
177959
  }
177886
177960
  async addAttributions(cards, vp) {
177887
177961
  // eslint-disable-next-line @typescript-eslint/no-deprecated
@@ -178490,7 +178564,10 @@ class WmsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE
178490
178564
  // Don't throw error if unauthorized status:
178491
178565
  // We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
178492
178566
  // When credentials will be provided, a new provider will be created, and initialization should be fine.
178493
- if (error?.status === 401) {
178567
+ if (error instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError) {
178568
+ this.reportBlockedOrigin(error.url);
178569
+ }
178570
+ else if (error?.status === 401) {
178494
178571
  this.setStatus(_tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerImageryProviderStatus.RequireAuth);
178495
178572
  }
178496
178573
  else {
@@ -178652,7 +178729,8 @@ class WmtsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODUL
178652
178729
  }
178653
178730
  async initialize() {
178654
178731
  try {
178655
- this._capabilities = await _tile_internal__WEBPACK_IMPORTED_MODULE_2__.WmtsCapabilities.create(this._baseUrl);
178732
+ const credentials = (this._settings.userName && this._settings.password ? { user: this._settings.userName, password: this._settings.password } : undefined);
178733
+ this._capabilities = await _tile_internal__WEBPACK_IMPORTED_MODULE_2__.WmtsCapabilities.create(this._baseUrl, credentials);
178656
178734
  this.initPreferredTileMatrixSet();
178657
178735
  this.initPreferredStyle();
178658
178736
  this.initDisplayedLayer();
@@ -178665,7 +178743,10 @@ class WmtsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODUL
178665
178743
  // Don't throw error if unauthorized status:
178666
178744
  // We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
178667
178745
  // When credentials will be provided, a new provider will be created, and initialization should be fine.
178668
- if (error?.status === 401) {
178746
+ if (error instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerUntrustedOriginError) {
178747
+ this.reportBlockedOrigin(error.url);
178748
+ }
178749
+ else if (error?.status === 401) {
178669
178750
  this.setStatus(_tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerImageryProviderStatus.RequireAuth);
178670
178751
  }
178671
178752
  else {
@@ -179476,14 +179557,18 @@ __webpack_require__.r(__webpack_exports__);
179476
179557
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
179477
179558
  /* harmony export */ WmsUtilities: () => (/* binding */ WmsUtilities)
179478
179559
  /* harmony export */ });
179479
- /* harmony import */ var _request_Request__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../request/Request */ "../../core/frontend/lib/esm/request/Request.js");
179480
- /* harmony import */ var _request_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../request/utils */ "../../core/frontend/lib/esm/request/utils.js");
179560
+ /* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
179561
+ /* harmony import */ var _request_Request__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../request/Request */ "../../core/frontend/lib/esm/request/Request.js");
179562
+ /* harmony import */ var _request_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../request/utils */ "../../core/frontend/lib/esm/request/utils.js");
179563
+ /* harmony import */ var _tile_internal__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../tile/internal */ "../../core/frontend/lib/esm/tile/internal.js");
179481
179564
  /*---------------------------------------------------------------------------------------------
179482
179565
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
179483
179566
  * See LICENSE.md in the project root for license terms and full copyright notice.
179484
179567
  *--------------------------------------------------------------------------------------------*/
179485
179568
 
179486
179569
 
179570
+
179571
+
179487
179572
  /** @packageDocumentation
179488
179573
  * @module Tiles
179489
179574
  */
@@ -179500,16 +179585,35 @@ class WmsUtilities {
179500
179585
  static async fetchXml(url, credentials) {
179501
179586
  let headers;
179502
179587
  if (credentials && credentials.user && credentials.password) {
179503
- headers = new Headers();
179504
- (0,_request_utils__WEBPACK_IMPORTED_MODULE_1__.setBasicAuthorization)(headers, credentials);
179588
+ // Basic credentials are considered settings-derived credentials for this source. When the registry is
179589
+ // enforcing trusted origins, the source URL itself is the only implicitly trusted origin for basic auth;
179590
+ // opaque/custom-protocol URLs have no network origin and must therefore be treated as untrusted.
179591
+ const allowBasicAuth = !_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins
179592
+ || _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, url);
179593
+ if (allowBasicAuth) {
179594
+ headers = new Headers();
179595
+ (0,_request_utils__WEBPACK_IMPORTED_MODULE_2__.setBasicAuthorization)(headers, credentials);
179596
+ }
179505
179597
  }
179506
179598
  let response = await fetch(url, { method: "GET", headers });
179507
- if (!credentials && response.status === 401 && (0,_request_utils__WEBPACK_IMPORTED_MODULE_1__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
179508
- // We got a http 401 challenge, lets try SSO (i.e. Windows Authentication)
179509
- response = await fetch(url, { method: "GET", credentials: "include" });
179599
+ if (!headers && credentials && credentials.user && credentials.password && (response.status === 401 || response.status === 403)) {
179600
+ throw new _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError(url);
179601
+ }
179602
+ if (!credentials && response.status === 401 && (0,_request_utils__WEBPACK_IMPORTED_MODULE_2__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
179603
+ // fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
179604
+ const challengedUrl = response.url || url;
179605
+ if (!_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(challengedUrl))
179606
+ throw new _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError(challengedUrl);
179607
+ _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(challengedUrl);
179608
+ // We got a http 401 challenge, lets try SSO (i.e. Windows Authentication).
179609
+ response = await fetch(challengedUrl, {
179610
+ method: "GET",
179611
+ credentials: "include",
179612
+ redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
179613
+ });
179510
179614
  }
179511
179615
  if (response.status !== 200)
179512
- throw new _request_Request__WEBPACK_IMPORTED_MODULE_0__.HttpResponseError(response.status, await response.text());
179616
+ throw new _request_Request__WEBPACK_IMPORTED_MODULE_1__.HttpResponseError(response.status, await response.text());
179513
179617
  return response.text();
179514
179618
  }
179515
179619
  }
@@ -191923,6 +192027,7 @@ __webpack_require__.r(__webpack_exports__);
191923
192027
  /* harmony export */ MapLayerSourceStatus: () => (/* reexport safe */ _map_MapLayerSources__WEBPACK_IMPORTED_MODULE_86__.MapLayerSourceStatus),
191924
192028
  /* harmony export */ MapLayerSources: () => (/* reexport safe */ _map_MapLayerSources__WEBPACK_IMPORTED_MODULE_86__.MapLayerSources),
191925
192029
  /* harmony export */ MapLayerTileTreeReference: () => (/* reexport safe */ _map_MapLayerTileTreeReference__WEBPACK_IMPORTED_MODULE_64__.MapLayerTileTreeReference),
192030
+ /* harmony export */ MapLayerUntrustedOriginError: () => (/* reexport safe */ _map_MapLayerFormatRegistry__WEBPACK_IMPORTED_MODULE_42__.MapLayerUntrustedOriginError),
191926
192031
  /* harmony export */ MapTile: () => (/* reexport safe */ _map_MapTile__WEBPACK_IMPORTED_MODULE_70__.MapTile),
191927
192032
  /* harmony export */ MapTileLoader: () => (/* reexport safe */ _internal_tile_map_MapTileLoader__WEBPACK_IMPORTED_MODULE_72__.MapTileLoader),
191928
192033
  /* harmony export */ MapTileProjection: () => (/* reexport safe */ _map_MapTile__WEBPACK_IMPORTED_MODULE_70__.MapTileProjection),
@@ -192018,6 +192123,7 @@ __webpack_require__.r(__webpack_exports__);
192018
192123
  /* harmony export */ decodeMeshoptBuffer: () => (/* reexport safe */ _internal_tile_MeshoptCompression__WEBPACK_IMPORTED_MODULE_93__.decodeMeshoptBuffer),
192019
192124
  /* harmony export */ deflateCoordinates: () => (/* reexport safe */ _internal_tile_map_ImageryProviders_CoordinatesUtils__WEBPACK_IMPORTED_MODULE_47__.deflateCoordinates),
192020
192125
  /* harmony export */ disposeTileTreesForGeometricModels: () => (/* reexport safe */ _internal_tile_PrimaryTileTree__WEBPACK_IMPORTED_MODULE_82__.disposeTileTreesForGeometricModels),
192126
+ /* harmony export */ escapeHtml: () => (/* reexport safe */ _map_MapLayerImageryProvider__WEBPACK_IMPORTED_MODULE_49__.escapeHtml),
192021
192127
  /* harmony export */ getCesiumAccessClient: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAccessClient),
192022
192128
  /* harmony export */ getCesiumAccessTokenAndEndpointUrl: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAccessTokenAndEndpointUrl),
192023
192129
  /* harmony export */ getCesiumAssetUrl: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAssetUrl),
@@ -192037,7 +192143,8 @@ __webpack_require__.r(__webpack_exports__);
192037
192143
  /* harmony export */ readImdlContent: () => (/* reexport safe */ _ImdlReader__WEBPACK_IMPORTED_MODULE_35__.readImdlContent),
192038
192144
  /* harmony export */ readPntsColors: () => (/* reexport safe */ _internal_tile_PntsReader__WEBPACK_IMPORTED_MODULE_76__.readPntsColors),
192039
192145
  /* harmony export */ readPointCloudTileContent: () => (/* reexport safe */ _internal_tile_PntsReader__WEBPACK_IMPORTED_MODULE_76__.readPointCloudTileContent),
192040
- /* harmony export */ tileTreeReferenceFromRenderGraphic: () => (/* reexport safe */ _RenderGraphicTileTree__WEBPACK_IMPORTED_MODULE_78__.tileTreeReferenceFromRenderGraphic)
192146
+ /* harmony export */ tileTreeReferenceFromRenderGraphic: () => (/* reexport safe */ _RenderGraphicTileTree__WEBPACK_IMPORTED_MODULE_78__.tileTreeReferenceFromRenderGraphic),
192147
+ /* harmony export */ tryGetOrigin: () => (/* reexport safe */ _map_MapLayerImageryProvider__WEBPACK_IMPORTED_MODULE_49__.tryGetOrigin)
192041
192148
  /* harmony export */ });
192042
192149
  /* harmony import */ var _internal_tile_ViewFlagOverrides__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../internal/tile/ViewFlagOverrides */ "../../core/frontend/lib/esm/internal/tile/ViewFlagOverrides.js");
192043
192150
  /* harmony import */ var _map_MapCartoRectangle__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./map/MapCartoRectangle */ "../../core/frontend/lib/esm/tile/map/MapCartoRectangle.js");
@@ -193736,7 +193843,8 @@ __webpack_require__.r(__webpack_exports__);
193736
193843
  __webpack_require__.r(__webpack_exports__);
193737
193844
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
193738
193845
  /* harmony export */ MapLayerFormat: () => (/* binding */ MapLayerFormat),
193739
- /* harmony export */ MapLayerFormatRegistry: () => (/* binding */ MapLayerFormatRegistry)
193846
+ /* harmony export */ MapLayerFormatRegistry: () => (/* binding */ MapLayerFormatRegistry),
193847
+ /* harmony export */ MapLayerUntrustedOriginError: () => (/* binding */ MapLayerUntrustedOriginError)
193740
193848
  /* harmony export */ });
193741
193849
  /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
193742
193850
  /* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
@@ -193751,7 +193859,7 @@ __webpack_require__.r(__webpack_exports__);
193751
193859
 
193752
193860
 
193753
193861
 
193754
- const loggerCategory = "ArcGISFeatureProvider";
193862
+ const loggerCategory = "MapLayerFormatRegistry";
193755
193863
  /**
193756
193864
  * Class representing a map-layer format.
193757
193865
  * Each format has it's unique 'formatId' string, used to uniquely identify a format in the [[MapLayerFormatRegistry]].
@@ -193800,16 +193908,127 @@ class MapLayerFormat {
193800
193908
  return undefined;
193801
193909
  }
193802
193910
  }
193911
+ /** Error thrown when an NTLM or Negotiate http 401 challenge could not be answered because the request
193912
+ * URL's origin is not listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]]
193913
+ * (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
193914
+ * Thrown by the static map-layer utilities (e.g. capabilities / service-metadata fetches) that have no
193915
+ * provider instance on which to report the blocked origin; callers convert it to
193916
+ * [[MapLayerImageryProviderStatus.UntrustedOrigin]] (provider initialization) or
193917
+ * [[MapLayerSourceStatus.UntrustedOrigin]] (source validation).
193918
+ * @internal
193919
+ */
193920
+ class MapLayerUntrustedOriginError extends Error {
193921
+ /** The URL of the request whose authentication challenge was left unanswered. */
193922
+ url;
193923
+ constructor(url) {
193924
+ super(`Authentication blocked: origin of '${url}' is not listed in MapLayerFormatRegistry.trustedCredentialsOrigins`);
193925
+ this.url = url;
193926
+ }
193927
+ }
193803
193928
  /**
193804
193929
  * A registry of MapLayerFormats identified by their unique format IDs. The registry can be accessed via [[IModelApp.mapLayerFormatRegistry]].
193805
193930
  * @public
193806
193931
  */
193807
193932
  class MapLayerFormatRegistry {
193808
193933
  _configOptions;
193934
+ _trustedCredentialsOrigins = [];
193935
+ /** Opt-in enforcement of origin restrictions on map-layer credentials.
193936
+ * When enabled, map layer providers:
193937
+ * - attach the basic-auth credentials stored in the layer settings only to requests targeting the origin
193938
+ * of the layer's settings URL or an origin listed in [[trustedCredentialsOrigins]];
193939
+ * - retry a request with browser credentials included (i.e. SSO / Windows Authentication) after an NTLM
193940
+ * or Negotiate http 401 challenge only for origins explicitly listed in [[trustedCredentialsOrigins]]
193941
+ * (the settings-URL origin is NOT implicitly trusted for SSO, since map-layer URLs may originate from
193942
+ * untrusted user input while SSO shares the user's ambient identity).
193943
+ * Default is false, preserving the legacy behavior of sending credentials to any request URL.
193944
+ * @beta
193945
+ */
193946
+ restrictCredentialsToTrustedOrigins = false;
193809
193947
  constructor(opts) {
193810
193948
  this._configOptions = opts ?? {};
193811
193949
  _internal__WEBPACK_IMPORTED_MODULE_2__.internalMapLayerImageryFormats.forEach((format) => this.register(format));
193812
193950
  }
193951
+ /** Origins (e.g. "https://tiles.example.com") to which map layer providers may send credentials —
193952
+ * both the basic-auth credentials stored in the layer settings and browser credentials for
193953
+ * SSO (i.e. Windows Authentication) retries after an NTLM or Negotiate http 401 challenge.
193954
+ * Only enforced when [[restrictCredentialsToTrustedOrigins]] is enabled.
193955
+ * For basic-auth, the origin of each map layer's settings URL is always implicitly trusted; for SSO,
193956
+ * origins must be explicitly listed here.
193957
+ * Entries are normalized to their origin (scheme + host + port); only `http:` and `https:` URLs are accepted,
193958
+ * and any other entry is ignored and logged. Opaque schemes such as `file:`, `data:`, `about:` and custom
193959
+ * Electron protocols are rejected because they all share the same serialized origin, so trusting one would
193960
+ * trust every other.
193961
+ * @beta
193962
+ */
193963
+ get trustedCredentialsOrigins() {
193964
+ return this._trustedCredentialsOrigins;
193965
+ }
193966
+ set trustedCredentialsOrigins(origins) {
193967
+ const normalized = [];
193968
+ for (const entry of origins) {
193969
+ const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(entry);
193970
+ if (origin !== undefined)
193971
+ normalized.push(origin);
193972
+ else
193973
+ _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(loggerCategory, `trustedCredentialsOrigins: ignoring '${entry}'; entries must be http or https URLs.`);
193974
+ }
193975
+ this._trustedCredentialsOrigins = normalized;
193976
+ }
193977
+ /** Returns true if a request to the given URL may be retried with browser credentials included
193978
+ * (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
193979
+ * Always true unless [[restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
193980
+ * When enabled, the URL's origin must be explicitly listed in [[trustedCredentialsOrigins]];
193981
+ * unlike basic-auth, the settings-URL origin is NOT implicitly trusted because SSO shares the user's
193982
+ * ambient identity, and map-layer URLs may originate from untrusted user input.
193983
+ * @internal
193984
+ */
193985
+ isSsoAllowed(url) {
193986
+ if (!this.restrictCredentialsToTrustedOrigins)
193987
+ return true;
193988
+ const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url);
193989
+ // Entries are normalized to their origin by the [[trustedCredentialsOrigins]] setter.
193990
+ return origin !== undefined && this._trustedCredentialsOrigins.includes(origin);
193991
+ }
193992
+ /** Returns true if the basic-auth credentials belonging to a map-layer source or settings URL may be
193993
+ * attached to a request to the given URL. Always true unless [[restrictCredentialsToTrustedOrigins]]
193994
+ * is enabled (opt-in). When enabled, the origin of `settingsUrl` is implicitly trusted (the credentials
193995
+ * belong to that server); any other origin must be listed in [[trustedCredentialsOrigins]].
193996
+ * @internal
193997
+ */
193998
+ isCredentialsSharingAllowed(url, settingsUrl) {
193999
+ if (!this.restrictCredentialsToTrustedOrigins)
194000
+ return true;
194001
+ const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url);
194002
+ if (origin === undefined)
194003
+ return false;
194004
+ if (origin === (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(settingsUrl))
194005
+ return true;
194006
+ // Entries are normalized to their origin by the [[trustedCredentialsOrigins]] setter.
194007
+ return this._trustedCredentialsOrigins.includes(origin);
194008
+ }
194009
+ /** Origins for which a "credentials sent to untrusted origin" warning was already logged;
194010
+ * used to log the discovery warning only once per origin.
194011
+ */
194012
+ _untrustedUseLogged = new Set();
194013
+ /** Logs a warning (once per origin) when credentials are sent to an origin that would be blocked
194014
+ * if [[restrictCredentialsToTrustedOrigins]] were enabled.
194015
+ * Helps applications discover the origins they need to whitelist before opting in to the restriction.
194016
+ * If `settingsUrl` is supplied, requests sharing its origin are not logged, since that origin is
194017
+ * implicitly trusted for basic-auth.
194018
+ * @internal
194019
+ */
194020
+ logUntrustedOriginUse(url, settingsUrl) {
194021
+ if (this.restrictCredentialsToTrustedOrigins)
194022
+ return; // restriction active; nothing to preview
194023
+ const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url) ?? url;
194024
+ if (settingsUrl !== undefined && origin === (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(settingsUrl))
194025
+ return; // implicitly trusted for basic-auth
194026
+ if (this._untrustedUseLogged.has(origin) || this._trustedCredentialsOrigins.includes(origin))
194027
+ return;
194028
+ this._untrustedUseLogged.add(origin);
194029
+ _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(loggerCategory, `Credentials sent to origin '${origin}' which is not in MapLayerFormatRegistry.trustedCredentialsOrigins; `
194030
+ + "this request would be blocked if restrictCredentialsToTrustedOrigins were enabled.");
194031
+ }
193813
194032
  _formats = new Map();
193814
194033
  isRegistered(formatId) { return this._formats.get(formatId) !== undefined; }
193815
194034
  register(formatClass) {
@@ -193975,6 +194194,14 @@ class WmsMapLayerFormat extends ImageryMapLayerFormat {
193975
194194
  return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.Valid, subLayers };
193976
194195
  }
193977
194196
  catch (err) {
194197
+ if (err instanceof _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError) {
194198
+ let blockedOrigin;
194199
+ try {
194200
+ blockedOrigin = new URL(err.url).origin;
194201
+ }
194202
+ catch { /* non-hierarchical URL */ }
194203
+ return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
194204
+ }
193978
194205
  let status = _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidUrl;
193979
194206
  if (err?.status === 401) {
193980
194207
  status = ((userName && password) ? _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidCredentials : _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.RequireAuth);
@@ -194040,6 +194267,14 @@ class WmtsMapLayerFormat extends ImageryMapLayerFormat {
194040
194267
  return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.Valid, subLayers };
194041
194268
  }
194042
194269
  catch (err) {
194270
+ if (err instanceof _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError) {
194271
+ let blockedOrigin;
194272
+ try {
194273
+ blockedOrigin = new URL(err.url).origin;
194274
+ }
194275
+ catch { /* non-hierarchical URL */ }
194276
+ return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
194277
+ }
194043
194278
  let status = _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidUrl;
194044
194279
  if (err?.status === 401) {
194045
194280
  status = ((userName && password) ? _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidCredentials : _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.RequireAuth);
@@ -194104,7 +194339,9 @@ const internalMapLayerImageryFormats = [WmsMapLayerFormat, WmtsMapLayerFormat, A
194104
194339
  __webpack_require__.r(__webpack_exports__);
194105
194340
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
194106
194341
  /* harmony export */ MapLayerImageryProvider: () => (/* binding */ MapLayerImageryProvider),
194107
- /* harmony export */ MapLayerImageryProviderStatus: () => (/* binding */ MapLayerImageryProviderStatus)
194342
+ /* harmony export */ MapLayerImageryProviderStatus: () => (/* binding */ MapLayerImageryProviderStatus),
194343
+ /* harmony export */ escapeHtml: () => (/* binding */ escapeHtml),
194344
+ /* harmony export */ tryGetOrigin: () => (/* binding */ tryGetOrigin)
194108
194345
  /* harmony export */ });
194109
194346
  /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
194110
194347
  /* harmony import */ var _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @itwin/core-common */ "../../core/common/lib/esm/core-common.js");
@@ -194131,6 +194368,34 @@ __webpack_require__.r(__webpack_exports__);
194131
194368
  const tileImageSize = 256, untiledImageSize = 256;
194132
194369
  const earthRadius = 6378137;
194133
194370
  const doDebugToolTips = false;
194371
+ /** Escapes HTML metacharacters so the text renders literally when assigned to `innerHTML`.
194372
+ * Use for any server- or user-supplied string that ends up in the map tooltip, which is rendered
194373
+ * as HTML by [[MapLayerTileTreeReference.getToolTip]].
194374
+ * @internal
194375
+ */
194376
+ function escapeHtml(text) {
194377
+ return text.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
194378
+ }
194379
+ /** Returns the origin (scheme + host + port) of the given URL, or undefined if it cannot be parsed or does
194380
+ * not denote a distinct network origin.
194381
+ *
194382
+ * Only `http:` and `https:` URLs yield an origin. Every other scheme is rejected because opaque URLs
194383
+ * — `file:`, `data:`, `about:`, `blob:null`, and the custom protocols Electron hosts commonly register —
194384
+ * all serialize to the literal string `"null"`. Comparing those would make unrelated URLs look same-origin,
194385
+ * so a single trusted entry could unlock all of them. Callers use this for credential-trust decisions, and
194386
+ * returning `undefined` keeps those decisions fail-closed.
194387
+ * @internal
194388
+ */
194389
+ function tryGetOrigin(url) {
194390
+ let parsed;
194391
+ try {
194392
+ parsed = new URL(url);
194393
+ }
194394
+ catch {
194395
+ return undefined;
194396
+ }
194397
+ return (parsed.protocol === "http:" || parsed.protocol === "https:") ? parsed.origin : undefined;
194398
+ }
194134
194399
  /** The status of the map layer imagery provider that lets you know if authentication is needed to request tiles.
194135
194400
  * @public
194136
194401
  */
@@ -194138,6 +194403,12 @@ var MapLayerImageryProviderStatus;
194138
194403
  (function (MapLayerImageryProviderStatus) {
194139
194404
  MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["Valid"] = 0] = "Valid";
194140
194405
  MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["RequireAuth"] = 1] = "RequireAuth";
194406
+ /** A request received an authentication challenge, but credentials were withheld because the request origin
194407
+ * is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
194408
+ * The blocked origins are available via [[MapLayerImageryProvider.blockedOrigins]].
194409
+ * @beta
194410
+ */
194411
+ MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["UntrustedOrigin"] = 2] = "UntrustedOrigin";
194141
194412
  })(MapLayerImageryProviderStatus || (MapLayerImageryProviderStatus = {}));
194142
194413
  /** Abstract class for map layer imagery providers.
194143
194414
  * 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.
@@ -194155,7 +194426,41 @@ class MapLayerImageryProvider {
194155
194426
  /** @internal */
194156
194427
  _status = MapLayerImageryProviderStatus.Valid;
194157
194428
  /** @internal */
194158
- _includeUserCredentials = false;
194429
+ _blockedOrigins = new Set();
194430
+ /** Origins of requests for which credentials were withheld because they are not trusted
194431
+ * (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
194432
+ * Populated when [[status]] transitions to [[MapLayerImageryProviderStatus.UntrustedOrigin]];
194433
+ * [[onStatusChanged]] is raised again each time a new origin is added. Cleared by [[resetStatus]].
194434
+ * @beta
194435
+ */
194436
+ get blockedOrigins() { return [...this._blockedOrigins]; }
194437
+ /** Origins for which a previous SSO handshake (i.e. Windows Authentication) succeeded.
194438
+ * Browser credentials are only included for subsequent requests targeting these origins,
194439
+ * so that a successful handshake with one host does not leak credentials to other hosts
194440
+ * this provider may contact.
194441
+ * @internal
194442
+ */
194443
+ _ssoSucceededOrigins = new Set();
194444
+ /** Returns true if browser credentials should be included for the given URL because a previous
194445
+ * SSO handshake succeeded for its origin AND the origin is still allowed by the current policy
194446
+ * (see [[MapLayerFormatRegistry.isSsoAllowed]]). Re-checking the policy ensures a handshake recorded
194447
+ * while enforcement was disabled — or before an origin was removed from
194448
+ * [[MapLayerFormatRegistry.trustedCredentialsOrigins]] — does not keep latching credentials on.
194449
+ * @internal
194450
+ */
194451
+ includeUserCredentials(url) {
194452
+ const origin = tryGetOrigin(url);
194453
+ return origin !== undefined && this._ssoSucceededOrigins.has(origin) && this.isSsoAllowed(url);
194454
+ }
194455
+ /** Records that an SSO handshake succeeded for the given URL's origin, so subsequent requests
194456
+ * to that origin include browser credentials without going through another 401 challenge.
194457
+ * @internal
194458
+ */
194459
+ recordSsoSucceeded(url) {
194460
+ const origin = tryGetOrigin(url);
194461
+ if (origin !== undefined)
194462
+ this._ssoSucceededOrigins.add(origin);
194463
+ }
194159
194464
  /** @internal */
194160
194465
  onFirstRequestCompleted = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.BeEvent();
194161
194466
  /** @internal */
@@ -194171,7 +194476,17 @@ class MapLayerImageryProvider {
194171
194476
  * @public
194172
194477
  */
194173
194478
  get supportsMapFeatureInfo() { return false; }
194174
- resetStatus() { this.setStatus(MapLayerImageryProviderStatus.Valid); }
194479
+ /** Reset the provider's status to [[MapLayerImageryProviderStatus.Valid]] and clear the list of
194480
+ * [[blockedOrigins]] accumulated while in the [[MapLayerImageryProviderStatus.UntrustedOrigin]] state.
194481
+ * Raises [[onStatusChanged]] if the status actually changes.
194482
+ * Typically called after the user has provided credentials or the application has updated
194483
+ * [[MapLayerFormatRegistry.trustedCredentialsOrigins]], so that subsequent requests are re-attempted.
194484
+ * @beta
194485
+ */
194486
+ resetStatus() {
194487
+ this._blockedOrigins.clear();
194488
+ this.setStatus(MapLayerImageryProviderStatus.Valid);
194489
+ }
194175
194490
  /** @internal */
194176
194491
  get tileSize() { return this._usesCachedTiles ? tileImageSize : untiledImageSize; }
194177
194492
  /** @internal */
@@ -194345,6 +194660,32 @@ class MapLayerImageryProvider {
194345
194660
  (0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.setBasicAuthorization)(headers, this._settings.userName, this._settings.password);
194346
194661
  }
194347
194662
  }
194663
+ /** Returns true if the given URL has the same origin as this layer's settings URL.
194664
+ * Used to avoid leaking credentials to third-party hosts.
194665
+ * @internal
194666
+ */
194667
+ matchesSettingsUrlOrigin(url) {
194668
+ const origin = tryGetOrigin(url);
194669
+ return origin !== undefined && origin === tryGetOrigin(this._settings.url);
194670
+ }
194671
+ /** Returns true if the basic-auth credentials from the layer settings may be attached to a request to the given URL.
194672
+ * Always true unless [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
194673
+ * When enabled, the origin of this layer's settings URL is implicitly trusted (the credentials belong to that
194674
+ * server); other origins must be listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]].
194675
+ * See [[MapLayerFormatRegistry.isCredentialsSharingAllowed]].
194676
+ * @internal
194677
+ */
194678
+ isCredentialsSharingAllowed(url) {
194679
+ return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, this._settings.url);
194680
+ }
194681
+ /** Returns true if a request to the given URL may be retried with browser credentials included
194682
+ * (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
194683
+ * See [[MapLayerFormatRegistry.isSsoAllowed]].
194684
+ * @internal
194685
+ */
194686
+ isSsoAllowed(url) {
194687
+ return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(url);
194688
+ }
194348
194689
  /** @internal */
194349
194690
  async makeTileRequest(url, timeoutMs, authorization) {
194350
194691
  // We want to complete the first request before letting other requests go;
@@ -194364,41 +194705,133 @@ class MapLayerImageryProvider {
194364
194705
  throw new Error("fetch call failed");
194365
194706
  return response;
194366
194707
  }
194708
+ /** Records the given URL's origin and transitions the status to [[MapLayerImageryProviderStatus.UntrustedOrigin]].
194709
+ * Called when a request received an authentication challenge that could not be answered because the origin
194710
+ * is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
194711
+ * Raises [[onStatusChanged]] on the status transition, and again whenever a new origin is added.
194712
+ * @internal
194713
+ */
194714
+ reportBlockedOrigin(url) {
194715
+ const origin = tryGetOrigin(url) ?? url;
194716
+ const isNewOrigin = !this._blockedOrigins.has(origin);
194717
+ this._blockedOrigins.add(origin);
194718
+ if (this._status !== MapLayerImageryProviderStatus.UntrustedOrigin)
194719
+ this.setStatus(MapLayerImageryProviderStatus.UntrustedOrigin);
194720
+ else if (isNewOrigin)
194721
+ this.onStatusChanged.raiseEvent(this); // status unchanged, but a new origin was blocked
194722
+ }
194723
+ /** Logs a warning (once per origin, app-wide) when credentials are sent to an origin that would be blocked
194724
+ * if [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] were enabled.
194725
+ * Helps applications discover the origins they need to whitelist before opting in to the restriction.
194726
+ * See [[MapLayerFormatRegistry.logUntrustedOriginUse]].
194727
+ * @internal
194728
+ */
194729
+ logUntrustedOriginUse(url) {
194730
+ _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(url);
194731
+ }
194732
+ /** The redirect policy to apply to a request that carries browser credentials (see [[includeUserCredentials]]).
194733
+ *
194734
+ * When [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled, redirects are refused
194735
+ * outright (`"error"`). `fetch` cannot be asked to follow only same-origin redirects, and by the time a
194736
+ * followed redirect can be inspected the credentials have already been delivered to the destination — so
194737
+ * refusing is the only way to honour the guarantee that credentials reach none but the origins listed in
194738
+ * [[MapLayerFormatRegistry.trustedCredentialsOrigins]]. Legitimate same-origin redirects fail as a result;
194739
+ * that is the cost of the opt-in restriction.
194740
+ *
194741
+ * When the restriction is disabled (the default), redirects are followed as before and
194742
+ * [[checkCredentialedRedirect]] reports the destination after the fact.
194743
+ * @internal
194744
+ */
194745
+ get credentialedRedirect() {
194746
+ return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
194747
+ }
194748
+ /** Detects that a request carrying browser credentials (see [[includeUserCredentials]]) was transparently
194749
+ * redirected to a different origin, and reports or logs that origin.
194750
+ *
194751
+ * This is a **best-effort, after-the-fact** signal used only while
194752
+ * [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is disabled, where credentialed requests
194753
+ * still follow redirects (see [[credentialedRedirect]]). It cannot prevent the exposure — the credentials
194754
+ * have already been sent — and it does not fire at all when the destination denies CORS, because `fetch`
194755
+ * then rejects instead of returning a `Response`. The destination origin is never latched as SSO-succeeded,
194756
+ * so credentials do not keep flowing to it.
194757
+ * @internal
194758
+ */
194759
+ checkCredentialedRedirect(requestedUrl, response) {
194760
+ const finalOrigin = tryGetOrigin(response.url);
194761
+ if (!response.url || finalOrigin === undefined || finalOrigin === tryGetOrigin(requestedUrl))
194762
+ return;
194763
+ if (!this.isSsoAllowed(response.url))
194764
+ this.reportBlockedOrigin(response.url);
194765
+ else
194766
+ this.logUntrustedOriginUse(response.url); // no-op when the restriction is enabled
194767
+ }
194367
194768
  /** @internal */
194368
194769
  async makeRequest(url, timeoutMs, authorization) {
194369
194770
  let response;
194370
194771
  let headers;
194371
194772
  let hasCreds = false;
194773
+ // Whether this request had basic-auth credentials of its own to offer. Requests carrying a caller-supplied
194774
+ // `authorization` are excluded: those bypass the origin policy entirely.
194775
+ const hasSettingsCreds = !authorization && !!this._settings.userName && !!this._settings.password;
194372
194776
  if (authorization) {
194373
194777
  headers = new Headers();
194374
194778
  headers.set("Authorization", authorization);
194375
194779
  }
194376
- else if (this._settings.userName && this._settings.password) {
194377
- hasCreds = true;
194378
- headers = new Headers();
194379
- this.setRequestAuthorization(headers);
194780
+ else if (hasSettingsCreds) {
194781
+ if (this.isCredentialsSharingAllowed(url)) {
194782
+ hasCreds = true;
194783
+ headers = new Headers();
194784
+ this.setRequestAuthorization(headers);
194785
+ if (!this.matchesSettingsUrlOrigin(url))
194786
+ this.logUntrustedOriginUse(url);
194787
+ }
194380
194788
  }
194789
+ const includeCredentials = this.includeUserCredentials(url);
194381
194790
  const opts = {
194382
194791
  method: "GET",
194383
194792
  headers,
194384
- credentials: this._includeUserCredentials ? "include" : undefined,
194793
+ credentials: includeCredentials ? "include" : undefined,
194794
+ redirect: includeCredentials ? this.credentialedRedirect : undefined,
194385
194795
  };
194386
194796
  if (timeoutMs !== undefined)
194387
194797
  (0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.setRequestTimeout)(opts, timeoutMs);
194388
194798
  response = await fetch(url, opts);
194799
+ if (includeCredentials)
194800
+ this.checkCredentialedRedirect(url, response);
194801
+ // fetch follows redirects transparently, so all trust decisions below target the final
194802
+ // (post-redirect) URL reported by the response, not the URL we asked for.
194803
+ const challengedUrl = response.url || url;
194389
194804
  if (response.status === 401
194390
194805
  && (0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])
194391
- && !this._includeUserCredentials
194806
+ && !includeCredentials
194392
194807
  && !hasCreds) {
194393
- // Removed the previous headers and make sure "include" credentials is set
194394
- opts.headers = undefined;
194395
- opts.credentials = "include";
194396
- // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
194397
- response = await fetch(url, opts);
194398
- if (response.status === 200) {
194399
- this._includeUserCredentials = true; // avoid going through 401 challenges over and over
194808
+ if (this.isSsoAllowed(challengedUrl)) {
194809
+ // Removed the previous headers and make sure "include" credentials is set
194810
+ opts.headers = undefined;
194811
+ opts.credentials = "include";
194812
+ // A Negotiate/NTLM handshake is normally a same-URL 401 round-trip, but in legacy mode we preserve
194813
+ // the previous behavior and allow the browser to follow redirects after the authenticated retry.
194814
+ opts.redirect = _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
194815
+ this.logUntrustedOriginUse(challengedUrl);
194816
+ // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
194817
+ response = await fetch(challengedUrl, opts);
194818
+ if (response.status === 200) {
194819
+ this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
194820
+ }
194821
+ }
194822
+ else {
194823
+ this.reportBlockedOrigin(challengedUrl);
194400
194824
  }
194401
194825
  }
194826
+ else if ((response.status === 401 || response.status === 403) && hasSettingsCreds && !this.isCredentialsSharingAllowed(challengedUrl)) {
194827
+ // Some servers answer an unauthenticated request with 403 (Forbidden) rather than a 401 challenge;
194828
+ // since this request could not present its credentials to the challenging origin, either status most
194829
+ // likely results from that. The permission is recomputed for the challenged URL rather than reusing the
194830
+ // decision made for the requested one: `fetch` strips the Authorization header when it follows a
194831
+ // cross-origin redirect, so a trusted request can still arrive unauthenticated at an untrusted origin,
194832
+ // and conversely a request that started out untrusted may end up at an origin that is trusted.
194833
+ this.reportBlockedOrigin(challengedUrl);
194834
+ }
194402
194835
  return response;
194403
194836
  }
194404
194837
  /** Returns a map layer tile at the specified settings. */
@@ -194429,16 +194862,28 @@ class MapLayerImageryProvider {
194429
194862
  }
194430
194863
  /** @internal */
194431
194864
  async toolTipFromUrl(strings, url) {
194432
- const headers = new Headers();
194433
- this.setRequestAuthorization(headers);
194865
+ let headers;
194866
+ if (this.isCredentialsSharingAllowed(url)) {
194867
+ headers = new Headers();
194868
+ this.setRequestAuthorization(headers);
194869
+ }
194434
194870
  try {
194871
+ const includeCredentials = this.includeUserCredentials(url);
194435
194872
  const response = await fetch(url, {
194436
194873
  method: "GET",
194437
194874
  headers,
194438
- credentials: this._includeUserCredentials ? "include" : undefined,
194875
+ credentials: includeCredentials ? "include" : undefined,
194876
+ redirect: includeCredentials ? this.credentialedRedirect : undefined,
194439
194877
  });
194440
- const text = await response.text();
194441
- if (undefined !== text) {
194878
+ if (includeCredentials)
194879
+ this.checkCredentialedRedirect(url, response);
194880
+ let text = await response.text();
194881
+ if (text) {
194882
+ // Tooltip content (e.g. WMS GetFeatureInfo responses) is rendered as HTML downstream and may
194883
+ // deliberately contain markup; text from origins not trusted for credentials is escaped.
194884
+ // fetch follows redirects transparently, so the text may come from a different origin than requested.
194885
+ if (!this.isCredentialsSharingAllowed(response.url || url))
194886
+ text = escapeHtml(text);
194442
194887
  strings.push(text);
194443
194888
  }
194444
194889
  }
@@ -194618,6 +195063,12 @@ var MapLayerSourceStatus;
194618
195063
  /** Format is not compatible with the URL provided.
194619
195064
  */
194620
195065
  MapLayerSourceStatus[MapLayerSourceStatus["IncompatibleFormat"] = 7] = "IncompatibleFormat";
195066
+ /** Authentication could not be attempted because the source's origin is not trusted
195067
+ * (see [MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]($frontend)). Add the origin to
195068
+ * [MapLayerFormatRegistry.trustedCredentialsOrigins]($frontend) rather than prompting for credentials.
195069
+ * @beta
195070
+ */
195071
+ MapLayerSourceStatus[MapLayerSourceStatus["UntrustedOrigin"] = 8] = "UntrustedOrigin";
194621
195072
  })(MapLayerSourceStatus || (MapLayerSourceStatus = {}));
194622
195073
  /** A source for map layers. These may be catalogued for convenient use by users or applications.
194623
195074
  * @public
@@ -194905,10 +195356,8 @@ class MapLayerTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_3__.T
194905
195356
  const tree = this.treeOwner.tileTree;
194906
195357
  if (undefined === tree || hit.iModel !== tree.iModel || tree.modelId !== hit.sourceId)
194907
195358
  return undefined;
194908
- const strings = [];
194909
- strings.push(`Map Layer: ${this._layerSettings.name}`);
194910
195359
  const div = document.createElement("div");
194911
- div.innerHTML = strings.join("<br>");
195360
+ div.textContent = `Map Layer: ${this._layerSettings.name}`;
194912
195361
  return div;
194913
195362
  }
194914
195363
  decorate(_context) {
@@ -196617,7 +197066,9 @@ class MapTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_7__.TileTr
196617
197066
  let carto;
196618
197067
  const strings = [];
196619
197068
  const getTooltipFunc = async (imageryTreeRef, quadId, cartoGraphic, imageryTree) => {
196620
- strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_4__.IModelApp.localization.getLocalizedString("iModelJs:MapLayers.ImageryLayer")}: ${imageryTreeRef.layerSettings.name}`);
197069
+ // innerHTML is used below because imageryLoader.getToolTip may deliberately supply markup.
197070
+ const layerName = (0,_internal__WEBPACK_IMPORTED_MODULE_7__.escapeHtml)(imageryTreeRef.layerSettings.name);
197071
+ strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_4__.IModelApp.localization.getLocalizedString("iModelJs:MapLayers.ImageryLayer")}: ${layerName}`);
196621
197072
  carto = cartoGraphic;
196622
197073
  await imageryTree.imageryLoader.getToolTip(strings, quadId, cartoGraphic, imageryTree);
196623
197074
  };
@@ -342457,7 +342908,7 @@ class TestContext {
342457
342908
  this.initializeRpcInterfaces({ title: this.settings.Backend.name, version: this.settings.Backend.version });
342458
342909
  const iModelClient = new imodels_client_management_1.IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } });
342459
342910
  await core_frontend_1.NoRenderApp.startup({
342460
- applicationVersion: "5.13.0-dev.16",
342911
+ applicationVersion: "5.13.0-dev.17",
342461
342912
  applicationId: this.settings.gprid,
342462
342913
  authorizationClient: new frontend_1.TestFrontendAuthorizationClient(this.serviceAuthToken),
342463
342914
  hubAccess: new imodels_access_frontend_1.FrontendIModelsAccess(iModelClient),
@@ -367652,7 +368103,7 @@ var loadLanguages = instance.loadLanguages;
367652
368103
  (module) {
367653
368104
 
367654
368105
  "use strict";
367655
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.13.0-dev.16","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"}}');
368106
+ 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"}}');
367656
368107
 
367657
368108
  /***/ },
367658
368109