Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / content / browser / notifications / platform_notification_context_unittest.cc
blob6dca0d0534ce71211f730266881a624542858f75
1 // Copyright 2015 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.
5 #include "base/bind.h"
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/run_loop.h"
9 #include "content/browser/notifications/platform_notification_context_impl.h"
10 #include "content/browser/service_worker/embedded_worker_test_helper.h"
11 #include "content/browser/service_worker/service_worker_context_wrapper.h"
12 #include "content/common/service_worker/service_worker_types.h"
13 #include "content/public/browser/notification_database_data.h"
14 #include "content/public/test/test_browser_thread_bundle.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "url/gurl.h"
18 namespace content {
20 // Fake render process id to use in tests requiring one.
21 const int kFakeRenderProcessId = 99;
23 // Fake Service Worker registration id to use in tests requiring one.
24 const int64_t kFakeServiceWorkerRegistrationId = 42;
26 class PlatformNotificationContextTest : public ::testing::Test {
27 public:
28 PlatformNotificationContextTest()
29 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
30 success_(false) {}
32 // Callback to provide when reading a single notification from the database.
33 void DidReadNotificationData(
34 bool success, const NotificationDatabaseData& database_data) {
35 success_ = success;
36 database_data_ = database_data;
39 // Callback to provide when writing a notification to the database.
40 void DidWriteNotificationData(bool success, int64_t notification_id) {
41 success_ = success;
42 notification_id_ = notification_id;
45 // Callback to provide when deleting notification data from the database.
46 void DidDeleteNotificationData(bool success) {
47 success_ = success;
50 // Callback to provide when registering a Service Worker with a Service
51 // Worker Context. Will write the registration id to |store_registration_id|.
52 void DidRegisterServiceWorker(int64_t* store_registration_id,
53 ServiceWorkerStatusCode status,
54 const std::string& status_message,
55 int64_t service_worker_registration_id) {
56 DCHECK(store_registration_id);
57 EXPECT_EQ(SERVICE_WORKER_OK, status);
59 *store_registration_id = service_worker_registration_id;
62 // Callback to provide when unregistering a Service Worker. Will write the
63 // resulting status code to |store_status|.
64 void DidUnregisterServiceWorker(ServiceWorkerStatusCode* store_status,
65 ServiceWorkerStatusCode status) {
66 DCHECK(store_status);
67 *store_status = status;
70 // Callback to provide when reading multiple notifications from the database.
71 // Will store the success value in the class member, and write the read
72 // notification datas to |store_notification_datas|.
73 void DidReadAllNotificationDatas(
74 std::vector<NotificationDatabaseData>* store_notification_datas,
75 bool success,
76 const std::vector<NotificationDatabaseData>& notification_datas) {
77 DCHECK(store_notification_datas);
79 success_ = success;
80 *store_notification_datas = notification_datas;
83 protected:
84 // Creates a new PlatformNotificationContextImpl instance. When using this
85 // method, the underlying database will always be created in memory. The
86 // current message loop proxy will be used as the task runner.
87 PlatformNotificationContextImpl* CreatePlatformNotificationContext() {
88 PlatformNotificationContextImpl* context =
89 new PlatformNotificationContextImpl(base::FilePath(), nullptr);
90 context->Initialize();
92 OverrideTaskRunnerForTesting(context);
93 return context;
96 // Overrides the task runner in |context| with the current message loop
97 // proxy, to reduce the number of threads involved in the tests.
98 void OverrideTaskRunnerForTesting(PlatformNotificationContextImpl* context) {
99 context->SetTaskRunnerForTesting(base::MessageLoopProxy::current());
102 // Returns whether the last invoked callback finished successfully.
103 bool success() const { return success_; }
105 // Returns the NotificationDatabaseData associated with the last invoked
106 // ReadNotificationData callback.
107 const NotificationDatabaseData& database_data() const {
108 return database_data_;
111 // Returns the notification id of the notification last written.
112 int64_t notification_id() const { return notification_id_; }
114 private:
115 TestBrowserThreadBundle thread_bundle_;
117 bool success_;
118 NotificationDatabaseData database_data_;
119 int64_t notification_id_;
122 TEST_F(PlatformNotificationContextTest, ReadNonExistentNotification) {
123 scoped_refptr<PlatformNotificationContextImpl> context =
124 CreatePlatformNotificationContext();
126 context->ReadNotificationData(
127 42 /* notification_id */,
128 GURL("https://example.com"),
129 base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
130 base::Unretained(this)));
132 base::RunLoop().RunUntilIdle();
134 // The read operation should have failed, as it does not exist.
135 ASSERT_FALSE(success());
138 TEST_F(PlatformNotificationContextTest, WriteReadNotification) {
139 scoped_refptr<PlatformNotificationContextImpl> context =
140 CreatePlatformNotificationContext();
142 GURL origin("https://example.com");
143 NotificationDatabaseData notification_database_data;
144 notification_database_data.origin = origin;
146 context->WriteNotificationData(
147 origin,
148 notification_database_data,
149 base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
150 base::Unretained(this)));
152 base::RunLoop().RunUntilIdle();
154 // The write operation should have succeeded with a notification id.
155 ASSERT_TRUE(success());
156 EXPECT_GT(notification_id(), 0);
158 context->ReadNotificationData(
159 notification_id(),
160 origin,
161 base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
162 base::Unretained(this)));
164 base::RunLoop().RunUntilIdle();
166 // The read operation should have succeeded, with the right notification.
167 ASSERT_TRUE(success());
169 const NotificationDatabaseData& read_database_data = database_data();
170 EXPECT_EQ(notification_database_data.origin, read_database_data.origin);
173 TEST_F(PlatformNotificationContextTest, DeleteInvalidNotification) {
174 scoped_refptr<PlatformNotificationContextImpl> context =
175 CreatePlatformNotificationContext();
177 context->DeleteNotificationData(
178 42 /* notification_id */,
179 GURL("https://example.com"),
180 base::Bind(&PlatformNotificationContextTest::DidDeleteNotificationData,
181 base::Unretained(this)));
183 base::RunLoop().RunUntilIdle();
185 // The notification may not have existed, but since the goal of deleting data
186 // is to make sure that it's gone, the goal has been satisfied. As such,
187 // deleting a non-existent notification is considered to be a success.
188 EXPECT_TRUE(success());
191 TEST_F(PlatformNotificationContextTest, DeleteNotification) {
192 scoped_refptr<PlatformNotificationContextImpl> context =
193 CreatePlatformNotificationContext();
195 GURL origin("https://example.com");
196 NotificationDatabaseData notification_database_data;
198 context->WriteNotificationData(
199 origin,
200 notification_database_data,
201 base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
202 base::Unretained(this)));
204 base::RunLoop().RunUntilIdle();
206 // The write operation should have succeeded with a notification id.
207 ASSERT_TRUE(success());
208 EXPECT_GT(notification_id(), 0);
210 context->DeleteNotificationData(
211 notification_id(),
212 origin,
213 base::Bind(&PlatformNotificationContextTest::DidDeleteNotificationData,
214 base::Unretained(this)));
216 base::RunLoop().RunUntilIdle();
218 // The notification existed, so it should have been removed successfully.
219 ASSERT_TRUE(success());
221 context->ReadNotificationData(
222 notification_id(),
223 origin,
224 base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
225 base::Unretained(this)));
227 base::RunLoop().RunUntilIdle();
229 // The notification was removed, so we shouldn't be able to read it from
230 // the database anymore.
231 EXPECT_FALSE(success());
234 TEST_F(PlatformNotificationContextTest, ServiceWorkerUnregistered) {
235 scoped_ptr<EmbeddedWorkerTestHelper> embedded_worker_test_helper(
236 new EmbeddedWorkerTestHelper(base::FilePath(), kFakeRenderProcessId));
238 // Manually create the PlatformNotificationContextImpl so that the Service
239 // Worker context wrapper can be passed in.
240 scoped_refptr<PlatformNotificationContextImpl> notification_context(
241 new PlatformNotificationContextImpl(
242 base::FilePath(),
243 embedded_worker_test_helper->context_wrapper()));
244 notification_context->Initialize();
246 OverrideTaskRunnerForTesting(notification_context.get());
248 GURL origin("https://example.com");
249 GURL script_url("https://example.com/worker.js");
251 int64_t service_worker_registration_id = kInvalidServiceWorkerRegistrationId;
253 // Register a Service Worker to get a valid registration id.
254 embedded_worker_test_helper->context()->RegisterServiceWorker(
255 origin,
256 script_url,
257 nullptr /* provider_host */,
258 base::Bind(&PlatformNotificationContextTest::DidRegisterServiceWorker,
259 base::Unretained(this), &service_worker_registration_id));
261 base::RunLoop().RunUntilIdle();
262 ASSERT_NE(service_worker_registration_id,
263 kInvalidServiceWorkerRegistrationId);
265 NotificationDatabaseData notification_database_data;
267 // Create a notification for that Service Worker registration.
268 notification_context->WriteNotificationData(
269 origin,
270 notification_database_data,
271 base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
272 base::Unretained(this)));
274 base::RunLoop().RunUntilIdle();
276 ASSERT_TRUE(success());
277 EXPECT_GT(notification_id(), 0);
279 ServiceWorkerStatusCode unregister_status;
281 // Now drop the Service Worker registration which owns that notification.
282 embedded_worker_test_helper->context()->UnregisterServiceWorker(
283 origin,
284 base::Bind(&PlatformNotificationContextTest::DidUnregisterServiceWorker,
285 base::Unretained(this), &unregister_status));
287 base::RunLoop().RunUntilIdle();
288 ASSERT_EQ(SERVICE_WORKER_OK, unregister_status);
290 // And verify that the associated notification has indeed been dropped.
291 notification_context->ReadNotificationData(
292 notification_id(),
293 origin,
294 base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
295 base::Unretained(this)));
297 base::RunLoop().RunUntilIdle();
299 EXPECT_FALSE(success());
302 TEST_F(PlatformNotificationContextTest, DestroyDatabaseOnStorageWiped) {
303 scoped_refptr<PlatformNotificationContextImpl> context =
304 CreatePlatformNotificationContext();
306 GURL origin("https://example.com");
307 NotificationDatabaseData notification_database_data;
309 context->WriteNotificationData(
310 origin,
311 notification_database_data,
312 base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
313 base::Unretained(this)));
315 base::RunLoop().RunUntilIdle();
317 // The write operation should have succeeded with a notification id.
318 ASSERT_TRUE(success());
319 EXPECT_GT(notification_id(), 0);
321 // Call the OnStorageWiped override from the ServiceWorkerContextObserver,
322 // which indicates that the database should go away entirely.
323 context->OnStorageWiped();
325 // Verify that reading notification data fails because the data does not
326 // exist anymore. Deliberately omit RunUntilIdle(), since this is unlikely to
327 // be the case when OnStorageWiped gets called in production.
328 context->ReadNotificationData(
329 notification_id(),
330 origin,
331 base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
332 base::Unretained(this)));
334 base::RunLoop().RunUntilIdle();
336 EXPECT_FALSE(success());
339 TEST_F(PlatformNotificationContextTest, DestroyOnDiskDatabase) {
340 base::ScopedTempDir database_dir;
341 ASSERT_TRUE(database_dir.CreateUniqueTempDir());
343 // Manually construct the PlatformNotificationContextImpl because this test
344 // requires the database to be created on the filesystem.
345 scoped_refptr<PlatformNotificationContextImpl> context(
346 new PlatformNotificationContextImpl(database_dir.path(), nullptr));
348 OverrideTaskRunnerForTesting(context.get());
350 // Trigger a read-operation to force creating the database.
351 context->ReadNotificationData(
352 42 /* notification_id */,
353 GURL("https://example.com"),
354 base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
355 base::Unretained(this)));
357 base::RunLoop().RunUntilIdle();
359 EXPECT_FALSE(IsDirectoryEmpty(database_dir.path()));
360 EXPECT_FALSE(success());
362 // Blow away the database by faking a Service Worker Context wipe-out.
363 context->OnStorageWiped();
365 base::RunLoop().RunUntilIdle();
367 // The database's directory should be empty at this point.
368 EXPECT_TRUE(IsDirectoryEmpty(database_dir.path()));
371 TEST_F(PlatformNotificationContextTest, ReadAllServiceWorkerDataEmpty) {
372 scoped_refptr<PlatformNotificationContextImpl> context =
373 CreatePlatformNotificationContext();
375 GURL origin("https://example.com");
377 std::vector<NotificationDatabaseData> notification_database_datas;
378 context->ReadAllNotificationDataForServiceWorkerRegistration(
379 origin,
380 kFakeServiceWorkerRegistrationId,
381 base::Bind(&PlatformNotificationContextTest::DidReadAllNotificationDatas,
382 base::Unretained(this),
383 &notification_database_datas));
385 base::RunLoop().RunUntilIdle();
387 EXPECT_TRUE(success());
388 EXPECT_EQ(0u, notification_database_datas.size());
391 TEST_F(PlatformNotificationContextTest, ReadAllServiceWorkerDataFilled) {
392 scoped_refptr<PlatformNotificationContextImpl> context =
393 CreatePlatformNotificationContext();
395 GURL origin("https://example.com");
397 NotificationDatabaseData notification_database_data;
398 notification_database_data.origin = origin;
399 notification_database_data.service_worker_registration_id =
400 kFakeServiceWorkerRegistrationId;
402 // Insert ten notifications into the database belonging to origin and the
403 // test Service Worker Registration id.
404 for (int i = 0; i < 10; ++i) {
405 context->WriteNotificationData(
406 origin,
407 notification_database_data,
408 base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
409 base::Unretained(this)));
411 base::RunLoop().RunUntilIdle();
413 ASSERT_TRUE(success());
416 // Now read the notifications from the database again. There should be ten,
417 // all set with the correct origin and Service Worker Registration id.
418 std::vector<NotificationDatabaseData> notification_database_datas;
419 context->ReadAllNotificationDataForServiceWorkerRegistration(
420 origin,
421 kFakeServiceWorkerRegistrationId,
422 base::Bind(&PlatformNotificationContextTest::DidReadAllNotificationDatas,
423 base::Unretained(this),
424 &notification_database_datas));
426 base::RunLoop().RunUntilIdle();
428 ASSERT_TRUE(success());
429 ASSERT_EQ(10u, notification_database_datas.size());
431 for (int i = 0; i < 10; ++i) {
432 EXPECT_EQ(origin, notification_database_datas[i].origin);
433 EXPECT_EQ(kFakeServiceWorkerRegistrationId,
434 notification_database_datas[i].service_worker_registration_id);
438 } // namespace content