If we start with this:
Compartment 1 | Compartment 2
-------------------------------------------
CCW1 --> XrayWaiver -> WindowProxy
Then create a new realm + WindowProxy in compartment 1 and transplant the WindowProxy in compartment 2, we get:
Compartment 1 | Compartment 2
-------------------------------------------------
CCW1 --> XrayWaiver -> CCW2(WindowProxy)
XrayWaiver
WindowProxy
In FixWaiverAfterTransplant we then recompute all CCWs for the old XrayWaiver in compartment 2 to point to the new XrayWaiver in compartment 1. However CCW1 and the new XrayWaiver are now same-compartment so we fail an assert in js::RemapWrapper.
Initially I thought we could transplant the CCW with a same-compartment wrapper to the same-compartment XrayWaiver, like this:
ompartment 1 | Compartment 2
--------------------------------------------------------
Wrapper [unused XrayWaiver] -> CCW2(WindowProxy)
-> XrayWaiver
-> WindowProxy
It works but it breaks the invariant [0] that XrayWaivers are only referenced by CCWs. Another option is to do an UncheckedUnwrap, eliminating the XrayWaiver but this might be wrong if we then again load a content page and transplant the WindowProxy in compartment 1 with a CCW? Then we will end up with a vanilla non-waived Xray I think.
[0] https://searchfox.org/mozilla-central/rev/70a4778dd84ec94b4b3a2537fd28482de45b9a00/js/xpconnect/wrappers/WrapperFactory.cpp#624-626
Bug 1516237 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.
If we start with this:
Compartment 1 | Compartment 2
-------------------------------------------
CCW1 --> XrayWaiver -> WindowProxy
Then create a new realm + WindowProxy in compartment 1 and transplant the WindowProxy in compartment 2, we get:
Compartment 1 | Compartment 2
-------------------------------------------------
CCW1 --> XrayWaiver -> CCW2(WindowProxy)
XrayWaiver
WindowProxy
In FixWaiverAfterTransplant we then recompute all CCWs for the old XrayWaiver in compartment 2 to point to the new XrayWaiver in compartment 1. However CCW1 and the new XrayWaiver are now same-compartment so we fail an assert in js::RemapWrapper.
Initially I thought we could transplant the CCW with a same-compartment wrapper to the same-compartment XrayWaiver, like this:
Compartment 1 | Compartment 2
--------------------------------------------------------
Wrapper [unused XrayWaiver] -> CCW2(WindowProxy)
-> XrayWaiver
-> WindowProxy
It works but it breaks the invariant [0] that XrayWaivers are only referenced by CCWs. Another option is to do an UncheckedUnwrap, eliminating the XrayWaiver but this might be wrong if we then again load a content page and transplant the WindowProxy in compartment 1 with a CCW? Then we will end up with a vanilla non-waived Xray I think.
[0] https://searchfox.org/mozilla-central/rev/70a4778dd84ec94b4b3a2537fd28482de45b9a00/js/xpconnect/wrappers/WrapperFactory.cpp#624-626