caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
author Nicholas D. Matsakis <nmatsakis@mozilla.com>
Thu, 01 Nov 2012 15:13:58 -0700
changeset 112021 35b68eb3abd141837359196b60218d103784e792
parent 109189 07a2bbf2c3323c268c234fb9906002a5bad4f187
permissions -rw-r--r--
Invalidate all compilation modes if only a JSScript* is available.

<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=758258
-->
<head>
  <meta charset="utf-8">
  <title>Test for nsIPrincipal extendedOrigin, appStatus and appId</title>
  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=758258">Mozilla Bug 758258</a>
<p id="display"></p>
<div id="content">

</div>
<pre id="test">
<script type="application/javascript;version=1.7">

/** Test for Bug 758258 **/

var Ci = Components.interfaces;

SimpleTest.waitForExplicitFinish();

/*
 * gData is an array of objects. Each object represents a test case.
 * - app: gives the app manifest URL, will set mozapp to it on the iframe;
 * - origin: gives the origin of the iframe. This is the URL thas is going to
 *           to be passed as iframe.src but also the expected principal's
 *           origin.
 * - isapp: tells if the iframe is really a mozapp. If the manifest url isn't
 *          valid, the iframe will not be considered as a mozapp.
 * - browser: say if the iframe should be a mozbrowser. This is implicit when
 *            app is set.
 * - test: an array of tests to run for this test case:
 *   - eo-unique: the extendedOrigin of the prinicpal must be unique in the
 *                current list.
 *   - eo-as-last: the extendedOrigin of the principal must be the same as the
 *                 last added to the list.
 */
var gData = [
  {
    app: "http://example.org/manifest.webapp",
    src: "http://example.org/",
    isapp: true,
    test: [ "eo-unique" ],
  },
  {
    app: "https://example.com/manifest.webapp",
    src: "https://example.com/",
    isapp: true,
    test: [ "eo-unique" ],
  },
  {
    app: "http://test1.example.org/manifest.webapp",
    src: "http://test1.example.org/",
    isapp: true,
    test: [ "eo-unique" ],
  },
  {
    app: "http://test1.example.org:8000/manifest.webapp",
    src: "http://test1.example.org:8000/",
    isapp: true,
    test: [ "eo-unique" ],
  },
  {
    app: "http://sub1.test1.example.org/manifest.webapp",
    src: "http://sub1.test1.example.org/",
    isapp: true,
    test: [ "eo-unique" ],
  },
// WebApps implementation doesn't allow apps with the same origin. Sad...
//  {
//    app: "http://example.org/foo/manifest.webapp",
//    src: "http://example.org/",
//    isapp: true,
//    test: [ "eo-unique" ],
//  },
//  {
//    app: "http://example.org/bar/manifest.webapp",
//    src: "http://example.org/",
//    isapp: true,
//    test: [ "eo-unique" ],
//  },
  {
    src: "http://example.org/",
    isapp: false,
    test: [ "eo-unique" ],
  },
  {
    browser: true,
    src: "http://example.org/",
    isapp: false,
    test: [ "eo-unique" ],
  },
  {
    app: "http://example.org/wedonthaveanyappinthatdirectory/manifest.webapp",
    src: "http://example.org/",
    isapp: false,
    // TODO: this is a browser because we need apps to be browser and it's not
    // an app because the manifest is invalid. Ideally, it should not be a
    // browser.
    browser: true,
    test: [ "eo-as-last" ],
  },
//  {
//    app: "http://example.org/manifest.webapp",
//    src: "data:text/html,foobar",
//    test: [ "todo-src" ],
//  },
//  {
//    app: "http://example.org/manifest.webapp",
//    src: "data:text/html,foobar2",
//    test: [ "todo-src" ],
//  },
  {
    src: "file:///",
    isapp: false,
    test: [ "eo-unique" ],
  },
  {
    src: "file:///tmp/",
    isapp: false,
    test: [ "eo-unique" ],
  },
  {
    app: "http://example.org/manifest.webapp",
    src: "file:///",
    isapp: true,
    test: [ "eo-unique", "in-app-not-installed" ],
  },
  {
    app: "http://example.org/manifest.webapp",
    src: "file:///tmp/",
    isapp: true,
    test: [ "eo-unique", "in-app-not-installed" ],
  },
  // iframe inside an app is part of the app.
  {
    app: "http://example.org/manifest.webapp",
    src: "http://example.org/",
    isapp: true,
    child: {
      src: "http://example.org/chrome/",
      isapp: true
    },
    test: [ "child-has-same-eo" ],
  },
  // app A inside app B aren't the same app.
  {
    app: "http://example.org/manifest.webapp",
    src: "http://example.org/",
    isapp: true,
    child: {
      app: "https://example.com/manifest.webapp",
      src: "https://example.com/chrome/",
      isapp: true
    },
    test: [ "child-has-different-eo", "child-has-same-appstatus", "child-has-different-appid" ],
  },
  // app A inside app A are the same app.
  {
    app: "http://example.org/manifest.webapp",
    src: "http://example.org/",
    isapp: true,
    child: {
      app: "http://example.org/manifest.webapp",
      src: "http://example.org/chrome/",
      isapp: true
    },
    test: [ "child-has-same-eo" ],
  },
  // app inside a regular iframe is an app.
  {
    src: "http://example.org/",
    isapp: false,
    child: {
      app: "http://example.org/manifest.webapp",
      src: "http://example.org/chrome/",
      isapp: true
    },
    test: [ "child-has-different-eo", "child-has-different-appstatus", "child-has-different-appid" ],
  },
  // browser inside app is a browser, has appid but isn't installed.
  {
    src: "http://example.org/",
    app: "http://example.org/manifest.webapp",
    isapp: true,
    child: {
      src: "http://example.org/chrome/",
      isapp: false,
      browser: true,
    },
    test: [ "child-has-different-eo", "child-has-different-appstatus", "child-has-same-appid" ],
  },
  // app inside a browser is an app.
  {
    src: "http://example.org/",
    isapp: false,
    browser: true,
    child: {
      app: "http://example.org/manifest.webapp",
      src: "http://example.org/chrome/",
      isapp: true,
    },
    test: [ "child-has-different-eo", "child-has-different-appstatus", "child-has-different-appid" ],
  },
  // browser inside a browser are two browsers
  {
    src: "http://example.org/",
    isapp: false,
    browser: true,
    child: {
      src: "http://example.org/chrome/",
      isapp: false,
      browser: true,
    },
    test: [ "child-has-same-eo" ],
  },
  // browser inside a browser are two browsers
  {
    src: "http://example.org/",
    isapp: false,
    browser: true,
    child: {
      src: "https://example.com/chrome/",
      isapp: false,
      browser: true,
    },
    test: [ "child-has-different-eo", "child-has-same-appstatus", "child-has-same-appid" ],
  },
  // iframe containing a browser
  {
    src: "http://example.org/",
    isapp: false,
    browser: false,
    child: {
      src: "http://example.org/chrome/",
      isapp: false,
      browser: true,
    },
    test: [ "child-has-different-eo", "child-has-same-appstatus", "child-has-same-appid" ],
  },
  // browser containing an iframe is part of the browser
  {
    src: "http://example.org/",
    isapp: false,
    browser: true,
    child: {
      src: "http://example.org/chrome/",
      isapp: false,
      inBrowser: true,
    },
    test: [ "child-has-same-eo" ],
  },
];

