Commit aaf07d2f authored by Nate Chapin's avatar Nate Chapin Committed by Commit Bot

DocumentLoader::CommitNavigation cleanup

Split most of the window initialization logic out into a helper.

Also, it's not clear that GlobalObjectReusePolicy needs to be an enum.
Return a boolean for whether we should reuse the dom window, and use
the bool |should_reset_browser_interface_broker| for all of the layers
of load commit callbacks, rather than switching from enum to bool
part way.

Change-Id: I8ff3c514115ff6b94f7992af8a73c5cc06e77623
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2341346
Commit-Queue: Nate Chapin <japhet@chromium.org>
Auto-Submit: Nate Chapin <japhet@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796055}
parent 9d7d2d0a
...@@ -540,7 +540,7 @@ void LocalFrameClientImpl::DispatchDidReceiveTitle(const String& title) { ...@@ -540,7 +540,7 @@ void LocalFrameClientImpl::DispatchDidReceiveTitle(const String& title) {
void LocalFrameClientImpl::DispatchDidCommitLoad( void LocalFrameClientImpl::DispatchDidCommitLoad(
HistoryItem* item, HistoryItem* item,
WebHistoryCommitType commit_type, WebHistoryCommitType commit_type,
GlobalObjectReusePolicy global_object_reuse_policy) { bool should_reset_browser_interface_broker) {
if (!web_frame_->Parent()) { if (!web_frame_->Parent()) {
web_frame_->ViewImpl()->DidCommitLoad(commit_type == kWebStandardCommit, web_frame_->ViewImpl()->DidCommitLoad(commit_type == kWebStandardCommit,
false); false);
...@@ -549,7 +549,7 @@ void LocalFrameClientImpl::DispatchDidCommitLoad( ...@@ -549,7 +549,7 @@ void LocalFrameClientImpl::DispatchDidCommitLoad(
if (web_frame_->Client()) { if (web_frame_->Client()) {
web_frame_->Client()->DidCommitNavigation( web_frame_->Client()->DidCommitNavigation(
WebHistoryItem(item), commit_type, WebHistoryItem(item), commit_type,
global_object_reuse_policy == GlobalObjectReusePolicy::kCreateNew); should_reset_browser_interface_broker);
if (web_frame_->GetFrame()->IsLocalRoot()) { if (web_frame_->GetFrame()->IsLocalRoot()) {
// This update should be sent as soon as loading the new document begins // This update should be sent as soon as loading the new document begins
// so that the browser and compositor could reset their states. However, // so that the browser and compositor could reset their states. However,
......
...@@ -52,7 +52,6 @@ class BrowserInterfaceBrokerProxy; ...@@ -52,7 +52,6 @@ class BrowserInterfaceBrokerProxy;
class WebDevToolsAgentImpl; class WebDevToolsAgentImpl;
class WebLocalFrameImpl; class WebLocalFrameImpl;
class WebSpellCheckPanelHostClient; class WebSpellCheckPanelHostClient;
enum class GlobalObjectReusePolicy;
class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient { class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
public: public:
...@@ -101,9 +100,10 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient { ...@@ -101,9 +100,10 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
WebHistoryCommitType, WebHistoryCommitType,
bool content_initiated) override; bool content_initiated) override;
void DispatchDidReceiveTitle(const String&) override; void DispatchDidReceiveTitle(const String&) override;
void DispatchDidCommitLoad(HistoryItem*, void DispatchDidCommitLoad(
WebHistoryCommitType, HistoryItem*,
GlobalObjectReusePolicy) override; WebHistoryCommitType,
bool should_reset_browser_interface_broker) override;
void DispatchDidFailLoad(const ResourceError&, WebHistoryCommitType) override; void DispatchDidFailLoad(const ResourceError&, WebHistoryCommitType) override;
void DispatchDidFinishDocumentLoad() override; void DispatchDidFinishDocumentLoad() override;
void DispatchDidFinishLoad() override; void DispatchDidFinishLoad() override;
......
...@@ -131,9 +131,10 @@ class CORE_EXPORT LocalFrameClient : public FrameClient { ...@@ -131,9 +131,10 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
WebHistoryCommitType, WebHistoryCommitType,
bool content_initiated) {} bool content_initiated) {}
virtual void DispatchDidReceiveTitle(const String&) = 0; virtual void DispatchDidReceiveTitle(const String&) = 0;
virtual void DispatchDidCommitLoad(HistoryItem*, virtual void DispatchDidCommitLoad(
WebHistoryCommitType, HistoryItem*,
GlobalObjectReusePolicy) = 0; WebHistoryCommitType,
bool should_reset_browser_interface_broker) = 0;
virtual void DispatchDidFailLoad(const ResourceError&, virtual void DispatchDidFailLoad(const ResourceError&,
WebHistoryCommitType) = 0; WebHistoryCommitType) = 0;
virtual void DispatchDidFinishDocumentLoad() = 0; virtual void DispatchDidFinishDocumentLoad() = 0;
......
...@@ -1602,15 +1602,12 @@ scoped_refptr<SecurityOrigin> DocumentLoader::CalculateOrigin( ...@@ -1602,15 +1602,12 @@ scoped_refptr<SecurityOrigin> DocumentLoader::CalculateOrigin(
return origin; return origin;
} }
GlobalObjectReusePolicy DocumentLoader::CalculateGlobalObjectReusePolicy( bool ShouldReuseDOMWindow(LocalFrame* frame, SecurityOrigin* security_origin) {
SecurityOrigin* security_origin) {
// Secure transitions can only happen when navigating from the initial empty // Secure transitions can only happen when navigating from the initial empty
// document. // document.
if (!GetFrameLoader().StateMachine()->IsDisplayingInitialEmptyDocument()) if (!frame->Loader().StateMachine()->IsDisplayingInitialEmptyDocument())
return GlobalObjectReusePolicy::kCreateNew; return false;
if (!frame_->DomWindow()->GetSecurityOrigin()->CanAccess(security_origin)) return frame->DomWindow()->GetSecurityOrigin()->CanAccess(security_origin);
return GlobalObjectReusePolicy::kCreateNew;
return GlobalObjectReusePolicy::kUseExisting;
} }
WindowAgent* GetWindowAgentForOrigin(LocalFrame* frame, WindowAgent* GetWindowAgentForOrigin(LocalFrame* frame,
...@@ -1625,53 +1622,10 @@ WindowAgent* GetWindowAgentForOrigin(LocalFrame* frame, ...@@ -1625,53 +1622,10 @@ WindowAgent* GetWindowAgentForOrigin(LocalFrame* frame,
V8PerIsolateData::MainThreadIsolate(), origin); V8PerIsolateData::MainThreadIsolate(), origin);
} }
void DocumentLoader::CommitNavigation() { void DocumentLoader::InitializeWindow(Document* owner_document) {
CHECK_GE(state_, kCommitted);
DCHECK(frame_->GetPage());
DCHECK(!frame_->GetDocument() || !frame_->GetDocument()->IsActive());
DCHECK_EQ(frame_->Tree().ChildCount(), 0u);
// Prepare a DocumentInit before clearing the frame, because it may need to
// inherit an aliased security context.
Document* owner_document = nullptr;
// TODO(dcheng): This differs from the behavior of both IE and Firefox: the
// origin is inherited from the document that loaded the URL.
if (Document::ShouldInheritSecurityOriginFromOwner(Url())) {
Frame* owner_frame = frame_->Tree().Parent();
if (!owner_frame)
owner_frame = frame_->Loader().Opener();
if (auto* owner_local_frame = DynamicTo<LocalFrame>(owner_frame))
owner_document = owner_local_frame->GetDocument();
}
// Re-validate Document Policy feature before installing the new document.
if (!RuntimeEnabledFeatures::DocumentPolicyEnabled(
owner_document ? owner_document->GetExecutionContext() : nullptr)) {
document_policy_ = DocumentPolicy::ParsedDocumentPolicy{};
}
if (document_policy_.feature_state.contains(
mojom::blink::DocumentPolicyFeature::kForceLoadAtTop)) {
navigation_scroll_allowed_ = !(
document_policy_
.feature_state[mojom::blink::DocumentPolicyFeature::kForceLoadAtTop]
.BoolValue());
}
auto sandbox_flags = CalculateSandboxFlags(); auto sandbox_flags = CalculateSandboxFlags();
auto security_origin = CalculateOrigin(owner_document, sandbox_flags); auto security_origin = CalculateOrigin(owner_document, sandbox_flags);
GlobalObjectReusePolicy global_object_reuse_policy =
CalculateGlobalObjectReusePolicy(security_origin.get());
if (GetFrameLoader().StateMachine()->IsDisplayingInitialEmptyDocument()) {
GetFrameLoader().StateMachine()->AdvanceTo(
FrameLoaderStateMachine::kCommittedFirstRealLoad);
}
LocalDOMWindow* previous_window = frame_->DomWindow();
// In some rare cases, we'll re-use a LocalDOMWindow for a new Document. For // In some rare cases, we'll re-use a LocalDOMWindow for a new Document. For
// example, when a script calls window.open("..."), the browser gives // example, when a script calls window.open("..."), the browser gives
// JavaScript a window synchronously but kicks off the load in the window // JavaScript a window synchronously but kicks off the load in the window
...@@ -1680,7 +1634,7 @@ void DocumentLoader::CommitNavigation() { ...@@ -1680,7 +1634,7 @@ void DocumentLoader::CommitNavigation() {
// commits. To make that happen, we "securely transition" the existing // commits. To make that happen, we "securely transition" the existing
// LocalDOMWindow to the Document that results from the network load. See also // LocalDOMWindow to the Document that results from the network load. See also
// Document::IsSecureTransitionTo. // Document::IsSecureTransitionTo.
if (global_object_reuse_policy != GlobalObjectReusePolicy::kUseExisting) { if (!ShouldReuseDOMWindow(frame_.Get(), security_origin.get())) {
auto* agent = GetWindowAgentForOrigin(frame_.Get(), security_origin.get()); auto* agent = GetWindowAgentForOrigin(frame_.Get(), security_origin.get());
frame_->SetDOMWindow(MakeGarbageCollected<LocalDOMWindow>(*frame_, agent)); frame_->SetDOMWindow(MakeGarbageCollected<LocalDOMWindow>(*frame_, agent));
...@@ -1723,18 +1677,69 @@ void DocumentLoader::CommitNavigation() { ...@@ -1723,18 +1677,69 @@ void DocumentLoader::CommitNavigation() {
security_origin = security_origin->GetOriginForAgentCluster( security_origin = security_origin->GetOriginForAgentCluster(
frame_->DomWindow()->GetAgent()->cluster_id()); frame_->DomWindow()->GetAgent()->cluster_id());
frame_->DomWindow()->GetSecurityContext().SetContentSecurityPolicy( SecurityContext& security_context = frame_->DomWindow()->GetSecurityContext();
content_security_policy_.Get()); security_context.SetContentSecurityPolicy(content_security_policy_.Get());
frame_->DomWindow()->GetSecurityContext().ApplySandboxFlags(sandbox_flags); security_context.ApplySandboxFlags(sandbox_flags);
// Conceptually, SecurityOrigin doesn't have to be initialized after sandbox // Conceptually, SecurityOrigin doesn't have to be initialized after sandbox
// flags are applied, but there's a UseCounter in SetSecurityOrigin() that // flags are applied, but there's a UseCounter in SetSecurityOrigin() that
// wants to inspect sandbox flags. // wants to inspect sandbox flags.
frame_->DomWindow()->GetSecurityContext().SetSecurityOrigin( security_context.SetSecurityOrigin(std::move(security_origin));
std::move(security_origin));
// Requires SecurityOrigin to be initialized. // Requires SecurityOrigin to be initialized.
OriginTrialContext::AddTokensFromHeader( OriginTrialContext::AddTokensFromHeader(
frame_->DomWindow(), response_.HttpHeaderField(http_names::kOriginTrial)); frame_->DomWindow(), response_.HttpHeaderField(http_names::kOriginTrial));
if (auto* parent = frame_->Tree().Parent()) {
const SecurityContext* parent_context = parent->GetSecurityContext();
security_context.SetInsecureRequestPolicy(
parent_context->GetInsecureRequestPolicy());
for (auto to_upgrade : parent_context->InsecureNavigationsToUpgrade())
security_context.AddInsecureNavigationUpgrade(to_upgrade);
}
frame_->DomWindow()->SetAddressSpace(ip_address_space_);
}
void DocumentLoader::CommitNavigation() {
CHECK_GE(state_, kCommitted);
DCHECK(frame_->GetPage());
DCHECK(!frame_->GetDocument() || !frame_->GetDocument()->IsActive());
DCHECK_EQ(frame_->Tree().ChildCount(), 0u);
// Prepare a DocumentInit before clearing the frame, because it may need to
// inherit an aliased security context.
Document* owner_document = nullptr;
// TODO(dcheng): This differs from the behavior of both IE and Firefox: the
// origin is inherited from the document that loaded the URL.
if (Document::ShouldInheritSecurityOriginFromOwner(Url())) {
Frame* owner_frame = frame_->Tree().Parent();
if (!owner_frame)
owner_frame = frame_->Loader().Opener();
if (auto* owner_local_frame = DynamicTo<LocalFrame>(owner_frame))
owner_document = owner_local_frame->GetDocument();
}
// Re-validate Document Policy feature before installing the new document.
if (!RuntimeEnabledFeatures::DocumentPolicyEnabled(
owner_document ? owner_document->GetExecutionContext() : nullptr)) {
document_policy_ = DocumentPolicy::ParsedDocumentPolicy{};
}
if (document_policy_.feature_state.contains(
mojom::blink::DocumentPolicyFeature::kForceLoadAtTop)) {
navigation_scroll_allowed_ = !(
document_policy_
.feature_state[mojom::blink::DocumentPolicyFeature::kForceLoadAtTop]
.BoolValue());
}
LocalDOMWindow* previous_window = frame_->DomWindow();
InitializeWindow(owner_document);
if (GetFrameLoader().StateMachine()->IsDisplayingInitialEmptyDocument()) {
GetFrameLoader().StateMachine()->AdvanceTo(
FrameLoaderStateMachine::kCommittedFirstRealLoad);
}
SecurityContextInit security_init(frame_->DomWindow()); SecurityContextInit security_init(frame_->DomWindow());
// FeaturePolicy and DocumentPolicy require SecurityOrigin and origin trials // FeaturePolicy and DocumentPolicy require SecurityOrigin and origin trials
// to be initialized. // to be initialized.
...@@ -1752,26 +1757,16 @@ void DocumentLoader::CommitNavigation() { ...@@ -1752,26 +1757,16 @@ void DocumentLoader::CommitNavigation() {
document_policy_, document_policy_,
response_.HttpHeaderField(http_names::kDocumentPolicyReportOnly)); response_.HttpHeaderField(http_names::kDocumentPolicyReportOnly));
if (auto* parent = frame_->Tree().Parent()) {
SecurityContext& this_context = frame_->DomWindow()->GetSecurityContext();
const SecurityContext* parent_context = parent->GetSecurityContext();
this_context.SetInsecureRequestPolicy(
parent_context->GetInsecureRequestPolicy());
for (auto to_upgrade : parent_context->InsecureNavigationsToUpgrade())
this_context.AddInsecureNavigationUpgrade(to_upgrade);
}
frame_->DomWindow()->SetAddressSpace(ip_address_space_);
WillCommitNavigation(); WillCommitNavigation();
DocumentInit init = DocumentInit::Create() Document* document = frame_->DomWindow()->InstallNewDocument(
.WithWindow(frame_->DomWindow(), owner_document) DocumentInit::Create()
.WithURL(Url()) .WithWindow(frame_->DomWindow(), owner_document)
.WithTypeFrom(MimeType()) .WithURL(Url())
.WithSrcdocDocument(loading_srcdoc_) .WithTypeFrom(MimeType())
.WithNewRegistrationContext() .WithSrcdocDocument(loading_srcdoc_)
.WithWebBundleClaimedUrl(web_bundle_claimed_url_); .WithNewRegistrationContext()
Document* document = frame_->DomWindow()->InstallNewDocument(init); .WithWebBundleClaimedUrl(web_bundle_claimed_url_));
// Clear the user activation state. // Clear the user activation state.
// TODO(crbug.com/736415): Clear this bit unconditionally for all frames. // TODO(crbug.com/736415): Clear this bit unconditionally for all frames.
...@@ -1898,7 +1893,7 @@ void DocumentLoader::CommitNavigation() { ...@@ -1898,7 +1893,7 @@ void DocumentLoader::CommitNavigation() {
} else { } else {
GetLocalFrameClient().DispatchDidCommitLoad( GetLocalFrameClient().DispatchDidCommitLoad(
history_item_.Get(), LoadTypeToCommitType(load_type_), history_item_.Get(), LoadTypeToCommitType(load_type_),
global_object_reuse_policy); previous_window != frame_->DomWindow());
} }
// TODO(dgozman): make DidCreateScriptContext notification call currently // TODO(dgozman): make DidCreateScriptContext notification call currently
// triggered by installing new document happen here, after commit. // triggered by installing new document happen here, after commit.
......
...@@ -99,12 +99,6 @@ namespace mojom { ...@@ -99,12 +99,6 @@ namespace mojom {
enum class CommitResult : int32_t; enum class CommitResult : int32_t;
} }
// Indicates whether the global object (i.e. Window instance) associated with
// the previous document in a browsing context was replaced or reused for the
// new Document corresponding to the just-committed navigation; effective in the
// main world and all isolated worlds. WindowProxies are not affected.
enum class GlobalObjectReusePolicy { kCreateNew, kUseExisting };
// The DocumentLoader fetches a main resource and handles the result. // The DocumentLoader fetches a main resource and handles the result.
// TODO(https://crbug.com/855189). This was originally structured to have a // TODO(https://crbug.com/855189). This was originally structured to have a
// provisional load, then commit but that is no longer necessary and this class // provisional load, then commit but that is no longer necessary and this class
...@@ -343,7 +337,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>, ...@@ -343,7 +337,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
scoped_refptr<SecurityOrigin> CalculateOrigin( scoped_refptr<SecurityOrigin> CalculateOrigin(
Document* owner_document, Document* owner_document,
network::mojom::blink::WebSandboxFlags); network::mojom::blink::WebSandboxFlags);
GlobalObjectReusePolicy CalculateGlobalObjectReusePolicy(SecurityOrigin*); void InitializeWindow(Document* owner_document);
void DidInstallNewDocument(Document*); void DidInstallNewDocument(Document*);
void WillCommitNavigation(); void WillCommitNavigation();
void DidCommitNavigation(); void DidCommitNavigation();
......
...@@ -83,8 +83,6 @@ class Cursor; ...@@ -83,8 +83,6 @@ class Cursor;
namespace blink { namespace blink {
enum class GlobalObjectReusePolicy;
class CORE_EXPORT EmptyChromeClient : public ChromeClient { class CORE_EXPORT EmptyChromeClient : public ChromeClient {
public: public:
~EmptyChromeClient() override = default; ~EmptyChromeClient() override = default;
...@@ -248,7 +246,7 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient { ...@@ -248,7 +246,7 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
void DispatchDidReceiveTitle(const String&) override {} void DispatchDidReceiveTitle(const String&) override {}
void DispatchDidCommitLoad(HistoryItem*, void DispatchDidCommitLoad(HistoryItem*,
WebHistoryCommitType, WebHistoryCommitType,
GlobalObjectReusePolicy) override {} bool) override {}
void DispatchDidFailLoad(const ResourceError&, void DispatchDidFailLoad(const ResourceError&,
WebHistoryCommitType) override {} WebHistoryCommitType) override {}
void DispatchDidFinishDocumentLoad() override {} void DispatchDidFinishDocumentLoad() override {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment