blob: 5e66e6d94c2cca9c39255065676cf72a4d112552 [file] [log] [blame]
// Copyright 2018 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 "services/content/public/cpp/navigable_contents_view.h"
#include <map>
#include "base/callback.h"
#include "base/no_destructor.h"
#include "base/synchronization/atomic_flag.h"
#include "base/unguessable_token.h"
#include "services/content/public/cpp/buildflags.h"
#if defined(TOOLKIT_VIEWS)
#include "ui/views/layout/fill_layout.h" // nogncheck
#include "ui/views/view.h" // nogncheck
#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
#include "services/ui/public/interfaces/window_tree_constants.mojom.h" // nogncheck
#include "ui/base/ui_base_features.h" // nogncheck
#include "ui/views/mus/remote_view/remote_view_host.h" // nogncheck
#endif // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
#endif // defined(TOOLKIT_VIEWS)
namespace content {
namespace {
using InProcessEmbeddingMap =
std::map<base::UnguessableToken,
base::OnceCallback<void(NavigableContentsView*)>>;
InProcessEmbeddingMap& GetInProcessEmbeddingMap() {
static base::NoDestructor<InProcessEmbeddingMap> embedding_map;
return *embedding_map;
}
base::AtomicFlag& GetInServiceProcessFlag() {
static base::NoDestructor<base::AtomicFlag> in_service_process;
return *in_service_process;
}
} // namespace
NavigableContentsView::~NavigableContentsView() = default;
// static
void NavigableContentsView::SetClientRunningInServiceProcess() {
GetInServiceProcessFlag().Set();
}
// static
bool NavigableContentsView::IsClientRunningInServiceProcess() {
return GetInServiceProcessFlag().IsSet();
}
NavigableContentsView::NavigableContentsView() {
#if defined(TOOLKIT_VIEWS)
view_ = std::make_unique<views::View>();
view_->set_owned_by_client();
view_->SetLayoutManager(std::make_unique<views::FillLayout>());
#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
if (!IsClientRunningInServiceProcess()) {
DCHECK(!remote_view_host_);
remote_view_host_ = new views::RemoteViewHost;
view_->AddChildView(remote_view_host_);
}
#endif // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
#endif // defined(TOOLKIT_VIEWS)
}
void NavigableContentsView::EmbedUsingToken(
const base::UnguessableToken& token) {
#if defined(TOOLKIT_VIEWS)
#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
if (remote_view_host_) {
const uint32_t kEmbedFlags =
ui::mojom::kEmbedFlagEmbedderInterceptsEvents |
ui::mojom::kEmbedFlagEmbedderControlsVisibility;
remote_view_host_->EmbedUsingToken(token, kEmbedFlags, base::DoNothing());
return;
}
#endif // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
DCHECK(IsClientRunningInServiceProcess());
// |token| should already have an embed callback entry in the in-process
// callback map, injected by the in-process Content Service implementation.
auto& embeddings = GetInProcessEmbeddingMap();
auto it = embeddings.find(token);
if (it == embeddings.end()) {
DLOG(ERROR) << "Unable to embed with unknown token " << token.ToString();
return;
}
auto callback = std::move(it->second);
embeddings.erase(it);
std::move(callback).Run(this);
#endif // defined(TOOLKIT_VIEWS)
}
// static
void NavigableContentsView::RegisterInProcessEmbedCallback(
const base::UnguessableToken& token,
base::OnceCallback<void(NavigableContentsView*)> callback) {
GetInProcessEmbeddingMap()[token] = std::move(callback);
}
} // namespace content