desk_model_wrapper_unittests.cc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. // Copyright 2022 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 <memory>
  5. #include "components/desks_storage/core/desk_model_wrapper.h"
  6. #include "ash/public/cpp/desk_template.h"
  7. #include "base/files/file_path.h"
  8. #include "base/files/file_util.h"
  9. #include "base/files/scoped_temp_dir.h"
  10. #include "base/guid.h"
  11. #include "base/run_loop.h"
  12. #include "base/strings/stringprintf.h"
  13. #include "base/strings/utf_string_conversions.h"
  14. #include "base/test/bind.h"
  15. #include "base/test/simple_test_clock.h"
  16. #include "base/test/task_environment.h"
  17. #include "components/account_id/account_id.h"
  18. #include "components/app_constants/constants.h"
  19. #include "components/app_restore/app_launch_info.h"
  20. #include "components/desks_storage/core/desk_model_observer.h"
  21. #include "components/desks_storage/core/desk_sync_bridge.h"
  22. #include "components/desks_storage/core/desk_template_conversion.h"
  23. #include "components/desks_storage/core/desk_template_util.h"
  24. #include "components/desks_storage/core/desk_test_util.h"
  25. #include "components/desks_storage/core/local_desk_data_manager.h"
  26. #include "components/services/app_service/public/cpp/app_registry_cache.h"
  27. #include "components/services/app_service/public/cpp/app_registry_cache_wrapper.h"
  28. #include "components/services/app_service/public/cpp/app_types.h"
  29. #include "components/services/app_service/public/cpp/features.h"
  30. #include "components/sync/model/entity_change.h"
  31. #include "components/sync/model/in_memory_metadata_change_list.h"
  32. #include "components/sync/model/metadata_batch.h"
  33. #include "components/sync/protocol/entity_data.h"
  34. #include "components/sync/protocol/model_type_state.pb.h"
  35. #include "components/sync/test/mock_model_type_change_processor.h"
  36. #include "components/sync/test/model_type_store_test_util.h"
  37. #include "components/sync/test/test_matchers.h"
  38. #include "desk_model_wrapper.h"
  39. #include "testing/gmock/include/gmock/gmock.h"
  40. #include "testing/gtest/include/gtest/gtest.h"
  41. namespace desks_storage {
  42. namespace {
  43. constexpr char kTemplateFileNameFormat[] = "%s.saveddesk";
  44. constexpr char kUuidFormat[] = "1c186d5a-502e-49ce-9ee1-00000000000%d";
  45. constexpr char kTemplateNameFormat[] = "desk_%d";
  46. const std::string kTestUuid1 = base::StringPrintf(kUuidFormat, 1);
  47. const std::string kTestUuid2 = base::StringPrintf(kUuidFormat, 2);
  48. const std::string kTestUuid3 = base::StringPrintf(kUuidFormat, 3);
  49. const std::string kTestUuid4 = base::StringPrintf(kUuidFormat, 4);
  50. const std::string kTestUuid5 = base::StringPrintf(kUuidFormat, 5);
  51. const std::string kTestFileName1 =
  52. base::StringPrintf(kTemplateFileNameFormat, kTestUuid1.c_str());
  53. const std::string kPolicyWithOneTemplate =
  54. "[{\"version\":1,\"uuid\":\"" + kTestUuid5 +
  55. "\",\"name\":\""
  56. "Admin Template 1"
  57. "\",\"created_time_usec\":\"1633535632\",\"updated_time_usec\": "
  58. "\"1633535632\",\"desk\":{\"apps\":[{\"window_"
  59. "bound\":{\"left\":0,\"top\":1,\"height\":121,\"width\":120},\"window_"
  60. "state\":\"NORMAL\",\"z_index\":1,\"app_type\":\"BROWSER\",\"tabs\":[{"
  61. "\"url\":\"https://example.com\",\"title\":\"Example\"},{\"url\":\"https://"
  62. "example.com/"
  63. "2\",\"title\":\"Example2\"}],\"active_tab_index\":1,\"window_id\":0,"
  64. "\"display_id\":\"100\",\"pre_minimized_window_state\":\"NORMAL\"}]}}]";
  65. // Search `entry_list` for `uuid_query` as a uuid and returns true if
  66. // found, false if not.
  67. bool FindUuidInUuidList(
  68. const std::string& uuid_query,
  69. const std::vector<const ash::DeskTemplate*>& entry_list) {
  70. base::GUID guid = base::GUID::ParseCaseInsensitive(uuid_query);
  71. DCHECK(guid.is_valid());
  72. for (auto* entry : entry_list) {
  73. if (entry->uuid() == guid)
  74. return true;
  75. }
  76. return false;
  77. }
  78. // Verifies that the status passed into it is kOk
  79. void VerifyEntryAddedCorrectly(DeskModel::AddOrUpdateEntryStatus status) {
  80. EXPECT_EQ(status, DeskModel::AddOrUpdateEntryStatus::kOk);
  81. }
  82. void VerifyEntryAddedErrorHitMaximumLimit(
  83. DeskModel::AddOrUpdateEntryStatus status) {
  84. EXPECT_EQ(status, DeskModel::AddOrUpdateEntryStatus::kHitMaximumLimit);
  85. }
  86. // Make test template with ID containing the index. Defaults to desk template
  87. // type if a type is not specified.
  88. std::unique_ptr<ash::DeskTemplate> MakeTestDeskTemplate(
  89. int index,
  90. ash::DeskTemplateType type) {
  91. const std::string template_uuid = base::StringPrintf(kUuidFormat, index);
  92. const std::string template_name =
  93. base::StringPrintf(kTemplateNameFormat, index);
  94. std::unique_ptr<ash::DeskTemplate> desk_template =
  95. std::make_unique<ash::DeskTemplate>(
  96. base::GUID::ParseCaseInsensitive(template_uuid),
  97. ash::DeskTemplateSource::kUser, template_name, base::Time::Now(),
  98. type);
  99. desk_template->set_desk_restore_data(
  100. std::make_unique<app_restore::RestoreData>());
  101. return desk_template;
  102. }
  103. // Make test template with default restore data.
  104. std::unique_ptr<ash::DeskTemplate> MakeTestDeskTemplate(
  105. const std::string& uuid,
  106. ash::DeskTemplateSource source,
  107. const std::string& name,
  108. const base::Time created_time) {
  109. auto entry = std::make_unique<ash::DeskTemplate>(
  110. base::GUID::ParseCaseInsensitive(uuid), source, name, created_time,
  111. ash::DeskTemplateType::kTemplate);
  112. entry->set_desk_restore_data(std::make_unique<app_restore::RestoreData>());
  113. return entry;
  114. }
  115. // Make test save and recall desk with default restore data.
  116. std::unique_ptr<ash::DeskTemplate> MakeTestSaveAndRecallDesk(
  117. const std::string& uuid,
  118. const std::string& name,
  119. const base::Time created_time) {
  120. auto entry = std::make_unique<ash::DeskTemplate>(
  121. base::GUID::ParseCaseInsensitive(uuid), ash::DeskTemplateSource::kUser,
  122. name, created_time, ash::DeskTemplateType::kSaveAndRecall);
  123. entry->set_desk_restore_data(std::make_unique<app_restore::RestoreData>());
  124. return entry;
  125. }
  126. } // namespace
  127. class MockDeskModelObserver : public DeskModelObserver {
  128. public:
  129. MOCK_METHOD0(DeskModelLoaded, void());
  130. MOCK_METHOD1(EntriesAddedOrUpdatedRemotely,
  131. void(const std::vector<const ash::DeskTemplate*>&));
  132. MOCK_METHOD1(EntriesRemovedRemotely, void(const std::vector<std::string>&));
  133. MOCK_METHOD1(EntriesAddedOrUpdatedLocally,
  134. void(const std::vector<const ash::DeskTemplate*>&));
  135. MOCK_METHOD1(EntriesRemovedLocally, void(const std::vector<std::string>&));
  136. };
  137. // This test class only tests the overall wrapper desk model class. The
  138. // correctness of the underlying desk model storages that
  139. // `DeskModelWrapper` uses are tested in their own unittests.
  140. class DeskModelWrapperTest : public testing::Test {
  141. public:
  142. DeskModelWrapperTest()
  143. : sample_desk_template_one_(
  144. MakeTestDeskTemplate(kTestUuid1,
  145. ash::DeskTemplateSource::kUser,
  146. "desk_01",
  147. base::Time::Now())),
  148. sample_desk_template_two_(
  149. MakeTestDeskTemplate(kTestUuid2,
  150. ash::DeskTemplateSource::kUser,
  151. "desk_02",
  152. base::Time::Now())),
  153. sample_save_and_recall_desk_one_(
  154. MakeTestSaveAndRecallDesk(kTestUuid3,
  155. "save_and_recall_desk_01",
  156. base::Time::Now())),
  157. sample_save_and_recall_desk_two_(
  158. MakeTestSaveAndRecallDesk(kTestUuid4,
  159. "save_and_recall_desk_02",
  160. base::Time::Now())),
  161. task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
  162. cache_(std::make_unique<apps::AppRegistryCache>()),
  163. account_id_(AccountId::FromUserEmail("test@gmail.com")),
  164. data_manager_(std::unique_ptr<LocalDeskDataManager>()),
  165. store_(syncer::ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()) {}
  166. DeskModelWrapperTest(const DeskModelWrapperTest&) = delete;
  167. DeskModelWrapperTest& operator=(const DeskModelWrapperTest&) = delete;
  168. ~DeskModelWrapperTest() override = default;
  169. void SetUp() override {
  170. EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
  171. data_manager_ = std::make_unique<LocalDeskDataManager>(temp_dir_.GetPath(),
  172. account_id_);
  173. data_manager_->SetExcludeSaveAndRecallDeskInMaxEntryCountForTesting(false);
  174. desk_test_util::PopulateAppRegistryCache(account_id_, cache_.get());
  175. model_wrapper_ = std::make_unique<DeskModelWrapper>(data_manager_.get());
  176. task_environment_.RunUntilIdle();
  177. testing::Test::SetUp();
  178. }
  179. void CreateBridge() {
  180. ON_CALL(mock_processor_, IsTrackingMetadata())
  181. .WillByDefault(testing::Return(true));
  182. bridge_ = std::make_unique<DeskSyncBridge>(
  183. mock_processor_.CreateForwardingProcessor(),
  184. syncer::ModelTypeStoreTestUtil::FactoryForForwardingStore(store_.get()),
  185. account_id_);
  186. bridge_->AddObserver(&mock_observer_);
  187. }
  188. void FinishInitialization() { base::RunLoop().RunUntilIdle(); }
  189. void InitializeBridge() {
  190. CreateBridge();
  191. FinishInitialization();
  192. model_wrapper_->SetDeskSyncBridge(bridge_.get());
  193. }
  194. void ShutdownBridge() {
  195. base::RunLoop().RunUntilIdle();
  196. bridge_->RemoveObserver(&mock_observer_);
  197. }
  198. void RestartBridge() {
  199. ShutdownBridge();
  200. InitializeBridge();
  201. }
  202. void AddTwoTemplates() {
  203. base::RunLoop loop1;
  204. model_wrapper_->AddOrUpdateEntry(
  205. std::move(sample_desk_template_one_),
  206. base::BindLambdaForTesting(
  207. [&](DeskModel::AddOrUpdateEntryStatus status) {
  208. EXPECT_EQ(status, DeskModel::AddOrUpdateEntryStatus::kOk);
  209. loop1.Quit();
  210. }));
  211. loop1.Run();
  212. base::RunLoop loop2;
  213. model_wrapper_->AddOrUpdateEntry(
  214. std::move(sample_desk_template_two_),
  215. base::BindLambdaForTesting(
  216. [&](DeskModel::AddOrUpdateEntryStatus status) {
  217. EXPECT_EQ(status, DeskModel::AddOrUpdateEntryStatus::kOk);
  218. loop2.Quit();
  219. }));
  220. loop2.Run();
  221. }
  222. void AddTwoSaveAndRecallDeskTemplates() {
  223. base::RunLoop loop1;
  224. model_wrapper_->AddOrUpdateEntry(
  225. std::move(sample_save_and_recall_desk_one_),
  226. base::BindLambdaForTesting(
  227. [&](DeskModel::AddOrUpdateEntryStatus status) {
  228. EXPECT_EQ(status, DeskModel::AddOrUpdateEntryStatus::kOk);
  229. loop1.Quit();
  230. }));
  231. loop1.Run();
  232. base::RunLoop loop2;
  233. model_wrapper_->AddOrUpdateEntry(
  234. std::move(sample_save_and_recall_desk_two_),
  235. base::BindLambdaForTesting(
  236. [&](DeskModel::AddOrUpdateEntryStatus status) {
  237. EXPECT_EQ(status, DeskModel::AddOrUpdateEntryStatus::kOk);
  238. loop2.Quit();
  239. }));
  240. loop2.Run();
  241. }
  242. void AddSavedDeskToDeskModel(std::unique_ptr<ash::DeskTemplate> entry) {
  243. base::RunLoop loop;
  244. model_wrapper_->AddOrUpdateEntry(
  245. std::move(entry),
  246. base::BindLambdaForTesting(
  247. [&](DeskModel::AddOrUpdateEntryStatus status) {
  248. EXPECT_EQ(status, DeskModel::AddOrUpdateEntryStatus::kOk);
  249. loop.Quit();
  250. }));
  251. loop.Run();
  252. }
  253. void VerifyAllEntries(size_t expected_size, const std::string& trace_string) {
  254. SCOPED_TRACE(trace_string);
  255. task_environment_.RunUntilIdle();
  256. auto result = model_wrapper_->GetAllEntries();
  257. EXPECT_EQ(result.status, DeskModel::GetAllEntriesStatus::kOk);
  258. EXPECT_EQ(result.entries.size(), expected_size);
  259. }
  260. base::ScopedTempDir temp_dir_;
  261. std::unique_ptr<ash::DeskTemplate> sample_desk_template_one_;
  262. std::unique_ptr<ash::DeskTemplate> sample_desk_template_two_;
  263. std::unique_ptr<ash::DeskTemplate> sample_save_and_recall_desk_one_;
  264. std::unique_ptr<ash::DeskTemplate> sample_save_and_recall_desk_two_;
  265. base::test::TaskEnvironment task_environment_;
  266. std::unique_ptr<apps::AppRegistryCache> cache_;
  267. AccountId account_id_;
  268. std::unique_ptr<LocalDeskDataManager> data_manager_;
  269. std::unique_ptr<syncer::ModelTypeStore> store_;
  270. testing::NiceMock<syncer::MockModelTypeChangeProcessor> mock_processor_;
  271. std::unique_ptr<DeskSyncBridge> bridge_;
  272. testing::NiceMock<MockDeskModelObserver> mock_observer_;
  273. std::unique_ptr<DeskModelWrapper> model_wrapper_;
  274. };
  275. TEST_F(DeskModelWrapperTest, CanAddDeskTemplateEntry) {
  276. InitializeBridge();
  277. model_wrapper_->AddOrUpdateEntry(std::move(sample_desk_template_one_),
  278. base::BindOnce(&VerifyEntryAddedCorrectly));
  279. VerifyAllEntries(1ul, "Added one desk template");
  280. // Verify that it's not desk template entry in the save and recall desk
  281. // storage.
  282. auto result = model_wrapper_->GetAllEntries();
  283. EXPECT_EQ(result.status, DeskModel::GetAllEntriesStatus::kOk);
  284. EXPECT_EQ(result.entries.size(), 1ul);
  285. EXPECT_EQ(result.entries[0]->type(), ash::DeskTemplateType::kTemplate);
  286. EXPECT_EQ(model_wrapper_->GetDeskTemplateEntryCount(), 1ul);
  287. EXPECT_EQ(model_wrapper_->GetSaveAndRecallDeskEntryCount(), 0ul);
  288. }
  289. TEST_F(DeskModelWrapperTest, CanAddSaveAndRecallDeskEntry) {
  290. InitializeBridge();
  291. model_wrapper_->AddOrUpdateEntry(
  292. MakeTestDeskTemplate(1u, ash::DeskTemplateType::kSaveAndRecall),
  293. base::BindOnce(&VerifyEntryAddedCorrectly));
  294. VerifyAllEntries(1ul, "Added one save and recall desk");
  295. // Verify that it's not SaveAndRecall entry in the desk template storage.
  296. auto result = model_wrapper_->GetAllEntries();
  297. EXPECT_EQ(result.status, DeskModel::GetAllEntriesStatus::kOk);
  298. EXPECT_EQ(result.entries.size(), 1ul);
  299. EXPECT_EQ(result.entries[0]->type(), ash::DeskTemplateType::kSaveAndRecall);
  300. EXPECT_EQ(model_wrapper_->GetDeskTemplateEntryCount(), 0ul);
  301. EXPECT_EQ(model_wrapper_->GetSaveAndRecallDeskEntryCount(), 1ul);
  302. }
  303. TEST_F(DeskModelWrapperTest,
  304. ReturnsErrorWhenAddingTooManySaveAndRecallDeskEntry) {
  305. InitializeBridge();
  306. for (std::size_t index = 0;
  307. index < model_wrapper_->GetMaxSaveAndRecallDeskEntryCount(); ++index) {
  308. AddSavedDeskToDeskModel(
  309. MakeTestDeskTemplate(index, ash::DeskTemplateType::kSaveAndRecall));
  310. }
  311. model_wrapper_->AddOrUpdateEntry(
  312. MakeTestDeskTemplate(
  313. model_wrapper_->GetMaxSaveAndRecallDeskEntryCount() + 1,
  314. ash::DeskTemplateType::kSaveAndRecall),
  315. base::BindOnce(&VerifyEntryAddedErrorHitMaximumLimit));
  316. task_environment_.RunUntilIdle();
  317. }
  318. TEST_F(DeskModelWrapperTest, CanGetAllEntries) {
  319. InitializeBridge();
  320. AddTwoTemplates();
  321. auto result = model_wrapper_->GetAllEntries();
  322. EXPECT_EQ(result.status, DeskModel::GetAllEntriesStatus::kOk);
  323. EXPECT_EQ(result.entries.size(), 2ul);
  324. EXPECT_TRUE(FindUuidInUuidList(kTestUuid1, result.entries));
  325. EXPECT_TRUE(FindUuidInUuidList(kTestUuid2, result.entries));
  326. // Sanity check for the search function.
  327. EXPECT_FALSE(FindUuidInUuidList(kTestUuid3, result.entries));
  328. }
  329. TEST_F(DeskModelWrapperTest, GetAllEntriesIncludesPolicyValues) {
  330. InitializeBridge();
  331. AddTwoTemplates();
  332. AddTwoSaveAndRecallDeskTemplates();
  333. model_wrapper_->SetPolicyDeskTemplates(kPolicyWithOneTemplate);
  334. auto result = model_wrapper_->GetAllEntries();
  335. EXPECT_EQ(result.status, DeskModel::GetAllEntriesStatus::kOk);
  336. EXPECT_EQ(result.entries.size(), 5ul);
  337. EXPECT_TRUE(FindUuidInUuidList(kTestUuid1, result.entries));
  338. EXPECT_TRUE(FindUuidInUuidList(kTestUuid2, result.entries));
  339. EXPECT_TRUE(FindUuidInUuidList(kTestUuid3, result.entries));
  340. EXPECT_TRUE(FindUuidInUuidList(kTestUuid4, result.entries));
  341. EXPECT_TRUE(FindUuidInUuidList(kTestUuid5, result.entries));
  342. // One of these templates should be from policy.
  343. EXPECT_EQ(base::ranges::count_if(result.entries,
  344. [](const ash::DeskTemplate* entry) {
  345. return entry->source() ==
  346. ash::DeskTemplateSource::kPolicy;
  347. }),
  348. 1l);
  349. model_wrapper_->SetPolicyDeskTemplates("");
  350. }
  351. TEST_F(DeskModelWrapperTest, CanDetectDuplicateEntryNames) {
  352. InitializeBridge();
  353. // Add desk template entry to desk model.
  354. AddSavedDeskToDeskModel(std::move(sample_desk_template_one_));
  355. // Add desk template entry with the duplicated name to desk model.
  356. auto dupe_template_uuid = base::StringPrintf(kUuidFormat, 6);
  357. auto dupe_desk_template =
  358. MakeTestDeskTemplate(dupe_template_uuid, ash::DeskTemplateSource::kUser,
  359. "desk_01", base::Time::Now());
  360. AddSavedDeskToDeskModel(std::move(dupe_desk_template));
  361. // Add save and recall desk to desk model.
  362. AddSavedDeskToDeskModel(std::move(sample_save_and_recall_desk_one_));
  363. // Add save and recall entry with the duplicated name to desk model.
  364. auto dupe_save_and_recall_uuid = base::StringPrintf(kUuidFormat, 7);
  365. auto dupe_save_and_recall_desk = MakeTestSaveAndRecallDesk(
  366. dupe_save_and_recall_uuid, "save_and_recall_desk_01", base::Time::Now());
  367. AddSavedDeskToDeskModel(std::move(dupe_save_and_recall_desk));
  368. // Add save and recall entry with the duplicated name as a desk template to
  369. // desk model. This is to test that the two desk types don't share the same
  370. // namespace for the sake of duplication checks.
  371. auto dupe_second_save_and_recall_uuid = base::StringPrintf(kUuidFormat, 8);
  372. auto dupe_second_save_and_recall_desk = MakeTestSaveAndRecallDesk(
  373. dupe_second_save_and_recall_uuid, "desk_01", base::Time::Now());
  374. AddSavedDeskToDeskModel(std::move(dupe_second_save_and_recall_desk));
  375. auto result = model_wrapper_->GetAllEntries();
  376. EXPECT_EQ(result.status, DeskModel::GetAllEntriesStatus::kOk);
  377. EXPECT_EQ(result.entries.size(), 5ul);
  378. const ash::DeskTemplate* duplicate_desk_template =
  379. model_wrapper_->FindOtherEntryWithName(
  380. u"desk_01", ash::DeskTemplateType::kTemplate,
  381. base::GUID::ParseCaseInsensitive(dupe_template_uuid));
  382. EXPECT_TRUE(duplicate_desk_template);
  383. const ash::DeskTemplate* duplicate_save_and_recall =
  384. model_wrapper_->FindOtherEntryWithName(
  385. u"save_and_recall_desk_01", ash::DeskTemplateType::kSaveAndRecall,
  386. base::GUID::ParseCaseInsensitive(dupe_template_uuid));
  387. EXPECT_TRUE(duplicate_save_and_recall);
  388. const ash::DeskTemplate* duplicate_save_and_recall_not_found =
  389. model_wrapper_->FindOtherEntryWithName(
  390. u"desk_01", ash::DeskTemplateType::kSaveAndRecall,
  391. base::GUID::ParseCaseInsensitive(dupe_second_save_and_recall_uuid));
  392. EXPECT_FALSE(duplicate_save_and_recall_not_found);
  393. }
  394. TEST_F(DeskModelWrapperTest, CanDetectNoDuplicateEntryNames) {
  395. InitializeBridge();
  396. // Add desk template entry to desk model.
  397. AddSavedDeskToDeskModel(std::move(sample_desk_template_one_));
  398. // Add a second desk template entry to the desk model with a unique name.
  399. auto second_template_uuid = base::StringPrintf(kUuidFormat, 7);
  400. auto second_desk_template =
  401. MakeTestDeskTemplate(second_template_uuid, ash::DeskTemplateSource::kUser,
  402. "desk_02", base::Time::Now());
  403. AddSavedDeskToDeskModel(std::move(second_desk_template));
  404. // Add save and recall desk to desk model.
  405. AddSavedDeskToDeskModel(std::move(sample_save_and_recall_desk_one_));
  406. // Add save and recall entry with the duplicated name to desk model.
  407. auto second_save_and_recall_uuid = base::StringPrintf(kUuidFormat, 7);
  408. auto second_save_and_recall_desk =
  409. MakeTestSaveAndRecallDesk(second_save_and_recall_uuid,
  410. "save_and_recall_desk_02", base::Time::Now());
  411. AddSavedDeskToDeskModel(std::move(second_save_and_recall_desk));
  412. auto result = model_wrapper_->GetAllEntries();
  413. EXPECT_EQ(result.status, DeskModel::GetAllEntriesStatus::kOk);
  414. EXPECT_EQ(result.entries.size(), 4ul);
  415. const ash::DeskTemplate* duplicate_desk_template =
  416. model_wrapper_->FindOtherEntryWithName(
  417. u"desk_02", ash::DeskTemplateType::kTemplate,
  418. base::GUID::ParseCaseInsensitive(second_template_uuid));
  419. EXPECT_FALSE(duplicate_desk_template);
  420. const ash::DeskTemplate* duplicate_save_and_recall =
  421. model_wrapper_->FindOtherEntryWithName(
  422. u"save_and_recall_desk_02", ash::DeskTemplateType::kSaveAndRecall,
  423. base::GUID::ParseCaseInsensitive(second_save_and_recall_uuid));
  424. EXPECT_FALSE(duplicate_save_and_recall);
  425. }
  426. TEST_F(DeskModelWrapperTest, CanGetEntryByUuid) {
  427. InitializeBridge();
  428. // Add desk template entry to desk model.
  429. AddSavedDeskToDeskModel(std::move(sample_desk_template_one_));
  430. // Add save and recall desk to desk model.
  431. AddSavedDeskToDeskModel(std::move(sample_save_and_recall_desk_one_));
  432. // Find the desk template by its uuid.
  433. model_wrapper_->GetEntryByUUID(
  434. kTestUuid1,
  435. base::BindLambdaForTesting([&](DeskModel::GetEntryByUuidStatus status,
  436. std::unique_ptr<ash::DeskTemplate> entry) {
  437. EXPECT_EQ(status, DeskModel::GetEntryByUuidStatus::kOk);
  438. EXPECT_EQ(entry->uuid(), base::GUID::ParseCaseInsensitive(kTestUuid1));
  439. EXPECT_EQ(base::UTF16ToUTF8(entry->template_name()), "desk_01");
  440. }));
  441. // Find the save and recall desk by its uuid.
  442. model_wrapper_->GetEntryByUUID(
  443. kTestUuid3,
  444. base::BindLambdaForTesting([&](DeskModel::GetEntryByUuidStatus status,
  445. std::unique_ptr<ash::DeskTemplate> entry) {
  446. EXPECT_EQ(status, DeskModel::GetEntryByUuidStatus::kOk);
  447. EXPECT_EQ(entry->uuid(), base::GUID::ParseCaseInsensitive(kTestUuid3));
  448. EXPECT_EQ(base::UTF16ToUTF8(entry->template_name()),
  449. "save_and_recall_desk_01");
  450. }));
  451. task_environment_.RunUntilIdle();
  452. }
  453. TEST_F(DeskModelWrapperTest, GetEntryByUuidShouldReturnAdminTemplate) {
  454. InitializeBridge();
  455. AddSavedDeskToDeskModel(std::move(sample_desk_template_one_));
  456. // Set admin template with UUID: kTestUuid5.
  457. model_wrapper_->SetPolicyDeskTemplates(kPolicyWithOneTemplate);
  458. // Check that the admin template is included as an entry.
  459. EXPECT_EQ(model_wrapper_->GetAllEntryUuids().size(), 2ul);
  460. model_wrapper_->GetEntryByUUID(
  461. kTestUuid5,
  462. base::BindLambdaForTesting([&](DeskModel::GetEntryByUuidStatus status,
  463. std::unique_ptr<ash::DeskTemplate> entry) {
  464. EXPECT_EQ(status, DeskModel::GetEntryByUuidStatus::kOk);
  465. EXPECT_EQ(entry->uuid(), base::GUID::ParseCaseInsensitive(kTestUuid5));
  466. EXPECT_EQ(entry->source(), ash::DeskTemplateSource::kPolicy);
  467. EXPECT_EQ(base::UTF16ToUTF8(entry->template_name()),
  468. "Admin Template 1");
  469. }));
  470. }
  471. TEST_F(DeskModelWrapperTest, GetEntryByUuidReturnsNotFoundIfEntryDoesNotExist) {
  472. InitializeBridge();
  473. base::RunLoop loop;
  474. model_wrapper_->GetEntryByUUID(
  475. kTestUuid1,
  476. base::BindLambdaForTesting([&](DeskModel::GetEntryByUuidStatus status,
  477. std::unique_ptr<ash::DeskTemplate> entry) {
  478. EXPECT_EQ(status, DeskModel::GetEntryByUuidStatus::kNotFound);
  479. loop.Quit();
  480. }));
  481. loop.Run();
  482. }
  483. TEST_F(DeskModelWrapperTest, CanUpdateEntry) {
  484. InitializeBridge();
  485. // Make a clone of a desk template and modify its name.
  486. auto modified_desk_template = sample_desk_template_one_->Clone();
  487. modified_desk_template->set_template_name(u"desk_01_mod");
  488. AddSavedDeskToDeskModel(std::move(sample_desk_template_one_));
  489. AddSavedDeskToDeskModel(std::move(modified_desk_template));
  490. // Make a clone of a save and recall desk and modify its name.
  491. auto modified_save_and_recall_desk =
  492. sample_save_and_recall_desk_one_->Clone();
  493. modified_save_and_recall_desk->set_template_name(
  494. u"save_and_recall_desk_01_mod");
  495. AddSavedDeskToDeskModel(std::move(sample_save_and_recall_desk_one_));
  496. AddSavedDeskToDeskModel(std::move(modified_save_and_recall_desk));
  497. // Check that the entries are updated.
  498. model_wrapper_->GetEntryByUUID(
  499. kTestUuid1,
  500. base::BindLambdaForTesting([&](DeskModel::GetEntryByUuidStatus status,
  501. std::unique_ptr<ash::DeskTemplate> entry) {
  502. EXPECT_EQ(status, DeskModel::GetEntryByUuidStatus::kOk);
  503. EXPECT_EQ(entry->uuid(), base::GUID::ParseCaseInsensitive(kTestUuid1));
  504. EXPECT_EQ(entry->template_name(),
  505. base::UTF8ToUTF16(std::string("desk_01_mod")));
  506. }));
  507. model_wrapper_->GetEntryByUUID(
  508. kTestUuid3,
  509. base::BindLambdaForTesting([&](DeskModel::GetEntryByUuidStatus status,
  510. std::unique_ptr<ash::DeskTemplate> entry) {
  511. EXPECT_EQ(status, DeskModel::GetEntryByUuidStatus::kOk);
  512. EXPECT_EQ(entry->uuid(), base::GUID::ParseCaseInsensitive(kTestUuid3));
  513. EXPECT_EQ(entry->template_name(), u"save_and_recall_desk_01_mod");
  514. }));
  515. task_environment_.RunUntilIdle();
  516. }
  517. TEST_F(DeskModelWrapperTest, CanDeleteDeskTemplateEntry) {
  518. InitializeBridge();
  519. model_wrapper_->AddOrUpdateEntry(std::move(sample_desk_template_one_),
  520. base::BindOnce(&VerifyEntryAddedCorrectly));
  521. model_wrapper_->DeleteEntry(
  522. kTestUuid1,
  523. base::BindLambdaForTesting([&](DeskModel::DeleteEntryStatus status) {
  524. EXPECT_EQ(status, DeskModel::DeleteEntryStatus::kOk);
  525. }));
  526. VerifyAllEntries(0ul, "Delete desk template");
  527. }
  528. TEST_F(DeskModelWrapperTest, CanDeleteSaveAndRecallDeskEntry) {
  529. InitializeBridge();
  530. model_wrapper_->AddOrUpdateEntry(std::move(sample_save_and_recall_desk_one_),
  531. base::BindOnce(&VerifyEntryAddedCorrectly));
  532. model_wrapper_->DeleteEntry(
  533. kTestUuid3,
  534. base::BindLambdaForTesting([&](DeskModel::DeleteEntryStatus status) {
  535. EXPECT_EQ(status, DeskModel::DeleteEntryStatus::kOk);
  536. }));
  537. VerifyAllEntries(0ul, "Delete save and recall desk");
  538. }
  539. TEST_F(DeskModelWrapperTest, CanDeleteAllEntries) {
  540. InitializeBridge();
  541. AddTwoTemplates();
  542. AddTwoSaveAndRecallDeskTemplates();
  543. model_wrapper_->DeleteAllEntries(
  544. base::BindLambdaForTesting([&](DeskModel::DeleteEntryStatus status) {
  545. EXPECT_EQ(status, DeskModel::DeleteEntryStatus::kOk);
  546. }));
  547. VerifyAllEntries(0ul,
  548. "Delete all entries after adding two desk templates and two "
  549. "save and recall desks");
  550. }
  551. TEST_F(DeskModelWrapperTest,
  552. GetEntryCountShouldIncludeBothUserAndAdminTemplates) {
  553. InitializeBridge();
  554. // Add two user templates.
  555. AddTwoTemplates();
  556. // Add two save and recall desks templates.
  557. AddTwoSaveAndRecallDeskTemplates();
  558. // Set one admin template.
  559. model_wrapper_->SetPolicyDeskTemplates(kPolicyWithOneTemplate);
  560. // There should be 5 templates: 2 user templates + 1 admin template + 2 save
  561. // and recall desks.
  562. EXPECT_EQ(model_wrapper_->GetEntryCount(), 5ul);
  563. // MaxEntryCount should be 6 max save and recall desks + 6 max user templates
  564. // + 1 admin template.
  565. EXPECT_EQ(model_wrapper_->GetMaxEntryCount(), 13ul);
  566. }
  567. TEST_F(DeskModelWrapperTest, GetMaxEntryCountShouldIncreaseWithAdminTemplates) {
  568. InitializeBridge();
  569. // Add two user templates.
  570. AddTwoTemplates();
  571. std::size_t max_entry_count = model_wrapper_->GetMaxDeskTemplateEntryCount();
  572. // Set one admin template.
  573. model_wrapper_->SetPolicyDeskTemplates(kPolicyWithOneTemplate);
  574. // The max entry count should increase by 1 since we have set an admin
  575. // template.
  576. EXPECT_EQ(model_wrapper_->GetMaxDeskTemplateEntryCount(),
  577. max_entry_count + 1ul);
  578. // Sanity check to make sure that save and recall desk max count isn't
  579. // affected by the admin template.
  580. EXPECT_EQ(model_wrapper_->GetMaxSaveAndRecallDeskEntryCount(), 6ul);
  581. }
  582. TEST_F(DeskModelWrapperTest, AddDeskTemplatesAndSaveAndRecallDeskEntries) {
  583. InitializeBridge();
  584. // Add two user templates.
  585. AddTwoTemplates();
  586. // Add two SaveAndRecall desks.
  587. AddTwoSaveAndRecallDeskTemplates();
  588. EXPECT_EQ(model_wrapper_->GetEntryCount(), 4ul);
  589. EXPECT_EQ(model_wrapper_->GetDeskTemplateEntryCount(), 2ul);
  590. EXPECT_EQ(model_wrapper_->GetSaveAndRecallDeskEntryCount(), 2ul);
  591. auto result = model_wrapper_->GetAllEntries();
  592. EXPECT_EQ(result.status, DeskModel::GetAllEntriesStatus::kOk);
  593. VerifyAllEntries(4ul,
  594. "Add two desks templates and two saved and recall desks");
  595. }
  596. TEST_F(DeskModelWrapperTest, AddSaveAndRecallDeskEntry) {
  597. InitializeBridge();
  598. model_wrapper_->AddOrUpdateEntry(
  599. MakeTestDeskTemplate(1u, ash::DeskTemplateType::kSaveAndRecall),
  600. base::BindOnce(&VerifyEntryAddedCorrectly));
  601. VerifyAllEntries(1ul, "Added one save and recall desk");
  602. // Verify that it's not SaveAndRecall entry in the desk template cache.
  603. auto result = model_wrapper_->GetAllEntries();
  604. EXPECT_EQ(result.status, DeskModel::GetAllEntriesStatus::kOk);
  605. EXPECT_EQ(result.entries.size(), 1ul);
  606. EXPECT_EQ(result.entries[0]->type(), ash::DeskTemplateType::kSaveAndRecall);
  607. EXPECT_EQ(model_wrapper_->GetDeskTemplateEntryCount(), 0ul);
  608. EXPECT_EQ(model_wrapper_->GetSaveAndRecallDeskEntryCount(), 1ul);
  609. }
  610. TEST_F(DeskModelWrapperTest, CanAddMaxEntriesForBothTypes) {
  611. InitializeBridge();
  612. for (std::size_t index = 0u;
  613. index < model_wrapper_->GetMaxSaveAndRecallDeskEntryCount(); ++index) {
  614. model_wrapper_->AddOrUpdateEntry(
  615. MakeTestDeskTemplate(index, ash::DeskTemplateType::kSaveAndRecall),
  616. base::BindOnce(&VerifyEntryAddedCorrectly));
  617. }
  618. for (std::size_t index = 0u;
  619. index < model_wrapper_->GetMaxDeskTemplateEntryCount(); ++index) {
  620. model_wrapper_->AddOrUpdateEntry(
  621. MakeTestDeskTemplate(index, ash::DeskTemplateType::kTemplate),
  622. base::BindOnce(&VerifyEntryAddedCorrectly));
  623. }
  624. VerifyAllEntries(
  625. 12ul, "Added max number of save and recall desks and desk templates");
  626. EXPECT_EQ(model_wrapper_->GetDeskTemplateEntryCount(), 6ul);
  627. EXPECT_EQ(model_wrapper_->GetSaveAndRecallDeskEntryCount(), 6ul);
  628. }
  629. TEST_F(DeskModelWrapperTest,
  630. CanAddMaxEntriesDeskTemplatesAndStillAddEntryForSaveAndRecallDesks) {
  631. InitializeBridge();
  632. for (std::size_t index = 0u;
  633. index < model_wrapper_->GetMaxDeskTemplateEntryCount(); ++index) {
  634. model_wrapper_->AddOrUpdateEntry(
  635. MakeTestDeskTemplate(index, ash::DeskTemplateType::kTemplate),
  636. base::BindOnce(&VerifyEntryAddedCorrectly));
  637. }
  638. model_wrapper_->AddOrUpdateEntry(
  639. MakeTestDeskTemplate(1ul, ash::DeskTemplateType::kSaveAndRecall),
  640. base::BindOnce(&VerifyEntryAddedCorrectly));
  641. VerifyAllEntries(7ul,
  642. "Added one save and recall desk after capping "
  643. "desk template entries");
  644. EXPECT_EQ(model_wrapper_->GetDeskTemplateEntryCount(), 6ul);
  645. EXPECT_EQ(model_wrapper_->GetSaveAndRecallDeskEntryCount(), 1ul);
  646. }
  647. TEST_F(DeskModelWrapperTest,
  648. CanAddMaxEntriesForSaveAndRecallDeskAndStillAddEntryForDeskTemplate) {
  649. InitializeBridge();
  650. for (std::size_t index = 0u;
  651. index < model_wrapper_->GetMaxSaveAndRecallDeskEntryCount(); ++index) {
  652. model_wrapper_->AddOrUpdateEntry(
  653. MakeTestDeskTemplate(index, ash::DeskTemplateType::kSaveAndRecall),
  654. base::BindOnce(&VerifyEntryAddedCorrectly));
  655. }
  656. model_wrapper_->AddOrUpdateEntry(
  657. MakeTestDeskTemplate(1ul, ash::DeskTemplateType::kTemplate),
  658. base::BindOnce(&VerifyEntryAddedCorrectly));
  659. VerifyAllEntries(7ul,
  660. "Added one desk template after capping "
  661. "save and recall desk entries");
  662. EXPECT_EQ(model_wrapper_->GetDeskTemplateEntryCount(), 1ul);
  663. EXPECT_EQ(model_wrapper_->GetSaveAndRecallDeskEntryCount(), 6ul);
  664. }
  665. } // namespace desks_storage