@itwin/core-frontend 5.13.0-dev.8 → 5.14.0-dev.1
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.
- package/CHANGELOG.md +35 -1
- package/lib/cjs/BriefcaseTxns.d.ts +9 -0
- package/lib/cjs/BriefcaseTxns.d.ts.map +1 -1
- package/lib/cjs/BriefcaseTxns.js +9 -0
- package/lib/cjs/BriefcaseTxns.js.map +1 -1
- package/lib/cjs/EmphasizeElements.d.ts +4 -1
- package/lib/cjs/EmphasizeElements.d.ts.map +1 -1
- package/lib/cjs/EmphasizeElements.js +16 -9
- package/lib/cjs/EmphasizeElements.js.map +1 -1
- package/lib/cjs/IModelApp.d.ts +11 -1
- package/lib/cjs/IModelApp.d.ts.map +1 -1
- package/lib/cjs/IModelApp.js +14 -1
- package/lib/cjs/IModelApp.js.map +1 -1
- package/lib/cjs/IModeljs-css.d.ts.map +1 -1
- package/lib/cjs/IModeljs-css.js +4 -2
- package/lib/cjs/IModeljs-css.js.map +1 -1
- package/lib/cjs/RealityDataSource.d.ts.map +1 -1
- package/lib/cjs/RealityDataSource.js +7 -4
- package/lib/cjs/RealityDataSource.js.map +1 -1
- package/lib/cjs/TxnEntityChanges.d.ts +4 -18
- package/lib/cjs/TxnEntityChanges.d.ts.map +1 -1
- package/lib/cjs/TxnEntityChanges.js.map +1 -1
- package/lib/cjs/ViewManager.d.ts +3 -0
- package/lib/cjs/ViewManager.d.ts.map +1 -1
- package/lib/cjs/ViewManager.js +9 -1
- package/lib/cjs/ViewManager.js.map +1 -1
- package/lib/cjs/Viewport.d.ts +7 -1
- package/lib/cjs/Viewport.d.ts.map +1 -1
- package/lib/cjs/Viewport.js +13 -1
- package/lib/cjs/Viewport.js.map +1 -1
- package/lib/cjs/core-frontend.d.ts +7 -1
- package/lib/cjs/core-frontend.d.ts.map +1 -1
- package/lib/cjs/core-frontend.js.map +1 -1
- package/lib/cjs/internal/GoogleMapsDecorator.js +1 -1
- package/lib/cjs/internal/GoogleMapsDecorator.js.map +1 -1
- package/lib/cjs/internal/tile/OrbitGtTileTree.d.ts +11 -1
- package/lib/cjs/internal/tile/OrbitGtTileTree.d.ts.map +1 -1
- package/lib/cjs/internal/tile/OrbitGtTileTree.js +49 -3
- package/lib/cjs/internal/tile/OrbitGtTileTree.js.map +1 -1
- package/lib/cjs/internal/tile/RealityModelTileTree.d.ts.map +1 -1
- package/lib/cjs/internal/tile/RealityModelTileTree.js +5 -1
- package/lib/cjs/internal/tile/RealityModelTileTree.js.map +1 -1
- package/lib/cjs/internal/tile/map/ArcGisUtilities.d.ts +3 -0
- package/lib/cjs/internal/tile/map/ArcGisUtilities.d.ts.map +1 -1
- package/lib/cjs/internal/tile/map/ArcGisUtilities.js +32 -4
- package/lib/cjs/internal/tile/map/ArcGisUtilities.js.map +1 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/ArcGISImageryProvider.d.ts.map +1 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/ArcGISImageryProvider.js +28 -6
- package/lib/cjs/internal/tile/map/ImageryProviders/ArcGISImageryProvider.js.map +1 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.d.ts.map +1 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.js +7 -3
- package/lib/cjs/internal/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.js.map +1 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/BingImageryProvider.d.ts.map +1 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/BingImageryProvider.js +1 -7
- package/lib/cjs/internal/tile/map/ImageryProviders/BingImageryProvider.js.map +1 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/WmsMapLayerImageryProvider.d.ts.map +1 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/WmsMapLayerImageryProvider.js +4 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/WmsMapLayerImageryProvider.js.map +1 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/WmtsMapLayerImageryProvider.d.ts.map +1 -1
- package/lib/cjs/internal/tile/map/ImageryProviders/WmtsMapLayerImageryProvider.js +6 -2
- package/lib/cjs/internal/tile/map/ImageryProviders/WmtsMapLayerImageryProvider.js.map +1 -1
- package/lib/cjs/internal/tile/map/WmsCapabilities.d.ts +2 -0
- package/lib/cjs/internal/tile/map/WmsCapabilities.d.ts.map +1 -1
- package/lib/cjs/internal/tile/map/WmsCapabilities.js +28 -6
- package/lib/cjs/internal/tile/map/WmsCapabilities.js.map +1 -1
- package/lib/cjs/internal/tile/map/WmsUtilities.d.ts.map +1 -1
- package/lib/cjs/internal/tile/map/WmsUtilities.js +25 -4
- package/lib/cjs/internal/tile/map/WmsUtilities.js.map +1 -1
- package/lib/cjs/quantity-formatting/QuantityFormatter.d.ts.map +1 -1
- package/lib/cjs/quantity-formatting/QuantityFormatter.js +14 -6
- package/lib/cjs/quantity-formatting/QuantityFormatter.js.map +1 -1
- package/lib/cjs/tile/map/MapLayerFormatRegistry.d.ts +74 -0
- package/lib/cjs/tile/map/MapLayerFormatRegistry.d.ts.map +1 -1
- package/lib/cjs/tile/map/MapLayerFormatRegistry.js +114 -2
- package/lib/cjs/tile/map/MapLayerFormatRegistry.js.map +1 -1
- package/lib/cjs/tile/map/MapLayerImageryFormats.d.ts.map +1 -1
- package/lib/cjs/tile/map/MapLayerImageryFormats.js +16 -0
- package/lib/cjs/tile/map/MapLayerImageryFormats.js.map +1 -1
- package/lib/cjs/tile/map/MapLayerImageryProvider.d.ts +118 -2
- package/lib/cjs/tile/map/MapLayerImageryProvider.d.ts.map +1 -1
- package/lib/cjs/tile/map/MapLayerImageryProvider.js +230 -20
- package/lib/cjs/tile/map/MapLayerImageryProvider.js.map +1 -1
- package/lib/cjs/tile/map/MapLayerSources.d.ts +7 -1
- package/lib/cjs/tile/map/MapLayerSources.d.ts.map +1 -1
- package/lib/cjs/tile/map/MapLayerSources.js +6 -0
- package/lib/cjs/tile/map/MapLayerSources.js.map +1 -1
- package/lib/cjs/tile/map/MapLayerTileTreeReference.d.ts.map +1 -1
- package/lib/cjs/tile/map/MapLayerTileTreeReference.js +1 -3
- package/lib/cjs/tile/map/MapLayerTileTreeReference.js.map +1 -1
- package/lib/cjs/tile/map/MapTileTree.d.ts.map +1 -1
- package/lib/cjs/tile/map/MapTileTree.js +3 -1
- package/lib/cjs/tile/map/MapTileTree.js.map +1 -1
- package/lib/cjs/tools/Tool.d.ts +5 -1
- package/lib/cjs/tools/Tool.d.ts.map +1 -1
- package/lib/cjs/tools/Tool.js +5 -1
- package/lib/cjs/tools/Tool.js.map +1 -1
- package/lib/cjs/tools/ToolAdmin.d.ts +2 -1
- package/lib/cjs/tools/ToolAdmin.d.ts.map +1 -1
- package/lib/cjs/tools/ToolAdmin.js +81 -19
- package/lib/cjs/tools/ToolAdmin.js.map +1 -1
- package/lib/esm/BriefcaseTxns.d.ts +9 -0
- package/lib/esm/BriefcaseTxns.d.ts.map +1 -1
- package/lib/esm/BriefcaseTxns.js +9 -0
- package/lib/esm/BriefcaseTxns.js.map +1 -1
- package/lib/esm/EmphasizeElements.d.ts +4 -1
- package/lib/esm/EmphasizeElements.d.ts.map +1 -1
- package/lib/esm/EmphasizeElements.js +16 -9
- package/lib/esm/EmphasizeElements.js.map +1 -1
- package/lib/esm/IModelApp.d.ts +11 -1
- package/lib/esm/IModelApp.d.ts.map +1 -1
- package/lib/esm/IModelApp.js +14 -1
- package/lib/esm/IModelApp.js.map +1 -1
- package/lib/esm/IModeljs-css.d.ts.map +1 -1
- package/lib/esm/IModeljs-css.js +4 -2
- package/lib/esm/IModeljs-css.js.map +1 -1
- package/lib/esm/RealityDataSource.d.ts.map +1 -1
- package/lib/esm/RealityDataSource.js +7 -4
- package/lib/esm/RealityDataSource.js.map +1 -1
- package/lib/esm/TxnEntityChanges.d.ts +4 -18
- package/lib/esm/TxnEntityChanges.d.ts.map +1 -1
- package/lib/esm/TxnEntityChanges.js.map +1 -1
- package/lib/esm/ViewManager.d.ts +3 -0
- package/lib/esm/ViewManager.d.ts.map +1 -1
- package/lib/esm/ViewManager.js +9 -1
- package/lib/esm/ViewManager.js.map +1 -1
- package/lib/esm/Viewport.d.ts +7 -1
- package/lib/esm/Viewport.d.ts.map +1 -1
- package/lib/esm/Viewport.js +13 -1
- package/lib/esm/Viewport.js.map +1 -1
- package/lib/esm/core-frontend.d.ts +7 -1
- package/lib/esm/core-frontend.d.ts.map +1 -1
- package/lib/esm/core-frontend.js.map +1 -1
- package/lib/esm/internal/GoogleMapsDecorator.js +1 -1
- package/lib/esm/internal/GoogleMapsDecorator.js.map +1 -1
- package/lib/esm/internal/tile/OrbitGtTileTree.d.ts +11 -1
- package/lib/esm/internal/tile/OrbitGtTileTree.d.ts.map +1 -1
- package/lib/esm/internal/tile/OrbitGtTileTree.js +49 -4
- package/lib/esm/internal/tile/OrbitGtTileTree.js.map +1 -1
- package/lib/esm/internal/tile/RealityModelTileTree.d.ts.map +1 -1
- package/lib/esm/internal/tile/RealityModelTileTree.js +5 -1
- package/lib/esm/internal/tile/RealityModelTileTree.js.map +1 -1
- package/lib/esm/internal/tile/map/ArcGisUtilities.d.ts +3 -0
- package/lib/esm/internal/tile/map/ArcGisUtilities.d.ts.map +1 -1
- package/lib/esm/internal/tile/map/ArcGisUtilities.js +33 -5
- package/lib/esm/internal/tile/map/ArcGisUtilities.js.map +1 -1
- package/lib/esm/internal/tile/map/ImageryProviders/ArcGISImageryProvider.d.ts.map +1 -1
- package/lib/esm/internal/tile/map/ImageryProviders/ArcGISImageryProvider.js +29 -7
- package/lib/esm/internal/tile/map/ImageryProviders/ArcGISImageryProvider.js.map +1 -1
- package/lib/esm/internal/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.d.ts.map +1 -1
- package/lib/esm/internal/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.js +8 -4
- package/lib/esm/internal/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.js.map +1 -1
- package/lib/esm/internal/tile/map/ImageryProviders/BingImageryProvider.d.ts.map +1 -1
- package/lib/esm/internal/tile/map/ImageryProviders/BingImageryProvider.js +1 -7
- package/lib/esm/internal/tile/map/ImageryProviders/BingImageryProvider.js.map +1 -1
- package/lib/esm/internal/tile/map/ImageryProviders/WmsMapLayerImageryProvider.d.ts.map +1 -1
- package/lib/esm/internal/tile/map/ImageryProviders/WmsMapLayerImageryProvider.js +5 -2
- package/lib/esm/internal/tile/map/ImageryProviders/WmsMapLayerImageryProvider.js.map +1 -1
- package/lib/esm/internal/tile/map/ImageryProviders/WmtsMapLayerImageryProvider.d.ts.map +1 -1
- package/lib/esm/internal/tile/map/ImageryProviders/WmtsMapLayerImageryProvider.js +7 -3
- package/lib/esm/internal/tile/map/ImageryProviders/WmtsMapLayerImageryProvider.js.map +1 -1
- package/lib/esm/internal/tile/map/WmsCapabilities.d.ts +2 -0
- package/lib/esm/internal/tile/map/WmsCapabilities.d.ts.map +1 -1
- package/lib/esm/internal/tile/map/WmsCapabilities.js +28 -6
- package/lib/esm/internal/tile/map/WmsCapabilities.js.map +1 -1
- package/lib/esm/internal/tile/map/WmsUtilities.d.ts.map +1 -1
- package/lib/esm/internal/tile/map/WmsUtilities.js +25 -4
- package/lib/esm/internal/tile/map/WmsUtilities.js.map +1 -1
- package/lib/esm/quantity-formatting/QuantityFormatter.d.ts.map +1 -1
- package/lib/esm/quantity-formatting/QuantityFormatter.js +14 -6
- package/lib/esm/quantity-formatting/QuantityFormatter.js.map +1 -1
- package/lib/esm/tile/map/MapLayerFormatRegistry.d.ts +74 -0
- package/lib/esm/tile/map/MapLayerFormatRegistry.d.ts.map +1 -1
- package/lib/esm/tile/map/MapLayerFormatRegistry.js +113 -2
- package/lib/esm/tile/map/MapLayerFormatRegistry.js.map +1 -1
- package/lib/esm/tile/map/MapLayerImageryFormats.d.ts.map +1 -1
- package/lib/esm/tile/map/MapLayerImageryFormats.js +17 -1
- package/lib/esm/tile/map/MapLayerImageryFormats.js.map +1 -1
- package/lib/esm/tile/map/MapLayerImageryProvider.d.ts +118 -2
- package/lib/esm/tile/map/MapLayerImageryProvider.d.ts.map +1 -1
- package/lib/esm/tile/map/MapLayerImageryProvider.js +228 -20
- package/lib/esm/tile/map/MapLayerImageryProvider.js.map +1 -1
- package/lib/esm/tile/map/MapLayerSources.d.ts +7 -1
- package/lib/esm/tile/map/MapLayerSources.d.ts.map +1 -1
- package/lib/esm/tile/map/MapLayerSources.js +6 -0
- package/lib/esm/tile/map/MapLayerSources.js.map +1 -1
- package/lib/esm/tile/map/MapLayerTileTreeReference.d.ts.map +1 -1
- package/lib/esm/tile/map/MapLayerTileTreeReference.js +1 -3
- package/lib/esm/tile/map/MapLayerTileTreeReference.js.map +1 -1
- package/lib/esm/tile/map/MapTileTree.d.ts.map +1 -1
- package/lib/esm/tile/map/MapTileTree.js +4 -2
- package/lib/esm/tile/map/MapTileTree.js.map +1 -1
- package/lib/esm/tools/Tool.d.ts +5 -1
- package/lib/esm/tools/Tool.d.ts.map +1 -1
- package/lib/esm/tools/Tool.js +5 -1
- package/lib/esm/tools/Tool.js.map +1 -1
- package/lib/esm/tools/ToolAdmin.d.ts +2 -1
- package/lib/esm/tools/ToolAdmin.d.ts.map +1 -1
- package/lib/esm/tools/ToolAdmin.js +82 -20
- package/lib/esm/tools/ToolAdmin.js.map +1 -1
- package/lib/public/scripts/parse-imdl-worker.js +1 -1
- package/package.json +21 -24
|
@@ -7,12 +7,35 @@ import { ScreenViewport } from "../../Viewport";
|
|
|
7
7
|
import { ImageryMapTile, ImageryMapTileTree, MapCartoRectangle, MapFeatureInfoOptions, MapLayerFeatureInfo, MapTilingScheme, QuadId } from "../internal";
|
|
8
8
|
import { HitDetail } from "../../HitDetail";
|
|
9
9
|
import { DecorateContext } from "../../ViewContext";
|
|
10
|
+
/** Escapes HTML metacharacters so the text renders literally when assigned to `innerHTML`.
|
|
11
|
+
* Use for any server- or user-supplied string that ends up in the map tooltip, which is rendered
|
|
12
|
+
* as HTML by [[MapLayerTileTreeReference.getToolTip]].
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export declare function escapeHtml(text: string): string;
|
|
16
|
+
/** Returns the origin (scheme + host + port) of the given URL, or undefined if it cannot be parsed or does
|
|
17
|
+
* not denote a distinct network origin.
|
|
18
|
+
*
|
|
19
|
+
* Only `http:` and `https:` URLs yield an origin. Every other scheme is rejected because opaque URLs
|
|
20
|
+
* — `file:`, `data:`, `about:`, `blob:null`, and the custom protocols Electron hosts commonly register —
|
|
21
|
+
* all serialize to the literal string `"null"`. Comparing those would make unrelated URLs look same-origin,
|
|
22
|
+
* so a single trusted entry could unlock all of them. Callers use this for credential-trust decisions, and
|
|
23
|
+
* returning `undefined` keeps those decisions fail-closed.
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
export declare function tryGetOrigin(url: string): string | undefined;
|
|
10
27
|
/** The status of the map layer imagery provider that lets you know if authentication is needed to request tiles.
|
|
11
28
|
* @public
|
|
12
29
|
*/
|
|
13
30
|
export declare enum MapLayerImageryProviderStatus {
|
|
14
31
|
Valid = 0,
|
|
15
|
-
RequireAuth = 1
|
|
32
|
+
RequireAuth = 1,
|
|
33
|
+
/** A request received an authentication challenge, but credentials were withheld because the request origin
|
|
34
|
+
* is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
35
|
+
* The blocked origins are available via [[MapLayerImageryProvider.blockedOrigins]].
|
|
36
|
+
* @beta
|
|
37
|
+
*/
|
|
38
|
+
UntrustedOrigin = 2
|
|
16
39
|
}
|
|
17
40
|
/** @internal */
|
|
18
41
|
export interface WGS84Extent {
|
|
@@ -37,7 +60,34 @@ export declare abstract class MapLayerImageryProvider {
|
|
|
37
60
|
/** @internal */
|
|
38
61
|
private _status;
|
|
39
62
|
/** @internal */
|
|
40
|
-
|
|
63
|
+
private readonly _blockedOrigins;
|
|
64
|
+
/** Origins of requests for which credentials were withheld because they are not trusted
|
|
65
|
+
* (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
66
|
+
* Populated when [[status]] transitions to [[MapLayerImageryProviderStatus.UntrustedOrigin]];
|
|
67
|
+
* [[onStatusChanged]] is raised again each time a new origin is added. Cleared by [[resetStatus]].
|
|
68
|
+
* @beta
|
|
69
|
+
*/
|
|
70
|
+
get blockedOrigins(): ReadonlyArray<string>;
|
|
71
|
+
/** Origins for which a previous SSO handshake (i.e. Windows Authentication) succeeded.
|
|
72
|
+
* Browser credentials are only included for subsequent requests targeting these origins,
|
|
73
|
+
* so that a successful handshake with one host does not leak credentials to other hosts
|
|
74
|
+
* this provider may contact.
|
|
75
|
+
* @internal
|
|
76
|
+
*/
|
|
77
|
+
private readonly _ssoSucceededOrigins;
|
|
78
|
+
/** Returns true if browser credentials should be included for the given URL because a previous
|
|
79
|
+
* SSO handshake succeeded for its origin AND the origin is still allowed by the current policy
|
|
80
|
+
* (see [[MapLayerFormatRegistry.isSsoAllowed]]). Re-checking the policy ensures a handshake recorded
|
|
81
|
+
* while enforcement was disabled — or before an origin was removed from
|
|
82
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]] — does not keep latching credentials on.
|
|
83
|
+
* @internal
|
|
84
|
+
*/
|
|
85
|
+
protected includeUserCredentials(url: string): boolean;
|
|
86
|
+
/** Records that an SSO handshake succeeded for the given URL's origin, so subsequent requests
|
|
87
|
+
* to that origin include browser credentials without going through another 401 challenge.
|
|
88
|
+
* @internal
|
|
89
|
+
*/
|
|
90
|
+
protected recordSsoSucceeded(url: string): void;
|
|
41
91
|
/** @internal */
|
|
42
92
|
protected readonly onFirstRequestCompleted: BeEvent<() => void>;
|
|
43
93
|
/** @internal */
|
|
@@ -53,6 +103,13 @@ export declare abstract class MapLayerImageryProvider {
|
|
|
53
103
|
* @public
|
|
54
104
|
*/
|
|
55
105
|
get supportsMapFeatureInfo(): boolean;
|
|
106
|
+
/** Reset the provider's status to [[MapLayerImageryProviderStatus.Valid]] and clear the list of
|
|
107
|
+
* [[blockedOrigins]] accumulated while in the [[MapLayerImageryProviderStatus.UntrustedOrigin]] state.
|
|
108
|
+
* Raises [[onStatusChanged]] if the status actually changes.
|
|
109
|
+
* Typically called after the user has provided credentials or the application has updated
|
|
110
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]], so that subsequent requests are re-attempted.
|
|
111
|
+
* @beta
|
|
112
|
+
*/
|
|
56
113
|
resetStatus(): void;
|
|
57
114
|
/** @internal */
|
|
58
115
|
get tileSize(): number;
|
|
@@ -152,8 +209,67 @@ export declare abstract class MapLayerImageryProvider {
|
|
|
152
209
|
protected onStatusUpdated(_newStatus: MapLayerImageryProviderStatus): void;
|
|
153
210
|
/** @internal */
|
|
154
211
|
protected setRequestAuthorization(headers: Headers): void;
|
|
212
|
+
/** Returns true if the given URL has the same origin as this layer's settings URL.
|
|
213
|
+
* Used to avoid leaking credentials to third-party hosts.
|
|
214
|
+
* @internal
|
|
215
|
+
*/
|
|
216
|
+
protected matchesSettingsUrlOrigin(url: string): boolean;
|
|
217
|
+
/** Returns true if the basic-auth credentials from the layer settings may be attached to a request to the given URL.
|
|
218
|
+
* Always true unless [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
|
|
219
|
+
* When enabled, the origin of this layer's settings URL is implicitly trusted (the credentials belong to that
|
|
220
|
+
* server); other origins must be listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]].
|
|
221
|
+
* See [[MapLayerFormatRegistry.isCredentialsSharingAllowed]].
|
|
222
|
+
* @internal
|
|
223
|
+
*/
|
|
224
|
+
protected isCredentialsSharingAllowed(url: string): boolean;
|
|
225
|
+
/** Returns true if a request to the given URL may be retried with browser credentials included
|
|
226
|
+
* (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
|
|
227
|
+
* See [[MapLayerFormatRegistry.isSsoAllowed]].
|
|
228
|
+
* @internal
|
|
229
|
+
*/
|
|
230
|
+
protected isSsoAllowed(url: string): boolean;
|
|
155
231
|
/** @internal */
|
|
156
232
|
makeTileRequest(url: string, timeoutMs?: number, authorization?: string): Promise<Response>;
|
|
233
|
+
/** Records the given URL's origin and transitions the status to [[MapLayerImageryProviderStatus.UntrustedOrigin]].
|
|
234
|
+
* Called when a request received an authentication challenge that could not be answered because the origin
|
|
235
|
+
* is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
236
|
+
* Raises [[onStatusChanged]] on the status transition, and again whenever a new origin is added.
|
|
237
|
+
* @internal
|
|
238
|
+
*/
|
|
239
|
+
protected reportBlockedOrigin(url: string): void;
|
|
240
|
+
/** Logs a warning (once per origin, app-wide) when credentials are sent to an origin that would be blocked
|
|
241
|
+
* if [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] were enabled.
|
|
242
|
+
* Helps applications discover the origins they need to whitelist before opting in to the restriction.
|
|
243
|
+
* See [[MapLayerFormatRegistry.logUntrustedOriginUse]].
|
|
244
|
+
* @internal
|
|
245
|
+
*/
|
|
246
|
+
protected logUntrustedOriginUse(url: string): void;
|
|
247
|
+
/** The redirect policy to apply to a request that carries browser credentials (see [[includeUserCredentials]]).
|
|
248
|
+
*
|
|
249
|
+
* When [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled, redirects are refused
|
|
250
|
+
* outright (`"error"`). `fetch` cannot be asked to follow only same-origin redirects, and by the time a
|
|
251
|
+
* followed redirect can be inspected the credentials have already been delivered to the destination — so
|
|
252
|
+
* refusing is the only way to honour the guarantee that credentials reach none but the origins listed in
|
|
253
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]]. Legitimate same-origin redirects fail as a result;
|
|
254
|
+
* that is the cost of the opt-in restriction.
|
|
255
|
+
*
|
|
256
|
+
* When the restriction is disabled (the default), redirects are followed as before and
|
|
257
|
+
* [[checkCredentialedRedirect]] reports the destination after the fact.
|
|
258
|
+
* @internal
|
|
259
|
+
*/
|
|
260
|
+
protected get credentialedRedirect(): RequestRedirect | undefined;
|
|
261
|
+
/** Detects that a request carrying browser credentials (see [[includeUserCredentials]]) was transparently
|
|
262
|
+
* redirected to a different origin, and reports or logs that origin.
|
|
263
|
+
*
|
|
264
|
+
* This is a **best-effort, after-the-fact** signal used only while
|
|
265
|
+
* [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is disabled, where credentialed requests
|
|
266
|
+
* still follow redirects (see [[credentialedRedirect]]). It cannot prevent the exposure — the credentials
|
|
267
|
+
* have already been sent — and it does not fire at all when the destination denies CORS, because `fetch`
|
|
268
|
+
* then rejects instead of returning a `Response`. The destination origin is never latched as SSO-succeeded,
|
|
269
|
+
* so credentials do not keep flowing to it.
|
|
270
|
+
* @internal
|
|
271
|
+
*/
|
|
272
|
+
protected checkCredentialedRedirect(requestedUrl: string, response: Response): void;
|
|
157
273
|
/** @internal */
|
|
158
274
|
makeRequest(url: string, timeoutMs?: number, authorization?: string): Promise<Response>;
|
|
159
275
|
/** Returns a map layer tile at the specified settings. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapLayerImageryProvider.d.ts","sourceRoot":"","sources":["../../../../src/tile/map/MapLayerImageryProvider.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAU,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,WAAW,EAAqB,MAAM,oBAAoB,CAAC;AAIzG,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAA6C,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,EAA2B,MAAM,aAAa,CAAC;AAC7N,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAOpD;;GAEG;AACH,oBAAY,6BAA6B;IACvC,KAAK,IAAA;IACL,WAAW,IAAA;
|
|
1
|
+
{"version":3,"file":"MapLayerImageryProvider.d.ts","sourceRoot":"","sources":["../../../../src/tile/map/MapLayerImageryProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,34 @@ import { headersIncludeAuthMethod, setBasicAuthorization, setRequestTimeout } fr
|
|
|
16
16
|
const tileImageSize = 256, untiledImageSize = 256;
|
|
17
17
|
const earthRadius = 6378137;
|
|
18
18
|
const doDebugToolTips = false;
|
|
19
|
+
/** Escapes HTML metacharacters so the text renders literally when assigned to `innerHTML`.
|
|
20
|
+
* Use for any server- or user-supplied string that ends up in the map tooltip, which is rendered
|
|
21
|
+
* as HTML by [[MapLayerTileTreeReference.getToolTip]].
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export function escapeHtml(text) {
|
|
25
|
+
return text.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
|
|
26
|
+
}
|
|
27
|
+
/** Returns the origin (scheme + host + port) of the given URL, or undefined if it cannot be parsed or does
|
|
28
|
+
* not denote a distinct network origin.
|
|
29
|
+
*
|
|
30
|
+
* Only `http:` and `https:` URLs yield an origin. Every other scheme is rejected because opaque URLs
|
|
31
|
+
* — `file:`, `data:`, `about:`, `blob:null`, and the custom protocols Electron hosts commonly register —
|
|
32
|
+
* all serialize to the literal string `"null"`. Comparing those would make unrelated URLs look same-origin,
|
|
33
|
+
* so a single trusted entry could unlock all of them. Callers use this for credential-trust decisions, and
|
|
34
|
+
* returning `undefined` keeps those decisions fail-closed.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
export function tryGetOrigin(url) {
|
|
38
|
+
let parsed;
|
|
39
|
+
try {
|
|
40
|
+
parsed = new URL(url);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
return (parsed.protocol === "http:" || parsed.protocol === "https:") ? parsed.origin : undefined;
|
|
46
|
+
}
|
|
19
47
|
/** The status of the map layer imagery provider that lets you know if authentication is needed to request tiles.
|
|
20
48
|
* @public
|
|
21
49
|
*/
|
|
@@ -23,6 +51,12 @@ export var MapLayerImageryProviderStatus;
|
|
|
23
51
|
(function (MapLayerImageryProviderStatus) {
|
|
24
52
|
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["Valid"] = 0] = "Valid";
|
|
25
53
|
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["RequireAuth"] = 1] = "RequireAuth";
|
|
54
|
+
/** A request received an authentication challenge, but credentials were withheld because the request origin
|
|
55
|
+
* is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
56
|
+
* The blocked origins are available via [[MapLayerImageryProvider.blockedOrigins]].
|
|
57
|
+
* @beta
|
|
58
|
+
*/
|
|
59
|
+
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["UntrustedOrigin"] = 2] = "UntrustedOrigin";
|
|
26
60
|
})(MapLayerImageryProviderStatus || (MapLayerImageryProviderStatus = {}));
|
|
27
61
|
/** Abstract class for map layer imagery providers.
|
|
28
62
|
* 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.
|
|
@@ -40,7 +74,41 @@ export class MapLayerImageryProvider {
|
|
|
40
74
|
/** @internal */
|
|
41
75
|
_status = MapLayerImageryProviderStatus.Valid;
|
|
42
76
|
/** @internal */
|
|
43
|
-
|
|
77
|
+
_blockedOrigins = new Set();
|
|
78
|
+
/** Origins of requests for which credentials were withheld because they are not trusted
|
|
79
|
+
* (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
80
|
+
* Populated when [[status]] transitions to [[MapLayerImageryProviderStatus.UntrustedOrigin]];
|
|
81
|
+
* [[onStatusChanged]] is raised again each time a new origin is added. Cleared by [[resetStatus]].
|
|
82
|
+
* @beta
|
|
83
|
+
*/
|
|
84
|
+
get blockedOrigins() { return [...this._blockedOrigins]; }
|
|
85
|
+
/** Origins for which a previous SSO handshake (i.e. Windows Authentication) succeeded.
|
|
86
|
+
* Browser credentials are only included for subsequent requests targeting these origins,
|
|
87
|
+
* so that a successful handshake with one host does not leak credentials to other hosts
|
|
88
|
+
* this provider may contact.
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
_ssoSucceededOrigins = new Set();
|
|
92
|
+
/** Returns true if browser credentials should be included for the given URL because a previous
|
|
93
|
+
* SSO handshake succeeded for its origin AND the origin is still allowed by the current policy
|
|
94
|
+
* (see [[MapLayerFormatRegistry.isSsoAllowed]]). Re-checking the policy ensures a handshake recorded
|
|
95
|
+
* while enforcement was disabled — or before an origin was removed from
|
|
96
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]] — does not keep latching credentials on.
|
|
97
|
+
* @internal
|
|
98
|
+
*/
|
|
99
|
+
includeUserCredentials(url) {
|
|
100
|
+
const origin = tryGetOrigin(url);
|
|
101
|
+
return origin !== undefined && this._ssoSucceededOrigins.has(origin) && this.isSsoAllowed(url);
|
|
102
|
+
}
|
|
103
|
+
/** Records that an SSO handshake succeeded for the given URL's origin, so subsequent requests
|
|
104
|
+
* to that origin include browser credentials without going through another 401 challenge.
|
|
105
|
+
* @internal
|
|
106
|
+
*/
|
|
107
|
+
recordSsoSucceeded(url) {
|
|
108
|
+
const origin = tryGetOrigin(url);
|
|
109
|
+
if (origin !== undefined)
|
|
110
|
+
this._ssoSucceededOrigins.add(origin);
|
|
111
|
+
}
|
|
44
112
|
/** @internal */
|
|
45
113
|
onFirstRequestCompleted = new BeEvent();
|
|
46
114
|
/** @internal */
|
|
@@ -56,7 +124,17 @@ export class MapLayerImageryProvider {
|
|
|
56
124
|
* @public
|
|
57
125
|
*/
|
|
58
126
|
get supportsMapFeatureInfo() { return false; }
|
|
59
|
-
|
|
127
|
+
/** Reset the provider's status to [[MapLayerImageryProviderStatus.Valid]] and clear the list of
|
|
128
|
+
* [[blockedOrigins]] accumulated while in the [[MapLayerImageryProviderStatus.UntrustedOrigin]] state.
|
|
129
|
+
* Raises [[onStatusChanged]] if the status actually changes.
|
|
130
|
+
* Typically called after the user has provided credentials or the application has updated
|
|
131
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]], so that subsequent requests are re-attempted.
|
|
132
|
+
* @beta
|
|
133
|
+
*/
|
|
134
|
+
resetStatus() {
|
|
135
|
+
this._blockedOrigins.clear();
|
|
136
|
+
this.setStatus(MapLayerImageryProviderStatus.Valid);
|
|
137
|
+
}
|
|
60
138
|
/** @internal */
|
|
61
139
|
get tileSize() { return this._usesCachedTiles ? tileImageSize : untiledImageSize; }
|
|
62
140
|
/** @internal */
|
|
@@ -230,6 +308,32 @@ export class MapLayerImageryProvider {
|
|
|
230
308
|
setBasicAuthorization(headers, this._settings.userName, this._settings.password);
|
|
231
309
|
}
|
|
232
310
|
}
|
|
311
|
+
/** Returns true if the given URL has the same origin as this layer's settings URL.
|
|
312
|
+
* Used to avoid leaking credentials to third-party hosts.
|
|
313
|
+
* @internal
|
|
314
|
+
*/
|
|
315
|
+
matchesSettingsUrlOrigin(url) {
|
|
316
|
+
const origin = tryGetOrigin(url);
|
|
317
|
+
return origin !== undefined && origin === tryGetOrigin(this._settings.url);
|
|
318
|
+
}
|
|
319
|
+
/** Returns true if the basic-auth credentials from the layer settings may be attached to a request to the given URL.
|
|
320
|
+
* Always true unless [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
|
|
321
|
+
* When enabled, the origin of this layer's settings URL is implicitly trusted (the credentials belong to that
|
|
322
|
+
* server); other origins must be listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]].
|
|
323
|
+
* See [[MapLayerFormatRegistry.isCredentialsSharingAllowed]].
|
|
324
|
+
* @internal
|
|
325
|
+
*/
|
|
326
|
+
isCredentialsSharingAllowed(url) {
|
|
327
|
+
return IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, this._settings.url);
|
|
328
|
+
}
|
|
329
|
+
/** Returns true if a request to the given URL may be retried with browser credentials included
|
|
330
|
+
* (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
|
|
331
|
+
* See [[MapLayerFormatRegistry.isSsoAllowed]].
|
|
332
|
+
* @internal
|
|
333
|
+
*/
|
|
334
|
+
isSsoAllowed(url) {
|
|
335
|
+
return IModelApp.mapLayerFormatRegistry.isSsoAllowed(url);
|
|
336
|
+
}
|
|
233
337
|
/** @internal */
|
|
234
338
|
async makeTileRequest(url, timeoutMs, authorization) {
|
|
235
339
|
// We want to complete the first request before letting other requests go;
|
|
@@ -249,40 +353,132 @@ export class MapLayerImageryProvider {
|
|
|
249
353
|
throw new Error("fetch call failed");
|
|
250
354
|
return response;
|
|
251
355
|
}
|
|
356
|
+
/** Records the given URL's origin and transitions the status to [[MapLayerImageryProviderStatus.UntrustedOrigin]].
|
|
357
|
+
* Called when a request received an authentication challenge that could not be answered because the origin
|
|
358
|
+
* is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
359
|
+
* Raises [[onStatusChanged]] on the status transition, and again whenever a new origin is added.
|
|
360
|
+
* @internal
|
|
361
|
+
*/
|
|
362
|
+
reportBlockedOrigin(url) {
|
|
363
|
+
const origin = tryGetOrigin(url) ?? url;
|
|
364
|
+
const isNewOrigin = !this._blockedOrigins.has(origin);
|
|
365
|
+
this._blockedOrigins.add(origin);
|
|
366
|
+
if (this._status !== MapLayerImageryProviderStatus.UntrustedOrigin)
|
|
367
|
+
this.setStatus(MapLayerImageryProviderStatus.UntrustedOrigin);
|
|
368
|
+
else if (isNewOrigin)
|
|
369
|
+
this.onStatusChanged.raiseEvent(this); // status unchanged, but a new origin was blocked
|
|
370
|
+
}
|
|
371
|
+
/** Logs a warning (once per origin, app-wide) when credentials are sent to an origin that would be blocked
|
|
372
|
+
* if [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] were enabled.
|
|
373
|
+
* Helps applications discover the origins they need to whitelist before opting in to the restriction.
|
|
374
|
+
* See [[MapLayerFormatRegistry.logUntrustedOriginUse]].
|
|
375
|
+
* @internal
|
|
376
|
+
*/
|
|
377
|
+
logUntrustedOriginUse(url) {
|
|
378
|
+
IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(url);
|
|
379
|
+
}
|
|
380
|
+
/** The redirect policy to apply to a request that carries browser credentials (see [[includeUserCredentials]]).
|
|
381
|
+
*
|
|
382
|
+
* When [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled, redirects are refused
|
|
383
|
+
* outright (`"error"`). `fetch` cannot be asked to follow only same-origin redirects, and by the time a
|
|
384
|
+
* followed redirect can be inspected the credentials have already been delivered to the destination — so
|
|
385
|
+
* refusing is the only way to honour the guarantee that credentials reach none but the origins listed in
|
|
386
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]]. Legitimate same-origin redirects fail as a result;
|
|
387
|
+
* that is the cost of the opt-in restriction.
|
|
388
|
+
*
|
|
389
|
+
* When the restriction is disabled (the default), redirects are followed as before and
|
|
390
|
+
* [[checkCredentialedRedirect]] reports the destination after the fact.
|
|
391
|
+
* @internal
|
|
392
|
+
*/
|
|
393
|
+
get credentialedRedirect() {
|
|
394
|
+
return IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
|
|
395
|
+
}
|
|
396
|
+
/** Detects that a request carrying browser credentials (see [[includeUserCredentials]]) was transparently
|
|
397
|
+
* redirected to a different origin, and reports or logs that origin.
|
|
398
|
+
*
|
|
399
|
+
* This is a **best-effort, after-the-fact** signal used only while
|
|
400
|
+
* [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is disabled, where credentialed requests
|
|
401
|
+
* still follow redirects (see [[credentialedRedirect]]). It cannot prevent the exposure — the credentials
|
|
402
|
+
* have already been sent — and it does not fire at all when the destination denies CORS, because `fetch`
|
|
403
|
+
* then rejects instead of returning a `Response`. The destination origin is never latched as SSO-succeeded,
|
|
404
|
+
* so credentials do not keep flowing to it.
|
|
405
|
+
* @internal
|
|
406
|
+
*/
|
|
407
|
+
checkCredentialedRedirect(requestedUrl, response) {
|
|
408
|
+
const finalOrigin = tryGetOrigin(response.url);
|
|
409
|
+
if (!response.url || finalOrigin === undefined || finalOrigin === tryGetOrigin(requestedUrl))
|
|
410
|
+
return;
|
|
411
|
+
if (!this.isSsoAllowed(response.url))
|
|
412
|
+
this.reportBlockedOrigin(response.url);
|
|
413
|
+
else
|
|
414
|
+
this.logUntrustedOriginUse(response.url); // no-op when the restriction is enabled
|
|
415
|
+
}
|
|
252
416
|
/** @internal */
|
|
253
417
|
async makeRequest(url, timeoutMs, authorization) {
|
|
254
418
|
let response;
|
|
255
419
|
let headers;
|
|
256
420
|
let hasCreds = false;
|
|
421
|
+
// Whether this request had basic-auth credentials of its own to offer. Requests carrying a caller-supplied
|
|
422
|
+
// `authorization` are excluded: those bypass the origin policy entirely.
|
|
423
|
+
const hasSettingsCreds = !authorization && !!this._settings.userName && !!this._settings.password;
|
|
257
424
|
if (authorization) {
|
|
258
425
|
headers = new Headers();
|
|
259
426
|
headers.set("Authorization", authorization);
|
|
260
427
|
}
|
|
261
|
-
else if (
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
428
|
+
else if (hasSettingsCreds) {
|
|
429
|
+
if (this.isCredentialsSharingAllowed(url)) {
|
|
430
|
+
hasCreds = true;
|
|
431
|
+
headers = new Headers();
|
|
432
|
+
this.setRequestAuthorization(headers);
|
|
433
|
+
if (!this.matchesSettingsUrlOrigin(url))
|
|
434
|
+
this.logUntrustedOriginUse(url);
|
|
435
|
+
}
|
|
265
436
|
}
|
|
437
|
+
const includeCredentials = this.includeUserCredentials(url);
|
|
266
438
|
const opts = {
|
|
267
439
|
method: "GET",
|
|
268
440
|
headers,
|
|
269
|
-
credentials:
|
|
441
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
442
|
+
redirect: includeCredentials ? this.credentialedRedirect : undefined,
|
|
270
443
|
};
|
|
271
444
|
if (timeoutMs !== undefined)
|
|
272
445
|
setRequestTimeout(opts, timeoutMs);
|
|
273
446
|
response = await fetch(url, opts);
|
|
447
|
+
if (includeCredentials)
|
|
448
|
+
this.checkCredentialedRedirect(url, response);
|
|
449
|
+
// fetch follows redirects transparently, so all trust decisions below target the final
|
|
450
|
+
// (post-redirect) URL reported by the response, not the URL we asked for.
|
|
451
|
+
const challengedUrl = response.url || url;
|
|
274
452
|
if (response.status === 401
|
|
275
453
|
&& headersIncludeAuthMethod(response.headers, ["ntlm", "negotiate"])
|
|
276
|
-
&& !
|
|
454
|
+
&& !includeCredentials
|
|
277
455
|
&& !hasCreds) {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
456
|
+
if (this.isSsoAllowed(challengedUrl)) {
|
|
457
|
+
// Removed the previous headers and make sure "include" credentials is set
|
|
458
|
+
opts.headers = undefined;
|
|
459
|
+
opts.credentials = "include";
|
|
460
|
+
// A Negotiate/NTLM handshake is normally a same-URL 401 round-trip, but in legacy mode we preserve
|
|
461
|
+
// the previous behavior and allow the browser to follow redirects after the authenticated retry.
|
|
462
|
+
opts.redirect = IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
|
|
463
|
+
this.logUntrustedOriginUse(challengedUrl);
|
|
464
|
+
// We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
|
|
465
|
+
response = await fetch(challengedUrl, opts);
|
|
466
|
+
if (response.status === 200) {
|
|
467
|
+
this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
|
|
468
|
+
}
|
|
285
469
|
}
|
|
470
|
+
else {
|
|
471
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
else if ((response.status === 401 || response.status === 403) && hasSettingsCreds && !this.isCredentialsSharingAllowed(challengedUrl)) {
|
|
475
|
+
// Some servers answer an unauthenticated request with 403 (Forbidden) rather than a 401 challenge;
|
|
476
|
+
// since this request could not present its credentials to the challenging origin, either status most
|
|
477
|
+
// likely results from that. The permission is recomputed for the challenged URL rather than reusing the
|
|
478
|
+
// decision made for the requested one: `fetch` strips the Authorization header when it follows a
|
|
479
|
+
// cross-origin redirect, so a trusted request can still arrive unauthenticated at an untrusted origin,
|
|
480
|
+
// and conversely a request that started out untrusted may end up at an origin that is trusted.
|
|
481
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
286
482
|
}
|
|
287
483
|
return response;
|
|
288
484
|
}
|
|
@@ -314,16 +510,28 @@ export class MapLayerImageryProvider {
|
|
|
314
510
|
}
|
|
315
511
|
/** @internal */
|
|
316
512
|
async toolTipFromUrl(strings, url) {
|
|
317
|
-
|
|
318
|
-
this.
|
|
513
|
+
let headers;
|
|
514
|
+
if (this.isCredentialsSharingAllowed(url)) {
|
|
515
|
+
headers = new Headers();
|
|
516
|
+
this.setRequestAuthorization(headers);
|
|
517
|
+
}
|
|
319
518
|
try {
|
|
519
|
+
const includeCredentials = this.includeUserCredentials(url);
|
|
320
520
|
const response = await fetch(url, {
|
|
321
521
|
method: "GET",
|
|
322
522
|
headers,
|
|
323
|
-
credentials:
|
|
523
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
524
|
+
redirect: includeCredentials ? this.credentialedRedirect : undefined,
|
|
324
525
|
});
|
|
325
|
-
|
|
326
|
-
|
|
526
|
+
if (includeCredentials)
|
|
527
|
+
this.checkCredentialedRedirect(url, response);
|
|
528
|
+
let text = await response.text();
|
|
529
|
+
if (text) {
|
|
530
|
+
// Tooltip content (e.g. WMS GetFeatureInfo responses) is rendered as HTML downstream and may
|
|
531
|
+
// deliberately contain markup; text from origins not trusted for credentials is escaped.
|
|
532
|
+
// fetch follows redirects transparently, so the text may come from a different origin than requested.
|
|
533
|
+
if (!this.isCredentialsSharingAllowed(response.url || url))
|
|
534
|
+
text = escapeHtml(text);
|
|
327
535
|
strings.push(text);
|
|
328
536
|
}
|
|
329
537
|
}
|