Revision 4e5f09f89e6f1976dd49a57ba46cd447c7e19a1e authored by Alex Moshchuk on 13 April 2018, 15:22:14 UTC, committed by Chromium WPT Sync on 13 April 2018, 15:22:14 UTC
Changes from original attempt at https://crrev.com/c/999182:
- fix flakiness in two additional ChromeOS login tests
- fix CSP WPT tests to not depend on ordering between iframe's onload
  and postMessage - see https://crbug.com/832319.

Previously, we sent the IPC to forward a cross-process postMessage
immediately.  This caused a behavioral difference from the
same-process case where the postMessage is always scheduled.  Namely,
in a scenario like this:

  frame.postMessage(...);
  doSomethingThatSendsIPCsToFrame(frame);

the IPCs from JS following the postMessage would've been ordered
incorrectly, causing |frame| to see their side effects after the
postMessage dispatch in the cross-process case, whereas they would be
seen before the postMessage dispatch in the same-process case.  One
example of this is frame.focus(), and another is a frame element
onload event (dispatched via FrameHostMsg_DispatchLoad) arriving after
a postMessage dispatched from an inline script while the frame was
still loading.

To resolve these ordering concerns, this CL changes cross-process
postMessage to do a PostTask on the sender side before sending the
message to the browser process.  This improves the current state of
the world, but does not yet achieve a perfect match for the IPC
ordering in the same-process case - see discussion on the bug.

