| OLD | NEW |
| (Empty) |
| 1 <!DOCTYPE html> | |
| 2 <title>Service Worker: Navigation redirection</title> | |
| 3 <script src="../resources/testharness.js"></script> | |
| 4 <script src="../resources/testharnessreport.js"></script> | |
| 5 <script src="../resources/get-host-info.js?pipe=sub"></script> | |
| 6 <script src="resources/test-helpers.js"></script> | |
| 7 <body> | |
| 8 <script> | |
| 9 | |
| 10 var host_info = get_host_info(); | |
| 11 | |
| 12 // This test registers three Service Workers at SCOPE1, SCOPE2 and | |
| 13 // OTHER_ORIGIN_SCOPE. And checks the redirected page's URL and the requests | |
| 14 // which are intercepted by Service Worker while loading redirect page. | |
| 15 var BASE_URL = host_info['HTTP_ORIGIN'] + base_path(); | |
| 16 var OTHER_BASE_URL = host_info['HTTP_REMOTE_ORIGIN'] + base_path(); | |
| 17 | |
| 18 var SCOPE1 = BASE_URL + 'resources/navigation-redirect-scope1.php?'; | |
| 19 var SCOPE2 = BASE_URL + 'resources/navigation-redirect-scope2.php?'; | |
| 20 var OUT_SCOPE = BASE_URL + 'resources/navigation-redirect-out-scope.php?'; | |
| 21 var SCRIPT = 'resources/navigation-redirect-worker.js'; | |
| 22 | |
| 23 var OTHER_ORIGIN_IFRAME_URL = | |
| 24 OTHER_BASE_URL + 'resources/navigation-redirect-other-origin.html'; | |
| 25 var OTHER_ORIGIN_SCOPE = | |
| 26 OTHER_BASE_URL + 'resources/navigation-redirect-scope1.php?'; | |
| 27 var OTHER_ORIGIN_OUT_SCOPE = | |
| 28 OTHER_BASE_URL + 'resources/navigation-redirect-out-scope.php?'; | |
| 29 | |
| 30 var workers; | |
| 31 var other_origin_frame; | |
| 32 var setup_environment_promise; | |
| 33 var message_resolvers = {}; | |
| 34 var next_message_id = 0; | |
| 35 | |
| 36 function setup_environment(t) { | |
| 37 if (setup_environment_promise) | |
| 38 return setup_environment_promise; | |
| 39 setup_environment_promise = | |
| 40 with_iframe(OTHER_ORIGIN_IFRAME_URL) | |
| 41 .then(function(f) { | |
| 42 // In this frame we register a Service Worker at OTHER_ORIGIN_SCOPE. | |
| 43 // And will use this frame to communicate with the worker. | |
| 44 other_origin_frame = f; | |
| 45 return Promise.all( | |
| 46 [service_worker_unregister_and_register(t, SCRIPT, SCOPE1), | |
| 47 service_worker_unregister_and_register(t, SCRIPT, SCOPE2)]); | |
| 48 }) | |
| 49 .then(function(registrations) { | |
| 50 add_completion_callback(function() { | |
| 51 registrations[0].unregister(); | |
| 52 registrations[1].unregister(); | |
| 53 send_to_iframe(other_origin_frame, 'unregister') | |
| 54 .then(function() { other_origin_frame.remove(); }); | |
| 55 }); | |
| 56 workers = registrations.map(get_effective_worker); | |
| 57 return Promise.all([ | |
| 58 wait_for_state(t, workers[0], 'activated'), | |
| 59 wait_for_state(t, workers[1], 'activated'), | |
| 60 // This promise will resolve when |wait_for_worker_promise| | |
| 61 // in OTHER_ORIGIN_IFRAME_URL resolves. | |
| 62 send_to_iframe(other_origin_frame, 'wait_for_worker')]); | |
| 63 }); | |
| 64 return setup_environment_promise; | |
| 65 } | |
| 66 | |
| 67 function get_effective_worker(registration) { | |
| 68 if (registration.active) | |
| 69 return registration.active; | |
| 70 if (registration.waiting) | |
| 71 return registration.waiting; | |
| 72 if (registration.installing) | |
| 73 return registration.installing; | |
| 74 } | |
| 75 | |
| 76 function check_all_intercepted_urls(expected_urls) { | |
| 77 return Promise.all( | |
| 78 [ | |
| 79 // Gets the request URLs which are intercepted by SCOPE1's SW. | |
| 80 get_intercepted_urls(workers[0]), | |
| 81 // Gets the request URLs which are intercepted by SCOPE2's SW. | |
| 82 get_intercepted_urls(workers[1]), | |
| 83 // Gets the request URLs which are intercepted by OTHER_ORIGIN_SCOPE's | |
| 84 // SW. This promise will resolve when get_intercepted_urls() in | |
| 85 // OTHER_ORIGIN_IFRAME_URL resolves. | |
| 86 send_to_iframe(other_origin_frame, 'get_intercepted_urls') | |
| 87 ]) | |
| 88 .then(function(urls) { | |
| 89 assert_object_equals( | |
| 90 urls, expected_urls, | |
| 91 'Intercepted URLs should match.'); | |
| 92 }); | |
| 93 } | |
| 94 | |
| 95 function test_redirect(url, expected_last_url, | |
| 96 expected_intercepted_urls) { | |
| 97 var message_promise = new Promise(function(resolve) { | |
| 98 // A message which ID is 'last_url' will be sent from the iframe. | |
| 99 message_resolvers['last_url'] = resolve; | |
| 100 }); | |
| 101 return with_iframe(url) | |
| 102 .then(function(f) { | |
| 103 f.remove(); | |
| 104 return check_all_intercepted_urls(expected_intercepted_urls); | |
| 105 }) | |
| 106 .then(function() { return message_promise; }) | |
| 107 .then(function(last_url) { | |
| 108 assert_equals( | |
| 109 last_url, expected_last_url, | |
| 110 'Last URL should match.'); | |
| 111 }); | |
| 112 } | |
| 113 | |
| 114 window.addEventListener('message', on_message, false); | |
| 115 | |
| 116 function on_message(e) { | |
| 117 if (e.origin != host_info['HTTP_REMOTE_ORIGIN'] && | |
| 118 e.origin != host_info['HTTP_ORIGIN'] ) { | |
| 119 console.error('invalid origin: ' + e.origin); | |
| 120 return; | |
| 121 } | |
| 122 var resolve = message_resolvers[e.data.id]; | |
| 123 delete message_resolvers[e.data.id]; | |
| 124 resolve(e.data.result); | |
| 125 } | |
| 126 | |
| 127 function send_to_iframe(frame, message) { | |
| 128 var message_id = next_message_id++; | |
| 129 return new Promise(function(resolve) { | |
| 130 message_resolvers[message_id] = resolve; | |
| 131 frame.contentWindow.postMessage( | |
| 132 {id: message_id, message: message}, | |
| 133 host_info['HTTP_REMOTE_ORIGIN']); | |
| 134 }); | |
| 135 } | |
| 136 | |
| 137 function get_intercepted_urls(worker) { | |
| 138 return new Promise(function(resolve) { | |
| 139 var channel = new MessageChannel(); | |
| 140 channel.port1.onmessage = function(msg) { resolve(msg.data.urls); }; | |
| 141 worker.postMessage({port: channel.port2}, [channel.port2]); | |
| 142 }); | |
| 143 } | |
| 144 | |
| 145 // Normal redirect. | |
| 146 promise_test(function(t) { | |
| 147 return setup_environment(t).then(function() { | |
| 148 return test_redirect( | |
| 149 OUT_SCOPE + 'url=' + encodeURIComponent(SCOPE1), | |
| 150 SCOPE1, | |
| 151 [[SCOPE1], [], []]); | |
| 152 }); | |
| 153 }, 'Normal redirect to same-origin scope.'); | |
| 154 promise_test(function(t) { | |
| 155 return setup_environment(t).then(function() { | |
| 156 return test_redirect( | |
| 157 OUT_SCOPE + 'url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
| 158 OTHER_ORIGIN_SCOPE, | |
| 159 [[], [], [OTHER_ORIGIN_SCOPE]]); | |
| 160 }); | |
| 161 }, 'Normal redirect to other-origin scope.'); | |
| 162 | |
| 163 // SW fallbacked redirect. SW doesn't handle the fetch request. | |
| 164 promise_test(function(t) { | |
| 165 return setup_environment(t).then(function() { | |
| 166 return test_redirect( | |
| 167 SCOPE1 + 'url=' + encodeURIComponent(OUT_SCOPE), | |
| 168 OUT_SCOPE, | |
| 169 [[SCOPE1 + 'url=' + encodeURIComponent(OUT_SCOPE)], [], []]); | |
| 170 }); | |
| 171 }, 'SW-fallbacked redirect to same-origin out-scope.'); | |
| 172 promise_test(function(t) { | |
| 173 return setup_environment(t).then(function() { | |
| 174 return test_redirect( | |
| 175 SCOPE1 + 'url=' + encodeURIComponent(SCOPE1), | |
| 176 SCOPE1, | |
| 177 [[SCOPE1 + 'url=' + encodeURIComponent(SCOPE1), SCOPE1], [], []]); | |
| 178 }); | |
| 179 }, 'SW-fallbacked redirect to same-origin same-scope.'); | |
| 180 promise_test(function(t) { | |
| 181 return setup_environment(t).then(function() { | |
| 182 return test_redirect( | |
| 183 SCOPE1 + 'url=' + encodeURIComponent(SCOPE2), | |
| 184 SCOPE2, | |
| 185 [[SCOPE1 + 'url=' + encodeURIComponent(SCOPE2)], [SCOPE2], []]); | |
| 186 }); | |
| 187 }, 'SW-fallbacked redirect to same-origin other-scope.'); | |
| 188 promise_test(function(t) { | |
| 189 return setup_environment(t).then(function() { | |
| 190 return test_redirect( | |
| 191 SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE), | |
| 192 OTHER_ORIGIN_OUT_SCOPE, | |
| 193 [[SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE)], | |
| 194 [], | |
| 195 []]); | |
| 196 }); | |
| 197 }, 'SW-fallbacked redirect to other-origin out-scope.'); | |
| 198 promise_test(function(t) { | |
| 199 return setup_environment(t).then(function() { | |
| 200 return test_redirect( | |
| 201 SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
| 202 OTHER_ORIGIN_SCOPE, | |
| 203 [[SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE)], | |
| 204 [], | |
| 205 [OTHER_ORIGIN_SCOPE]]); | |
| 206 }); | |
| 207 }, 'SW-fallbacked redirect to other-origin in-scope.'); | |
| 208 | |
| 209 // SW generated redirect. | |
| 210 // SW: event.respondWith(Response.redirect(params['url'])); | |
| 211 promise_test(function(t) { | |
| 212 return setup_environment(t).then(function() { | |
| 213 return test_redirect( | |
| 214 SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE), | |
| 215 OUT_SCOPE, | |
| 216 [[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE)], [], []]); | |
| 217 }); | |
| 218 }, 'SW-generated redirect to same-origin out-scope.'); | |
| 219 promise_test(function(t) { | |
| 220 return setup_environment(t).then(function() { | |
| 221 return test_redirect( | |
| 222 SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE1), | |
| 223 SCOPE1, | |
| 224 [[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE1), SCOPE1], | |
| 225 [], | |
| 226 []]); | |
| 227 }); | |
| 228 }, 'SW-generated redirect to same-origin same-scope.'); | |
| 229 promise_test(function(t) { | |
| 230 return setup_environment(t).then(function() { | |
| 231 return test_redirect( | |
| 232 SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE2), | |
| 233 SCOPE2, | |
| 234 [[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE2)], | |
| 235 [SCOPE2], | |
| 236 []]); | |
| 237 }); | |
| 238 }, 'SW-generated redirect to same-origin other-scope.'); | |
| 239 promise_test(function(t) { | |
| 240 return setup_environment(t).then(function() { | |
| 241 return test_redirect( | |
| 242 SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE), | |
| 243 OTHER_ORIGIN_OUT_SCOPE, | |
| 244 [[SCOPE1 + 'sw=gen&url=' + | |
| 245 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE)], | |
| 246 [], | |
| 247 []]); | |
| 248 }); | |
| 249 }, 'SW-generated redirect to other-origin out-scope.'); | |
| 250 promise_test(function(t) { | |
| 251 return setup_environment(t).then(function() { | |
| 252 return test_redirect( | |
| 253 SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
| 254 OTHER_ORIGIN_SCOPE, | |
| 255 [[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE)], | |
| 256 [], | |
| 257 [OTHER_ORIGIN_SCOPE]]); | |
| 258 }); | |
| 259 }, 'SW-generated redirect to other-origin in-scope.'); | |
| 260 | |
| 261 // SW fetched redirect. | |
| 262 // SW: event.respondWith(fetch(event.request)); | |
| 263 promise_test(function(t) { | |
| 264 return setup_environment(t).then(function() { | |
| 265 return test_redirect( | |
| 266 SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(OUT_SCOPE), | |
| 267 OUT_SCOPE, | |
| 268 [[SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(OUT_SCOPE)], | |
| 269 [], | |
| 270 []]); | |
| 271 }); | |
| 272 }, 'SW-fetched redirect to same-origin out-scope.'); | |
| 273 promise_test(function(t) { | |
| 274 return setup_environment(t).then(function() { | |
| 275 return test_redirect( | |
| 276 SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE1), | |
| 277 SCOPE1, | |
| 278 [[SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE1), SCOPE1], | |
| 279 [], | |
| 280 []]); | |
| 281 }); | |
| 282 }, 'SW-fetched redirect to same-origin same-scope.'); | |
| 283 promise_test(function(t) { | |
| 284 return setup_environment(t).then(function() { | |
| 285 return test_redirect( | |
| 286 SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE2), | |
| 287 SCOPE2, | |
| 288 [[SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE2)], | |
| 289 [SCOPE2], | |
| 290 []]); | |
| 291 }); | |
| 292 }, 'SW-fetched redirect to same-origin other-scope.'); | |
| 293 promise_test(function(t) { | |
| 294 return setup_environment(t).then(function() { | |
| 295 return test_redirect( | |
| 296 SCOPE1 + 'sw=fetch&url=' + | |
| 297 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE), | |
| 298 OTHER_ORIGIN_OUT_SCOPE, | |
| 299 [[SCOPE1 + 'sw=fetch&url=' + | |
| 300 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE)], | |
| 301 [], | |
| 302 []]); | |
| 303 }); | |
| 304 }, 'SW-fetched redirect to other-origin out-scope.'); | |
| 305 promise_test(function(t) { | |
| 306 return setup_environment(t).then(function() { | |
| 307 return test_redirect( | |
| 308 SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
| 309 OTHER_ORIGIN_SCOPE, | |
| 310 [[SCOPE1 + 'sw=fetch&url=' + | |
| 311 encodeURIComponent(OTHER_ORIGIN_SCOPE)], | |
| 312 [], | |
| 313 [OTHER_ORIGIN_SCOPE]]); | |
| 314 }); | |
| 315 }, 'SW-fetched redirect to other-origin in-scope.'); | |
| 316 | |
| 317 // Opaque redirect. | |
| 318 // SW: event.respondWith(fetch( | |
| 319 // new Request(event.request.url, {redirect: 'manual'}))); | |
| 320 promise_test(function(t) { | |
| 321 return setup_environment(t).then(function() { | |
| 322 return test_redirect( | |
| 323 SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(OUT_SCOPE), | |
| 324 OUT_SCOPE, | |
| 325 [[SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(OUT_SCOPE)], | |
| 326 [], | |
| 327 []]); | |
| 328 }); | |
| 329 }, 'Redirect to same-origin out-scope with opaque redirect response.'); | |
| 330 promise_test(function(t) { | |
| 331 return setup_environment(t).then(function() { | |
| 332 return test_redirect( | |
| 333 SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(SCOPE1), | |
| 334 SCOPE1, | |
| 335 [[SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(SCOPE1), SCOPE1], | |
| 336 [], | |
| 337 []]); | |
| 338 }); | |
| 339 }, 'Redirect to same-origin same-scope with opaque redirect response.'); | |
| 340 promise_test(function(t) { | |
| 341 return setup_environment(t).then(function() { | |
| 342 return test_redirect( | |
| 343 SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(SCOPE2), | |
| 344 SCOPE2, | |
| 345 [[SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(SCOPE2)], | |
| 346 [SCOPE2], | |
| 347 []]); | |
| 348 }); | |
| 349 }, 'Redirect to same-origin other-scope with opaque redirect response.'); | |
| 350 promise_test(function(t) { | |
| 351 return setup_environment(t).then(function() { | |
| 352 return test_redirect( | |
| 353 SCOPE1 + 'sw=opaque&url=' + | |
| 354 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE), | |
| 355 OTHER_ORIGIN_OUT_SCOPE, | |
| 356 [[SCOPE1 + 'sw=opaque&url=' + | |
| 357 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE)], | |
| 358 [], | |
| 359 []]); | |
| 360 }); | |
| 361 }, 'Redirect to other-origin out-scope with opaque redirect response.'); | |
| 362 promise_test(function(t) { | |
| 363 return setup_environment(t).then(function() { | |
| 364 return test_redirect( | |
| 365 SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
| 366 OTHER_ORIGIN_SCOPE, | |
| 367 [[SCOPE1 + 'sw=opaque&url=' + | |
| 368 encodeURIComponent(OTHER_ORIGIN_SCOPE)], | |
| 369 [], | |
| 370 [OTHER_ORIGIN_SCOPE]]); | |
| 371 }); | |
| 372 }, 'Redirect to other-origin in-scope with opaque redirect response.'); | |
| 373 promise_test(function(t) { | |
| 374 return setup_environment(t).then(function() { | |
| 375 return test_redirect( | |
| 376 SCOPE1 + 'sw=opaque&noLocationRedirect', | |
| 377 SCOPE1 + 'sw=opaque&noLocationRedirect', | |
| 378 [[SCOPE1 + 'sw=opaque&noLocationRedirect'], | |
| 379 [], | |
| 380 []]); | |
| 381 }); | |
| 382 }, 'No location redirect response.'); | |
| 383 | |
| 384 // Opaque redirect passed through Cache. | |
| 385 // SW responds with an opaque redirectresponse from the Cache API. | |
| 386 promise_test(function(t) { | |
| 387 return setup_environment(t).then(function() { | |
| 388 return test_redirect( | |
| 389 SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
| 390 encodeURIComponent(OUT_SCOPE), | |
| 391 OUT_SCOPE, | |
| 392 [[SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
| 393 encodeURIComponent(OUT_SCOPE)], | |
| 394 [], | |
| 395 []]); | |
| 396 }); | |
| 397 }, | |
| 398 'Redirect to same-origin out-scope with opaque redirect response which ' + | |
| 399 'is passed through Cache.'); | |
| 400 promise_test(function(t) { | |
| 401 return setup_environment(t).then(function() { | |
| 402 return test_redirect( | |
| 403 SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
| 404 encodeURIComponent(SCOPE1), | |
| 405 SCOPE1, | |
| 406 [[SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
| 407 encodeURIComponent(SCOPE1), SCOPE1], | |
| 408 [], | |
| 409 []]); | |
| 410 }); | |
| 411 }, | |
| 412 'Redirect to same-origin same-scope with opaque redirect response which ' + | |
| 413 'is passed through Cache.'); | |
| 414 promise_test(function(t) { | |
| 415 return setup_environment(t).then(function() { | |
| 416 return test_redirect( | |
| 417 SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
| 418 encodeURIComponent(SCOPE2), | |
| 419 SCOPE2, | |
| 420 [[SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
| 421 encodeURIComponent(SCOPE2)], | |
| 422 [SCOPE2], | |
| 423 []]); | |
| 424 }); | |
| 425 }, | |
| 426 'Redirect to same-origin other-scope with opaque redirect response which ' + | |
| 427 'is passed through Cache.'); | |
| 428 promise_test(function(t) { | |
| 429 return setup_environment(t).then(function() { | |
| 430 return test_redirect( | |
| 431 SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
| 432 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE), | |
| 433 OTHER_ORIGIN_OUT_SCOPE, | |
| 434 [[SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
| 435 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE)], | |
| 436 [], | |
| 437 []]); | |
| 438 }); | |
| 439 }, | |
| 440 'Redirect to other-origin out-scope with opaque redirect response which ' + | |
| 441 'is passed through Cache.'); | |
| 442 promise_test(function(t) { | |
| 443 return setup_environment(t).then(function() { | |
| 444 return test_redirect( | |
| 445 SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
| 446 encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
| 447 OTHER_ORIGIN_SCOPE, | |
| 448 [[SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
| 449 encodeURIComponent(OTHER_ORIGIN_SCOPE)], | |
| 450 [], | |
| 451 [OTHER_ORIGIN_SCOPE]]); | |
| 452 }); | |
| 453 }, | |
| 454 'Redirect to other-origin in-scope with opaque redirect response which ' + | |
| 455 'is passed through Cache.'); | |
| 456 promise_test(function(t) { | |
| 457 return setup_environment(t).then(function() { | |
| 458 return test_redirect( | |
| 459 SCOPE1 + 'sw=opaqueThroughCache&noLocationRedirect', | |
| 460 SCOPE1 + 'sw=opaqueThroughCache&noLocationRedirect', | |
| 461 [[SCOPE1 + 'sw=opaqueThroughCache&noLocationRedirect'], | |
| 462 [], | |
| 463 []]); | |
| 464 }); | |
| 465 }, 'No location redirect response via Cache.'); | |
| 466 | |
| 467 </script> | |
| 468 </body> | |
| OLD | NEW |