UNPKG

12.5 kBJavaScriptView Raw
1"use strict";
2/*
3 * Copyright (c) Microsoft Corporation. All rights reserved.
4 * Licensed under the MIT License.
5 */
6Object.defineProperty(exports, "__esModule", { value: true });
7exports.WindowUtils = void 0;
8var ClientAuthError_1 = require("../error/ClientAuthError");
9var UrlUtils_1 = require("./UrlUtils");
10var Constants_1 = require("./Constants");
11var TimeUtils_1 = require("./TimeUtils");
12var WindowUtils = /** @class */ (function () {
13 function WindowUtils() {
14 }
15 /**
16 * @hidden
17 * Checks if the current page is running in an iframe.
18 * @ignore
19 */
20 WindowUtils.isInIframe = function () {
21 return window.parent !== window;
22 };
23 /**
24 * @hidden
25 * Check if the current page is running in a popup.
26 * @ignore
27 */
28 WindowUtils.isInPopup = function () {
29 return !!(window.opener && window.opener !== window);
30 };
31 /**
32 * @hidden
33 * @param prefix
34 * @param scopes
35 * @param authority
36 */
37 WindowUtils.generateFrameName = function (prefix, requestSignature) {
38 return "" + prefix + Constants_1.Constants.resourceDelimiter + requestSignature;
39 };
40 /**
41 * @hidden
42 * Polls an iframe until it loads a url with a hash
43 * @ignore
44 */
45 WindowUtils.monitorIframeForHash = function (contentWindow, timeout, urlNavigate, logger) {
46 return new Promise(function (resolve, reject) {
47 /*
48 * Polling for iframes can be purely timing based,
49 * since we don't need to account for interaction.
50 */
51 var nowMark = TimeUtils_1.TimeUtils.relativeNowMs();
52 var timeoutMark = nowMark + timeout;
53 logger.verbose("monitorWindowForIframe polling started");
54 var intervalId = setInterval(function () {
55 if (TimeUtils_1.TimeUtils.relativeNowMs() > timeoutMark) {
56 logger.error("monitorIframeForHash unable to find hash in url, timing out");
57 logger.errorPii("monitorIframeForHash polling timed out for url: " + urlNavigate);
58 clearInterval(intervalId);
59 reject(ClientAuthError_1.ClientAuthError.createTokenRenewalTimeoutError());
60 return;
61 }
62 var href;
63 try {
64 /*
65 * Will throw if cross origin,
66 * which should be caught and ignored
67 * since we need the interval to keep running while on STS UI.
68 */
69 href = contentWindow.location.href;
70 }
71 catch (e) { }
72 if (href && UrlUtils_1.UrlUtils.urlContainsHash(href)) {
73 logger.verbose("monitorIframeForHash found url in hash");
74 clearInterval(intervalId);
75 resolve(contentWindow.location.hash);
76 }
77 }, WindowUtils.POLLING_INTERVAL_MS);
78 });
79 };
80 /**
81 * @hidden
82 * Polls a popup until it loads a url with a hash
83 * @ignore
84 */
85 WindowUtils.monitorPopupForHash = function (contentWindow, timeout, urlNavigate, logger) {
86 return new Promise(function (resolve, reject) {
87 /*
88 * Polling for popups needs to be tick-based,
89 * since a non-trivial amount of time can be spent on interaction (which should not count against the timeout).
90 */
91 var maxTicks = timeout / WindowUtils.POLLING_INTERVAL_MS;
92 var ticks = 0;
93 logger.verbose("monitorWindowForHash polling started");
94 var intervalId = setInterval(function () {
95 if (contentWindow.closed) {
96 logger.error("monitorWindowForHash window closed");
97 clearInterval(intervalId);
98 reject(ClientAuthError_1.ClientAuthError.createUserCancelledError());
99 return;
100 }
101 var href;
102 try {
103 /*
104 * Will throw if cross origin,
105 * which should be caught and ignored
106 * since we need the interval to keep running while on STS UI.
107 */
108 href = contentWindow.location.href;
109 }
110 catch (e) { }
111 // Don't process blank pages or cross domain
112 if (!href || href === "about:blank") {
113 return;
114 }
115 /*
116 * Only run clock when we are on same domain for popups
117 * as popup operations can take a long time.
118 */
119 ticks++;
120 if (href && UrlUtils_1.UrlUtils.urlContainsHash(href)) {
121 logger.verbose("monitorPopupForHash found url in hash");
122 clearInterval(intervalId);
123 var hash = contentWindow.location.hash;
124 WindowUtils.clearUrlFragment(contentWindow);
125 resolve(hash);
126 }
127 else if (ticks > maxTicks) {
128 logger.error("monitorPopupForHash unable to find hash in url, timing out");
129 logger.errorPii("monitorPopupForHash polling timed out for url: " + urlNavigate);
130 clearInterval(intervalId);
131 reject(ClientAuthError_1.ClientAuthError.createTokenRenewalTimeoutError());
132 }
133 }, WindowUtils.POLLING_INTERVAL_MS);
134 });
135 };
136 /**
137 * @hidden
138 * Loads iframe with authorization endpoint URL
139 * @ignore
140 */
141 WindowUtils.loadFrame = function (urlNavigate, frameName, timeoutMs, logger) {
142 var _this = this;
143 /*
144 * This trick overcomes iframe navigation in IE
145 * IE does not load the page consistently in iframe
146 */
147 logger.infoPii("LoadFrame: " + frameName);
148 return new Promise(function (resolve, reject) {
149 setTimeout(function () {
150 var frameHandle = _this.loadFrameSync(urlNavigate, frameName, logger);
151 if (!frameHandle) {
152 reject("Unable to load iframe with name: " + frameName);
153 return;
154 }
155 resolve(frameHandle);
156 }, timeoutMs);
157 });
158 };
159 /**
160 * @hidden
161 * Loads the iframe synchronously when the navigateTimeFrame is set to `0`
162 * @param urlNavigate
163 * @param frameName
164 * @param logger
165 */
166 WindowUtils.loadFrameSync = function (urlNavigate, frameName, logger) {
167 var frameHandle = WindowUtils.addHiddenIFrame(frameName, logger);
168 // returning to handle null in loadFrame, also to avoid null object access errors
169 if (!frameHandle) {
170 return null;
171 }
172 else if (frameHandle.src === "" || frameHandle.src === "about:blank") {
173 frameHandle.src = urlNavigate;
174 logger.infoPii("Frame Name : " + frameName + " Navigated to: " + urlNavigate);
175 }
176 return frameHandle;
177 };
178 /**
179 * @hidden
180 * Adds the hidden iframe for silent token renewal.
181 * @ignore
182 */
183 WindowUtils.addHiddenIFrame = function (iframeId, logger) {
184 if (typeof iframeId === "undefined") {
185 return null;
186 }
187 logger.info("Add msal iframe to document");
188 logger.infoPii("Add msal frame to document:" + iframeId);
189 var adalFrame = document.getElementById(iframeId);
190 if (!adalFrame) {
191 logger.verbose("Add msal iframe does not exist");
192 var ifr = document.createElement("iframe");
193 ifr.setAttribute("id", iframeId);
194 ifr.setAttribute("aria-hidden", "true");
195 ifr.style.visibility = "hidden";
196 ifr.style.position = "absolute";
197 ifr.style.width = ifr.style.height = "0";
198 ifr.style.border = "0";
199 ifr.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
200 adalFrame = document.getElementsByTagName("body")[0].appendChild(ifr);
201 }
202 else {
203 logger.verbose("Add msal iframe already exists");
204 }
205 return adalFrame;
206 };
207 /**
208 * @hidden
209 * Removes a hidden iframe from the page.
210 * @ignore
211 */
212 WindowUtils.removeHiddenIframe = function (iframe) {
213 if (document.body === iframe.parentNode) {
214 document.body.removeChild(iframe);
215 }
216 };
217 /**
218 * @hidden
219 * Find and return the iframe element with the given hash
220 * @ignore
221 */
222 WindowUtils.getIframeWithHash = function (hash) {
223 var iframes = document.getElementsByTagName("iframe");
224 var iframeArray = Array.apply(null, Array(iframes.length)).map(function (iframe, index) { return iframes.item(index); }); // eslint-disable-line prefer-spread
225 return iframeArray.filter(function (iframe) {
226 try {
227 return iframe.contentWindow.location.hash === hash;
228 }
229 catch (e) {
230 return false;
231 }
232 })[0];
233 };
234 /**
235 * @hidden
236 * Returns an array of all the popups opened by MSAL
237 * @ignore
238 */
239 WindowUtils.getPopups = function () {
240 if (!window.openedWindows) {
241 window.openedWindows = [];
242 }
243 return window.openedWindows;
244 };
245 /**
246 * @hidden
247 * Find and return the popup with the given hash
248 * @ignore
249 */
250 WindowUtils.getPopUpWithHash = function (hash) {
251 return WindowUtils.getPopups().filter(function (popup) {
252 try {
253 return popup.location.hash === hash;
254 }
255 catch (e) {
256 return false;
257 }
258 })[0];
259 };
260 /**
261 * @hidden
262 * Add the popup to the known list of popups
263 * @ignore
264 */
265 WindowUtils.trackPopup = function (popup) {
266 WindowUtils.getPopups().push(popup);
267 };
268 /**
269 * @hidden
270 * Close all popups
271 * @ignore
272 */
273 WindowUtils.closePopups = function () {
274 WindowUtils.getPopups().forEach(function (popup) { return popup.close(); });
275 };
276 /**
277 * @ignore
278 *
279 * blocks any login/acquireToken calls to reload from within a hidden iframe (generated for silent calls)
280 */
281 WindowUtils.blockReloadInHiddenIframes = function () {
282 // return an error if called from the hidden iframe created by the msal js silent calls
283 if (UrlUtils_1.UrlUtils.urlContainsHash(window.location.hash) && WindowUtils.isInIframe()) {
284 throw ClientAuthError_1.ClientAuthError.createBlockTokenRequestsInHiddenIframeError();
285 }
286 };
287 /**
288 *
289 * @param cacheStorage
290 */
291 WindowUtils.checkIfBackButtonIsPressed = function (cacheStorage) {
292 var redirectCache = cacheStorage.getItem(Constants_1.TemporaryCacheKeys.REDIRECT_REQUEST);
293 // if redirect request is set and there is no hash
294 if (redirectCache && !UrlUtils_1.UrlUtils.urlContainsHash(window.location.hash)) {
295 var splitCache = redirectCache.split(Constants_1.Constants.resourceDelimiter);
296 splitCache.shift();
297 var state = splitCache.length > 0 ? splitCache.join(Constants_1.Constants.resourceDelimiter) : null;
298 cacheStorage.resetTempCacheItems(state);
299 }
300 };
301 /**
302 * Removes url fragment from browser url
303 */
304 WindowUtils.clearUrlFragment = function (contentWindow) {
305 contentWindow.location.hash = "";
306 // Office.js sets history.replaceState to null
307 if (typeof contentWindow.history.replaceState === "function") {
308 // Full removes "#" from url
309 contentWindow.history.replaceState(null, null, "" + contentWindow.location.pathname + contentWindow.location.search);
310 }
311 };
312 /**
313 * @hidden
314 * Interval in milliseconds that we poll a window
315 * @ignore
316 */
317 WindowUtils.POLLING_INTERVAL_MS = 50;
318 return WindowUtils;
319}());
320exports.WindowUtils = WindowUtils;
321//# sourceMappingURL=WindowUtils.js.map
\No newline at end of file