Bug: 828529
Change-Id: I62a627c501526d09900be4f5bd2c899acf4d1e07
Reviewed-on: https://chromium-review.googlesource.com/999182
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Commit-Queue: Alex Moshchuk <alexmos@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#550284}
Reviewed-on: https://chromium-review.googlesource.com/1011287
Cr-Commit-Position: refs/heads/master@{#550621}
1 parent f90d3d6
Raw File
getSelection.html
<!doctype html>
<title>getSelection() tests</title>
<div id=log></div>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
"use strict";

// TODO: Figure out more places where defaultView is or is not guaranteed to be
// null, and test whether getSelection() is null.
//
// TODO: Figure out a good way to test display: none iframes.

test(function() {
    // Sanity checks like this are to flag known browser bugs with clearer
    // error messages, instead of throwing inscrutable exceptions.
    assert_true("Selection" in window,
        "Sanity check: window must have Selection property");

    assert_true(window.getSelection() instanceof Selection);
}, "window.getSelection() instanceof Selection");

test(function() {
    assert_equals(window.getSelection(), window.getSelection());
}, "window.getSelection() === window.getSelection()");

test(function() {
    assert_true("Selection" in window,
        "Sanity check: window must have Selection property");
    // This sanity check (which occurs a number of times below, too) is because
    // document.getSelection() is supposed to return null if defaultView is
    // null, so we need to figure out whether defaultView is null or not before
    // we can make correct assertions about getSelection().
    assert_not_equals(document.defaultView, null,
        "Sanity check: document.defaultView must not be null");

    assert_equals(typeof document.getSelection(), "object",
        "document.getSelection() must be an object");
    assert_true(document.getSelection() instanceof Selection);
}, "document.getSelection() instanceof Selection");

test(function() {
    assert_not_equals(document.defaultView, null,
        "Sanity check: document.defaultView must not be null");
    assert_equals(document.getSelection(), document.getSelection());
}, "document.getSelection() === document.getSelection()");

test(function() {
    assert_not_equals(document.defaultView, null,
        "Sanity check: document.defaultView must not be null");
    assert_equals(window.getSelection(), document.getSelection());
}, "window.getSelection() === document.getSelection()");

// "Each selection is associated with a single range, which may be null and is
// initially null."
//
// "The rangeCount attribute must return 0 if the context object's range is
// null, otherwise 1."
test(function() {
    assert_equals(window.getSelection().rangeCount, 0,
        "window.getSelection().rangeCount must initially be 0");
    assert_equals(typeof document.getSelection(), "object",
        "Sanity check: document.getSelection() must be an object");
    assert_equals(document.getSelection().rangeCount, 0,
        "document.getSelection().rangeCount must initially be 0");
}, "Selection's range must initially be null");

test(function() {
    var doc = document.implementation.createHTMLDocument("");
    assert_equals(doc.defaultView, null,
        "Sanity check: defaultView of created HTML document must be null");
    assert_equals(doc.getSelection(), null);
}, "getSelection() on HTML document with null defaultView must be null");

test(function() {
    var xmlDoc = document.implementation.createDocument(null, "", null);

    assert_true("getSelection" in xmlDoc, "XML document must have getSelection()");

    assert_equals(xmlDoc.defaultView, null,
        "Sanity check: defaultView of created XML document must be null");
    assert_equals(xmlDoc.getSelection(), null);
}, "getSelection() on XML document with null defaultView must be null");


// Run a bunch of iframe tests, once immediately after the iframe is appended
// to the document and once onload.  This makes a difference, because browsers
// differ (at the time of this writing) in whether they load about:blank in
// iframes synchronously or not.  Per the HTML spec, there must be a browsing
// context associated with the iframe as soon as it's appended to the document,
// so there should be a selection too.
var iframe = document.createElement("iframe");
add_completion_callback(function() {
    document.body.removeChild(iframe);
});

var testDescs = [];
var testFuncs = [];
testDescs.push("window.getSelection() instanceof Selection in an iframe");
testFuncs.push(function() {
    assert_true("Selection" in iframe.contentWindow,
        "Sanity check: window must have Selection property");
    assert_not_equals(iframe.contentWindow.document.defaultView, null,
        "Sanity check: document.defaultView must not be null");
    assert_not_equals(iframe.contentWindow.getSelection(), null,
        "window.getSelection() must not be null");
    assert_true(iframe.contentWindow.getSelection() instanceof iframe.contentWindow.Selection);
});

testDescs.push("document.getSelection() instanceof Selection in an iframe");
testFuncs.push(function() {
    assert_true("Selection" in iframe.contentWindow,
        "Sanity check: window must have Selection property");
    assert_not_equals(iframe.contentDocument.defaultView, null,
        "Sanity check: document.defaultView must not be null");
    assert_not_equals(iframe.contentDocument.getSelection(), null,
        "document.getSelection() must not be null");
    assert_equals(typeof iframe.contentDocument.getSelection(), "object",
        "document.getSelection() must be an object");
    assert_true(iframe.contentDocument.getSelection() instanceof iframe.contentWindow.Selection);
});

testDescs.push("window.getSelection() === document.getSelection() in an iframe");
testFuncs.push(function() {
    assert_not_equals(iframe.contentDocument.defaultView, null,
        "Sanity check: document.defaultView must not be null");
    assert_equals(iframe.contentWindow.getSelection(), iframe.contentDocument.getSelection());
});

testDescs.push("getSelection() inside and outside iframe must return different objects");
testFuncs.push(function() {
    assert_not_equals(iframe.contentWindow.getSelection(), getSelection());
});

testDescs.push("getSelection() on HTML document with null defaultView must be null inside an iframe");
testFuncs.push(function() {
    var doc = iframe.contentDocument.implementation.createHTMLDocument("");
    assert_equals(doc.defaultView, null,
        "Sanity check: defaultView of created HTML document must be null");
    assert_equals(doc.getSelection(), null);
});

var asyncTests = [];
testDescs.forEach(function(desc) {
    asyncTests.push(async_test(desc + " onload"));
});

iframe.onload = function() {
    asyncTests.forEach(function(t, i) {
        t.step(testFuncs[i]);
        t.done();
    });
};

document.body.appendChild(iframe);

testDescs.forEach(function(desc, i) {
    test(testFuncs[i], desc + " immediately after appendChild");
});
</script>
back to top