// The list of all data ids generated by this test.
var eoList = [];

var content = document.getElementById('content');
var checkedCount = 0;
var checksTodo = gData.length;

function checkIFrame(aFrame, data) {
  var principal = aFrame.contentDocument.nodePrincipal;

  if (!data.test) {
    data.test = [];
  }

  if (navigator.platform.indexOf("Mac") != -1) {
    is(principal.URI.spec,
       data.src.replace('file:///tmp/', 'file:///private/tmp/'),
       'the correct URL should have been loaded');
  } else {
    is(principal.URI.spec, data.src,
       'the correct URL should have been loaded');
  }

  if (data.isapp) {
    if (data.test.indexOf("in-app-not-installed") != -1) {
      is(principal.appStatus, Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED, 'this should not be an installed app');
    } else {
      is(principal.appStatus, Ci.nsIPrincipal.APP_STATUS_INSTALLED, 'this should be an installed app');
    }
  } else {
    is(principal.appStatus, Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED,
       'this should not be an installed app');
    is(principal.appId, Ci.nsIScriptSecurityManager.NO_APP_ID,
       "principals from non-installed app should have NO_APP_ID");
  }

  if (!data.isapp && !data.browser) {
    is(principal.extendedOrigin, principal.origin,
       'extendedOrigin should return the origin for non-app and non-browsers principals');
  } else {
    isnot(principal.extendedOrigin, principal.origin,
          'extendedOrigin should not return the origin for apps or mozbrowsers');
  }

  if (data.test.indexOf("eo-unique") != -1) {
    is(eoList.indexOf(principal.extendedOrigin), -1,
       "extendedOrigin should be unique");
  }
  if (data.test.indexOf("eo-as-last") != -1) {
    is(principal.extendedOrigin, eoList[eoList.length-1],
       "extendedOrigin should be the same as the last inserted one");
  }

  is(principal.isInBrowserElement, !!data.browser,
     "check principal.isInBrowserElement");

  if (data.child) {
    let childPrincipal = aFrame.contentWindow.frames[0].document.nodePrincipal;

    if (data.child.isapp) {
      is(childPrincipal.appStatus, Ci.nsIPrincipal.APP_STATUS_INSTALLED,
         "child should be an installed app");
    }

    is(childPrincipal.isInBrowserElement, !!data.child.browser || !!data.child.inBrowser,
       "check childPrincipal.isInBrowserElement");

    if (data.test.indexOf("child-has-same-eo") != -1) {
      is(childPrincipal.extendedOrigin, principal.extendedOrigin,
         "child should have the same extendedOrigin as parent");
      is(childPrincipal.appStatus, principal.appStatus,
         "child should have the same appStatus if it has the same extendedOrigin");
      is(childPrincipal.appId, principal.appId,
         "child should have the same appId if it has the same extendedOrigin");
    }

    if (data.test.indexOf("child-has-different-eo") != -1) {
      isnot(childPrincipal.extendedOrigin, principal.extendedOrigin,
            "child should not have the same extendedOrigin as parent");
    }

    if (data.test.indexOf("child-has-same-appstatus") != -1) {
      is(childPrincipal.appStatus, principal.appStatus,
         "childPrincipal and parent principal should have the same appStatus");
    }

    if (data.test.indexOf("child-has-different-appstatus") != -1) {
      isnot(childPrincipal.appStatus, principal.appStatus,
            "childPrincipal and parent principal should not have the same appStatus");
    }

    if (data.test.indexOf("child-has-same-appid") != -1) {
      is(childPrincipal.appId, principal.appId,
         "childPrincipal and parent principal should have the same appId");
    }

    if (data.test.indexOf("child-has-different-appid") != -1) {
      isnot(childPrincipal.appId, principal.appId,
            "childPrincipal and parent principal should have different appId");
    }
  }

  eoList.push(principal.extendedOrigin);

  checkedCount++;
  if (checkedCount == checksTodo) {
    SpecialPowers.removePermission("browser", "http://example.org");
    SpecialPowers.removePermission("embed-apps", "http://example.org");
    SimpleTest.finish();
  } else {
    gTestRunner.next();
  }
}

