1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
content / browser / renderer_host / concurrent_navigations_commit_deferring_condition.cc [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/renderer_host/concurrent_navigations_commit_deferring_condition.h"
#include "base/memory/ptr_util.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_request.h"
namespace content {
// static
std::unique_ptr<CommitDeferringCondition>
ConcurrentNavigationsCommitDeferringCondition::MaybeCreate(
NavigationRequest& navigation_request,
NavigationType navigation_type) {
// Only defer back/forward cache or prerender activations here. Non-activation
// navigations are handled by code in NavigationRequest instead.
if (!navigation_request.IsServedFromBackForwardCache() &&
navigation_type != NavigationType::kPrerenderedPageActivation) {
return nullptr;
}
// Currently only navigations in the primary main frame can restore pages
// from BFCache or activate prerendered pages.
DCHECK(navigation_request.IsInPrimaryMainFrame());
return base::WrapUnique(
new ConcurrentNavigationsCommitDeferringCondition(navigation_request));
}
ConcurrentNavigationsCommitDeferringCondition::
ConcurrentNavigationsCommitDeferringCondition(
NavigationRequest& navigation_request)
: CommitDeferringCondition(navigation_request) {}
ConcurrentNavigationsCommitDeferringCondition::
~ConcurrentNavigationsCommitDeferringCondition() = default;
CommitDeferringCondition::Result
ConcurrentNavigationsCommitDeferringCondition::WillCommitNavigation(
base::OnceClosure resume) {
auto* request = NavigationRequest::From(&GetNavigationHandle());
// See if there is a speculative RFH that has a pending commit cross-document
// navigation. It's possible for a speculative RenderFrameHost to exist for
// another navigation as we don't delete existing speculative RFHs that have
// in-flight commits when we start a new navigation. We need to defer our
// navigation while the older commit continues, to avoid deleting a pending
// commit RFH.
if (request->ShouldQueueDueToExistingPendingCommitRFH()) {
DCHECK(!request->IsQueued());
request->set_resume_commit_closure(std::move(resume));
return Result::kDefer;
}
return Result::kProceed;
}
const char* ConcurrentNavigationsCommitDeferringCondition::TraceEventName()
const {
return "ConcurrentNavigationsCommitDeferringCondition";
}
} // namespace content