Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc

Issue 2934293003: The chrome.lockScreen.data API implementation (Closed)
Patch Set: switch to BackendTaskRunner Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
5 #include "extensions/browser/api/lock_screen_data/lock_screen_item_storage.h"
6
7 #include <map>
8 #include <memory>
9 #include <queue>
10 #include <set>
11 #include <utility>
12 #include <vector>
13
14 #include "base/callback.h"
15 #include "base/files/file_path.h"
16 #include "base/files/file_util.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/memory/ptr_util.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/run_loop.h"
21 #include "base/task_scheduler/post_task.h"
22 #include "base/time/time.h"
23 #include "chromeos/login/login_state.h"
24 #include "components/prefs/scoped_user_pref_update.h"
25 #include "components/prefs/testing_pref_service.h"
26 #include "components/sync_preferences/testing_pref_service_syncable.h"
27 #include "components/user_prefs/user_prefs.h"
28 #include "content/public/test/test_browser_context.h"
29 #include "content/public/test/test_browser_thread_bundle.h"
30 #include "extensions/browser/api/lock_screen_data/data_item.h"
31 #include "extensions/browser/api/lock_screen_data/operation_result.h"
32 #include "extensions/browser/event_router.h"
33 #include "extensions/browser/event_router_factory.h"
34 #include "extensions/browser/extension_registry.h"
35 #include "extensions/browser/extensions_test.h"
36 #include "extensions/browser/test_extensions_browser_client.h"
37 #include "extensions/common/api/lock_screen_data.h"
38 #include "extensions/common/extension_builder.h"
39 #include "extensions/common/value_builder.h"
40 #include "testing/gtest/include/gtest/gtest.h"
41
42 namespace extensions {
43 namespace lock_screen_data {
44
45 namespace {
46
47 const char kTestUserIdHash[] = "user_id_hash";
48 const char kTestSymmetricKey[] = "fake_symmetric_key";
49
50 void RecordCreateResult(OperationResult* result_out,
51 const DataItem** item_out,
52 OperationResult result,
53 const DataItem* item) {
54 *result_out = result;
55 *item_out = item;
56 }
57
58 void RecordGetAllItemsResult(std::vector<std::string>* items_out,
59 const std::vector<const DataItem*>& items) {
60 items_out->clear();
61 for (const DataItem* item : items)
62 items_out->push_back(item->id());
63 }
64
65 void RecordWriteResult(OperationResult* result_out, OperationResult result) {
66 *result_out = result;
67 }
68
69 void RecordReadResult(OperationResult* result_out,
70 std::unique_ptr<std::vector<char>>* content_out,
71 OperationResult result,
72 std::unique_ptr<std::vector<char>> content) {
73 *result_out = result;
74 *content_out = std::move(content);
75 }
76
77 class TestEventRouter : public extensions::EventRouter {
78 public:
79 explicit TestEventRouter(content::BrowserContext* context)
80 : extensions::EventRouter(context, nullptr) {}
81 ~TestEventRouter() override = default;
82
83 bool ExtensionHasEventListener(const std::string& extension_id,
84 const std::string& event_name) const override {
85 return event_name ==
86 extensions::api::lock_screen_data::OnDataItemsAvailable::kEventName;
87 }
88
89 void BroadcastEvent(std::unique_ptr<extensions::Event> event) override {}
90
91 void DispatchEventToExtension(
92 const std::string& extension_id,
93 std::unique_ptr<extensions::Event> event) override {
94 if (event->event_name !=
95 extensions::api::lock_screen_data::OnDataItemsAvailable::kEventName) {
96 return;
97 }
98 ASSERT_TRUE(event->event_args);
99 const base::Value* arg_value = nullptr;
100 ASSERT_TRUE(event->event_args->Get(0, &arg_value));
101 ASSERT_TRUE(arg_value);
102
103 std::unique_ptr<extensions::api::lock_screen_data::DataItemsAvailableEvent>
104 event_args = extensions::api::lock_screen_data::
105 DataItemsAvailableEvent::FromValue(*arg_value);
106 ASSERT_TRUE(event_args);
107 was_locked_values_.push_back(event_args->was_locked);
108 }
109
110 const std::vector<bool>& was_locked_values() const {
111 return was_locked_values_;
112 }
113
114 void ClearWasLockedValues() { was_locked_values_.clear(); }
115
116 private:
117 std::vector<bool> was_locked_values_;
118
119 DISALLOW_COPY_AND_ASSIGN(TestEventRouter);
120 };
121
122 std::unique_ptr<KeyedService> TestEventRouterFactoryFunction(
123 content::BrowserContext* context) {
124 return base::MakeUnique<TestEventRouter>(context);
125 }
126
127 // Keeps track of all fake data items registered during a test.
128 class ItemRegistry {
129 public:
130 explicit ItemRegistry(const std::string& extension_id)
131 : extension_id_(extension_id) {}
132 ~ItemRegistry() = default;
133
134 // Adds a new item to set of registered items.
135 bool Add(const std::string& item_id) {
136 EXPECT_FALSE(items_.count(item_id));
137
138 if (!allow_new_)
139 return false;
140 items_.insert(item_id);
141 return true;
142 }
143
144 // Removes an item from the set of registered items.
145 void Remove(const std::string& item_id) {
146 ASSERT_TRUE(items_.count(item_id));
147 items_.erase(item_id);
148 }
149
150 void RemoveAll() { items_.clear(); }
151
152 // Gets the set of registered data items.
153 void HandleGetRequest(const DataItem::RegisteredValuesCallback& callback) {
154 if (!throttle_get_) {
155 RunCallback(callback);
156 return;
157 }
158
159 ASSERT_TRUE(pending_callback_.is_null());
160 pending_callback_ = callback;
161 }
162
163 // Completes a pending |HandleGetRequest| request.
164 void RunPendingCallback() {
165 ASSERT_FALSE(pending_callback_.is_null());
166 DataItem::RegisteredValuesCallback callback = pending_callback_;
167 pending_callback_.Reset();
168 RunCallback(callback);
169 }
170
171 bool HasPendingCallback() const { return !pending_callback_.is_null(); }
172
173 void set_allow_new(bool allow_new) { allow_new_ = allow_new; }
174 void set_fail(bool fail) { fail_ = fail; }
175 void set_throttle_get(bool throttle_get) { throttle_get_ = throttle_get; }
176
177 private:
178 void RunCallback(const DataItem::RegisteredValuesCallback& callback) {
179 callback.Run(fail_ ? OperationResult::kFailed : OperationResult::kSuccess,
180 ItemsToValue());
181 }
182
183 std::unique_ptr<base::DictionaryValue> ItemsToValue() {
184 if (fail_)
185 return nullptr;
186
187 std::unique_ptr<base::DictionaryValue> result =
188 base::MakeUnique<base::DictionaryValue>();
189
190 for (const std::string& item_id : items_)
191 result->Set(item_id, base::MakeUnique<base::DictionaryValue>());
192
193 return result;
194 }
195
196 const std::string extension_id_;
197 // Whether data item registration should succeed.
198 bool allow_new_ = true;
199 // Whether data item retrievals should fail.
200 bool fail_ = false;
201 // Whether the data item retrivals should be throttled. If set,
202 // |HandleGetRequest| callback will be saved to |pending_callback_| without
203 // returning. Test will have to invoke |RunPendingCallback| in order to
204 // complete the request.
205 bool throttle_get_ = false;
206
207 DataItem::RegisteredValuesCallback pending_callback_;
208 // Set of registered item ids.
209 std::set<std::string> items_;
210
211 DISALLOW_COPY_AND_ASSIGN(ItemRegistry);
212 };
213
214 // Keeps track of all operations requested from the test data item.
215 // The operations will remain in pending state until completed by calling
216 // CompleteNextOperation.
217 // This is owned by the test class, but data items created during the test have
218 // a reference to the object. More than one data item can have a reference to
219 // this - data items with the same ID will get the same operation queue.
220 class OperationQueue {
221 public:
222 enum class OperationType { kWrite, kRead, kDelete };
223
224 struct PendingOperation {
225 explicit PendingOperation(OperationType type) : type(type) {}
226
227 OperationType type;
228 // Set only for write - data to be written.
229 std::vector<char> data;
230
231 // Callback for write operation.
232 DataItem::WriteCallback write_callback;
233
234 // Callback for read operation.
235 DataItem::ReadCallback read_callback;
236
237 // Callback for delete operation.
238 DataItem::WriteCallback delete_callback;
239 };
240
241 OperationQueue(const std::string& id, ItemRegistry* item_registry)
242 : id_(id), item_registry_(item_registry) {}
243
244 ~OperationQueue() = default;
245
246 void Register(const DataItem::WriteCallback& callback) {
247 bool registered = item_registry_->Add(id_);
248 callback.Run(registered ? OperationResult::kSuccess
249 : OperationResult::kFailed);
250 }
251
252 void AddWrite(const std::vector<char>& data,
253 const DataItem::WriteCallback& callback) {
254 PendingOperation operation(OperationType::kWrite);
255 operation.data = data;
256 operation.write_callback = callback;
257
258 pending_operations_.emplace(std::move(operation));
259 }
260
261 void AddRead(const DataItem::ReadCallback& callback) {
262 PendingOperation operation(OperationType::kRead);
263 operation.read_callback = callback;
264
265 pending_operations_.emplace(std::move(operation));
266 }
267
268 void AddDelete(const DataItem::WriteCallback& callback) {
269 PendingOperation operation(OperationType::kDelete);
270 operation.delete_callback = callback;
271
272 pending_operations_.emplace(std::move(operation));
273 }
274
275 // Completes the next pendig operation.
276 // |expected_type| - the expected type of the next operation - this will fail
277 // if the operation does not match.
278 // |result| - the intended operation result.
279 void CompleteNextOperation(OperationType expected_type,
280 OperationResult result) {
281 ASSERT_FALSE(pending_operations_.empty());
282 ASSERT_FALSE(deleted_);
283
284 const PendingOperation& operation = pending_operations_.front();
285
286 ASSERT_EQ(expected_type, operation.type);
287
288 switch (expected_type) {
289 case OperationType::kWrite: {
290 if (result == OperationResult::kSuccess)
291 content_ = operation.data;
292 DataItem::WriteCallback callback = operation.write_callback;
293 pending_operations_.pop();
294 callback.Run(result);
295 break;
296 }
297 case OperationType::kDelete: {
298 if (result == OperationResult::kSuccess) {
299 deleted_ = true;
300 item_registry_->Remove(id_);
301 content_ = std::vector<char>();
302 }
303
304 DataItem::WriteCallback callback = operation.delete_callback;
305 pending_operations_.pop();
306 callback.Run(result);
307 break;
308 }
309 case OperationType::kRead: {
310 std::unique_ptr<std::vector<char>> result_data;
311 if (result == OperationResult::kSuccess) {
312 result_data = base::MakeUnique<std::vector<char>>(content_.begin(),
313 content_.end());
314 }
315
316 DataItem::ReadCallback callback = operation.read_callback;
317 pending_operations_.pop();
318 callback.Run(result, std::move(result_data));
319 break;
320 }
321 default:
322 ADD_FAILURE() << "Unexpected operation";
323 return;
324 }
325 }
326
327 bool HasPendingOperations() const { return !pending_operations_.empty(); }
328
329 bool deleted() const { return deleted_; }
330
331 const std::vector<char>& content() const { return content_; }
332
333 private:
334 std::string id_;
335 ItemRegistry* item_registry_;
336 std::queue<PendingOperation> pending_operations_;
337 std::vector<char> content_;
338 bool deleted_ = false;
339
340 DISALLOW_COPY_AND_ASSIGN(OperationQueue);
341 };
342
343 // Test data item - routes all requests to the OperationQueue provided through
344 // the ctor - the owning test is responsible for completing the started
345 // operations.
346 class TestDataItem : public DataItem {
347 public:
348 // |operations| - Operation queue used by this data item - not owned by this,
349 // and expected to outlive this object.
350 TestDataItem(const std::string& id,
351 const std::string& extension_id,
352 const std::string& crypto_key,
353 OperationQueue* operations)
354 : DataItem(id, extension_id, nullptr, nullptr, nullptr, crypto_key),
355 operations_(operations) {}
356
357 ~TestDataItem() override = default;
358
359 void Register(const WriteCallback& callback) override {
360 operations_->Register(callback);
361 }
362
363 void Write(const std::vector<char>& data,
364 const WriteCallback& callback) override {
365 operations_->AddWrite(data, callback);
366 }
367
368 void Read(const ReadCallback& callback) override {
369 operations_->AddRead(callback);
370 }
371
372 void Delete(const WriteCallback& callback) override {
373 operations_->AddDelete(callback);
374 }
375
376 private:
377 OperationQueue* operations_;
378
379 DISALLOW_COPY_AND_ASSIGN(TestDataItem);
380 };
381
382 class LockScreenItemStorageTest : public ExtensionsTest {
383 public:
384 LockScreenItemStorageTest()
385 : ExtensionsTest(base::MakeUnique<content::TestBrowserThreadBundle>()) {}
386 ~LockScreenItemStorageTest() override = default;
387
388 void SetUp() override {
389 ExtensionsTest::SetUp();
390
391 ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
392 LockScreenItemStorage::RegisterLocalState(local_state_.registry());
393 user_prefs::UserPrefs::Set(browser_context(), &testing_pref_service_);
394 extensions_browser_client()->set_lock_screen_context(&lock_screen_context_);
395
396 chromeos::LoginState::Initialize();
397 chromeos::LoginState::Get()->SetLoggedInStateAndPrimaryUser(
398 chromeos::LoginState::LOGGED_IN_ACTIVE,
399 chromeos::LoginState::LOGGED_IN_USER_REGULAR, kTestUserIdHash);
400
401 CreateTestExtension();
402 item_registry_ = base::MakeUnique<ItemRegistry>(extension()->id());
403
404 // Inject custom data item factory to be used with LockScreenItemStorage
405 // instances.
406 item_factory_ = base::Bind(&LockScreenItemStorageTest::CreateItem,
407 base::Unretained(this));
408 registered_items_getter_ = base::Bind(
409 &LockScreenItemStorageTest::GetRegisteredItems, base::Unretained(this));
410 item_store_deleter_ = base::Bind(&LockScreenItemStorageTest::RemoveAllItems,
411 base::Unretained(this));
412 LockScreenItemStorage::SetItemProvidersForTesting(
413 &registered_items_getter_, &item_factory_, &item_store_deleter_);
414
415 ResetLockScreenItemStorage();
416 }
417
418 void TearDown() override {
419 lock_screen_item_storage_.reset();
420 operations_.clear();
421 item_registry_.reset();
422 LockScreenItemStorage::SetItemProvidersForTesting(nullptr, nullptr,
423 nullptr);
424 chromeos::LoginState::Shutdown();
425 ExtensionsTest::TearDown();
426 }
427
428 OperationQueue* GetOperations(const std::string& id) {
429 return operations_[id].get();
430 }
431
432 void UnsetLockScreenItemStorage() { lock_screen_item_storage_.reset(); }
433
434 void ResetLockScreenItemStorage() {
435 lock_screen_item_storage_.reset();
436 lock_screen_item_storage_ = base::MakeUnique<LockScreenItemStorage>(
437 browser_context(), &local_state_, kTestSymmetricKey,
438 test_dir_.GetPath());
439 }
440
441 // Utility method for setting test item content.
442 bool SetItemContent(const std::string& id, const std::vector<char>& content) {
443 OperationQueue* item_operations = GetOperations(id);
444 if (!item_operations) {
445 ADD_FAILURE() << "No item operations";
446 return false;
447 }
448 OperationResult write_result = OperationResult::kFailed;
449 lock_screen_item_storage()->SetItemContent(
450 extension()->id(), id, content,
451 base::Bind(&RecordWriteResult, &write_result));
452 if (!item_operations->HasPendingOperations()) {
453 ADD_FAILURE() << "Write not registered";
454 return false;
455 }
456 item_operations->CompleteNextOperation(
457 OperationQueue::OperationType::kWrite, OperationResult::kSuccess);
458 EXPECT_EQ(OperationResult::kSuccess, write_result);
459 return write_result == OperationResult::kSuccess;
460 }
461
462 const DataItem* CreateNewItem() {
463 OperationResult create_result = OperationResult::kFailed;
464 const DataItem* item = nullptr;
465 lock_screen_item_storage()->CreateItem(
466 extension()->id(),
467 base::Bind(&RecordCreateResult, &create_result, &item));
468 EXPECT_EQ(OperationResult::kSuccess, create_result);
469
470 return item;
471 }
472
473 // Utility method for creating a new testing data item, and setting its
474 // content.
475 const DataItem* CreateItemWithContent(const std::vector<char>& content) {
476 const DataItem* item = CreateNewItem();
477 if (!item) {
478 ADD_FAILURE() << "Item creation failed";
479 return nullptr;
480 }
481
482 if (!SetItemContent(item->id(), content))
483 return nullptr;
484
485 return item;
486 }
487
488 void GetAllItems(std::vector<std::string>* all_items) {
489 lock_screen_item_storage()->GetAllForExtension(
490 extension()->id(), base::Bind(&RecordGetAllItemsResult, all_items));
491 }
492
493 // Finds an item with the ID |id| in list of items |items|.
494 const DataItem* FindItem(const std::string& id,
495 const std::vector<const DataItem*> items) {
496 for (const auto* item : items) {
497 if (item && item->id() == id)
498 return item;
499 }
500 return nullptr;
501 }
502
503 LockScreenItemStorage* lock_screen_item_storage() {
504 return lock_screen_item_storage_.get();
505 }
506
507 content::BrowserContext* lock_screen_context() {
508 return &lock_screen_context_;
509 }
510
511 const Extension* extension() const { return extension_.get(); }
512
513 const base::FilePath& test_dir() const { return test_dir_.GetPath(); }
514
515 PrefService* local_state() { return &local_state_; }
516
517 ItemRegistry* item_registry() { return item_registry_.get(); }
518
519 private:
520 void CreateTestExtension() {
521 DictionaryBuilder app_builder;
522 app_builder.Set("background",
523 DictionaryBuilder()
524 .Set("scripts", ListBuilder().Append("script").Build())
525 .Build());
526 ListBuilder app_handlers_builder;
527 app_handlers_builder.Append(DictionaryBuilder()
528 .Set("action", "new_note")
529 .SetBoolean("enabled_on_lock_screen", true)
530 .Build());
531 extension_ =
532 ExtensionBuilder()
533 .SetManifest(
534 DictionaryBuilder()
535 .Set("name", "Test app")
536 .Set("version", "1.0")
537 .Set("manifest_version", 2)
538 .Set("app", app_builder.Build())
539 .Set("action_handlers", app_handlers_builder.Build())
540 .Set("permissions",
541 ListBuilder().Append("lockScreen").Build())
542 .Build())
543 .Build();
544 ExtensionRegistry::Get(browser_context())->AddEnabled(extension_);
545 }
546
547 // Callback for creating test data items - this is the callback passed to
548 // LockScreenItemStorage via SetItemFactoryForTesting.
549 std::unique_ptr<DataItem> CreateItem(const std::string& id,
550 const std::string& extension_id,
551 const std::string& crypto_key) {
552 EXPECT_EQ(extension()->id(), extension_id);
553 EXPECT_EQ(kTestSymmetricKey, crypto_key);
554
555 // If there is an operation queue for the item id, reuse it in order to
556 // retain state on LockScreenItemStorage restart.
557 OperationQueue* operation_queue = GetOperations(id);
558 if (!operation_queue) {
559 operations_[id] =
560 base::MakeUnique<OperationQueue>(id, item_registry_.get());
561 operation_queue = operations_[id].get();
562 }
563 return base::MakeUnique<TestDataItem>(id, extension_id, crypto_key,
564 operation_queue);
565 }
566
567 void GetRegisteredItems(const std::string& extension_id,
568 const DataItem::RegisteredValuesCallback& callback) {
569 if (extension()->id() != extension_id) {
570 callback.Run(OperationResult::kUnknownExtension, nullptr);
571 return;
572 }
573 item_registry_->HandleGetRequest(callback);
574 }
575
576 void RemoveAllItems(const std::string& extension_id,
577 const base::Closure& callback) {
578 ASSERT_EQ(extension()->id(), extension_id);
579 item_registry_->RemoveAll();
580 callback.Run();
581 }
582
583 std::unique_ptr<LockScreenItemStorage> lock_screen_item_storage_;
584
585 content::TestBrowserContext lock_screen_context_;
586 TestingPrefServiceSimple local_state_;
587
588 base::ScopedTempDir test_dir_;
589
590 sync_preferences::TestingPrefServiceSyncable testing_pref_service_;
591
592 LockScreenItemStorage::ItemFactoryCallback item_factory_;
593 LockScreenItemStorage::RegisteredItemsGetter registered_items_getter_;
594 LockScreenItemStorage::ItemStoreDeleter item_store_deleter_;
595
596 scoped_refptr<const Extension> extension_;
597
598 std::unique_ptr<ItemRegistry> item_registry_;
599 std::map<std::string, std::unique_ptr<OperationQueue>> operations_;
600
601 DISALLOW_COPY_AND_ASSIGN(LockScreenItemStorageTest);
602 };
603
604 } // namespace
605
606 TEST_F(LockScreenItemStorageTest, GetDependingOnSessionState) {
607 // Session state not initialized.
608 EXPECT_FALSE(LockScreenItemStorage::GetIfAllowed(browser_context()));
609 EXPECT_FALSE(LockScreenItemStorage::GetIfAllowed(lock_screen_context()));
610
611 // Locked session.
612 lock_screen_item_storage()->SetSessionLocked(true);
613 EXPECT_FALSE(LockScreenItemStorage::GetIfAllowed(browser_context()));
614 EXPECT_EQ(lock_screen_item_storage(),
615 LockScreenItemStorage::GetIfAllowed(lock_screen_context()));
616
617 lock_screen_item_storage()->SetSessionLocked(false);
618
619 EXPECT_EQ(lock_screen_item_storage(),
620 LockScreenItemStorage::GetIfAllowed(browser_context()));
621 EXPECT_FALSE(LockScreenItemStorage::GetIfAllowed(lock_screen_context()));
622 }
623
624 TEST_F(LockScreenItemStorageTest, SetAndGetContent) {
625 lock_screen_item_storage()->SetSessionLocked(true);
626
627 const DataItem* item = CreateNewItem();
628 ASSERT_TRUE(item);
629
630 std::vector<std::string> all_items;
631 GetAllItems(&all_items);
632 ASSERT_EQ(1u, all_items.size());
633 EXPECT_EQ(item->id(), all_items[0]);
634
635 OperationQueue* item_operations = GetOperations(item->id());
636 ASSERT_TRUE(item_operations);
637 EXPECT_FALSE(item_operations->HasPendingOperations());
638
639 std::vector<char> content = {'f', 'i', 'l', 'e'};
640 OperationResult write_result = OperationResult::kFailed;
641 lock_screen_item_storage()->SetItemContent(
642 extension()->id(), item->id(), content,
643 base::Bind(&RecordWriteResult, &write_result));
644
645 item_operations->CompleteNextOperation(OperationQueue::OperationType::kWrite,
646 OperationResult::kSuccess);
647
648 EXPECT_EQ(OperationResult::kSuccess, write_result);
649 EXPECT_EQ(content, item_operations->content());
650
651 OperationResult read_result = OperationResult::kFailed;
652 std::unique_ptr<std::vector<char>> read_content;
653
654 lock_screen_item_storage()->GetItemContent(
655 extension()->id(), item->id(),
656 base::Bind(&RecordReadResult, &read_result, &read_content));
657
658 item_operations->CompleteNextOperation(OperationQueue::OperationType::kRead,
659 OperationResult::kSuccess);
660 EXPECT_EQ(OperationResult::kSuccess, read_result);
661 EXPECT_EQ(content, *read_content);
662
663 OperationResult delete_result = OperationResult::kFailed;
664 lock_screen_item_storage()->DeleteItem(
665 extension()->id(), item->id(),
666 base::Bind(&RecordWriteResult, &delete_result));
667
668 item_operations->CompleteNextOperation(OperationQueue::OperationType::kDelete,
669 OperationResult::kSuccess);
670 EXPECT_EQ(OperationResult::kSuccess, delete_result);
671 EXPECT_TRUE(item_operations->deleted());
672 }
673
674 TEST_F(LockScreenItemStorageTest, FailToInitializeData) {
675 lock_screen_item_storage()->SetSessionLocked(true);
676
677 const DataItem* item = CreateNewItem();
678 ASSERT_TRUE(item);
679 const std::string item_id = item->id();
680
681 ResetLockScreenItemStorage();
682 item_registry()->set_fail(true);
683
684 OperationResult write_result = OperationResult::kFailed;
685 lock_screen_item_storage()->SetItemContent(
686 extension()->id(), item_id, {'x'},
687 base::Bind(&RecordWriteResult, &write_result));
688 EXPECT_EQ(OperationResult::kNotFound, write_result);
689
690 OperationResult read_result = OperationResult::kFailed;
691 std::unique_ptr<std::vector<char>> read_content;
692 lock_screen_item_storage()->GetItemContent(
693 extension()->id(), item_id,
694 base::Bind(&RecordReadResult, &read_result, &read_content));
695 EXPECT_EQ(OperationResult::kNotFound, read_result);
696
697 OperationResult delete_result = OperationResult::kFailed;
698 lock_screen_item_storage()->DeleteItem(
699 extension()->id(), "non_existen",
700 base::Bind(&RecordWriteResult, &delete_result));
701 EXPECT_EQ(OperationResult::kNotFound, delete_result);
702
703 OperationQueue* operations = GetOperations(item_id);
704 ASSERT_TRUE(operations);
705 EXPECT_FALSE(operations->HasPendingOperations());
706
707 item_registry()->set_fail(false);
708
709 const DataItem* new_item = CreateNewItem();
710 ASSERT_TRUE(new_item);
711
712 write_result = OperationResult::kFailed;
713 lock_screen_item_storage()->SetItemContent(
714 extension()->id(), new_item->id(), {'y'},
715 base::Bind(&RecordWriteResult, &write_result));
716
717 OperationQueue* new_item_operations = GetOperations(new_item->id());
718 ASSERT_TRUE(new_item_operations);
719 new_item_operations->CompleteNextOperation(
720 OperationQueue::OperationType::kWrite, OperationResult::kSuccess);
721 EXPECT_EQ(OperationResult::kSuccess, write_result);
722
723 std::vector<std::string> items;
724 GetAllItems(&items);
725 ASSERT_EQ(1u, items.size());
726 EXPECT_EQ(new_item->id(), items[0]);
727 }
728
729 TEST_F(LockScreenItemStorageTest, RequestsDuringInitialLoad) {
730 lock_screen_item_storage()->SetSessionLocked(true);
731
732 const DataItem* item = CreateNewItem();
733 ASSERT_TRUE(item);
734 const std::string item_id = item->id();
735
736 item_registry()->set_throttle_get(true);
737 ResetLockScreenItemStorage();
738
739 EXPECT_FALSE(item_registry()->HasPendingCallback());
740
741 OperationResult write_result = OperationResult::kFailed;
742 lock_screen_item_storage()->SetItemContent(
743 extension()->id(), item_id, {'x'},
744 base::Bind(&RecordWriteResult, &write_result));
745
746 OperationResult read_result = OperationResult::kFailed;
747 std::unique_ptr<std::vector<char>> read_content;
748 lock_screen_item_storage()->GetItemContent(
749 extension()->id(), item_id,
750 base::Bind(&RecordReadResult, &read_result, &read_content));
751
752 std::vector<std::string> items;
753 lock_screen_item_storage()->GetAllForExtension(
754 extension()->id(), base::Bind(&RecordGetAllItemsResult, &items));
755 EXPECT_TRUE(items.empty());
756
757 OperationResult delete_result = OperationResult::kFailed;
758 lock_screen_item_storage()->DeleteItem(
759 extension()->id(), item_id,
760 base::Bind(&RecordWriteResult, &delete_result));
761
762 OperationQueue* operations = GetOperations(item_id);
763 ASSERT_TRUE(operations);
764 EXPECT_FALSE(operations->HasPendingOperations());
765
766 OperationResult create_result = OperationResult::kFailed;
767 const DataItem* new_item = nullptr;
768 lock_screen_item_storage()->CreateItem(
769 extension()->id(),
770 base::Bind(&RecordCreateResult, &create_result, &new_item));
771 EXPECT_FALSE(new_item);
772
773 EXPECT_TRUE(item_registry()->HasPendingCallback());
774 item_registry()->RunPendingCallback();
775
776 EXPECT_TRUE(operations->HasPendingOperations());
777
778 operations->CompleteNextOperation(OperationQueue::OperationType::kWrite,
779 OperationResult::kSuccess);
780 operations->CompleteNextOperation(OperationQueue::OperationType::kRead,
781 OperationResult::kSuccess);
782 operations->CompleteNextOperation(OperationQueue::OperationType::kDelete,
783 OperationResult::kSuccess);
784
785 EXPECT_EQ(OperationResult::kSuccess, write_result);
786 EXPECT_EQ(OperationResult::kSuccess, read_result);
787 ASSERT_TRUE(read_content);
788 EXPECT_EQ(std::vector<char>({'x'}), *read_content);
789 EXPECT_EQ(OperationResult::kSuccess, delete_result);
790 EXPECT_EQ(OperationResult::kSuccess, create_result);
791
792 EXPECT_TRUE(new_item);
793
794 ASSERT_EQ(1u, items.size());
795 EXPECT_EQ(item_id, items[0]);
796
797 GetAllItems(&items);
798 ASSERT_EQ(1u, items.size());
799 EXPECT_EQ(new_item->id(), items[0]);
800 }
801
802 TEST_F(LockScreenItemStorageTest, HandleNonExistent) {
803 lock_screen_item_storage()->SetSessionLocked(true);
804
805 const DataItem* item = CreateNewItem();
806 ASSERT_TRUE(item);
807
808 std::vector<char> content = {'x'};
809
810 OperationResult write_result = OperationResult::kFailed;
811 lock_screen_item_storage()->SetItemContent(
812 extension()->id(), "non_existent", content,
813 base::Bind(&RecordWriteResult, &write_result));
814 EXPECT_EQ(OperationResult::kNotFound, write_result);
815
816 write_result = OperationResult::kFailed;
817 lock_screen_item_storage()->SetItemContent(
818 "non_existent", item->id(), content,
819 base::Bind(&RecordWriteResult, &write_result));
820 EXPECT_EQ(OperationResult::kNotFound, write_result);
821
822 OperationResult read_result = OperationResult::kFailed;
823 std::unique_ptr<std::vector<char>> read_content;
824 lock_screen_item_storage()->GetItemContent(
825 extension()->id(), "non_existent",
826 base::Bind(&RecordReadResult, &read_result, &read_content));
827 EXPECT_EQ(OperationResult::kNotFound, read_result);
828 read_result = OperationResult::kFailed;
829
830 lock_screen_item_storage()->GetItemContent(
831 "non_existent", item->id(),
832 base::Bind(&RecordReadResult, &read_result, &read_content));
833 EXPECT_EQ(OperationResult::kNotFound, read_result);
834
835 OperationResult delete_result = OperationResult::kFailed;
836 lock_screen_item_storage()->DeleteItem(
837 extension()->id(), "non_existen",
838 base::Bind(&RecordWriteResult, &delete_result));
839 EXPECT_EQ(OperationResult::kNotFound, delete_result);
840
841 delete_result = OperationResult::kFailed;
842 lock_screen_item_storage()->DeleteItem(
843 "non_existent", item->id(),
844 base::Bind(&RecordWriteResult, &delete_result));
845 EXPECT_EQ(OperationResult::kNotFound, delete_result);
846 }
847
848 TEST_F(LockScreenItemStorageTest, HandleFailure) {
849 lock_screen_item_storage()->SetSessionLocked(true);
850
851 const DataItem* item = CreateItemWithContent({'x'});
852 ASSERT_TRUE(item);
853 OperationQueue* operations = GetOperations(item->id());
854 ASSERT_TRUE(operations);
855
856 OperationResult write_result = OperationResult::kFailed;
857 lock_screen_item_storage()->SetItemContent(
858 extension()->id(), item->id(), {'x'},
859 base::Bind(&RecordWriteResult, &write_result));
860 operations->CompleteNextOperation(OperationQueue::OperationType::kWrite,
861 OperationResult::kInvalidKey);
862 EXPECT_EQ(OperationResult::kInvalidKey, write_result);
863
864 OperationResult read_result = OperationResult::kFailed;
865 std::unique_ptr<std::vector<char>> read_content;
866 lock_screen_item_storage()->GetItemContent(
867 extension()->id(), item->id(),
868 base::Bind(&RecordReadResult, &read_result, &read_content));
869 operations->CompleteNextOperation(OperationQueue::OperationType::kRead,
870 OperationResult::kWrongKey);
871 EXPECT_EQ(OperationResult::kWrongKey, read_result);
872 EXPECT_FALSE(read_content);
873
874 EXPECT_FALSE(operations->HasPendingOperations());
875 }
876
877 TEST_F(LockScreenItemStorageTest, DataItemsAvailableEventOnUnlock) {
878 TestEventRouter* event_router = static_cast<TestEventRouter*>(
879 extensions::EventRouterFactory::GetInstance()->SetTestingFactoryAndUse(
880 browser_context(), &TestEventRouterFactoryFunction));
881 ASSERT_TRUE(event_router);
882
883 EXPECT_TRUE(event_router->was_locked_values().empty());
884
885 lock_screen_item_storage()->SetSessionLocked(true);
886 EXPECT_TRUE(event_router->was_locked_values().empty());
887
888 // No event since no data items associated with the app exist.
889 lock_screen_item_storage()->SetSessionLocked(false);
890 EXPECT_TRUE(event_router->was_locked_values().empty());
891
892 lock_screen_item_storage()->SetSessionLocked(true);
893 const DataItem* item = CreateItemWithContent({'f', 'i', 'l', 'e', '1'});
894 const std::string item_id = item->id();
895 EXPECT_TRUE(event_router->was_locked_values().empty());
896
897 // There's an available data item, so unlock should trigger the event.
898 lock_screen_item_storage()->SetSessionLocked(false);
899 EXPECT_EQ(std::vector<bool>({true}), event_router->was_locked_values());
900 event_router->ClearWasLockedValues();
901
902 // Update the item content while the session is unlocked.
903 EXPECT_TRUE(SetItemContent(item_id, {'f', 'i', 'l', 'e', '2'}));
904
905 lock_screen_item_storage()->SetSessionLocked(true);
906
907 // Data item is still around - notify the app it's available.
908 lock_screen_item_storage()->SetSessionLocked(false);
909 EXPECT_EQ(std::vector<bool>({true}), event_router->was_locked_values());
910 event_router->ClearWasLockedValues();
911
912 lock_screen_item_storage()->SetSessionLocked(true);
913
914 EXPECT_TRUE(SetItemContent(item_id, {'f', 'i', 'l', 'e', '3'}));
915
916 lock_screen_item_storage()->SetSessionLocked(false);
917 EXPECT_EQ(std::vector<bool>({true}), event_router->was_locked_values());
918 event_router->ClearWasLockedValues();
919
920 // When the item is deleted, the data item avilable event should stop firing.
921 OperationResult delete_result;
922 lock_screen_item_storage()->DeleteItem(
923 extension()->id(), item_id,
924 base::Bind(&RecordWriteResult, &delete_result));
925 OperationQueue* operations = GetOperations(item_id);
926 ASSERT_TRUE(operations);
927 operations->CompleteNextOperation(OperationQueue::OperationType::kDelete,
928 OperationResult::kSuccess);
929 lock_screen_item_storage()->SetSessionLocked(false);
930 lock_screen_item_storage()->SetSessionLocked(true);
931
932 EXPECT_TRUE(event_router->was_locked_values().empty());
933 }
934
935 TEST_F(LockScreenItemStorageTest,
936 NoDataItemsAvailableEventAfterFailedCreation) {
937 TestEventRouter* event_router = static_cast<TestEventRouter*>(
938 extensions::EventRouterFactory::GetInstance()->SetTestingFactoryAndUse(
939 browser_context(), &TestEventRouterFactoryFunction));
940 ASSERT_TRUE(event_router);
941
942 lock_screen_item_storage()->SetSessionLocked(true);
943
944 item_registry()->set_allow_new(false);
945
946 OperationResult create_result = OperationResult::kFailed;
947 const DataItem* item = nullptr;
948 lock_screen_item_storage()->CreateItem(
949 extension()->id(),
950 base::Bind(&RecordCreateResult, &create_result, &item));
951 EXPECT_EQ(OperationResult::kFailed, create_result);
952
953 lock_screen_item_storage()->SetSessionLocked(false);
954 lock_screen_item_storage()->SetSessionLocked(true);
955 EXPECT_TRUE(event_router->was_locked_values().empty());
956 }
957
958 TEST_F(LockScreenItemStorageTest, DataItemsAvailableEventOnRestart) {
959 TestEventRouter* event_router = static_cast<TestEventRouter*>(
960 extensions::EventRouterFactory::GetInstance()->SetTestingFactoryAndUse(
961 browser_context(), &TestEventRouterFactoryFunction));
962 ASSERT_TRUE(event_router);
963
964 EXPECT_TRUE(event_router->was_locked_values().empty());
965
966 lock_screen_item_storage()->SetSessionLocked(true);
967 EXPECT_TRUE(event_router->was_locked_values().empty());
968
969 const DataItem* item = CreateItemWithContent({'f', 'i', 'l', 'e', '1'});
970 EXPECT_TRUE(event_router->was_locked_values().empty());
971 const std::string item_id = item->id();
972
973 ResetLockScreenItemStorage();
974
975 EXPECT_TRUE(event_router->was_locked_values().empty());
976 lock_screen_item_storage()->SetSessionLocked(false);
977
978 EXPECT_EQ(std::vector<bool>({false}), event_router->was_locked_values());
979 event_router->ClearWasLockedValues();
980
981 // The event should be dispatched on next unlock event, as long as a valid
982 // item exists.
983 ResetLockScreenItemStorage();
984 lock_screen_item_storage()->SetSessionLocked(false);
985
986 EXPECT_EQ(std::vector<bool>({false}), event_router->was_locked_values());
987 event_router->ClearWasLockedValues();
988
989 ResetLockScreenItemStorage();
990
991 OperationResult delete_result = OperationResult::kFailed;
992 lock_screen_item_storage()->DeleteItem(
993 extension()->id(), item_id,
994 base::Bind(&RecordWriteResult, &delete_result));
995 OperationQueue* operations = GetOperations(item_id);
996 ASSERT_TRUE(operations);
997 operations->CompleteNextOperation(OperationQueue::OperationType::kDelete,
998 OperationResult::kSuccess);
999
1000 lock_screen_item_storage()->SetSessionLocked(false);
1001 EXPECT_TRUE(event_router->was_locked_values().empty());
1002 }
1003
1004 TEST_F(LockScreenItemStorageTest, ClearDataOnUninstall) {
1005 const DataItem* item = CreateItemWithContent({'x'});
1006 ASSERT_TRUE(item);
1007
1008 ExtensionRegistry::Get(browser_context())->RemoveEnabled(extension()->id());
1009 ExtensionRegistry::Get(browser_context())
1010 ->TriggerOnUninstalled(extension(), UNINSTALL_REASON_FOR_TESTING);
1011 ExtensionRegistry::Get(browser_context())->AddEnabled(extension());
1012
1013 std::vector<std::string> items;
1014 GetAllItems(&items);
1015 EXPECT_TRUE(items.empty());
1016 }
1017
1018 TEST_F(LockScreenItemStorageTest,
1019 ClearOnUninstallWhileLockScreenItemStorageNotSet) {
1020 TestEventRouter* event_router = static_cast<TestEventRouter*>(
1021 extensions::EventRouterFactory::GetInstance()->SetTestingFactoryAndUse(
1022 browser_context(), &TestEventRouterFactoryFunction));
1023 ASSERT_TRUE(event_router);
1024
1025 const DataItem* item = CreateItemWithContent({'x'});
1026 ASSERT_TRUE(item);
1027
1028 UnsetLockScreenItemStorage();
1029
1030 ExtensionRegistry::Get(browser_context())->RemoveEnabled(extension()->id());
1031 ExtensionRegistry::Get(browser_context())
1032 ->TriggerOnUninstalled(extension(), UNINSTALL_REASON_FOR_TESTING);
1033
1034 ResetLockScreenItemStorage();
1035 ExtensionRegistry::Get(browser_context())->AddEnabled(extension());
1036 lock_screen_item_storage()->SetSessionLocked(false);
1037
1038 std::vector<std::string> items;
1039 GetAllItems(&items);
1040 EXPECT_TRUE(items.empty());
1041
1042 EXPECT_TRUE(event_router->was_locked_values().empty());
1043 }
1044
1045 } // namespace lock_screen_data
1046 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698