is('appStatus' in document.nodePrincipal, true,
   'appStatus should be present in nsIPrincipal');
is('extendedOrigin' in document.nodePrincipal, true,
   'extendedOrigin should be present in nsIPrincipal');
is('appId' in document.nodePrincipal, true,
   'appId should be present in nsIPrincipal');

function runTest() {
  // We want to use a generator. Those only work in a one level stack so we
  // can't use .forEach() here.
  for (var i=0; i<gData.length; ++i) {
    let data = gData[i];

    var iframe = document.createElement('iframe');
    iframe.check = function() {
      checkIFrame(this, data);
    };
    iframe.addChild = function() {
      SpecialPowers.addPermission("browser", true, iframe.contentDocument);
      SpecialPowers.addPermission("embed-apps", true, iframe.contentDocument);

      var childFrame = document.createElement('iframe');

      if (data.child.app) {
        childFrame.setAttribute('mozapp', data.child.app)
        childFrame.setAttribute('mozbrowser', '');
      } else if (data.child.browser) {
        childFrame.setAttribute('mozbrowser', '');
      }

      childFrame.src = data.child.src;

      this.removeEventListener('load', this.addChild.bind(this));
      childFrame.addEventListener('load', this.check.bind(this));

      this.contentDocument.body.appendChild(childFrame);
    };

    if (data.app) {
      iframe.setAttribute('mozapp', data.app);
      iframe.setAttribute('mozbrowser', '');
    } else if (data.browser) {
      iframe.setAttribute('mozbrowser', '');
    }

    iframe.src = data.src;

    if (data.child) {
      iframe.addEventListener('load', iframe.addChild.bind(iframe));
    } else {
      iframe.addEventListener('load', iframe.check.bind(iframe));
    }

    content.appendChild(iframe);

    yield;
  }
}

var gTestRunner = runTest();

SpecialPowers.pushPrefEnv({'set':[["dom.mozBrowserFramesEnabled", true]]},
                           function() { gTestRunner.next(); });

</script>
</pre>
</body>
</html>