Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / notifications / extension_welcome_notification_unittest.cc
index 6f76168..f3952cc 100644 (file)
 #include "base/message_loop/message_loop.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/thread_task_runner_handle.h"
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/user_prefs/pref_registry_syncable.h"
+#include "sync/api/fake_sync_change_processor.h"
 #include "sync/api/sync_error_factory_mock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/message_center/fake_message_center.h"
@@ -27,7 +30,8 @@ class MockMessageCenter : public message_center::FakeMessageCenter {
   MockMessageCenter()
       : add_notification_calls_(0),
         remove_notification_calls_(0),
-        notifications_with_shown_as_popup_(0) {};
+        notifications_with_shown_as_popup_(0) {
+  }
 
   int add_notification_calls() { return add_notification_calls_; }
   int remove_notification_calls() { return remove_notification_calls_; }
@@ -67,19 +71,56 @@ class MockMessageCenter : public message_center::FakeMessageCenter {
   int add_notification_calls_;
   int remove_notification_calls_;
   int notifications_with_shown_as_popup_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockMessageCenter);
 };
 
-class TestSyncProcessor : public syncer::SyncChangeProcessor {
-  virtual syncer::SyncError ProcessSyncChanges(
+class WelcomeNotificationDelegate
+    : public ExtensionWelcomeNotification::Delegate {
+public:
+  WelcomeNotificationDelegate()
+      : start_time_(base::Time::Now()),
+        message_center_(new MockMessageCenter()) {
+  }
+
+  // ExtensionWelcomeNotification::Delegate
+  virtual message_center::MessageCenter* GetMessageCenter() OVERRIDE {
+    return message_center_.get();
+  }
+
+  virtual base::Time GetCurrentTime() OVERRIDE {
+    return start_time_ + elapsed_time_;
+  }
+
+  virtual void PostTask(
       const tracked_objects::Location& from_here,
-      const syncer::SyncChangeList& change_list) OVERRIDE {
-    return syncer::SyncError();
+      const base::Closure& task) OVERRIDE {
+    EXPECT_TRUE(pending_task_.is_null());
+    pending_task_ = task;
+  }
+
+  // WelcomeNotificationDelegate
+  MockMessageCenter* message_center() const { return message_center_.get(); }
+
+  base::Time GetStartTime() const { return start_time_; }
+
+  void SetElapsedTime(base::TimeDelta elapsed_time) {
+    elapsed_time_ = elapsed_time;
   }
 
-  virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type)
-      const OVERRIDE {
-    return syncer::SyncDataList();
+  void RunPendingTask() {
+    base::Closure task_to_run = pending_task_;
+    pending_task_.Reset();
+    task_to_run.Run();
   }
+
+ private:
+  const base::Time start_time_;
+  base::TimeDelta elapsed_time_;
+  scoped_ptr<MockMessageCenter> message_center_;
+  base::Closure pending_task_;
+
+  DISALLOW_COPY_AND_ASSIGN(WelcomeNotificationDelegate);
 };
 
 class ExtensionWelcomeNotificationTest : public testing::Test {
@@ -91,49 +132,74 @@ class ExtensionWelcomeNotificationTest : public testing::Test {
   }
 
   virtual void SetUp() {
-    message_loop_.reset(new base::MessageLoop());
+    task_runner_ = new base::TestSimpleTaskRunner();
+    thread_task_runner_handle_.reset(
+        new base::ThreadTaskRunnerHandle(task_runner_));
     profile_.reset(new TestingProfile());
-    message_center_.reset(new MockMessageCenter());
-    welcome_notification_.reset(new ExtensionWelcomeNotification(
-        kChromeNowExtensionID, profile_.get(), message_center_.get()));
+    delegate_ = new WelcomeNotificationDelegate();
+    welcome_notification_ = ExtensionWelcomeNotification::Create(
+        kChromeNowExtensionID, profile_.get(), delegate_);
   }
 
   virtual void TearDown() {
+    delegate_ = NULL;
     welcome_notification_.reset();
-    message_center_.reset();
     profile_.reset();
-    message_loop_.reset();
+    thread_task_runner_handle_.reset();
+    task_runner_ = NULL;
   }
 
-  void StartPreferenceSyncing() {
-    PrefServiceSyncable::FromProfile(profile())
+  void StartPreferenceSyncing() const {
+    PrefServiceSyncable::FromProfile(profile_.get())
         ->GetSyncableService(syncer::PREFERENCES)
-        ->MergeDataAndStartSyncing(
-              syncer::PREFERENCES,
-              syncer::SyncDataList(),
-              scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessor),
-              scoped_ptr<syncer::SyncErrorFactory>(
-                  new syncer::SyncErrorFactoryMock()));
+        ->MergeDataAndStartSyncing(syncer::PREFERENCES,
+                                   syncer::SyncDataList(),
+                                   scoped_ptr<syncer::SyncChangeProcessor>(
+                                       new syncer::FakeSyncChangeProcessor),
+                                   scoped_ptr<syncer::SyncErrorFactory>(
+                                       new syncer::SyncErrorFactoryMock()));
   }
 
-  void ShowChromeNowNotification() {
+  void ShowChromeNowNotification() const {
     ShowNotification(
         "ChromeNowNotification",
         message_center::NotifierId(message_center::NotifierId::APPLICATION,
                                    kChromeNowExtensionID));
   }
 
-  void ShowRegularNotification() {
+  void ShowRegularNotification() const {
     ShowNotification(
         "RegularNotification",
         message_center::NotifierId(message_center::NotifierId::APPLICATION,
                                    "aaaabbbbccccddddeeeeffffggghhhhi"));
   }
 
-  void FlushMessageLoop() { message_loop_->RunUntilIdle(); }
+  void FlushMessageLoop() { delegate_->RunPendingTask(); }
 
-  TestingProfile* profile() { return profile_.get(); }
-  MockMessageCenter* message_center() { return message_center_.get(); }
+  MockMessageCenter* message_center() const {
+    return delegate_->message_center();
+  }
+  base::TestSimpleTaskRunner* task_runner() const {
+    return task_runner_.get();
+  }
+  base::Time GetStartTime() const {
+    return delegate_->GetStartTime();
+  }
+  void SetElapsedTime(base::TimeDelta elapsed_time) const {
+    delegate_->SetElapsedTime(elapsed_time);
+  }
+  bool GetBooleanPref(const char* path) const {
+    return profile_->GetPrefs()->GetBoolean(path);
+  }
+  void SetBooleanPref(const char* path, bool value) const {
+    profile_->GetPrefs()->SetBoolean(path, value);
+  }
+  int64 GetInt64Pref(const char* path) const {
+    return profile_->GetPrefs()->GetInt64(path);
+  }
+  void SetInt64Pref(const char* path, int64 value) const {
+    profile_->GetPrefs()->SetInt64(path, value);
+  }
 
  private:
   class TestNotificationDelegate : public NotificationDelegate {
@@ -149,7 +215,7 @@ class ExtensionWelcomeNotificationTest : public testing::Test {
 
     virtual std::string id() const OVERRIDE { return id_; }
 
-    virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
+    virtual content::WebContents* GetWebContents() const OVERRIDE {
       return NULL;
     }
 
@@ -162,7 +228,7 @@ class ExtensionWelcomeNotificationTest : public testing::Test {
   };
 
   void ShowNotification(std::string notification_id,
-                        const message_center::NotifierId& notifier_id) {
+                        const message_center::NotifierId& notifier_id) const {
     message_center::RichNotificationData rich_notification_data;
     rich_notification_data.priority = 0;
     Notification notification(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
@@ -179,135 +245,168 @@ class ExtensionWelcomeNotificationTest : public testing::Test {
     welcome_notification_->ShowWelcomeNotificationIfNecessary(notification);
   }
 
+  scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+  scoped_ptr<base::ThreadTaskRunnerHandle> thread_task_runner_handle_;
   scoped_ptr<TestingProfile> profile_;
-  scoped_ptr<MockMessageCenter> message_center_;
+  // Weak Ref owned by welcome_notification_
+  WelcomeNotificationDelegate* delegate_;
   scoped_ptr<ExtensionWelcomeNotification> welcome_notification_;
-  scoped_ptr<base::MessageLoop> message_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionWelcomeNotificationTest);
 };
 
 // Show a regular notification. Expect that WelcomeNotification will
 // not show a welcome notification.
 TEST_F(ExtensionWelcomeNotificationTest, FirstRunShowRegularNotification) {
   StartPreferenceSyncing();
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   ShowRegularNotification();
 
-  EXPECT_TRUE(message_center()->add_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(message_center()->add_notification_calls(), 0);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 }
 
 // Show a Chrome Now notification. Expect that WelcomeNotification will
 // show a welcome notification.
 TEST_F(ExtensionWelcomeNotificationTest, FirstRunChromeNowNotification) {
   StartPreferenceSyncing();
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   ShowChromeNowNotification();
 
-  EXPECT_TRUE(message_center()->add_notification_calls() == 1);
-  EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(message_center()->add_notification_calls(), 1);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 }
 
 // Show a Chrome Now notification that was already shown before.
 TEST_F(ExtensionWelcomeNotificationTest, ShowWelcomeNotificationAgain) {
   StartPreferenceSyncing();
-  profile()->GetPrefs()->SetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  SetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   ShowChromeNowNotification();
 
-  EXPECT_TRUE(message_center()->add_notification_calls() == 1);
-  EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 1);
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(message_center()->add_notification_calls(), 1);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 1);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 }
 
-// Don't show a welcome notification if it was previously dismissed
+// Don't show a welcome notification if it was previously dismissed on another
+// machine that wrote the synced flag.
 TEST_F(ExtensionWelcomeNotificationTest,
        WelcomeNotificationPreviouslyDismissed) {
   StartPreferenceSyncing();
-  profile()->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissed, true);
-  EXPECT_TRUE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  SetBooleanPref(prefs::kWelcomeNotificationDismissed, true);
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   ShowChromeNowNotification();
 
-  EXPECT_TRUE(message_center()->add_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
-  EXPECT_TRUE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(message_center()->add_notification_calls(), 0);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+}
+
+// Don't show a welcome notification if it was previously dismissed on this
+// machine.
+TEST_F(ExtensionWelcomeNotificationTest,
+       WelcomeNotificationPreviouslyDismissedLocal) {
+  StartPreferenceSyncing();
+  SetBooleanPref(prefs::kWelcomeNotificationDismissedLocal, true);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+
+  ShowChromeNowNotification();
+
+  EXPECT_EQ(message_center()->add_notification_calls(), 0);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+}
+
+// Don't show a welcome notification if it was previously dismissed with the
+// local flag and synced flag. This case is possible but rare.
+TEST_F(ExtensionWelcomeNotificationTest,
+       WelcomeNotificationPreviouslyDismissedSyncedAndLocal) {
+  StartPreferenceSyncing();
+  SetBooleanPref(prefs::kWelcomeNotificationDismissed, true);
+  SetBooleanPref(prefs::kWelcomeNotificationDismissedLocal, true);
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+
+  ShowChromeNowNotification();
+
+  EXPECT_EQ(message_center()->add_notification_calls(), 0);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 }
 
 // Show a Chrome Now notification and dismiss it.
 // Expect welcome toast dismissed to be true.
 TEST_F(ExtensionWelcomeNotificationTest, DismissWelcomeNotification) {
   StartPreferenceSyncing();
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   ShowChromeNowNotification();
   message_center()->CloseCurrentNotification();
   FlushMessageLoop();
 
-  EXPECT_TRUE(message_center()->add_notification_calls() == 1);
-  EXPECT_TRUE(message_center()->remove_notification_calls() == 1);
-  EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
-  EXPECT_TRUE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(message_center()->add_notification_calls(), 1);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 1);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 }
 
 // Show a Chrome Now notification and dismiss it via a synced preference change.
 // Expect welcome toast dismissed to be true.
 TEST_F(ExtensionWelcomeNotificationTest, SyncedDismissalWelcomeNotification) {
   StartPreferenceSyncing();
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   ShowChromeNowNotification();
-  profile()->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissed, true);
-
-  EXPECT_TRUE(message_center()->add_notification_calls() == 1);
-  EXPECT_TRUE(message_center()->remove_notification_calls() == 1);
-  EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
-  EXPECT_TRUE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  SetBooleanPref(prefs::kWelcomeNotificationDismissed, true);
+
+  EXPECT_EQ(message_center()->add_notification_calls(), 1);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 1);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 }
 
 // Simulate a delayed preference sync when the welcome notification was
@@ -315,71 +414,135 @@ TEST_F(ExtensionWelcomeNotificationTest, SyncedDismissalWelcomeNotification) {
 TEST_F(ExtensionWelcomeNotificationTest,
        DelayedPreferenceSyncPreviouslyDismissed) {
   // Show a notification while the preference system is not syncing.
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   ShowChromeNowNotification();
 
-  EXPECT_TRUE(message_center()->add_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(message_center()->add_notification_calls(), 0);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   // Now start the preference syncing with a previously dismissed welcome.
-  profile()->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissed, true);
-  EXPECT_TRUE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  SetBooleanPref(prefs::kWelcomeNotificationDismissed, true);
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   StartPreferenceSyncing();
 
-  EXPECT_TRUE(message_center()->add_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
-  EXPECT_TRUE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(message_center()->add_notification_calls(), 0);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 }
 
 // Simulate a delayed preference sync when the welcome notification was
 // never shown.
 TEST_F(ExtensionWelcomeNotificationTest, DelayedPreferenceSyncNeverShown) {
   // Show a notification while the preference system is not syncing.
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   ShowChromeNowNotification();
 
-  EXPECT_TRUE(message_center()->add_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(message_center()->add_notification_calls(), 0);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
 
   // Now start the preference syncing with the default preference values.
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+
+  StartPreferenceSyncing();
+
+  EXPECT_EQ(message_center()->add_notification_calls(), 1);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+}
+
+// Simulate the passage of time when the welcome notification
+// automatically dismisses.
+TEST_F(ExtensionWelcomeNotificationTest, TimeExpiredNotification) {
+  StartPreferenceSyncing();
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(GetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp), 0);
+  EXPECT_TRUE(task_runner()->GetPendingTasks().empty());
+
+  ShowChromeNowNotification();
 
+  base::TimeDelta requested_show_time =
+      base::TimeDelta::FromDays(
+          ExtensionWelcomeNotification::kRequestedShowTimeDays);
+
+  EXPECT_EQ(task_runner()->GetPendingTasks().size(), 1U);
+  EXPECT_EQ(task_runner()->NextPendingTaskDelay(), requested_show_time);
+
+  EXPECT_EQ(message_center()->add_notification_calls(), 1);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(
+      GetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp),
+      (GetStartTime() + requested_show_time).ToInternalValue());
+
+  SetElapsedTime(requested_show_time);
+  task_runner()->RunPendingTasks();
+
+  EXPECT_TRUE(task_runner()->GetPendingTasks().empty());
+  EXPECT_EQ(message_center()->add_notification_calls(), 1);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 1);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(
+      GetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp),
+      (GetStartTime() + requested_show_time).ToInternalValue());
+}
+
+// Simulate the passage of time after Chrome is closed and the welcome
+// notification expiration elapses.
+TEST_F(ExtensionWelcomeNotificationTest, NotificationPreviouslyExpired) {
   StartPreferenceSyncing();
+  SetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
+  SetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp, 1);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(GetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp), 1);
+  EXPECT_TRUE(task_runner()->GetPendingTasks().empty());
+
+  const base::TimeDelta requested_show_time =
+      base::TimeDelta::FromDays(
+          ExtensionWelcomeNotification::kRequestedShowTimeDays);
+  SetElapsedTime(requested_show_time);
+  ShowChromeNowNotification();
 
-  EXPECT_TRUE(message_center()->add_notification_calls() == 1);
-  EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
-  EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
-  EXPECT_FALSE(
-      profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
-  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
-      prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_TRUE(task_runner()->GetPendingTasks().empty());
+  EXPECT_EQ(message_center()->add_notification_calls(), 0);
+  EXPECT_EQ(message_center()->remove_notification_calls(), 0);
+  EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
+  EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissedLocal));
+  EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
+  EXPECT_EQ(GetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp), 1);
 }