Bug 1955324 Comment 1 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

I think I managed to create a minimal browser test case

```
const CHROME_URI = "chrome://global/content/aboutSupport.xhtml";

add_task(async function test_chrome_uri_in_new_tab() {
  // open a tab with system principal due to chrome URI
  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, CHROME_URI);
  let browser = tab.linkedBrowser;

  await SpecialPowers.spawn(browser, [CHROME_URI], async (CHROME_URI) => {
    let bc = content.browsingContext;
    let contentPrincipal = content.document.nodePrincipal;
    Assert.ok(contentPrincipal.isSystemPrincipal, "tab has system principal");
    Assert.ok(bc.isContent, "tab BC is content");

    // within a system context, add a new iframe
    let iframe = content.document.createElement("iframe");
    iframe.src = CHROME_URI;
    content.document.documentElement.appendChild(iframe);

    // iframe will start with some different principal
    let ifrBC = iframe.browsingContext;
    let aboutBlankPrincipal = iframe.contentDocument.nodePrincipal;
    Assert.ok(iframe.contentDocument.isUncommittedInitialDocument, "iframe at uncommitted initial doc");
    Assert.ok(!aboutBlankPrincipal.isSystemPrincipal, "initial about:blank doesn't have system principal");
    Assert.ok(aboutBlankPrincipal.isNullPrincipal, "initial about:blank starts out with null principal");
    Assert.ok(ifrBC.isContent, "iframe BC is content");

    // inner window will be replaced
    iframe.contentWindow.foo = "bar";
    iframe.contentWindow.addEventListener("load", () => {
      Assert.ok(false, "load event never fired on initial iframe inner window");
    });

    await new Promise(res => iframe.addEventListener("load", res));

    // after load, iframe has system principal and inner window was replaced
    let chromeDocPrincipal = iframe.contentDocument.nodePrincipal;
    Assert.ok(chromeDocPrincipal.isSystemPrincipal, "after load, iframe has system principal");
    Assert.ok(ifrBC.isContent, "iframe BC stays content");
    Assert.ok(iframe.contentWindow.foo == undefined, "iframe inner window replaced");

    iframe.remove();
  });

  BrowserTestUtils.removeTab(tab);
});
```

So is this behavior expected? That when a privileged page adds an iframe, this iframe starts out with null principal and a consecutive load will replace the inner window? I'm pretty sure this causes a problem with devtools when they attach a load listener to the initial inner window immediately after page mount.
I think I managed to create a minimal browser test case

```
const CHROME_URI = "chrome://global/content/aboutSupport.xhtml";

add_task(async function test_chrome_uri_in_new_tab() {
  // open a tab with system principal due to chrome URI
  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, CHROME_URI);
  let browser = tab.linkedBrowser;

  await SpecialPowers.spawn(browser, [CHROME_URI], async (CHROME_URI) => {
    let bc = content.browsingContext;
    let contentPrincipal = content.document.nodePrincipal;
    Assert.ok(contentPrincipal.isSystemPrincipal, "tab has system principal");
    Assert.ok(bc.isContent, "tab BC is content");

    // within a system context, add a new iframe
    let iframe = content.document.createElement("iframe");
    iframe.src = CHROME_URI;
    content.document.documentElement.appendChild(iframe);

    // iframe will start with some different principal
    let ifrBC = iframe.browsingContext;
    let aboutBlankPrincipal = iframe.contentDocument.nodePrincipal;
    Assert.ok(iframe.contentDocument.isUncommittedInitialDocument, "iframe at uncommitted initial doc");
    Assert.ok(!aboutBlankPrincipal.isSystemPrincipal, "initial about:blank doesn't have system principal");
    Assert.ok(aboutBlankPrincipal.isNullPrincipal, "initial about:blank starts out with null principal");
    Assert.ok(ifrBC.isContent, "iframe BC is content");

    // inner window will be replaced
    iframe.contentWindow.foo = "bar";
    iframe.contentWindow.addEventListener("load", () => {
      Assert.ok(false, "load event never fired on initial iframe inner window");
    });

    await new Promise(res => iframe.addEventListener("load", res));

    // after load, iframe has system principal and inner window was replaced
    let chromeDocPrincipal = iframe.contentDocument.nodePrincipal;
    Assert.ok(chromeDocPrincipal.isSystemPrincipal, "after load, iframe has system principal");
    Assert.ok(ifrBC.isContent, "iframe BC stays content");
    Assert.ok(iframe.contentWindow.foo == undefined, "iframe inner window replaced");

    iframe.remove();
  });

  BrowserTestUtils.removeTab(tab);
});
```

So is this behavior expected? That when a privileged page adds an iframe, this iframe starts out with null principal and a consecutive load will replace the inner window? I'm pretty sure this causes a problem with devtools when they attach a load listener to the initial inner window immediately after page mount.

:hsivonen

Back to Bug 1955324 Comment 1