blob: 53fc7624f82314e416f3622be9a05f947603b419 [file] [log] [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 "extensions/browser/browser_frame_context_data.h"
#include <memory>
#include "content/public/browser/isolated_context_util.h"
#include "content/public/browser/isolated_web_apps_policy.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extensions_browser_client.h"
#include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom-forward.h"
#include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h"
namespace extensions {
std::unique_ptr<FrameContextData>
BrowserFrameContextData::CloneFrameContextData() const {
return std::make_unique<BrowserFrameContextData>(frame_);
}
bool BrowserFrameContextData::HasControlledFrameCapability() const {
return frame_ &&
frame_->IsFeatureEnabled(
network::mojom::PermissionsPolicyFeature::kControlledFrame) &&
content::HasIsolatedContextCapability(frame_) &&
ExtensionsBrowserClient::Get()->HasControlledFrameCapability(
frame_->GetBrowserContext(), GetUrl());
}
std::unique_ptr<FrameContextData>
BrowserFrameContextData::GetLocalParentOrOpener() const {
CHECK(frame_);
content::RenderFrameHost* parent_or_opener = frame_->GetParent();
// Non primary pages (e.g. fenced frame, prerendered page, bfcache) can't look
// at the opener, and WebContents::GetOpener returns the opener on the primary
// frame tree. Thus, GetOpener should be called when `frame_` is a primary
// main frame.
if (!parent_or_opener && frame_->IsInPrimaryMainFrame()) {
parent_or_opener =
content::WebContents::FromRenderFrameHost(frame_)->GetOpener();
}
if (!parent_or_opener) {
return nullptr;
}
// Renderer-side WebLocalFrameAdapter only considers local frames.
// Comparing processes is robust way to replicate such renderer-side checks,
// because out caller (DoesContentScriptMatch) accepts false positives.
// This comparison might be less accurate (e.g. give more false positives)
// than SiteInstance comparison, but comparing processes should be robust
// and stable as SiteInstanceGroup refactoring proceeds.
if (parent_or_opener->GetProcess() != frame_->GetProcess()) {
return nullptr;
}
return std::make_unique<BrowserFrameContextData>(parent_or_opener);
}
GURL BrowserFrameContextData::GetUrl() const {
CHECK(frame_);
if (frame_->GetLastCommittedURL().is_empty()) {
// It's possible for URL to be empty when `frame_` is on the initial empty
// document. TODO(crbug.com/40176869): Consider making `frame_`'s
// document's URL about:blank instead of empty in that case.
return GURL(url::kAboutBlankURL);
}
return frame_->GetLastCommittedURL();
}
url::Origin BrowserFrameContextData::GetOrigin() const {
CHECK(frame_);
return frame_->GetLastCommittedOrigin();
}
// BrowserFrameContextData::CanAccess is unable to replicate all of the
// WebSecurityOrigin::CanAccess checks, so these methods should not be called.
bool BrowserFrameContextData::CanAccess(const url::Origin& target) const {
NOTREACHED();
}
bool BrowserFrameContextData::CanAccess(const FrameContextData& target) const {
NOTREACHED();
}
uintptr_t BrowserFrameContextData::GetId() const {
CHECK(frame_);
return frame_->GetRoutingID();
}
} // namespace extensions