123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758 |
- // 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 "components/exo/seat.h"
- #include "base/containers/flat_map.h"
- #include "base/files/file_util.h"
- #include "base/memory/scoped_refptr.h"
- #include "base/pickle.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/task/thread_pool/thread_pool_instance.h"
- #include "base/test/bind.h"
- #include "components/exo/data_source.h"
- #include "components/exo/data_source_delegate.h"
- #include "components/exo/seat_observer.h"
- #include "components/exo/surface.h"
- #include "components/exo/test/exo_test_base.h"
- #include "components/exo/test/exo_test_data_exchange_delegate.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "ui/base/clipboard/clipboard.h"
- #include "ui/base/clipboard/clipboard_format_type.h"
- #include "ui/base/clipboard/custom_data_helper.h"
- #include "ui/base/clipboard/scoped_clipboard_writer.h"
- #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
- #include "ui/events/event.h"
- #include "ui/events/event_utils.h"
- namespace exo {
- namespace {
- using SeatTest = test::ExoTestBase;
- class TestSeatObserver : public SeatObserver {
- public:
- explicit TestSeatObserver(const base::RepeatingClosure& callback)
- : callback_(callback) {}
- // Overridden from SeatObserver:
- void OnSurfaceFocused(Surface* gained_focus,
- Surface* lost_focus,
- bool has_focused_surface) override {
- callback_.Run();
- }
- private:
- base::RepeatingClosure callback_;
- };
- class TestDataSourceDelegate : public DataSourceDelegate {
- public:
- TestDataSourceDelegate() {}
- TestDataSourceDelegate(const TestDataSourceDelegate&) = delete;
- TestDataSourceDelegate& operator=(const TestDataSourceDelegate&) = delete;
- bool cancelled() const { return cancelled_; }
- // Overridden from DataSourceDelegate:
- void OnDataSourceDestroying(DataSource* device) override {}
- void OnTarget(const absl::optional<std::string>& mime_type) override {}
- void OnSend(const std::string& mime_type, base::ScopedFD fd) override {
- if (data_map_.empty()) {
- const char kTestData[] = "TestData";
- ASSERT_TRUE(base::WriteFileDescriptor(fd.get(), kTestData));
- } else {
- ASSERT_TRUE(base::WriteFileDescriptor(fd.get(), data_map_[mime_type]));
- }
- }
- void OnCancelled() override { cancelled_ = true; }
- void OnDndDropPerformed() override {}
- void OnDndFinished() override {}
- void OnAction(DndAction dnd_action) override {}
- bool CanAcceptDataEventsForSurface(Surface* surface) const override {
- return can_accept_;
- }
- void SetData(const std::string& mime_type, std::vector<uint8_t> data) {
- data_map_[mime_type] = std::move(data);
- }
- bool can_accept_ = true;
- private:
- bool cancelled_ = false;
- base::flat_map<std::string, std::vector<uint8_t>> data_map_;
- };
- void RunReadingTask() {
- base::ThreadPoolInstance::Get()->FlushForTesting();
- base::RunLoop().RunUntilIdle();
- }
- class TestSeat : public Seat {
- public:
- TestSeat() : Seat(std::make_unique<TestDataExchangeDelegate>()) {}
- explicit TestSeat(
- std::unique_ptr<TestDataExchangeDelegate> data_exchange_delegate)
- : Seat(std::move(data_exchange_delegate)) {}
- TestSeat(const TestSeat&) = delete;
- void operator=(const TestSeat&) = delete;
- void set_focused_surface(Surface* surface) { surface_ = surface; }
- // Seat:
- Surface* GetFocusedSurface() override { return surface_; }
- private:
- Surface* surface_ = nullptr;
- };
- TEST_F(SeatTest, OnSurfaceFocused) {
- TestSeat seat;
- int callback_counter = 0;
- absl::optional<int> observer1_counter;
- TestSeatObserver observer1(base::BindLambdaForTesting(
- [&]() { observer1_counter = callback_counter++; }));
- absl::optional<int> observer2_counter;
- TestSeatObserver observer2(base::BindLambdaForTesting(
- [&]() { observer2_counter = callback_counter++; }));
- // Register observers in the reversed order.
- seat.AddObserver(&observer2, 1);
- seat.AddObserver(&observer1, 0);
- seat.OnWindowFocused(nullptr, nullptr);
- EXPECT_EQ(observer1_counter, 0);
- EXPECT_EQ(observer2_counter, 1);
- observer1_counter.reset();
- observer2_counter.reset();
- seat.RemoveObserver(&observer1);
- seat.RemoveObserver(&observer2);
- seat.OnWindowFocused(nullptr, nullptr);
- EXPECT_FALSE(observer1_counter.has_value());
- EXPECT_FALSE(observer2_counter.has_value());
- }
- TEST_F(SeatTest, SetSelection) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- source.Offer("text/plain;charset=utf-8");
- seat.SetSelection(&source);
- RunReadingTask();
- std::string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, std::string("TestData"));
- }
- TEST_F(SeatTest, SetSelectionReadDteFromLacros) {
- std::unique_ptr<TestDataExchangeDelegate> data_exchange_delegate(
- std::make_unique<TestDataExchangeDelegate>());
- data_exchange_delegate->set_endpoint_type(ui::EndpointType::kLacros);
- TestSeat seat(std::move(data_exchange_delegate));
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- const std::string kTestText = "TestData";
- const std::string kEncodedTestDte =
- R"({"endpoint_type":"url","url":"https://www.google.com"})";
- const std::string kTextMimeType = "text/plain;charset=utf-8";
- const std::string kDteMimeType = "chromium/x-data-transfer-endpoint";
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- source.Offer(kTextMimeType);
- delegate.SetData(kTextMimeType,
- std::vector<uint8_t>(kTestText.begin(), kTestText.end()));
- source.Offer(kDteMimeType);
- delegate.SetData(kDteMimeType, std::vector<uint8_t>(kEncodedTestDte.begin(),
- kEncodedTestDte.end()));
- seat.SetSelection(&source);
- RunReadingTask();
- std::string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, kTestText);
- const ui::DataTransferEndpoint* source_dte =
- ui::Clipboard::GetForCurrentThread()->GetSource(
- ui::ClipboardBuffer::kCopyPaste);
- ASSERT_TRUE(source_dte);
- EXPECT_EQ(ui::EndpointType::kUrl, source_dte->type());
- const ui::DataTransferEndpoint expected_dte =
- ui::DataTransferEndpoint((GURL("https://www.google.com")));
- EXPECT_EQ(*expected_dte.GetURL(), *source_dte->GetURL());
- }
- TEST_F(SeatTest, SetSelectionIgnoreDteFromNonLacros) {
- std::unique_ptr<TestDataExchangeDelegate> data_exchange_delegate(
- std::make_unique<TestDataExchangeDelegate>());
- data_exchange_delegate->set_endpoint_type(ui::EndpointType::kCrostini);
- TestSeat seat(std::move(data_exchange_delegate));
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- const std::string kTestText = "TestData";
- const std::string kEncodedTestDte =
- R"({"endpoint_type":"url","url":"https://www.google.com"})";
- const std::string kTextMimeType = "text/plain;charset=utf-8";
- const std::string kDteMimeType = "chromium/x-data-transfer-endpoint";
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- source.Offer(kTextMimeType);
- delegate.SetData(kTextMimeType,
- std::vector<uint8_t>(kTestText.begin(), kTestText.end()));
- source.Offer(kDteMimeType);
- delegate.SetData(kDteMimeType, std::vector<uint8_t>(kEncodedTestDte.begin(),
- kEncodedTestDte.end()));
- seat.SetSelection(&source);
- RunReadingTask();
- std::string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, kTestText);
- const ui::DataTransferEndpoint* source_dte =
- ui::Clipboard::GetForCurrentThread()->GetSource(
- ui::ClipboardBuffer::kCopyPaste);
- ASSERT_TRUE(source_dte);
- EXPECT_EQ(ui::EndpointType::kCrostini, source_dte->type());
- }
- TEST_F(SeatTest, SetSelectionTextUTF8) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- // UTF8 encoded data
- const uint8_t data[] = {
- 0xe2, 0x9d, 0x84, // SNOWFLAKE
- 0xf0, 0x9f, 0x94, 0xa5 // FIRE
- };
- std::u16string converted_data;
- EXPECT_TRUE(base::UTF8ToUTF16(reinterpret_cast<const char*>(data),
- sizeof(data), &converted_data));
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- const std::string kTextPlainType = "text/plain;charset=utf-8";
- const std::string kTextHtmlType = "text/html;charset=utf-8";
- source.Offer(kTextPlainType);
- source.Offer(kTextHtmlType);
- delegate.SetData(kTextPlainType,
- std::vector<uint8_t>(data, data + sizeof(data)));
- delegate.SetData(kTextHtmlType,
- std::vector<uint8_t>(data, data + sizeof(data)));
- seat.SetSelection(&source);
- RunReadingTask();
- std::u16string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, converted_data);
- std::string url;
- uint32_t start, end;
- ui::Clipboard::GetForCurrentThread()->ReadHTML(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard, &url,
- &start, &end);
- EXPECT_EQ(clipboard, converted_data);
- }
- TEST_F(SeatTest, SetSelectionTextUTF8Legacy) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- // UTF8 encoded data
- const uint8_t data[] = {
- 0xe2, 0x9d, 0x84, // SNOWFLAKE
- 0xf0, 0x9f, 0x94, 0xa5 // FIRE
- };
- std::u16string converted_data;
- EXPECT_TRUE(base::UTF8ToUTF16(reinterpret_cast<const char*>(data),
- sizeof(data), &converted_data));
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- const std::string kMimeType = "UTF8_STRING";
- source.Offer(kMimeType);
- delegate.SetData(kMimeType, std::vector<uint8_t>(data, data + sizeof(data)));
- seat.SetSelection(&source);
- RunReadingTask();
- std::u16string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, converted_data);
- }
- TEST_F(SeatTest, SetSelectionTextUTF16LE) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- // UTF16 little endian encoded data
- const uint8_t data[] = {
- 0xff, 0xfe, // Byte order mark
- 0x44, 0x27, // SNOWFLAKE
- 0x3d, 0xd8, 0x25, 0xdd, // FIRE
- };
- std::u16string converted_data;
- converted_data.push_back(0x2744);
- converted_data.push_back(0xd83d);
- converted_data.push_back(0xdd25);
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- const std::string kTextPlainType = "text/plain;charset=utf-16";
- const std::string kTextHtmlType = "text/html;charset=utf-16";
- source.Offer(kTextPlainType);
- source.Offer(kTextHtmlType);
- delegate.SetData(kTextPlainType,
- std::vector<uint8_t>(data, data + sizeof(data)));
- delegate.SetData(kTextHtmlType,
- std::vector<uint8_t>(data, data + sizeof(data)));
- seat.SetSelection(&source);
- RunReadingTask();
- std::u16string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, converted_data);
- std::string url;
- uint32_t start, end;
- ui::Clipboard::GetForCurrentThread()->ReadHTML(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard, &url,
- &start, &end);
- EXPECT_EQ(clipboard, converted_data);
- }
- TEST_F(SeatTest, SetSelectionTextUTF16BE) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- // UTF16 big endian encoded data
- const uint8_t data[] = {
- 0xfe, 0xff, // Byte order mark
- 0x27, 0x44, // SNOWFLAKE
- 0xd8, 0x3d, 0xdd, 0x25, // FIRE
- };
- std::u16string converted_data;
- converted_data.push_back(0x2744);
- converted_data.push_back(0xd83d);
- converted_data.push_back(0xdd25);
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- const std::string kTextPlainType = "text/plain;charset=utf-16";
- const std::string kTextHtmlType = "text/html;charset=utf-16";
- source.Offer(kTextPlainType);
- source.Offer(kTextHtmlType);
- delegate.SetData(kTextPlainType,
- std::vector<uint8_t>(data, data + sizeof(data)));
- delegate.SetData(kTextHtmlType,
- std::vector<uint8_t>(data, data + sizeof(data)));
- seat.SetSelection(&source);
- RunReadingTask();
- std::u16string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, converted_data);
- std::string url;
- uint32_t start, end;
- ui::Clipboard::GetForCurrentThread()->ReadHTML(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard, &url,
- &start, &end);
- EXPECT_EQ(clipboard, converted_data);
- }
- TEST_F(SeatTest, SetSelectionTextEmptyString) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- const uint8_t data[] = {};
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- const std::string kTextPlainType = "text/plain;charset=utf-8";
- const std::string kTextHtmlType = "text/html;charset=utf-16";
- source.Offer(kTextPlainType);
- source.Offer(kTextHtmlType);
- delegate.SetData(kTextPlainType,
- std::vector<uint8_t>(data, data + sizeof(data)));
- delegate.SetData(kTextHtmlType,
- std::vector<uint8_t>(data, data + sizeof(data)));
- seat.SetSelection(&source);
- RunReadingTask();
- std::u16string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard.size(), 0u);
- std::string url;
- uint32_t start, end;
- ui::Clipboard::GetForCurrentThread()->ReadHTML(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard, &url,
- &start, &end);
- EXPECT_EQ(clipboard.size(), 0u);
- }
- TEST_F(SeatTest, SetSelectionRTF) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- source.Offer("text/rtf");
- seat.SetSelection(&source);
- RunReadingTask();
- std::string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadRTF(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, std::string("TestData"));
- }
- TEST_F(SeatTest, SetSelectionFilenames) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- const std::string data("file:///path1\r\nfile:///path2");
- TestDataSourceDelegate delegate;
- const std::string kMimeType = "text/uri-list";
- delegate.SetData(kMimeType, std::vector<uint8_t>(data.begin(), data.end()));
- DataSource source(&delegate);
- source.Offer(kMimeType);
- seat.SetSelection(&source);
- RunReadingTask();
- std::vector<ui::FileInfo> filenames;
- ui::Clipboard::GetForCurrentThread()->ReadFilenames(
- ui::ClipboardBuffer::kCopyPaste,
- /*data_dst=*/nullptr, &filenames);
- EXPECT_EQ(ui::FileInfosToURIList(filenames), data);
- }
- TEST_F(SeatTest, SetSelectionWebCustomData) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- base::flat_map<std::u16string, std::u16string> custom_data;
- custom_data[u"text/uri-list"] = u"data";
- base::Pickle pickle;
- ui::WriteCustomDataToPickle(custom_data, &pickle);
- auto custom_data_str =
- std::string(reinterpret_cast<const char*>(pickle.data()), pickle.size());
- TestDataSourceDelegate delegate;
- const std::string kMimeType = "chromium/x-web-custom-data";
- delegate.SetData(kMimeType, std::vector<uint8_t>(custom_data_str.begin(),
- custom_data_str.end()));
- DataSource source(&delegate);
- source.Offer(kMimeType);
- seat.SetSelection(&source);
- RunReadingTask();
- std::u16string result;
- ui::Clipboard::GetForCurrentThread()->ReadCustomData(
- ui::ClipboardBuffer::kCopyPaste, u"text/uri-list", /*data_dst=*/nullptr,
- &result);
- EXPECT_EQ(result, u"data");
- }
- TEST_F(SeatTest, SetSelection_TwiceSame) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- seat.SetSelection(&source);
- RunReadingTask();
- seat.SetSelection(&source);
- RunReadingTask();
- EXPECT_FALSE(delegate.cancelled());
- }
- TEST_F(SeatTest, SetSelection_TwiceDifferent) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- TestDataSourceDelegate delegate1;
- DataSource source1(&delegate1);
- seat.SetSelection(&source1);
- RunReadingTask();
- EXPECT_FALSE(delegate1.cancelled());
- TestDataSourceDelegate delegate2;
- DataSource source2(&delegate2);
- seat.SetSelection(&source2);
- RunReadingTask();
- EXPECT_TRUE(delegate1.cancelled());
- }
- TEST_F(SeatTest, SetSelection_ClipboardChangedDuringSetSelection) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- seat.SetSelection(&source);
- {
- ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
- writer.WriteText(u"New data");
- }
- RunReadingTask();
- // The previous source should be cancelled.
- EXPECT_TRUE(delegate.cancelled());
- std::string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, "New data");
- }
- TEST_F(SeatTest, SetSelection_ClipboardChangedAfterSetSelection) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- seat.SetSelection(&source);
- RunReadingTask();
- {
- ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
- writer.WriteText(u"New data");
- }
- // The previous source should be cancelled.
- EXPECT_TRUE(delegate.cancelled());
- std::string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, "New data");
- }
- TEST_F(SeatTest, SetSelection_SourceDestroyedDuringSetSelection) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- {
- ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
- writer.WriteText(u"Original data");
- }
- {
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- seat.SetSelection(&source);
- // source destroyed here.
- }
- RunReadingTask();
- std::string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, "Original data");
- }
- TEST_F(SeatTest, SetSelection_SourceDestroyedAfterSetSelection) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- TestDataSourceDelegate delegate1;
- {
- DataSource source(&delegate1);
- seat.SetSelection(&source);
- RunReadingTask();
- // source destroyed here.
- }
- RunReadingTask();
- {
- TestDataSourceDelegate delegate2;
- DataSource source(&delegate2);
- seat.SetSelection(&source);
- RunReadingTask();
- // source destroyed here.
- }
- RunReadingTask();
- // delegate1 should not receive cancel request because the first data source
- // has already been destroyed.
- EXPECT_FALSE(delegate1.cancelled());
- }
- TEST_F(SeatTest, SetSelection_NullSource) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- source.Offer("text/plain;charset=utf-8");
- seat.SetSelection(&source);
- RunReadingTask();
- {
- ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
- writer.WriteText(u"Golden data");
- }
- // Should not affect the current state of the clipboard.
- seat.SetSelection(nullptr);
- ASSERT_TRUE(delegate.cancelled());
- std::string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
- EXPECT_EQ(clipboard, "Golden data");
- }
- TEST_F(SeatTest, SetSelection_NoFocusedSurface) {
- TestSeat seat;
- seat.set_focused_surface(nullptr);
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- source.Offer("text/plain;charset=utf-8");
- seat.SetSelection(&source);
- EXPECT_TRUE(delegate.cancelled());
- }
- TEST_F(SeatTest, SetSelection_ClientOutOfFocus) {
- TestSeat seat;
- Surface focused_surface;
- seat.set_focused_surface(&focused_surface);
- TestDataSourceDelegate delegate;
- delegate.can_accept_ = false;
- DataSource source(&delegate);
- source.Offer("text/plain;charset=utf-8");
- seat.SetSelection(&source);
- EXPECT_TRUE(delegate.cancelled());
- }
- TEST_F(SeatTest, PressedKeys) {
- TestSeat seat;
- ui::KeyEvent press_a(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::DomCode::US_A, 0);
- ui::KeyEvent release_a(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::DomCode::US_A, 0);
- ui::KeyEvent press_b(ui::ET_KEY_PRESSED, ui::VKEY_B, ui::DomCode::US_B, 0);
- ui::KeyEvent release_b(ui::ET_KEY_RELEASED, ui::VKEY_B, ui::DomCode::US_B, 0);
- // Press A, it should be in the map.
- seat.WillProcessEvent(&press_a);
- seat.OnKeyEvent(press_a.AsKeyEvent());
- seat.DidProcessEvent(&press_a);
- base::flat_map<ui::DomCode, KeyState> pressed_keys;
- pressed_keys[ui::CodeFromNative(&press_a)] = KeyState{press_a.code(), false};
- EXPECT_EQ(pressed_keys, seat.pressed_keys());
- // Press B, then A & B should be in the map.
- seat.WillProcessEvent(&press_b);
- seat.OnKeyEvent(press_b.AsKeyEvent());
- seat.DidProcessEvent(&press_b);
- pressed_keys[ui::CodeFromNative(&press_b)] = KeyState{press_b.code(), false};
- EXPECT_EQ(pressed_keys, seat.pressed_keys());
- // Release A, with the normal order where DidProcessEvent is after OnKeyEvent,
- // only B should be in the map.
- seat.WillProcessEvent(&release_a);
- seat.OnKeyEvent(release_a.AsKeyEvent());
- seat.DidProcessEvent(&release_a);
- pressed_keys.erase(ui::CodeFromNative(&press_a));
- EXPECT_EQ(pressed_keys, seat.pressed_keys());
- // Release B, do it out of order so DidProcessEvent is before OnKeyEvent, the
- // map should then be empty.
- seat.WillProcessEvent(&release_b);
- seat.DidProcessEvent(&release_b);
- seat.OnKeyEvent(release_b.AsKeyEvent());
- EXPECT_TRUE(seat.pressed_keys().empty());
- }
- TEST_F(SeatTest, DragDropAbort) {
- TestSeat seat;
- TestDataSourceDelegate delegate;
- DataSource source(&delegate);
- Surface origin, icon;
- // Give origin a root window for DragDropOperation.
- GetContext()->AddChild(origin.window());
- seat.StartDrag(&source, &origin, &icon, ui::mojom::DragEventSource::kMouse);
- EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
- seat.AbortPendingDragOperation();
- EXPECT_FALSE(seat.get_drag_drop_operation_for_testing());
- }
- } // namespace
- } // namespace exo
|