(window, allowedHostnames)
| 255 | * @visibleForTesting |
| 256 | */ |
| 257 | export function validateAllowedEmbeddingOrigins(window, allowedHostnames) { |
| 258 | if (!window.document.referrer) { |
| 259 | throw new Error('Referrer expected: ' + window.location.href); |
| 260 | } |
| 261 | const ancestors = window.location.ancestorOrigins; |
| 262 | // We prefer the unforgable ancestorOrigins, but referrer is better than |
| 263 | // nothing. |
| 264 | const ancestor = ancestors ? ancestors[0] : window.document.referrer; |
| 265 | let {hostname} = parseUrlDeprecated(ancestor); |
| 266 | if (isProxyOrigin(ancestor)) { |
| 267 | // If we are on the cache domain, parse the source hostname from |
| 268 | // the referrer. The referrer is used because it should be |
| 269 | // trustable. |
| 270 | hostname = parseUrlDeprecated( |
| 271 | getSourceUrl(window.document.referrer) |
| 272 | ).hostname; |
| 273 | } |
| 274 | for (let i = 0; i < allowedHostnames.length; i++) { |
| 275 | // Either the hostname is allowed |
| 276 | if (allowedHostnames[i] == hostname) { |
| 277 | return; |
| 278 | } |
| 279 | // Or it ends in .$hostname (aka is a sub domain of an allowed domain. |
| 280 | if (endsWith(hostname, '.' + allowedHostnames[i])) { |
| 281 | return; |
| 282 | } |
| 283 | } |
| 284 | throw new Error( |
| 285 | 'Invalid embedding hostname: ' + hostname + ' not in ' + allowedHostnames |
| 286 | ); |
| 287 | } |
| 288 | |
| 289 | /** |
| 290 | * Throws if this window is a top level window. |
no test coverage detected