Blob Blame History Raw
var BASE_URL = 'example.com/tests/dom/base/test/bug704320.sjs';

function createTestUrl(schemeFrom, schemeTo, policy, action, type) {
  return schemeTo + '://' + BASE_URL + '?' +
         'action=' + action + '&' +
         'scheme=' + schemeFrom + '-to-' + schemeTo + '&' +
         'policy=' + policy + '&' +
         'type=' + type;
}

function create2ndLevelIframeUrl(schemeFrom, schemeTo, policy, type) {
  return schemeFrom + '://' + BASE_URL + '?' +
         'action=create-2nd-level-iframe&' +
         'scheme-from=' + schemeFrom + '&' +
         'scheme-to=' + schemeTo + '&' +
         'policy=' + policy + '&' +
         'type=' + type;
}

// Creates the following test cases for the specified scheme and referrer
// policy combination:
//   <link>
//   @import
//   font-face
//   bg-url
//   <script>
//   <img>
//   <iframe>
//   <audio>
//   <video>
//   <object type="bogus">
//   <object type="image/svg+xml">
//   <a>
//   <a ping>
//   <form>
//   window.location
//   window.open
//   XMLHttpRequest
//   EventSource
//   TODO: XSLT?
//
// This returns a page that loads all of the above resources and contains a
// script that clicks a link after all resources are (hopefully)
// loaded. The click triggers a redirection to file_bug704320_redirect.html,
// which in turn notifies the main window that it's time to check the test
// results.
function createTest(schemeFrom, schemeTo, policy, optionalEarlierPolicy) {
  var _createTestUrl = createTestUrl.bind(
      null, schemeFrom, schemeTo, policy, 'test');

  var _create2ndLevelIframeUrl = create2ndLevelIframeUrl.bind(
      null, schemeFrom, schemeTo, policy);

  var metaReferrerPolicyString = '';
  if (optionalEarlierPolicy && optionalEarlierPolicy != '') {
    metaReferrerPolicyString += '<meta name="referrer" content="' + optionalEarlierPolicy + '">\n';
  }
  metaReferrerPolicyString += '<meta name="referrer" content="' + policy + '">';

  return '<!DOCTYPE HTML>\n\
         <html>\n\
         <head>\n\
	    '+metaReferrerPolicyString+'\n\
           <link rel="stylesheet" type="text/css" href="' + _createTestUrl('stylesheet') + '">\n\
           <style type="text/css">\n\
             @import "' + _createTestUrl('import-css') + '";\n\
             @font-face {\n\
               font-family: "Fake Serif Bold";\n\
               src: url("' + _createTestUrl('font-face') + '");\n\
             }\n\
             body {\n\
               font-family: "Fake Serif Bold", serif;\n\
               background: url("' + _createTestUrl('bg-url') + '");\n\
             }\n\
           </style>\n\
         </head>\n\
         <body>\n\
           <script src="' + _createTestUrl('script') + '"></script>\n\
           <img src="' + _createTestUrl('img') + '"></img>\n\
           <iframe src="' + _createTestUrl('iframe') + '"></iframe>\n\
           <audio src="' + _createTestUrl('audio') + '"></audio>\n\
           <video src="' + _createTestUrl('video') + '"></video>\n\
           <object type="bogus" data="' + _createTestUrl('object') + '"></object>\n\
           <object type="image/svg+xml" data="' + _createTestUrl('object-svg') + '"></object>\n\
           <a id="link" href="' + _createTestUrl('link') + '" ping="' + _createTestUrl('link-ping') + '"></a>\n\
           <iframe src="' + _create2ndLevelIframeUrl('form') + '"></iframe>\n\
           <iframe src="' + _create2ndLevelIframeUrl('window.location') + '"></iframe>\n\
           <script>\n\
              var _testFinished = 0\n\
             (function() {\n\
               var x = new XMLHttpRequest();\n\
               x.open("GET", "' + _createTestUrl('xmlhttprequest') + '");\n\
               x.send();\n\
             })();\n\
             (function() {\n\
               var eventSource = new EventSource("' + _createTestUrl('eventsource') + '");\n\
             })();' +

             // LOAD EVENT (most of the tests)
             // fires when the resources for the page are loaded
             'var _isLoaded = false;\n\
             window.addEventListener("load", function() {\n\
               this._isLoaded = true;\n\
               this.checkForFinish();\n\
             }.bind(window), false);' +

             // WINDOW.OPEN test
             // listen for incoming status from window.open, close the window
             // and check if we're done.
             'var _openedWindowLoaded = false;\n\
             window.addEventListener("message", function(message) {\n\
               if (message.data == "window.open") {\n\
                 this._openedWindowLoaded = true;\n\
                 this.win.close();\n\
                 this.checkForFinish();\n\
               }\n\
             }.bind(window), false);\n\
             var win = window.open("' + _createTestUrl('window.open') + '", "");' +

             // called by the two things that must complete: window.open page
             // and the window load event.  When both are complete, this
             // "finishes" the iframe subtest by clicking the link.
             // _testFinished avoids calling this function twice (which may happen)
             'function checkForFinish() {\n\
               if (window._isLoaded && window._openedWindowLoaded && !window._testFinished) {\n\
                 window._testFinished = 1;\n\
                 document.getElementById("link").click();\n\
               }\n\
             }\n\
           </script>\n\
         </body>\n\
         </html>';
}

