blob: 4f6b4ad3169f72722ca97c8ab4c5e81affe17932 [file] [log] [blame]
// Copyright 2017 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/renderer/mus/mus_embedded_frame.h"
#include <map>
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "cc/base/switches.h"
#include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
#include "components/viz/client/hit_test_data_provider.h"
#include "components/viz/client/local_surface_id_provider.h"
#include "content/renderer/mus/renderer_window_tree_client.h"
#include "services/ws/public/cpp/property_type_converters.h"
#include "services/ws/public/mojom/window_manager.mojom.h"
namespace content {
namespace {
// Callback from embedding a child frame.
void OnEmbedAck(bool success) {
DCHECK(success);
}
} // namespace
MusEmbeddedFrame::~MusEmbeddedFrame() {
renderer_window_tree_client_->OnEmbeddedFrameDestroyed(this);
// If the tree changed the old tree the window was created in was dropped and
// the server implictly cleaned up. As such, no need to do cleanup here (and
// we don't have a handle to the right WindowTree at this point).
if (tree_changed_)
return;
// If there is |pending_state_| it means we didn't actually create the window
// yet and there is nothing to do.
if (pending_state_)
return;
window_tree()->DeleteWindow(GetAndAdvanceNextChangeId(), window_id_);
}
void MusEmbeddedFrame::SetWindowBounds(
const viz::LocalSurfaceId& local_surface_id,
const gfx::Rect& bounds) {
if (tree_changed_)
return;
if (!window_tree()) {
DCHECK(pending_state_);
pending_state_->bounds = bounds;
pending_state_->local_surface_id = local_surface_id;
pending_state_->was_set_window_bounds_called = true;
return;
}
window_tree()->SetWindowBounds(GetAndAdvanceNextChangeId(), window_id_,
bounds, local_surface_id);
}
MusEmbeddedFrame::MusEmbeddedFrame(
RendererWindowTreeClient* renderer_window_tree_client,
MusEmbeddedFrameDelegate* delegate,
ws::ClientSpecificId window_id,
const base::UnguessableToken& token)
: renderer_window_tree_client_(renderer_window_tree_client),
delegate_(delegate),
window_id_(window_id) {
if (!window_tree()) {
pending_state_ = std::make_unique<PendingState>();
pending_state_->token = token;
return;
}
CreateChildWindowAndEmbed(token);
}
void MusEmbeddedFrame::CreateChildWindowAndEmbed(
const base::UnguessableToken& token) {
// Set a name for debugging.
base::flat_map<std::string, std::vector<uint8_t>> properties;
properties[ws::mojom::WindowManager::kName_Property] =
mojo::ConvertTo<std::vector<uint8_t>>(std::string("RendererFrame"));
window_tree()->NewWindow(GetAndAdvanceNextChangeId(), window_id_, properties);
window_tree()->AddWindow(GetAndAdvanceNextChangeId(),
renderer_window_tree_client_->root_window_id_,
window_id_);
window_tree()->EmbedUsingToken(window_id_, token, 0,
base::BindOnce(&OnEmbedAck));
}
void MusEmbeddedFrame::OnTreeAvailable() {
// See header for description, always called before OnTreeWillChange().
DCHECK(!tree_changed_);
std::unique_ptr<PendingState> pending_state = std::move(pending_state_);
CreateChildWindowAndEmbed(pending_state->token);
if (pending_state->was_set_window_bounds_called)
SetWindowBounds(pending_state->local_surface_id, pending_state->bounds);
}
void MusEmbeddedFrame::OnTreeWillChange() {
tree_changed_ = true;
}
uint32_t MusEmbeddedFrame::GetAndAdvanceNextChangeId() {
return renderer_window_tree_client_->GetAndAdvanceNextChangeId();
}
ws::mojom::WindowTree* MusEmbeddedFrame::window_tree() {
// Once |tree_changed_| is true the WindowTree this instance used has changed
// and it no longer makes sense to use it (the original window was deleted).
return tree_changed_ ? nullptr : renderer_window_tree_client_->tree_.get();
}
MusEmbeddedFrame::PendingState::PendingState() = default;
MusEmbeddedFrame::PendingState::~PendingState() = default;
} // namespace content