The Root Cause
Your assumption is wrong because of the BrowsingContext lifecycle and registration timing. Here's the key sequence in CreateFromIPC (docshell/base/BrowsingContext.cpp:637-639):
Register(context); // Line 637 - Context becomes findable
context->Attach(/* aFromIPC */ true, aOriginProcess); // Line 639
And in Attach (line 1035-1036):
if (IsContent() && !Canonical()->mWebProgress) {
Canonical()->mWebProgress = new BrowsingContextWebProgress(Canonical());
}
The Problem
BrowsingContexts are registered BEFORE their WebProgress is created. This creates a race condition:
1. Top BrowsingContext: Created, Register()ed (now findable via Top()), but Attach() hasn't completed yet
2. Child BrowsingContext: CreateFromIPC is called, which:
- Gets the parent via aInit.GetParent()
- Creates the child context with that parent
- Calls Register(context) - child is now findable
- Calls Attach() - which creates the child's WebProgress
3. In the child's BrowsingContextWebProgress constructor (line 50):
mScopedPrefs = aBrowsingContext->Top()->GetWebProgress()->mScopedPrefs;
- Top() walks up to find the top BrowsingContext - this succeeds (top exists)
- GetWebProgress() returns mWebProgress - this returns nullptr because top's Attach() hasn't created it yet
- CRASH when trying to access ->mScopedPrefs
Why Your Mental Model Was Wrong
You assumed that when creating a WebProgress for a non-top BrowsingContext, the top's WebProgress already exists. This is wrong because:
- Top BrowsingContext existence ≠ Top WebProgress existence
- The top BC is registered (and findable) before its Attach() runs
- WebProgress is created during Attach(), not during construction/registration
- IPC message processing order isn't guaranteed - child BCs can be processed while parent/top BCs are still being attached
When This Happens
This occurs when:
1. Multiple BrowsingContext IPC messages arrive in a batch
2. They're processed such that a child's Attach() runs before (or during) its top's Attach()
3. The top BC exists in memory but hasn't had its WebProgress created yet
The Fix
You need to handle the case where Top()->GetWebProgress() returns nullptr. Options:
1. Null check and defer - Check if top's WebProgress exists, if not, handle it (maybe set to nullptr and populate later)
2. Ensure ordering - Make sure top BCs complete Attach() before children (harder, may have other implications)
3. Lazy initialization - Don't access top's WebProgress in the constructor; defer until first use
Would you like me to help you implement one of these fixes?