This allows us to move away from using IsNavigating field in parent-controlled
paths. Use a new distinct error code in cases when we cancel loads in
Canonical BC due to another load starting. This way, we know to not reset the
urlbar if we are doing another load.
See https://bugzilla.mozilla.org/show_bug.cgi?id=1721217#c10 for longer
explanation of what is going on here.
Differential Revision: https://phabricator.services.mozilla.com/D126845
Add a synced ParentInitiatedNavigationEpoch field to browsing context, which
only gets incremented when we start navigations in the parent process. When a
child process initiates a navigation, it sends the current value of the field
that it sees via DocumentChannelCreationArgs. In the parent process, we can
compare the value of that field with the latest one for the same browsing
context. If the latest value is higher than the one provided by the content
process, it means that in the meantime parent process has started a navigation
so the earlier navigation originating in the content process will be cancelled.
Differential Revision: https://phabricator.services.mozilla.com/D126842
This allows us to move away from using IsNavigating field in parent-controlled
paths. Use a new distinct error code in cases when we cancel loads in
Canonical BC due to another load starting. This way, we know to not reset the
urlbar if we are doing another load.
See https://bugzilla.mozilla.org/show_bug.cgi?id=1721217#c10 for longer
explanation of what is going on here.
Differential Revision: https://phabricator.services.mozilla.com/D126845
Add a synced ParentInitiatedNavigationEpoch field to browsing context, which
only gets incremented when we start navigations in the parent process. When a
child process initiates a navigation, it sends the current value of the field
that it sees via DocumentChannelCreationArgs. In the parent process, we can
compare the value of that field with the latest one for the same browsing
context. If the latest value is higher than the one provided by the content
process, it means that in the meantime parent process has started a navigation
so the earlier navigation originating in the content process will be cancelled.
Differential Revision: https://phabricator.services.mozilla.com/D126842
When we navigate in history to the same entry that we're current at then we
actually do a reload. The problem is in the way we detect whether to do a reload
in the parent process.
If a page does a back and a forward one after the other in a script, then the
parent will calculate the index for the back and tell the child to load the
entry at that index. While the child is processing the load of that entry, the
BC in the parent process still has the same entry as its active entry (until the
child commits the load of the entry over IPC). The parent then processes the
forward, calculates the index for the forward and finds the entry at that index.
This is the same entry that we were at before doing anything, and so the same
entry as the active entry in the BC in the parent process. We used to compare
the entry that we're going to load with the active entry in the BC to determine
whether we're doing a reload, and so in this situation we would assume the
forward navigation was actually doing a reload. The child would reload the page,
and we'd run the script again and we'd end up in a reload loop.
Comparing the offset with 0 to determine whether we're doing a reload fixes this
issue.
Differential Revision: https://phabricator.services.mozilla.com/D126585
When we navigate in history to the same entry that we're current at then we
actually do a reload. The problem is in the way we detect whether to do a reload
in the parent process.
If a page does a back and a forward one after the other in a script, then the
parent will calculate the index for the back and tell the child to load the
entry at that index. While the child is processing the load of that entry, the
BC in the parent process still has the same entry as its active entry (until the
child commits the load of the entry over IPC). The parent then processes the
forward, calculates the index for the forward and finds the entry at that index.
This is the same entry that we were at before doing anything, and so the same
entry as the active entry in the BC in the parent process. We used to compare
the entry that we're going to load with the active entry in the BC to determine
whether we're doing a reload, and so in this situation we would assume the
forward navigation was actually doing a reload. The child would reload the page,
and we'd run the script again and we'd end up in a reload loop.
Comparing the offset with 0 to determine whether we're doing a reload fixes this
issue.
Differential Revision: https://phabricator.services.mozilla.com/D126585
This is a much simplified patch compared to the earlier changes, and
aims to be less risky and avoid whatever issues are being caused by the
process selection changes in the earlier patches. Unfortunately, I think
this patch may reduce the ability for a noopener window to be given a
distinct process, so I would prefer a more complete fix in the future.
This new patch also no longer has a fix for bug 1728331, so that will
need to be fixed separately.
Differential Revision: https://phabricator.services.mozilla.com/D126951
Using requestedIndex on the child side is hard, because there are race conditions when a session history load is triggered
and at the same time a non-session history load commits a new active entry.
Differential Revision: https://phabricator.services.mozilla.com/D126619
When we navigate in history to the same entry that we're current at then we
actually do a reload. The problem is in the way we detect whether to do a reload
in the parent process.
If a page does a back and a forward one after the other in a script, then the
parent will calculate the index for the back and tell the child to load the
entry at that index. While the child is processing the load of that entry, the
BC in the parent process still has the same entry as its active entry (until the
child commits the load of the entry over IPC). The parent then processes the
forward, calculates the index for the forward and finds the entry at that index.
This is the same entry that we were at before doing anything, and so the same
entry as the active entry in the BC in the parent process. We used to compare
the entry that we're going to load with the active entry in the BC to determine
whether we're doing a reload, and so in this situation we would assume the
forward navigation was actually doing a reload. The child would reload the page,
and we'd run the script again and we'd end up in a reload loop.
Comparing the offset with 0 to determine whether we're doing a reload fixes this
issue.
Differential Revision: https://phabricator.services.mozilla.com/D126585
This patch replaces the previous process selection infrastructure with a
new setup implemented entirely in C++, which should more accurately
track the set of processes in use, and should encourage re-use of the
existing content process when navigating by not counting the current
tab.
This approach intentionally allows for process switching to another
process during navigation if there is uneven load between processes to
encourage balanced process use.
I think this may also fix some of the session restore issues with many
tabs using the same process, rather than being spread over 4, as we now
track a tab earlier in its lifecycle before the BrowserParent instance
is created.
Differential Revision: https://phabricator.services.mozilla.com/D126405
This patch replaces the previous process selection infrastructure with a
new setup implemented entirely in C++, which should more accurately
track the set of processes in use, and should encourage re-use of the
existing content process when navigating by not counting the current
tab.
This approach intentionally allows for process switching to another
process during navigation if there is uneven load between processes to
encourage balanced process use.
I think this may also fix some of the session restore issues with many
tabs using the same process, rather than being spread over 4, as we now
track a tab earlier in its lifecycle before the BrowserParent instance
is created.
Differential Revision: https://phabricator.services.mozilla.com/D126405
The biggest change in this patch is around the PrepareToChangeRemoteness
promise. It is changed to directly interact with the DOM promise rather than
wrapping it into a MozPromise (which requires another trip through the event
loop), and tries to avoid waiting on the promise at all if it was immediately
resolved (which should always be the case with SHIP enabled, except for in a
single test).
Differential Revision: https://phabricator.services.mozilla.com/D124800
The biggest change in this patch is around the PrepareToChangeRemoteness
promise. It is changed to directly interact with the DOM promise rather than
wrapping it into a MozPromise (which requires another trip through the event
loop), and tries to avoid waiting on the promise at all if it was immediately
resolved (which should always be the case with SHIP enabled, except for in a
single test).
Differential Revision: https://phabricator.services.mozilla.com/D124800
The biggest change in this patch is around the PrepareToChangeRemoteness
promise. It is changed to directly interact with the DOM promise rather than
wrapping it into a MozPromise (which requires another trip through the event
loop), and tries to avoid waiting on the promise at all if it was immediately
resolved (which should always be the case with SHIP enabled, except for in a
single test).
Differential Revision: https://phabricator.services.mozilla.com/D124800
After some investigation, I was able to find a theoretical codepath
which could lead to the "missing initial frame browsing context" error:
1. Two iframes are created for the same origin, and begin process
switching.
2. The first iframe finishes process switching, but for some reason
(e.g. being in shutdown) the call to `LaunchSubprocessResolve`
errors.
3. The second callback is called and also calls LaunchSubprocessResolve,
which this time returns `true` due to it previously having been
called.
4. The BrowserParent is created in the new content process despite
`InitInternal()` never having been finished, and therefore the
ContentParent never becoming subscribed to the BrowsingContextGroup.
To fix this, I made 2 changes:
1. Abort from process switching if the target process which we're going
to be creating a BrowserParent in `IsDead()`, and
2. Track the return value from `LaunchSubprocessResolve`, so we return
`false` if it is called a second time after a failed content process
launch.
I'm not confident that this is the cause of the crashes, as I was unable
to reproduce the issue.
Differential Revision: https://phabricator.services.mozilla.com/D123548
Looks like the code below does similar thing already for iframes, so this is adding InternalSetRequestedIndex
call only for the top level case.
This is based on the same assumptions as bug 1697905, but unfortunately testing this is still
super hard.
Differential Revision: https://phabricator.services.mozilla.com/D122355
This is a large refactoring of the DocumentChannel process switch codepath,
with the end goal of being better able to support future process switch
requirements such as dynamic isolation on android, as well as the immediate
requirement of null principal handling.
The major changes include:
1. The logic is in C++ and has less failure cases, meaning it should be harder
for us to error out unexpectedly and not process switch.
2. Process selection decisions are more explicit, and tend to rely less on
state such as the current remoteType when possible. This makes reasoning
about where a specific load will complete easier.
3. Additional checks are made after a "WebContent" behavior is selected to
ensure that if an existing document in the same BCG is found, the load will
finish in the required content process. This should make dynamic checks such
as Android's logged-in site isolation easier to implement.
4. ProcessIsolation logging is split out from DocumentChannel so that it's
easier to log just the information related to process selection when
debugging.
5. Null result principal precursors are considered when performing process
selection.
Other uses of E10SUtils for process selection have not yet been migrated to the
new design as they have slightly different requirements. This will be done in
follow-up bugs.
Differential Revision: https://phabricator.services.mozilla.com/D120673
This is a large refactoring of the DocumentChannel process switch codepath,
with the end goal of being better able to support future process switch
requirements such as dynamic isolation on android, as well as the immediate
requirement of null principal handling.
The major changes include:
1. The logic is in C++ and has less failure cases, meaning it should be harder
for us to error out unexpectedly and not process switch.
2. Process selection decisions are more explicit, and tend to rely less on
state such as the current remoteType when possible. This makes reasoning
about where a specific load will complete easier.
3. Additional checks are made after a "WebContent" behavior is selected to
ensure that if an existing document in the same BCG is found, the load will
finish in the required content process. This should make dynamic checks such
as Android's logged-in site isolation easier to implement.
4. ProcessIsolation logging is split out from DocumentChannel so that it's
easier to log just the information related to process selection when
debugging.
5. Null result principal precursors are considered when performing process
selection.
Other uses of E10SUtils for process selection have not yet been migrated to the
new design as they have slightly different requirements. This will be done in
follow-up bugs.
Differential Revision: https://phabricator.services.mozilla.com/D120673
To support more cases, change this value to more general name and use a count instead, if the count is larger than zero, then we would not suspend the page.
In addition, this value now can be set in any processes (but still for the top level only), which is different from before where we would only set the value from the chrome process.
Differential Revision: https://phabricator.services.mozilla.com/D119837