data_source_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  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/data_source.h"
  5. #include <atomic>
  6. #include "base/barrier_closure.h"
  7. #include "base/bind.h"
  8. #include "base/callback_helpers.h"
  9. #include "base/files/file_util.h"
  10. #include "base/test/task_environment.h"
  11. #include "components/exo/data_source_delegate.h"
  12. #include "components/exo/test/exo_test_base.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. namespace exo {
  15. namespace {
  16. constexpr char kTestData[] = "Test Data";
  17. class DataSourceTest : public testing::Test {
  18. protected:
  19. base::test::TaskEnvironment task_environment_{
  20. base::test::TaskEnvironment::MainThreadType::DEFAULT,
  21. base::test::TaskEnvironment::ThreadPoolExecutionMode::ASYNC};
  22. };
  23. class TestDataSourceDelegate : public DataSourceDelegate {
  24. public:
  25. TestDataSourceDelegate() {}
  26. ~TestDataSourceDelegate() override {}
  27. // Overridden from DataSourceDelegate:
  28. void OnDataSourceDestroying(DataSource* source) override {}
  29. void OnTarget(const absl::optional<std::string>& mime_type) override {}
  30. void OnSend(const std::string& mime_type, base::ScopedFD fd) override {
  31. ASSERT_TRUE(base::WriteFileDescriptor(fd.get(), kTestData));
  32. }
  33. void OnCancelled() override {}
  34. void OnDndDropPerformed() override {}
  35. void OnDndFinished() override {}
  36. void OnAction(DndAction dnd_action) override {}
  37. bool CanAcceptDataEventsForSurface(Surface* surface) const override {
  38. return true;
  39. }
  40. };
  41. void CheckMimeType(const std::string& expected,
  42. base::OnceClosure counter,
  43. const std::string& mime_type,
  44. const std::vector<uint8_t>& data) {
  45. EXPECT_FALSE(expected.empty());
  46. EXPECT_EQ(expected, mime_type);
  47. std::move(counter).Run();
  48. }
  49. void CheckTextMimeType(const std::string& expected,
  50. base::OnceClosure counter,
  51. const std::string& mime_type,
  52. std::u16string data) {
  53. EXPECT_FALSE(expected.empty());
  54. EXPECT_EQ(expected, mime_type);
  55. std::move(counter).Run();
  56. }
  57. struct FileContents {
  58. std::string mime_type;
  59. std::string parsed_filename;
  60. };
  61. void CheckFileContentsMimeType(const FileContents& file_contents,
  62. base::OnceClosure counter,
  63. const std::string& mime_type,
  64. const base::FilePath& filename,
  65. const std::vector<uint8_t>& data) {
  66. EXPECT_FALSE(file_contents.mime_type.empty());
  67. EXPECT_EQ(file_contents.mime_type, mime_type);
  68. EXPECT_EQ(file_contents.parsed_filename, filename.value());
  69. std::move(counter).Run();
  70. }
  71. void CheckWebCustomDataMimeType(const std::string& expected,
  72. base::OnceClosure counter,
  73. const std::string& mime_type,
  74. const std::vector<uint8_t>& data) {
  75. EXPECT_FALSE(mime_type.empty());
  76. EXPECT_EQ(expected, mime_type);
  77. std::move(counter).Run();
  78. }
  79. void IncrementFailureCounter(std::atomic_int* failure_count,
  80. base::RepeatingClosure counter) {
  81. ++(*failure_count);
  82. std::move(counter).Run();
  83. }
  84. void CheckMimeTypesReceived(
  85. DataSource* data_source,
  86. const std::string& text_mime,
  87. const std::string& rtf_mime,
  88. const std::string& html_mime,
  89. const std::string& image_mime,
  90. const std::string& filenames_mime,
  91. const FileContents& file_contents,
  92. const std::string& web_custom_data_mime = std::string()) {
  93. base::RunLoop run_loop;
  94. base::RepeatingClosure counter =
  95. base::BarrierClosure(DataSource::kMaxDataTypes, run_loop.QuitClosure());
  96. std::atomic_int failure_count;
  97. failure_count.store(0);
  98. data_source->GetDataForPreferredMimeTypes(
  99. base::BindOnce(&CheckTextMimeType, text_mime, counter),
  100. base::BindOnce(&CheckMimeType, rtf_mime, counter),
  101. base::BindOnce(&CheckTextMimeType, html_mime, counter),
  102. base::BindOnce(&CheckMimeType, image_mime, counter),
  103. base::BindOnce(&CheckMimeType, filenames_mime, counter),
  104. base::BindOnce(&CheckFileContentsMimeType, file_contents, counter),
  105. base::BindOnce(&CheckWebCustomDataMimeType, web_custom_data_mime,
  106. counter),
  107. base::BindRepeating(&IncrementFailureCounter, &failure_count, counter));
  108. run_loop.Run();
  109. int expected_failure_count = 0;
  110. for (const auto& mime_type :
  111. {text_mime, rtf_mime, html_mime, image_mime, filenames_mime,
  112. file_contents.mime_type, web_custom_data_mime}) {
  113. if (mime_type.empty())
  114. ++expected_failure_count;
  115. }
  116. EXPECT_EQ(expected_failure_count, failure_count.load());
  117. }
  118. TEST_F(DataSourceTest, ReadData) {
  119. TestDataSourceDelegate delegate;
  120. DataSource data_source(&delegate);
  121. std::string mime_type("text/plain;charset=utf-8");
  122. data_source.Offer(mime_type.c_str());
  123. data_source.ReadDataForTesting(
  124. mime_type, base::BindOnce([](const std::string& mime_type,
  125. const std::vector<uint8_t>& data) {
  126. std::string string_data(data.begin(), data.end());
  127. EXPECT_EQ(std::string(kTestData), string_data);
  128. }));
  129. task_environment_.RunUntilIdle();
  130. }
  131. TEST_F(DataSourceTest, ReadDataArbitraryMimeType) {
  132. TestDataSourceDelegate delegate;
  133. DataSource data_source(&delegate);
  134. std::string mime_type("abc/def;key=value");
  135. data_source.Offer(mime_type.c_str());
  136. data_source.ReadDataForTesting(
  137. mime_type, base::BindOnce([](const std::string& mime_type,
  138. const std::vector<uint8_t>& data) {
  139. std::string string_data(data.begin(), data.end());
  140. EXPECT_EQ(std::string(kTestData), string_data);
  141. }));
  142. task_environment_.RunUntilIdle();
  143. }
  144. TEST_F(DataSourceTest, ReadData_UnknownMimeType) {
  145. TestDataSourceDelegate delegate;
  146. DataSource data_source(&delegate);
  147. data_source.Offer("text/plain;charset=utf-8");
  148. std::string unknown_type("text/unknown");
  149. data_source.ReadDataForTesting(
  150. unknown_type, base::BindOnce([](const std::string& mime_type,
  151. const std::vector<uint8_t>& data) {
  152. FAIL() << "Callback should not be invoked when known "
  153. "mimetype is not offerred";
  154. }));
  155. task_environment_.RunUntilIdle();
  156. }
  157. TEST_F(DataSourceTest, ReadData_Destroyed) {
  158. TestDataSourceDelegate delegate;
  159. {
  160. DataSource data_source(&delegate);
  161. std::string mime_type("text/plain;charset=utf-8");
  162. data_source.Offer(mime_type);
  163. data_source.ReadDataForTesting(
  164. mime_type, base::BindOnce([](const std::string& mime_type,
  165. const std::vector<uint8_t>& data) {
  166. FAIL() << "Callback should not be invoked after "
  167. "data source is destroyed";
  168. }));
  169. }
  170. task_environment_.RunUntilIdle();
  171. }
  172. TEST_F(DataSourceTest, ReadData_Cancelled) {
  173. TestDataSourceDelegate delegate;
  174. DataSource data_source(&delegate);
  175. std::string mime_type("text/plain;charset=utf-8");
  176. data_source.Offer(mime_type);
  177. data_source.ReadDataForTesting(
  178. mime_type, base::BindOnce([](const std::string& mime_type,
  179. const std::vector<uint8_t>& data) {
  180. FAIL() << "Callback should not be invoked after cancelled";
  181. }));
  182. data_source.Cancelled();
  183. task_environment_.RunUntilIdle();
  184. }
  185. TEST_F(DataSourceTest, CheckDteMimeTypeReceived) {
  186. TestDataSourceDelegate delegate;
  187. DataSource data_source(&delegate);
  188. const std::string kDteMimeType("chromium/x-data-transfer-endpoint");
  189. data_source.Offer(kDteMimeType);
  190. base::RunLoop run_loop;
  191. base::RepeatingClosure counter =
  192. base::BarrierClosure(1, run_loop.QuitClosure());
  193. std::atomic_int failure_count{0};
  194. data_source.ReadDataTransferEndpoint(
  195. base::BindOnce(&CheckTextMimeType, kDteMimeType, counter),
  196. base::BindRepeating(&IncrementFailureCounter, &failure_count, counter));
  197. run_loop.Run();
  198. EXPECT_EQ(0, failure_count.load());
  199. }
  200. TEST_F(DataSourceTest, PreferredMimeTypeUTF16) {
  201. TestDataSourceDelegate delegate;
  202. DataSource data_source(&delegate);
  203. data_source.Offer("text/plain;charset=utf-16");
  204. data_source.Offer("text/plain;charset=UTF-8");
  205. data_source.Offer("text/html;charset=UTF-16");
  206. data_source.Offer("text/html;charset=utf-8");
  207. CheckMimeTypesReceived(&data_source, "text/plain;charset=utf-16", "",
  208. "text/html;charset=UTF-16", "", "", {});
  209. }
  210. TEST_F(DataSourceTest, PreferredMimeTypeUTF16LE) {
  211. TestDataSourceDelegate delegate;
  212. DataSource data_source(&delegate);
  213. data_source.Offer("text/plain;charset=utf-16le");
  214. data_source.Offer("text/plain;charset=utf8");
  215. data_source.Offer("text/html;charset=utf16le");
  216. data_source.Offer("text/html;charset=utf-8");
  217. CheckMimeTypesReceived(&data_source, "text/plain;charset=utf-16le", "",
  218. "text/html;charset=utf16le", "", "", {});
  219. }
  220. TEST_F(DataSourceTest, PreferredMimeTypeUTF16BE) {
  221. TestDataSourceDelegate delegate;
  222. DataSource data_source(&delegate);
  223. data_source.Offer("text/plain;charset=utf-16be");
  224. data_source.Offer("text/plain;charset=UTF8");
  225. data_source.Offer("text/html;charset=UTF16be");
  226. data_source.Offer("text/html;charset=utf-8");
  227. CheckMimeTypesReceived(&data_source, "text/plain;charset=utf-16be", "",
  228. "text/html;charset=UTF16be", "", "", {});
  229. }
  230. TEST_F(DataSourceTest, PreferredMimeTypeUTFToOther) {
  231. TestDataSourceDelegate delegate;
  232. DataSource data_source(&delegate);
  233. data_source.Offer("text/plain;charset=utf-8");
  234. data_source.Offer("text/plain;charset=iso-8859-1");
  235. data_source.Offer("text/html;charset=utf-8");
  236. data_source.Offer("text/html;charset=iso-8859-1");
  237. CheckMimeTypesReceived(&data_source, "text/plain;charset=utf-8", "",
  238. "text/html;charset=utf-8", "", "", {});
  239. }
  240. TEST_F(DataSourceTest, RecogniseUTF8Legaccy) {
  241. TestDataSourceDelegate delegate;
  242. DataSource data_source(&delegate);
  243. data_source.Offer("UTF8_STRING");
  244. data_source.Offer("text/plain;charset=iso-8859-1");
  245. CheckMimeTypesReceived(&data_source, "UTF8_STRING", "", "", "", "", {});
  246. }
  247. TEST_F(DataSourceTest, PreferredMimeTypeOtherToAscii) {
  248. TestDataSourceDelegate delegate;
  249. DataSource data_source(&delegate);
  250. data_source.Offer("text/plain;charset=iso-8859-1");
  251. data_source.Offer("text/plain;charset=ASCII");
  252. data_source.Offer("text/html;charset=iso-8859-1");
  253. data_source.Offer("text/html;charset=ascii");
  254. CheckMimeTypesReceived(&data_source, "text/plain;charset=iso-8859-1", "",
  255. "text/html;charset=iso-8859-1", "", "", {});
  256. }
  257. TEST_F(DataSourceTest, PreferredMimeTypeOtherToUnspecified) {
  258. TestDataSourceDelegate delegate;
  259. DataSource data_source(&delegate);
  260. data_source.Offer("text/plain;charset=iso-8859-1");
  261. data_source.Offer("text/plain");
  262. data_source.Offer("text/html;charset=iso-8859-1");
  263. data_source.Offer("text/html");
  264. CheckMimeTypesReceived(&data_source, "text/plain;charset=iso-8859-1", "",
  265. "text/html;charset=iso-8859-1", "", "", {});
  266. }
  267. TEST_F(DataSourceTest, PreferredMimeTypeRTF) {
  268. TestDataSourceDelegate delegate;
  269. DataSource data_source(&delegate);
  270. data_source.Offer("text/rtf");
  271. CheckMimeTypesReceived(&data_source, "", "text/rtf", "", "", "", {});
  272. }
  273. TEST_F(DataSourceTest, PreferredMimeTypePNGtoBitmap) {
  274. TestDataSourceDelegate delegate;
  275. DataSource data_source(&delegate);
  276. data_source.Offer("image/bmp");
  277. data_source.Offer("image/png");
  278. CheckMimeTypesReceived(&data_source, "", "", "", "image/png", "", {});
  279. }
  280. TEST_F(DataSourceTest, PreferredMimeTypePNGToJPEG) {
  281. TestDataSourceDelegate delegate;
  282. DataSource data_source(&delegate);
  283. data_source.Offer("image/png");
  284. data_source.Offer("image/jpeg");
  285. data_source.Offer("image/jpg");
  286. CheckMimeTypesReceived(&data_source, "", "", "", "image/png", "", {});
  287. }
  288. TEST_F(DataSourceTest, PreferredMimeTypeBitmaptoJPEG) {
  289. TestDataSourceDelegate delegate;
  290. DataSource data_source(&delegate);
  291. data_source.Offer("image/bmp");
  292. data_source.Offer("image/jpeg");
  293. data_source.Offer("image/jpg");
  294. CheckMimeTypesReceived(&data_source, "", "", "", "image/bmp", "", {});
  295. }
  296. TEST_F(DataSourceTest, PreferredMimeTypeTextUriList) {
  297. TestDataSourceDelegate delegate;
  298. DataSource data_source(&delegate);
  299. data_source.Offer("text/uri-list");
  300. CheckMimeTypesReceived(&data_source, "", "", "", "", "text/uri-list", {});
  301. }
  302. TEST_F(DataSourceTest, PreferredMimeTypeOctetStream) {
  303. TestDataSourceDelegate delegate;
  304. DataSource data_source(&delegate);
  305. data_source.Offer("application/octet-stream;name=test.jpg");
  306. CheckMimeTypesReceived(
  307. &data_source, "", "", "", "", "",
  308. {"application/octet-stream;name=test.jpg", "test.jpg"});
  309. }
  310. TEST_F(DataSourceTest, OctetStreamWithoutName) {
  311. TestDataSourceDelegate delegate;
  312. DataSource data_source(&delegate);
  313. data_source.Offer("application/octet-stream");
  314. CheckMimeTypesReceived(&data_source, "", "", "", "", "", {});
  315. }
  316. TEST_F(DataSourceTest, OctetStreamWithQuotedName) {
  317. TestDataSourceDelegate delegate;
  318. DataSource data_source(&delegate);
  319. data_source.Offer("application/octet-stream;name=\"t\\\\est\\\".jpg\"");
  320. CheckMimeTypesReceived(
  321. &data_source, "", "", "", "", "",
  322. {"application/octet-stream;name=\"t\\\\est\\\".jpg\"", "t\\est\".jpg"});
  323. }
  324. TEST_F(DataSourceTest, WebCustomDataMime) {
  325. TestDataSourceDelegate delegate;
  326. DataSource data_source(&delegate);
  327. std::string web_custom_data_mime("chromium/x-web-custom-data");
  328. data_source.Offer(web_custom_data_mime);
  329. CheckMimeTypesReceived(&data_source, "", "", "", "", "", {},
  330. web_custom_data_mime);
  331. }
  332. } // namespace
  333. } // namespace exo