seat_unittest.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/exo/seat.h"
  5. #include "base/containers/flat_map.h"
  6. #include "base/files/file_util.h"
  7. #include "base/memory/scoped_refptr.h"
  8. #include "base/pickle.h"
  9. #include "base/strings/utf_string_conversions.h"
  10. #include "base/task/thread_pool/thread_pool_instance.h"
  11. #include "base/test/bind.h"
  12. #include "components/exo/data_source.h"
  13. #include "components/exo/data_source_delegate.h"
  14. #include "components/exo/seat_observer.h"
  15. #include "components/exo/surface.h"
  16. #include "components/exo/test/exo_test_base.h"
  17. #include "components/exo/test/exo_test_data_exchange_delegate.h"
  18. #include "testing/gtest/include/gtest/gtest.h"
  19. #include "third_party/abseil-cpp/absl/types/optional.h"
  20. #include "ui/base/clipboard/clipboard.h"
  21. #include "ui/base/clipboard/clipboard_format_type.h"
  22. #include "ui/base/clipboard/custom_data_helper.h"
  23. #include "ui/base/clipboard/scoped_clipboard_writer.h"
  24. #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
  25. #include "ui/events/event.h"
  26. #include "ui/events/event_utils.h"
  27. namespace exo {
  28. namespace {
  29. using SeatTest = test::ExoTestBase;
  30. class TestSeatObserver : public SeatObserver {
  31. public:
  32. explicit TestSeatObserver(const base::RepeatingClosure& callback)
  33. : callback_(callback) {}
  34. // Overridden from SeatObserver:
  35. void OnSurfaceFocused(Surface* gained_focus,
  36. Surface* lost_focus,
  37. bool has_focused_surface) override {
  38. callback_.Run();
  39. }
  40. private:
  41. base::RepeatingClosure callback_;
  42. };
  43. class TestDataSourceDelegate : public DataSourceDelegate {
  44. public:
  45. TestDataSourceDelegate() {}
  46. TestDataSourceDelegate(const TestDataSourceDelegate&) = delete;
  47. TestDataSourceDelegate& operator=(const TestDataSourceDelegate&) = delete;
  48. bool cancelled() const { return cancelled_; }
  49. // Overridden from DataSourceDelegate:
  50. void OnDataSourceDestroying(DataSource* device) override {}
  51. void OnTarget(const absl::optional<std::string>& mime_type) override {}
  52. void OnSend(const std::string& mime_type, base::ScopedFD fd) override {
  53. if (data_map_.empty()) {
  54. const char kTestData[] = "TestData";
  55. ASSERT_TRUE(base::WriteFileDescriptor(fd.get(), kTestData));
  56. } else {
  57. ASSERT_TRUE(base::WriteFileDescriptor(fd.get(), data_map_[mime_type]));
  58. }
  59. }
  60. void OnCancelled() override { cancelled_ = true; }
  61. void OnDndDropPerformed() override {}
  62. void OnDndFinished() override {}
  63. void OnAction(DndAction dnd_action) override {}
  64. bool CanAcceptDataEventsForSurface(Surface* surface) const override {
  65. return can_accept_;
  66. }
  67. void SetData(const std::string& mime_type, std::vector<uint8_t> data) {
  68. data_map_[mime_type] = std::move(data);
  69. }
  70. bool can_accept_ = true;
  71. private:
  72. bool cancelled_ = false;
  73. base::flat_map<std::string, std::vector<uint8_t>> data_map_;
  74. };
  75. void RunReadingTask() {
  76. base::ThreadPoolInstance::Get()->FlushForTesting();
  77. base::RunLoop().RunUntilIdle();
  78. }
  79. class TestSeat : public Seat {
  80. public:
  81. TestSeat() : Seat(std::make_unique<TestDataExchangeDelegate>()) {}
  82. explicit TestSeat(
  83. std::unique_ptr<TestDataExchangeDelegate> data_exchange_delegate)
  84. : Seat(std::move(data_exchange_delegate)) {}
  85. TestSeat(const TestSeat&) = delete;
  86. void operator=(const TestSeat&) = delete;
  87. void set_focused_surface(Surface* surface) { surface_ = surface; }
  88. // Seat:
  89. Surface* GetFocusedSurface() override { return surface_; }
  90. private:
  91. Surface* surface_ = nullptr;
  92. };
  93. TEST_F(SeatTest, OnSurfaceFocused) {
  94. TestSeat seat;
  95. int callback_counter = 0;
  96. absl::optional<int> observer1_counter;
  97. TestSeatObserver observer1(base::BindLambdaForTesting(
  98. [&]() { observer1_counter = callback_counter++; }));
  99. absl::optional<int> observer2_counter;
  100. TestSeatObserver observer2(base::BindLambdaForTesting(
  101. [&]() { observer2_counter = callback_counter++; }));
  102. // Register observers in the reversed order.
  103. seat.AddObserver(&observer2, 1);
  104. seat.AddObserver(&observer1, 0);
  105. seat.OnWindowFocused(nullptr, nullptr);
  106. EXPECT_EQ(observer1_counter, 0);
  107. EXPECT_EQ(observer2_counter, 1);
  108. observer1_counter.reset();
  109. observer2_counter.reset();
  110. seat.RemoveObserver(&observer1);
  111. seat.RemoveObserver(&observer2);
  112. seat.OnWindowFocused(nullptr, nullptr);
  113. EXPECT_FALSE(observer1_counter.has_value());
  114. EXPECT_FALSE(observer2_counter.has_value());
  115. }
  116. TEST_F(SeatTest, SetSelection) {
  117. TestSeat seat;
  118. Surface focused_surface;
  119. seat.set_focused_surface(&focused_surface);
  120. TestDataSourceDelegate delegate;
  121. DataSource source(&delegate);
  122. source.Offer("text/plain;charset=utf-8");
  123. seat.SetSelection(&source);
  124. RunReadingTask();
  125. std::string clipboard;
  126. ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
  127. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  128. EXPECT_EQ(clipboard, std::string("TestData"));
  129. }
  130. TEST_F(SeatTest, SetSelectionReadDteFromLacros) {
  131. std::unique_ptr<TestDataExchangeDelegate> data_exchange_delegate(
  132. std::make_unique<TestDataExchangeDelegate>());
  133. data_exchange_delegate->set_endpoint_type(ui::EndpointType::kLacros);
  134. TestSeat seat(std::move(data_exchange_delegate));
  135. Surface focused_surface;
  136. seat.set_focused_surface(&focused_surface);
  137. const std::string kTestText = "TestData";
  138. const std::string kEncodedTestDte =
  139. R"({"endpoint_type":"url","url":"https://www.google.com"})";
  140. const std::string kTextMimeType = "text/plain;charset=utf-8";
  141. const std::string kDteMimeType = "chromium/x-data-transfer-endpoint";
  142. TestDataSourceDelegate delegate;
  143. DataSource source(&delegate);
  144. source.Offer(kTextMimeType);
  145. delegate.SetData(kTextMimeType,
  146. std::vector<uint8_t>(kTestText.begin(), kTestText.end()));
  147. source.Offer(kDteMimeType);
  148. delegate.SetData(kDteMimeType, std::vector<uint8_t>(kEncodedTestDte.begin(),
  149. kEncodedTestDte.end()));
  150. seat.SetSelection(&source);
  151. RunReadingTask();
  152. std::string clipboard;
  153. ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
  154. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  155. EXPECT_EQ(clipboard, kTestText);
  156. const ui::DataTransferEndpoint* source_dte =
  157. ui::Clipboard::GetForCurrentThread()->GetSource(
  158. ui::ClipboardBuffer::kCopyPaste);
  159. ASSERT_TRUE(source_dte);
  160. EXPECT_EQ(ui::EndpointType::kUrl, source_dte->type());
  161. const ui::DataTransferEndpoint expected_dte =
  162. ui::DataTransferEndpoint((GURL("https://www.google.com")));
  163. EXPECT_EQ(*expected_dte.GetURL(), *source_dte->GetURL());
  164. }
  165. TEST_F(SeatTest, SetSelectionIgnoreDteFromNonLacros) {
  166. std::unique_ptr<TestDataExchangeDelegate> data_exchange_delegate(
  167. std::make_unique<TestDataExchangeDelegate>());
  168. data_exchange_delegate->set_endpoint_type(ui::EndpointType::kCrostini);
  169. TestSeat seat(std::move(data_exchange_delegate));
  170. Surface focused_surface;
  171. seat.set_focused_surface(&focused_surface);
  172. const std::string kTestText = "TestData";
  173. const std::string kEncodedTestDte =
  174. R"({"endpoint_type":"url","url":"https://www.google.com"})";
  175. const std::string kTextMimeType = "text/plain;charset=utf-8";
  176. const std::string kDteMimeType = "chromium/x-data-transfer-endpoint";
  177. TestDataSourceDelegate delegate;
  178. DataSource source(&delegate);
  179. source.Offer(kTextMimeType);
  180. delegate.SetData(kTextMimeType,
  181. std::vector<uint8_t>(kTestText.begin(), kTestText.end()));
  182. source.Offer(kDteMimeType);
  183. delegate.SetData(kDteMimeType, std::vector<uint8_t>(kEncodedTestDte.begin(),
  184. kEncodedTestDte.end()));
  185. seat.SetSelection(&source);
  186. RunReadingTask();
  187. std::string clipboard;
  188. ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
  189. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  190. EXPECT_EQ(clipboard, kTestText);
  191. const ui::DataTransferEndpoint* source_dte =
  192. ui::Clipboard::GetForCurrentThread()->GetSource(
  193. ui::ClipboardBuffer::kCopyPaste);
  194. ASSERT_TRUE(source_dte);
  195. EXPECT_EQ(ui::EndpointType::kCrostini, source_dte->type());
  196. }
  197. TEST_F(SeatTest, SetSelectionTextUTF8) {
  198. TestSeat seat;
  199. Surface focused_surface;
  200. seat.set_focused_surface(&focused_surface);
  201. // UTF8 encoded data
  202. const uint8_t data[] = {
  203. 0xe2, 0x9d, 0x84, // SNOWFLAKE
  204. 0xf0, 0x9f, 0x94, 0xa5 // FIRE
  205. };
  206. std::u16string converted_data;
  207. EXPECT_TRUE(base::UTF8ToUTF16(reinterpret_cast<const char*>(data),
  208. sizeof(data), &converted_data));
  209. TestDataSourceDelegate delegate;
  210. DataSource source(&delegate);
  211. const std::string kTextPlainType = "text/plain;charset=utf-8";
  212. const std::string kTextHtmlType = "text/html;charset=utf-8";
  213. source.Offer(kTextPlainType);
  214. source.Offer(kTextHtmlType);
  215. delegate.SetData(kTextPlainType,
  216. std::vector<uint8_t>(data, data + sizeof(data)));
  217. delegate.SetData(kTextHtmlType,
  218. std::vector<uint8_t>(data, data + sizeof(data)));
  219. seat.SetSelection(&source);
  220. RunReadingTask();
  221. std::u16string clipboard;
  222. ui::Clipboard::GetForCurrentThread()->ReadText(
  223. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  224. EXPECT_EQ(clipboard, converted_data);
  225. std::string url;
  226. uint32_t start, end;
  227. ui::Clipboard::GetForCurrentThread()->ReadHTML(
  228. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard, &url,
  229. &start, &end);
  230. EXPECT_EQ(clipboard, converted_data);
  231. }
  232. TEST_F(SeatTest, SetSelectionTextUTF8Legacy) {
  233. TestSeat seat;
  234. Surface focused_surface;
  235. seat.set_focused_surface(&focused_surface);
  236. // UTF8 encoded data
  237. const uint8_t data[] = {
  238. 0xe2, 0x9d, 0x84, // SNOWFLAKE
  239. 0xf0, 0x9f, 0x94, 0xa5 // FIRE
  240. };
  241. std::u16string converted_data;
  242. EXPECT_TRUE(base::UTF8ToUTF16(reinterpret_cast<const char*>(data),
  243. sizeof(data), &converted_data));
  244. TestDataSourceDelegate delegate;
  245. DataSource source(&delegate);
  246. const std::string kMimeType = "UTF8_STRING";
  247. source.Offer(kMimeType);
  248. delegate.SetData(kMimeType, std::vector<uint8_t>(data, data + sizeof(data)));
  249. seat.SetSelection(&source);
  250. RunReadingTask();
  251. std::u16string clipboard;
  252. ui::Clipboard::GetForCurrentThread()->ReadText(
  253. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  254. EXPECT_EQ(clipboard, converted_data);
  255. }
  256. TEST_F(SeatTest, SetSelectionTextUTF16LE) {
  257. TestSeat seat;
  258. Surface focused_surface;
  259. seat.set_focused_surface(&focused_surface);
  260. // UTF16 little endian encoded data
  261. const uint8_t data[] = {
  262. 0xff, 0xfe, // Byte order mark
  263. 0x44, 0x27, // SNOWFLAKE
  264. 0x3d, 0xd8, 0x25, 0xdd, // FIRE
  265. };
  266. std::u16string converted_data;
  267. converted_data.push_back(0x2744);
  268. converted_data.push_back(0xd83d);
  269. converted_data.push_back(0xdd25);
  270. TestDataSourceDelegate delegate;
  271. DataSource source(&delegate);
  272. const std::string kTextPlainType = "text/plain;charset=utf-16";
  273. const std::string kTextHtmlType = "text/html;charset=utf-16";
  274. source.Offer(kTextPlainType);
  275. source.Offer(kTextHtmlType);
  276. delegate.SetData(kTextPlainType,
  277. std::vector<uint8_t>(data, data + sizeof(data)));
  278. delegate.SetData(kTextHtmlType,
  279. std::vector<uint8_t>(data, data + sizeof(data)));
  280. seat.SetSelection(&source);
  281. RunReadingTask();
  282. std::u16string clipboard;
  283. ui::Clipboard::GetForCurrentThread()->ReadText(
  284. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  285. EXPECT_EQ(clipboard, converted_data);
  286. std::string url;
  287. uint32_t start, end;
  288. ui::Clipboard::GetForCurrentThread()->ReadHTML(
  289. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard, &url,
  290. &start, &end);
  291. EXPECT_EQ(clipboard, converted_data);
  292. }
  293. TEST_F(SeatTest, SetSelectionTextUTF16BE) {
  294. TestSeat seat;
  295. Surface focused_surface;
  296. seat.set_focused_surface(&focused_surface);
  297. // UTF16 big endian encoded data
  298. const uint8_t data[] = {
  299. 0xfe, 0xff, // Byte order mark
  300. 0x27, 0x44, // SNOWFLAKE
  301. 0xd8, 0x3d, 0xdd, 0x25, // FIRE
  302. };
  303. std::u16string converted_data;
  304. converted_data.push_back(0x2744);
  305. converted_data.push_back(0xd83d);
  306. converted_data.push_back(0xdd25);
  307. TestDataSourceDelegate delegate;
  308. DataSource source(&delegate);
  309. const std::string kTextPlainType = "text/plain;charset=utf-16";
  310. const std::string kTextHtmlType = "text/html;charset=utf-16";
  311. source.Offer(kTextPlainType);
  312. source.Offer(kTextHtmlType);
  313. delegate.SetData(kTextPlainType,
  314. std::vector<uint8_t>(data, data + sizeof(data)));
  315. delegate.SetData(kTextHtmlType,
  316. std::vector<uint8_t>(data, data + sizeof(data)));
  317. seat.SetSelection(&source);
  318. RunReadingTask();
  319. std::u16string clipboard;
  320. ui::Clipboard::GetForCurrentThread()->ReadText(
  321. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  322. EXPECT_EQ(clipboard, converted_data);
  323. std::string url;
  324. uint32_t start, end;
  325. ui::Clipboard::GetForCurrentThread()->ReadHTML(
  326. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard, &url,
  327. &start, &end);
  328. EXPECT_EQ(clipboard, converted_data);
  329. }
  330. TEST_F(SeatTest, SetSelectionTextEmptyString) {
  331. TestSeat seat;
  332. Surface focused_surface;
  333. seat.set_focused_surface(&focused_surface);
  334. const uint8_t data[] = {};
  335. TestDataSourceDelegate delegate;
  336. DataSource source(&delegate);
  337. const std::string kTextPlainType = "text/plain;charset=utf-8";
  338. const std::string kTextHtmlType = "text/html;charset=utf-16";
  339. source.Offer(kTextPlainType);
  340. source.Offer(kTextHtmlType);
  341. delegate.SetData(kTextPlainType,
  342. std::vector<uint8_t>(data, data + sizeof(data)));
  343. delegate.SetData(kTextHtmlType,
  344. std::vector<uint8_t>(data, data + sizeof(data)));
  345. seat.SetSelection(&source);
  346. RunReadingTask();
  347. std::u16string clipboard;
  348. ui::Clipboard::GetForCurrentThread()->ReadText(
  349. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  350. EXPECT_EQ(clipboard.size(), 0u);
  351. std::string url;
  352. uint32_t start, end;
  353. ui::Clipboard::GetForCurrentThread()->ReadHTML(
  354. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard, &url,
  355. &start, &end);
  356. EXPECT_EQ(clipboard.size(), 0u);
  357. }
  358. TEST_F(SeatTest, SetSelectionRTF) {
  359. TestSeat seat;
  360. Surface focused_surface;
  361. seat.set_focused_surface(&focused_surface);
  362. TestDataSourceDelegate delegate;
  363. DataSource source(&delegate);
  364. source.Offer("text/rtf");
  365. seat.SetSelection(&source);
  366. RunReadingTask();
  367. std::string clipboard;
  368. ui::Clipboard::GetForCurrentThread()->ReadRTF(
  369. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  370. EXPECT_EQ(clipboard, std::string("TestData"));
  371. }
  372. TEST_F(SeatTest, SetSelectionFilenames) {
  373. TestSeat seat;
  374. Surface focused_surface;
  375. seat.set_focused_surface(&focused_surface);
  376. const std::string data("file:///path1\r\nfile:///path2");
  377. TestDataSourceDelegate delegate;
  378. const std::string kMimeType = "text/uri-list";
  379. delegate.SetData(kMimeType, std::vector<uint8_t>(data.begin(), data.end()));
  380. DataSource source(&delegate);
  381. source.Offer(kMimeType);
  382. seat.SetSelection(&source);
  383. RunReadingTask();
  384. std::vector<ui::FileInfo> filenames;
  385. ui::Clipboard::GetForCurrentThread()->ReadFilenames(
  386. ui::ClipboardBuffer::kCopyPaste,
  387. /*data_dst=*/nullptr, &filenames);
  388. EXPECT_EQ(ui::FileInfosToURIList(filenames), data);
  389. }
  390. TEST_F(SeatTest, SetSelectionWebCustomData) {
  391. TestSeat seat;
  392. Surface focused_surface;
  393. seat.set_focused_surface(&focused_surface);
  394. base::flat_map<std::u16string, std::u16string> custom_data;
  395. custom_data[u"text/uri-list"] = u"data";
  396. base::Pickle pickle;
  397. ui::WriteCustomDataToPickle(custom_data, &pickle);
  398. auto custom_data_str =
  399. std::string(reinterpret_cast<const char*>(pickle.data()), pickle.size());
  400. TestDataSourceDelegate delegate;
  401. const std::string kMimeType = "chromium/x-web-custom-data";
  402. delegate.SetData(kMimeType, std::vector<uint8_t>(custom_data_str.begin(),
  403. custom_data_str.end()));
  404. DataSource source(&delegate);
  405. source.Offer(kMimeType);
  406. seat.SetSelection(&source);
  407. RunReadingTask();
  408. std::u16string result;
  409. ui::Clipboard::GetForCurrentThread()->ReadCustomData(
  410. ui::ClipboardBuffer::kCopyPaste, u"text/uri-list", /*data_dst=*/nullptr,
  411. &result);
  412. EXPECT_EQ(result, u"data");
  413. }
  414. TEST_F(SeatTest, SetSelection_TwiceSame) {
  415. TestSeat seat;
  416. Surface focused_surface;
  417. seat.set_focused_surface(&focused_surface);
  418. TestDataSourceDelegate delegate;
  419. DataSource source(&delegate);
  420. seat.SetSelection(&source);
  421. RunReadingTask();
  422. seat.SetSelection(&source);
  423. RunReadingTask();
  424. EXPECT_FALSE(delegate.cancelled());
  425. }
  426. TEST_F(SeatTest, SetSelection_TwiceDifferent) {
  427. TestSeat seat;
  428. Surface focused_surface;
  429. seat.set_focused_surface(&focused_surface);
  430. TestDataSourceDelegate delegate1;
  431. DataSource source1(&delegate1);
  432. seat.SetSelection(&source1);
  433. RunReadingTask();
  434. EXPECT_FALSE(delegate1.cancelled());
  435. TestDataSourceDelegate delegate2;
  436. DataSource source2(&delegate2);
  437. seat.SetSelection(&source2);
  438. RunReadingTask();
  439. EXPECT_TRUE(delegate1.cancelled());
  440. }
  441. TEST_F(SeatTest, SetSelection_ClipboardChangedDuringSetSelection) {
  442. TestSeat seat;
  443. Surface focused_surface;
  444. seat.set_focused_surface(&focused_surface);
  445. TestDataSourceDelegate delegate;
  446. DataSource source(&delegate);
  447. seat.SetSelection(&source);
  448. {
  449. ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
  450. writer.WriteText(u"New data");
  451. }
  452. RunReadingTask();
  453. // The previous source should be cancelled.
  454. EXPECT_TRUE(delegate.cancelled());
  455. std::string clipboard;
  456. ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
  457. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  458. EXPECT_EQ(clipboard, "New data");
  459. }
  460. TEST_F(SeatTest, SetSelection_ClipboardChangedAfterSetSelection) {
  461. TestSeat seat;
  462. Surface focused_surface;
  463. seat.set_focused_surface(&focused_surface);
  464. TestDataSourceDelegate delegate;
  465. DataSource source(&delegate);
  466. seat.SetSelection(&source);
  467. RunReadingTask();
  468. {
  469. ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
  470. writer.WriteText(u"New data");
  471. }
  472. // The previous source should be cancelled.
  473. EXPECT_TRUE(delegate.cancelled());
  474. std::string clipboard;
  475. ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
  476. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  477. EXPECT_EQ(clipboard, "New data");
  478. }
  479. TEST_F(SeatTest, SetSelection_SourceDestroyedDuringSetSelection) {
  480. TestSeat seat;
  481. Surface focused_surface;
  482. seat.set_focused_surface(&focused_surface);
  483. {
  484. ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
  485. writer.WriteText(u"Original data");
  486. }
  487. {
  488. TestDataSourceDelegate delegate;
  489. DataSource source(&delegate);
  490. seat.SetSelection(&source);
  491. // source destroyed here.
  492. }
  493. RunReadingTask();
  494. std::string clipboard;
  495. ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
  496. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  497. EXPECT_EQ(clipboard, "Original data");
  498. }
  499. TEST_F(SeatTest, SetSelection_SourceDestroyedAfterSetSelection) {
  500. TestSeat seat;
  501. Surface focused_surface;
  502. seat.set_focused_surface(&focused_surface);
  503. TestDataSourceDelegate delegate1;
  504. {
  505. DataSource source(&delegate1);
  506. seat.SetSelection(&source);
  507. RunReadingTask();
  508. // source destroyed here.
  509. }
  510. RunReadingTask();
  511. {
  512. TestDataSourceDelegate delegate2;
  513. DataSource source(&delegate2);
  514. seat.SetSelection(&source);
  515. RunReadingTask();
  516. // source destroyed here.
  517. }
  518. RunReadingTask();
  519. // delegate1 should not receive cancel request because the first data source
  520. // has already been destroyed.
  521. EXPECT_FALSE(delegate1.cancelled());
  522. }
  523. TEST_F(SeatTest, SetSelection_NullSource) {
  524. TestSeat seat;
  525. Surface focused_surface;
  526. seat.set_focused_surface(&focused_surface);
  527. TestDataSourceDelegate delegate;
  528. DataSource source(&delegate);
  529. source.Offer("text/plain;charset=utf-8");
  530. seat.SetSelection(&source);
  531. RunReadingTask();
  532. {
  533. ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
  534. writer.WriteText(u"Golden data");
  535. }
  536. // Should not affect the current state of the clipboard.
  537. seat.SetSelection(nullptr);
  538. ASSERT_TRUE(delegate.cancelled());
  539. std::string clipboard;
  540. ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
  541. ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &clipboard);
  542. EXPECT_EQ(clipboard, "Golden data");
  543. }
  544. TEST_F(SeatTest, SetSelection_NoFocusedSurface) {
  545. TestSeat seat;
  546. seat.set_focused_surface(nullptr);
  547. TestDataSourceDelegate delegate;
  548. DataSource source(&delegate);
  549. source.Offer("text/plain;charset=utf-8");
  550. seat.SetSelection(&source);
  551. EXPECT_TRUE(delegate.cancelled());
  552. }
  553. TEST_F(SeatTest, SetSelection_ClientOutOfFocus) {
  554. TestSeat seat;
  555. Surface focused_surface;
  556. seat.set_focused_surface(&focused_surface);
  557. TestDataSourceDelegate delegate;
  558. delegate.can_accept_ = false;
  559. DataSource source(&delegate);
  560. source.Offer("text/plain;charset=utf-8");
  561. seat.SetSelection(&source);
  562. EXPECT_TRUE(delegate.cancelled());
  563. }
  564. TEST_F(SeatTest, PressedKeys) {
  565. TestSeat seat;
  566. ui::KeyEvent press_a(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::DomCode::US_A, 0);
  567. ui::KeyEvent release_a(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::DomCode::US_A, 0);
  568. ui::KeyEvent press_b(ui::ET_KEY_PRESSED, ui::VKEY_B, ui::DomCode::US_B, 0);
  569. ui::KeyEvent release_b(ui::ET_KEY_RELEASED, ui::VKEY_B, ui::DomCode::US_B, 0);
  570. // Press A, it should be in the map.
  571. seat.WillProcessEvent(&press_a);
  572. seat.OnKeyEvent(press_a.AsKeyEvent());
  573. seat.DidProcessEvent(&press_a);
  574. base::flat_map<ui::DomCode, KeyState> pressed_keys;
  575. pressed_keys[ui::CodeFromNative(&press_a)] = KeyState{press_a.code(), false};
  576. EXPECT_EQ(pressed_keys, seat.pressed_keys());
  577. // Press B, then A & B should be in the map.
  578. seat.WillProcessEvent(&press_b);
  579. seat.OnKeyEvent(press_b.AsKeyEvent());
  580. seat.DidProcessEvent(&press_b);
  581. pressed_keys[ui::CodeFromNative(&press_b)] = KeyState{press_b.code(), false};
  582. EXPECT_EQ(pressed_keys, seat.pressed_keys());
  583. // Release A, with the normal order where DidProcessEvent is after OnKeyEvent,
  584. // only B should be in the map.
  585. seat.WillProcessEvent(&release_a);
  586. seat.OnKeyEvent(release_a.AsKeyEvent());
  587. seat.DidProcessEvent(&release_a);
  588. pressed_keys.erase(ui::CodeFromNative(&press_a));
  589. EXPECT_EQ(pressed_keys, seat.pressed_keys());
  590. // Release B, do it out of order so DidProcessEvent is before OnKeyEvent, the
  591. // map should then be empty.
  592. seat.WillProcessEvent(&release_b);
  593. seat.DidProcessEvent(&release_b);
  594. seat.OnKeyEvent(release_b.AsKeyEvent());
  595. EXPECT_TRUE(seat.pressed_keys().empty());
  596. }
  597. TEST_F(SeatTest, DragDropAbort) {
  598. TestSeat seat;
  599. TestDataSourceDelegate delegate;
  600. DataSource source(&delegate);
  601. Surface origin, icon;
  602. // Give origin a root window for DragDropOperation.
  603. GetContext()->AddChild(origin.window());
  604. seat.StartDrag(&source, &origin, &icon, ui::mojom::DragEventSource::kMouse);
  605. EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
  606. seat.AbortPendingDragOperation();
  607. EXPECT_FALSE(seat.get_drag_drop_operation_for_testing());
  608. }
  609. } // namespace
  610. } // namespace exo