blob: ee556a0da0050db353d42feaf257be1a9127248d [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/browsing_topics/browsing_topics_document_host.h"
#include "base/bind.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/document_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom.h"
namespace content {
BrowsingTopicsDocumentHost::BrowsingTopicsDocumentHost(
RenderFrameHost& render_frame_host,
mojo::PendingReceiver<blink::mojom::BrowsingTopicsDocumentService> receiver)
: DocumentService(render_frame_host, std::move(receiver)) {}
// static
void BrowsingTopicsDocumentHost::CreateMojoService(
RenderFrameHost* render_frame_host,
mojo::PendingReceiver<blink::mojom::BrowsingTopicsDocumentService>
receiver) {
CHECK(render_frame_host);
if (render_frame_host->GetLastCommittedOrigin().opaque()) {
mojo::ReportBadMessage(
"Unexpected BrowsingTopicsDocumentHost::CreateMojoService in an opaque "
"origin document.");
return;
}
if (render_frame_host->IsNestedWithinFencedFrame()) {
mojo::ReportBadMessage(
"Unexpected BrowsingTopicsDocumentHost::CreateMojoService in a fenced "
"frame.");
return;
}
if (render_frame_host->GetLifecycleState() ==
RenderFrameHost::LifecycleState::kPrerendering) {
mojo::ReportBadMessage(
"Unexpected BrowsingTopicsDocumentHost::CreateMojoService when the "
"page is being prerendered.");
return;
}
// We do not check for portals here and we check at the API entry points
// because whether or not a frame is in a portal is dynamic state that could
// change.
// The object is bound to the lifetime of |render_frame_host| and the mojo
// connection. See DocumentService for details.
new BrowsingTopicsDocumentHost(*render_frame_host, std::move(receiver));
}
void BrowsingTopicsDocumentHost::GetBrowsingTopics(
GetBrowsingTopicsCallback callback) {
// IPCs may race with navigation events, so:
// - Ignore non-active frames, e.g. a frame placed into bfcache, or a
// frame that has been detached (this could happen as a result of
// cross-process races when navigating).
if (!render_frame_host().IsActive() ||
// Ignore non-primary frames, e.g. frames in a portal. Fenced frames and
// prerendered pages are also covered in this condition but they should
// have already been checked in `CreateMojoService()`.
!render_frame_host().GetPage().IsPrimary() ||
// TODO(crbug.com/1244137): IsPrimary() doesn't actually detect portals
// yet. Remove this when it does.
render_frame_host().GetOutermostMainFrame() !=
render_frame_host().GetMainFrame()) {
std::move(callback).Run(
blink::mojom::GetBrowsingTopicsResult::NewErrorMessage(
"document.browsingTopics() is only allowed in the outermost page "
"and when the page is active."));
return;
}
std::move(callback).Run(
blink::mojom::GetBrowsingTopicsResult::NewBrowsingTopics(
GetContentClient()->browser()->GetBrowsingTopicsForJsApi(
render_frame_host().GetLastCommittedOrigin(),
render_frame_host().GetMainFrame())));
}
BrowsingTopicsDocumentHost::~BrowsingTopicsDocumentHost() = default;
} // namespace content