MojoIpcz: Ring buffer-based DataPipe

Mojo uses a shared memory ring buffer to implement data pipes.

MojoIpcz implemented DataPipes directly on top of ipcz portals
with the assumption that they should be roughly equivalent in terms
of performance, but this approach changes observable data pipe behavior.
Namely, writes are no longer coalesced and consumers therefore observe
data in chunks that reflect how it was written. This behavior should
be OK, but many consumers aren't built to handle it and this difference
has revealed multiple subtle browser and renderer bugs when trying to
enable MojoIpcz.

In the interest of eliminating a large class of unknowns from the
initial MojoIpcz launch, this CL reimplements the MojoIpcz DataPipe
to be equivalent to the current Mojo implementation, using a shared
memory ring buffer for data transfers, and using portals only to
signal end-to-end about how many bytes have been transacted.

Bug: 1380476
Change-Id: I14402c41eb8f3c23377bb646916f4385ecfe1d07
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4004417
Commit-Queue: Ken Rockot <rockot@google.com>
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1069465}
NOKEYCHECK=True
GitOrigin-RevId: c0c37122713e743b3434b502095243b0250bd29e
diff --git a/src/ipcz/router.cc b/src/ipcz/router.cc
index ba69842..582bb21 100644
--- a/src/ipcz/router.cc
+++ b/src/ipcz/router.cc
@@ -257,8 +257,14 @@
       // If this is a terminal router, we may have trap events to fire.
       status_.num_local_parcels = inbound_parcels_.GetNumAvailableElements();
       status_.num_local_bytes = inbound_parcels_.GetTotalAvailableElementSize();
-      traps_.UpdatePortalStatus(
-          context, status_, TrapSet::UpdateReason::kNewLocalParcel, dispatcher);
+      if (sequence_number < inbound_parcels_.GetCurrentSequenceLength()) {
+        // Only notify traps if the new parcel is actually available for
+        // reading, which may not be the case if some preceding parcels have yet
+        // to be received.
+        traps_.UpdatePortalStatus(context, status_,
+                                  TrapSet::UpdateReason::kNewLocalParcel,
+                                  dispatcher);
+      }
     }
   }