function createIframedFormTest(schemeFrom, schemeTo, policy) {
  var actionUrl = schemeTo + '://' + BASE_URL;

  return '<!DOCTYPE HTML>\n\
         <html>\n\
         <head>\n\
           <meta name="referrer" content="' + policy + '">\n\
         </head>\n\
         <body>\n\
           <form id="form" action="' + actionUrl + '">\n\
             <input type="hidden" name="action" value="test">\n\
             <input type="hidden" name="scheme" value="' + schemeFrom + '-to-' + schemeTo + '">\n\
             <input type="hidden" name="policy" value="' + policy + '">\n\
             <input type="hidden" name="type" value="form">\n\
           </form>\n\
           <script>\n\
             document.getElementById("form").submit();\n\
           </script>\n\
         </body>\n\
         </html>';
}

function createIframedWindowLocationTest(schemeFrom, schemeTo, policy) {
  var url = createTestUrl(
      schemeFrom, schemeTo, policy, 'test', 'window.location');

  return '<!DOCTYPE HTML>\n\
         <html>\n\
         <head>\n\
           <meta name="referrer" content="' + policy + '">\n\
         </head>\n\
         <body>\n\
           <script>\n\
            window.location = "' + url + '";\n\
           </script>\n\
         </body>\n\
         </html>';
}

function createPolicyTest(policy, optionalEarlierPolicy) {
  var metaReferrerPolicyString = '';
  if (optionalEarlierPolicy && optionalEarlierPolicy != '') {
    metaReferrerPolicyString += '<meta name="referrer" content="' + optionalEarlierPolicy + '">\n';
  }
  metaReferrerPolicyString += '<meta name="referrer" content="' + policy + '">';

  return '<!DOCTYPE HTML>\n\
          <html>\n\
          <head>\n\
	    '+metaReferrerPolicyString+'\n\
            <script type="text/javascript" src="/tests/dom/base/test/file_bug704320_preload_common.js"></script>\n\
          </head>\n\
          <body>\n\
            <img src="/tests/dom/base/test/bug704320_counter.sjs?type=img"\n\
                    onload="incrementLoad2(\'img\', 2);">\n\
            <img src="http://example.com/tests/dom/base/test/bug704320_counter.sjs?type=img"\n\
                    onload="incrementLoad2(\'img\', 2);">\n\
          </body>\n\
          </html>';
}

function handleRequest(request, response) {
  var sharedKey = 'bug704320.sjs';
  var params = request.queryString.split('&');
  var action = params[0].split('=')[1];

  if (action === 'create-1st-level-iframe') {
    // ?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=origin
    var schemeFrom = params[1].split('=')[1];
    var schemeTo = params[2].split('=')[1];
    var policy = params[3].split('=')[1];
    var optionalEarlierPolicy = '';
    if (params[4]) {
      optionalEarlierPolicy = params[4].split('=')[1];
    }

    response.setHeader('Content-Type', 'text/html; charset=utf-8', false);
    response.setHeader('Cache-Control', 'no-cache', false);
    response.write(createTest(schemeFrom, schemeTo, policy, optionalEarlierPolicy));
  }
  else if (action === 'create-2nd-level-iframe') {
    // ?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=origin&type=form"
    var schemeFrom = params[1].split('=')[1];
    var schemeTo = params[2].split('=')[1];
    var policy = params[3].split('=')[1];
    var type = params[4].split('=')[1];

    response.setHeader('Content-Type', 'text/html; charset=utf-8', false);
    response.setHeader('Cache-Control', 'no-cache', false);

    if (type === 'form') {
      response.write(createIframedFormTest(schemeFrom, schemeTo, policy));
    } else if (type === 'window.location') {
      response.write(createIframedWindowLocationTest(
            schemeFrom, schemeTo, policy));
    }
  }
  else if (action === 'test') {
    // ?action=test&scheme=http-to-https&policy=origin&type=img
    var scheme = params[1].split('=')[1];
    var policy = params[2].split('=')[1];
    var type = params[3].split('=')[1];
    var result = getSharedState(sharedKey);

    if (result === '') {
      result = {};
    } else {
      result = JSON.parse(result);
    }

    if (!result[type]) {
      result[type] = {};
    }

    if (!result[type][scheme]) {
      result[type][scheme] = {};
    }

    if (request.hasHeader('Referer')) {
      result[type][scheme][policy] = request.getHeader('Referer');
    } else {
      result[type][scheme][policy] = '';
    }

    setSharedState(sharedKey, JSON.stringify(result));

    if (type === 'link') {
      var loc = 'https://example.com/tests/dom/base/test/file_bug704320_redirect.html';
      response.setStatusLine('1.1', 302, 'Found');
      response.setHeader('Location', loc, false);
    }

    if (type === 'window.open') {
      response.setHeader('Cache-Control', 'no-cache', false);
      response.setHeader('Content-Type', 'text/html', false);
      response.write('<html><body><script>'
                   + 'window.opener.postMessage("window.open", "*");'
                   + '</script></body></html>');
    }
  }
  else if (action === 'get-test-results') {
    // ?action=get-result
    response.setHeader('Cache-Control', 'no-cache', false);
    response.setHeader('Content-Type', 'text/plain', false);
    response.write(getSharedState(sharedKey));
  }
  else if (action === 'generate-policy-test') {
    // ?action=generate-policy-test&policy=b64-encoded-string
    response.setHeader('Cache-Control', 'no-cache', false);
    response.setHeader('Content-Type', 'text/html', false);
    var policy = unescape(params[1].split('=')[1]);
    var optionalEarlierPolicy = '';
    if (params[2]) {
      optionalEarlierPolicy = params[2].split('=')[1];
    }

    response.write(createPolicyTest(policy, optionalEarlierPolicy));
  }
}