Bug 1709346 - Part 1: Track BrowsingContextWebProgress for subframes, r=mattwoodrow,kmag,necko-reviewers

This allows loads to be tracked as they are ongoing on a per-context basis in
the parent process, and for events to be generated for each subframe as it is
destroyed.

This patch also stops sending the `IsLoadingDocument` flag on the request to
the main process and removes RemoteWebProgress, as they are no longer necessary
due to being tracked directly.

Finally this patch also adds some logging to BrowsingContextWebProgress
to make it easier to diagnose this type of issue in the future.

Differential Revision: https://phabricator.services.mozilla.com/D115706
This commit is contained in:
Nika Layzell
2021-05-25 17:31:53 +00:00
parent a63f47ba30
commit 8eda0bc707
14 changed files with 378 additions and 260 deletions

View File

@@ -157,16 +157,61 @@ nsISecureBrowserUI* CanonicalBrowsingContext::GetSecureBrowserUI() {
return mSecureBrowserUI;
}
namespace {
// The DocShellProgressBridge is attached to a root content docshell loaded in
// the parent process. Notifications are paired up with the docshell which they
// came from, so that they can be fired to the correct
// BrowsingContextWebProgress and bubble through this tree separately.
//
// Notifications are filtered by a nsBrowserStatusFilter before being received
// by the DocShellProgressBridge.
class DocShellProgressBridge : public nsIWebProgressListener {
public:
NS_DECL_ISUPPORTS
// NOTE: This relies in the expansion of `NS_FORWARD_SAFE` and all listener
// methods accepting an `aWebProgress` argument. If this changes in the
// future, this may need to be written manually.
NS_FORWARD_SAFE_NSIWEBPROGRESSLISTENER(GetTargetContext(aWebProgress))
explicit DocShellProgressBridge(uint64_t aTopContextId)
: mTopContextId(aTopContextId) {}
private:
virtual ~DocShellProgressBridge() = default;
nsIWebProgressListener* GetTargetContext(nsIWebProgress* aWebProgress) {
RefPtr<CanonicalBrowsingContext> context;
if (nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aWebProgress)) {
context = docShell->GetBrowsingContext()->Canonical();
} else {
context = CanonicalBrowsingContext::Get(mTopContextId);
}
return context && !context->IsDiscarded() ? context->GetWebProgress()
: nullptr;
}
uint64_t mTopContextId = 0;
};
NS_IMPL_ISUPPORTS(DocShellProgressBridge, nsIWebProgressListener)
} // namespace
void CanonicalBrowsingContext::MaybeAddAsProgressListener(
nsIWebProgress* aWebProgress) {
if (!GetWebProgress()) {
// Only add as a listener if the created docshell is a toplevel content
// docshell. We'll get notifications for all of our subframes through a single
// listener.
if (!IsTopContent()) {
return;
}
if (!mStatusFilter) {
if (!mDocShellProgressBridge) {
mDocShellProgressBridge = new DocShellProgressBridge(Id());
mStatusFilter = new nsBrowserStatusFilter();
mStatusFilter->AddProgressListener(GetWebProgress(),
mStatusFilter->AddProgressListener(mDocShellProgressBridge,
nsIWebProgress::NOTIFY_ALL);
}
aWebProgress->AddProgressListener(mStatusFilter, nsIWebProgress::NOTIFY_ALL);
}
@@ -177,9 +222,10 @@ void CanonicalBrowsingContext::ReplacedBy(
MOZ_ASSERT(!aNewContext->mSessionHistory);
MOZ_ASSERT(IsTop() && aNewContext->IsTop());
if (mStatusFilter) {
mStatusFilter->RemoveProgressListener(mWebProgress);
mStatusFilter->RemoveProgressListener(mDocShellProgressBridge);
mStatusFilter = nullptr;
}
mWebProgress->ContextReplaced(aNewContext);
aNewContext->mWebProgress = std::move(mWebProgress);
// Use the Transaction for the fields which need to be updated whether or not
@@ -2234,7 +2280,7 @@ bool CanonicalBrowsingContext::AllowedInBFCache(
NS_IMPL_CYCLE_COLLECTION_INHERITED(CanonicalBrowsingContext, BrowsingContext,
mSessionHistory, mContainerFeaturePolicy,
mCurrentBrowserParent)
mCurrentBrowserParent, mWebProgress)
NS_IMPL_ADDREF_INHERITED(CanonicalBrowsingContext, BrowsingContext)
NS_IMPL_RELEASE_INHERITED(CanonicalBrowsingContext, BrowsingContext)