blob: bf3a202d45bdf9b4fa3656bda2f777b5d1afdf77 [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 "ui/views/mus/remote_view/remote_view_provider.h"
#include <memory>
#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/unguessable_token.h"
#include "ui/aura/mus/window_mus.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/mus/test_window_tree.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tracker.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/mus/remote_view/remote_view_provider_test_api.h"
namespace views {
class RemoteViewProviderTest : public aura::test::AuraTestBase {
public:
RemoteViewProviderTest() = default;
~RemoteViewProviderTest() override = default;
// aura::test::AuraTestBase
void SetUp() override {
EnableMusWithTestWindowTree();
AuraTestBase::SetUp();
test::RemoteViewProviderTestApi::SetWindowTreeClient(
window_tree_client_impl());
embedded_ = std::make_unique<aura::Window>(nullptr);
embedded_->set_owned_by_parent(false);
embedded_->Init(ui::LAYER_NOT_DRAWN);
embedded_->SetBounds(gfx::Rect(100, 50));
provider_ = std::make_unique<RemoteViewProvider>(embedded_.get());
}
void TearDown() override {
// EmbedRoot in |provider_| must be released before WindowTreeClient.
provider_.reset();
AuraTestBase::TearDown();
}
// Gets the embed token and waits for it.
base::UnguessableToken GetEmbedToken() {
base::RunLoop run_loop;
base::UnguessableToken token;
provider_->GetEmbedToken(base::BindOnce(
[](base::RunLoop* run_loop, base::UnguessableToken* out_token,
const base::UnguessableToken& token) {
*out_token = token;
run_loop->Quit();
},
&run_loop, &token));
run_loop.Run();
return token;
}
// Simulates EmbedUsingToken call on embedder side and waits for
// WindowTreeClient to create a local embedder window.
aura::Window* SimulateEmbedUsingTokenAndGetEmbedder(
const base::UnguessableToken& token) {
base::RunLoop run_loop;
aura::Window* embedder = nullptr;
provider_->SetCallbacks(
base::BindRepeating(
[](base::RunLoop* run_loop, aura::Window** out_embedder,
aura::Window* embedder) {
*out_embedder = embedder;
run_loop->Quit();
},
&run_loop, &embedder),
base::DoNothing() /* OnUnembedCallback */);
window_tree()->AddEmbedRootForToken(token);
run_loop.Run();
return embedder;
}
// Helper to simulate embed.
aura::Window* SimulateEmbed() {
base::UnguessableToken token = GetEmbedToken();
if (token.is_empty()) {
ADD_FAILURE() << "Failed to get embed token.";
return nullptr;
}
return SimulateEmbedUsingTokenAndGetEmbedder(token);
}
// Simulates the embedder window close.
void SimulateEmbedderClose(aura::Window* embedder) {
base::RunLoop run_loop;
provider_->SetCallbacks(
base::DoNothing() /* OnEmbedCallback */,
base::BindRepeating([](base::RunLoop* run_loop) { run_loop->Quit(); },
&run_loop));
const ui::Id embedder_window_id =
aura::WindowMus::Get(embedder)->server_id();
window_tree()->RemoveEmbedderWindow(embedder_window_id);
run_loop.Run();
}
protected:
std::unique_ptr<aura::Window> embedded_;
std::unique_ptr<RemoteViewProvider> provider_;
private:
DISALLOW_COPY_AND_ASSIGN(RemoteViewProviderTest);
};
// Tests the basics on the embedded client.
TEST_F(RemoteViewProviderTest, Embed) {
aura::Window* embedder = SimulateEmbed();
ASSERT_TRUE(embedder);
// |embedded_| has the same non-empty size with |embedder| after embed.
EXPECT_EQ(embedded_->bounds().size(), embedder->bounds().size());
EXPECT_FALSE(embedded_->bounds().IsEmpty());
EXPECT_FALSE(embedder->bounds().IsEmpty());
// |embedded_| resizes with |embedder|.
const gfx::Rect new_bounds(embedder->bounds().width() + 100,
embedder->bounds().height() + 50);
embedder->SetBounds(new_bounds);
EXPECT_EQ(embedded_->bounds().size(), embedder->bounds().size());
EXPECT_FALSE(embedded_->bounds().IsEmpty());
EXPECT_FALSE(embedder->bounds().IsEmpty());
}
// Tests when |embedded_| is released first.
TEST_F(RemoteViewProviderTest, EmbeddedReleasedFirst) {
SimulateEmbed();
embedded_.reset();
}
// Tests when |provider_| is released first.
TEST_F(RemoteViewProviderTest, ClientReleasedFirst) {
SimulateEmbed();
provider_.reset();
}
// Tests when embedder goes away first.
TEST_F(RemoteViewProviderTest, EmbedderReleasedFirst) {
aura::Window* embedder = SimulateEmbed();
ASSERT_TRUE(embedder);
SimulateEmbedderClose(embedder);
}
// Tests that the client can embed again.
TEST_F(RemoteViewProviderTest, EmbedAgain) {
aura::Window* embedder = SimulateEmbed();
ASSERT_TRUE(embedder);
aura::WindowTracker window_tracker;
window_tracker.Add(embedder);
SimulateEmbedderClose(embedder);
// SimulateEmbedderClose() should delete |embedder|.
EXPECT_TRUE(window_tracker.windows().empty());
aura::Window* new_embedder = SimulateEmbed();
// SimulateEmbed() should create a new window.
ASSERT_TRUE(new_embedder);
}
} // namespace views