Revision 8f1ef70886a1443ccd9980448031c88a44c3faea authored by Ben Pastene on 13 April 2018, 17:03:33 UTC, committed by Chromium WPT Sync on 13 April 2018, 17:03:33 UTC
This reverts commit 7c3d1d13f940e88ef6706fd8b5c257a81d340ed9.

Reason for revert: WebviewLoginTest.Basic is still flaky on linux-chromeos-rel
https://ci.chromium.org/buildbot/chromium.chromiumos/linux-chromeos-rel/6886
https://ci.chromium.org/buildbot/chromium.chromiumos/linux-chromeos-rel/6887

Original change's description:
> Reland: Use PostTask to schedule cross-process postMessage forwarding.
>
> 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}

TBR=xiyuan@chromium.org,dcheng@chromium.org,alexmos@chromium.org

Change-Id: Ic0637a6038bed6e5334a26e1934bee81faad3b9e
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 828529
Reviewed-on: https://chromium-review.googlesource.com/1012138
Reviewed-by: Ben Pastene <bpastene@chromium.org>
Commit-Queue: Ben Pastene <bpastene@chromium.org>
Cr-Commit-Position: refs/heads/master@{#550649}
1 parent 1e5a5fe
Raw File
PrefixedPostMessage.js
/**
 * Supports pseudo-"namespacing" for window-posted messages for a given test
 * by generating and using a unique prefix that gets wrapped into message
 * objects. This makes it more feasible to have multiple tests that use
 * `window.postMessage` in a single test file. Basically, make it possible
 * for the each test to listen for only the messages that are pertinent to it.
 *
 * 'Prefix' not an elegant term to use here but this models itself after
 * PrefixedLocalStorage.
 *
 * PrefixedMessageTest: Instantiate in testharness.js tests to generate
 *   a new unique-ish prefix that can be used by other test support files
 * PrefixedMessageResource: Instantiate in supporting test resource
 *   files to use/share a prefix generated by a test.
 */
var PrefixedMessage = function () {
  this.prefix = '';
  this.param = 'prefixedMessage'; // Param to use in querystrings
};

/**
 * Generate a URL that adds/replaces param with this object's prefix
 * Use to link to test support files that make use of
 * PrefixedMessageResource.
 */
PrefixedMessage.prototype.url = function (uri) {
  function updateUrlParameter (uri, key, value) {
    var i         = uri.indexOf('#');
    var hash      = (i === -1) ? '' : uri.substr(i);
    uri           = (i === -1) ? uri : uri.substr(0, i);
    var re        = new RegExp(`([?&])${key}=.*?(&|$)`, 'i');
    var separator = uri.indexOf('?') !== -1 ? '&' : '?';
    uri = (uri.match(re)) ? uri.replace(re, `$1${key}=${value}$2`) :
      `${uri}${separator}${key}=${value}`;
    return uri + hash;
  }
  return updateUrlParameter(uri, this.param, this.prefix);
};

/**
 * Add an eventListener on `message` but only invoke the given callback
 * for messages whose object contains this object's prefix. Remove the
 * event listener once the anticipated message has been received.
 */
PrefixedMessage.prototype.onMessage = function (fn) {
  window.addEventListener('message', e => {
    if (typeof e.data === 'object' && e.data.hasOwnProperty('prefix')) {
      if (e.data.prefix === this.prefix) {
        // Only invoke callback when `data` is an object containing
        // a `prefix` key with this object's prefix value
        // Note fn is invoked with "unwrapped" data first, then the event `e`
        // (which contains the full, wrapped e.data should it be needed)
        fn.call(this, e.data.data, e);
        window.removeEventListener('message', fn);
      }
    }
  });
};

/**
 * Instantiate in a test file (e.g. during `setup`) to create a unique-ish
 * prefix that can be shared by support files
 */
var PrefixedMessageTest = function () {
  PrefixedMessage.call(this);
  this.prefix = `${document.location.pathname}-${Math.random()}-${Date.now()}-`;
};
PrefixedMessageTest.prototype = Object.create(PrefixedMessage.prototype);
PrefixedMessageTest.prototype.constructor = PrefixedMessageTest;

/**
 * Instantiate in a test support script to use a "prefix" generated by a
 * PrefixedMessageTest in a controlling test file. It will look for
 * the prefix in a URL param (see also PrefixedMessage#url)
 */
var PrefixedMessageResource = function () {
  PrefixedMessage.call(this);
  // Check URL querystring for prefix to use
  var regex = new RegExp(`[?&]${this.param}(=([^&#]*)|&|#|$)`),
    results = regex.exec(document.location.href);
  if (results && results[2]) {
    this.prefix = results[2];
  }
};
PrefixedMessageResource.prototype = Object.create(PrefixedMessage.prototype);
PrefixedMessageResource.prototype.constructor = PrefixedMessageResource;

/**
 * This is how a test resource document can "send info" to its
 * opener context. It will whatever message is being sent (`data`) in
 * an object that injects the prefix.
 */
PrefixedMessageResource.prototype.postToOpener = function (data) {
  if (window.opener) {
    window.opener.postMessage({
      prefix: this.prefix,
      data: data
    }, '*');
  }
};
back to top