1 // Copyright 2014 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 "base/bind.h" 6 #include "base/callback.h" 7 #include "base/memory/weak_ptr.h" 8 #include "base/run_loop.h" 9 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/sync/glue/local_device_info_provider_mock.h" 11 #include "chrome/browser/sync/glue/synced_window_delegate.h" 12 #include "chrome/browser/sync/profile_sync_components_factory_mock.h" 13 #include "chrome/browser/sync/sessions/session_data_type_controller.h" 14 #include "chrome/browser/sync/sessions/synced_window_delegates_getter.h" 15 #include "chrome/test/base/testing_profile.h" 16 #include "content/public/browser/notification_service.h" 17 #include "content/public/test/test_browser_thread_bundle.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 20 namespace browser_sync { 21 22 namespace { 23 24 class MockSyncedWindowDelegate : public SyncedWindowDelegate { 25 public: 26 explicit MockSyncedWindowDelegate(Profile* profile) 27 : is_restore_in_progress_(false), 28 profile_(profile) {} 29 virtual ~MockSyncedWindowDelegate() {} 30 31 virtual bool HasWindow() const OVERRIDE { return false; } 32 virtual SessionID::id_type GetSessionId() const OVERRIDE { return 0; } 33 virtual int GetTabCount() const OVERRIDE { return 0; } 34 virtual int GetActiveIndex() const OVERRIDE { return 0; } 35 virtual bool IsApp() const OVERRIDE { return false; } 36 virtual bool IsTypeTabbed() const OVERRIDE { return false; } 37 virtual bool IsTypePopup() const OVERRIDE { return false; } 38 virtual bool IsTabPinned(const SyncedTabDelegate* tab) const OVERRIDE { 39 return false; 40 } 41 virtual SyncedTabDelegate* GetTabAt(int index) const OVERRIDE { return NULL; } 42 virtual SessionID::id_type GetTabIdAt(int index) const OVERRIDE { return 0; } 43 44 virtual bool IsSessionRestoreInProgress() const OVERRIDE { 45 return is_restore_in_progress_; 46 } 47 48 void SetSessionRestoreInProgress(bool is_restore_in_progress) { 49 is_restore_in_progress_ = is_restore_in_progress; 50 51 if (!is_restore_in_progress_) { 52 content::NotificationService::current()->Notify( 53 chrome::NOTIFICATION_SESSION_RESTORE_COMPLETE, 54 content::Source<Profile>(profile_), 55 content::NotificationService::NoDetails()); 56 } 57 } 58 59 private: 60 bool is_restore_in_progress_; 61 Profile* profile_; 62 }; 63 64 class MockSyncedWindowDelegatesGetter : public SyncedWindowDelegatesGetter { 65 public: 66 virtual const std::set<SyncedWindowDelegate*> 67 GetSyncedWindowDelegates() OVERRIDE { 68 return delegates_; 69 } 70 71 void Add(SyncedWindowDelegate* delegate) { 72 delegates_.insert(delegate); 73 } 74 75 private: 76 std::set<SyncedWindowDelegate*> delegates_; 77 }; 78 79 class SessionDataTypeControllerTest 80 : public testing::Test { 81 public: 82 SessionDataTypeControllerTest() 83 : load_finished_(false), 84 thread_bundle_(content::TestBrowserThreadBundle::DEFAULT), 85 weak_ptr_factory_(this), 86 last_type_(syncer::UNSPECIFIED) {} 87 virtual ~SessionDataTypeControllerTest() {} 88 89 virtual void SetUp() OVERRIDE { 90 synced_window_delegate_.reset(new MockSyncedWindowDelegate(&profile_)); 91 synced_window_getter_.reset(new MockSyncedWindowDelegatesGetter()); 92 synced_window_getter_->Add(synced_window_delegate_.get()); 93 94 local_device_.reset(new LocalDeviceInfoProviderMock( 95 "cache_guid", 96 "Wayne Gretzky's Hacking Box", 97 "Chromium 10k", 98 "Chrome 10k", 99 sync_pb::SyncEnums_DeviceType_TYPE_LINUX, 100 "device_id")); 101 102 controller_ = new SessionDataTypeController( 103 &profile_sync_factory_, 104 &profile_, 105 synced_window_getter_.get(), 106 local_device_.get()); 107 108 load_finished_ = false; 109 last_type_ = syncer::UNSPECIFIED; 110 last_error_ = syncer::SyncError(); 111 } 112 113 virtual void TearDown() OVERRIDE { 114 controller_ = NULL; 115 local_device_.reset(); 116 synced_window_getter_.reset(); 117 synced_window_delegate_.reset(); 118 } 119 120 void Start() { 121 controller_->LoadModels( 122 base::Bind(&SessionDataTypeControllerTest::OnLoadFinished, 123 weak_ptr_factory_.GetWeakPtr())); 124 } 125 126 void OnLoadFinished(syncer::ModelType type, syncer::SyncError error) { 127 load_finished_ = true; 128 last_type_ = type; 129 last_error_ = error; 130 } 131 132 testing::AssertionResult LoadResult() { 133 if (!load_finished_) { 134 return testing::AssertionFailure() << 135 "OnLoadFinished wasn't called"; 136 } 137 138 if (last_error_.IsSet()) { 139 return testing::AssertionFailure() << 140 "OnLoadFinished was called with a SyncError: " << 141 last_error_.ToString(); 142 } 143 144 if (last_type_ != syncer::SESSIONS) { 145 return testing::AssertionFailure() << 146 "OnLoadFinished was called with a wrong sync type: " << 147 last_type_; 148 } 149 150 return testing::AssertionSuccess(); 151 } 152 153 protected: 154 scoped_refptr<SessionDataTypeController> controller_; 155 scoped_ptr<MockSyncedWindowDelegatesGetter> synced_window_getter_; 156 scoped_ptr<LocalDeviceInfoProviderMock> local_device_; 157 scoped_ptr<MockSyncedWindowDelegate> synced_window_delegate_; 158 bool load_finished_; 159 160 private: 161 content::TestBrowserThreadBundle thread_bundle_; 162 ProfileSyncComponentsFactoryMock profile_sync_factory_; 163 TestingProfile profile_; 164 base::WeakPtrFactory<SessionDataTypeControllerTest> weak_ptr_factory_; 165 syncer::ModelType last_type_; 166 syncer::SyncError last_error_; 167 }; 168 169 TEST_F(SessionDataTypeControllerTest, StartModels) { 170 Start(); 171 EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, 172 controller_->state()); 173 EXPECT_TRUE(LoadResult()); 174 } 175 176 TEST_F(SessionDataTypeControllerTest, StartModelsDelayedByLocalDevice) { 177 local_device_->SetInitialized(false); 178 Start(); 179 EXPECT_FALSE(load_finished_); 180 EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, 181 controller_->state()); 182 183 local_device_->SetInitialized(true); 184 EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, 185 controller_->state()); 186 EXPECT_TRUE(LoadResult()); 187 } 188 189 TEST_F(SessionDataTypeControllerTest, StartModelsDelayedByRestoreInProgress) { 190 synced_window_delegate_->SetSessionRestoreInProgress(true); 191 Start(); 192 EXPECT_FALSE(load_finished_); 193 EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, 194 controller_->state()); 195 196 synced_window_delegate_->SetSessionRestoreInProgress(false); 197 EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, 198 controller_->state()); 199 EXPECT_TRUE(LoadResult()); 200 } 201 202 TEST_F(SessionDataTypeControllerTest, 203 StartModelsDelayedByLocalDeviceThenRestoreInProgress) { 204 local_device_->SetInitialized(false); 205 synced_window_delegate_->SetSessionRestoreInProgress(true); 206 Start(); 207 EXPECT_FALSE(load_finished_); 208 EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, 209 controller_->state()); 210 211 local_device_->SetInitialized(true); 212 EXPECT_FALSE(load_finished_); 213 EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, 214 controller_->state()); 215 216 synced_window_delegate_->SetSessionRestoreInProgress(false); 217 EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, 218 controller_->state()); 219 EXPECT_TRUE(LoadResult()); 220 } 221 222 TEST_F(SessionDataTypeControllerTest, 223 StartModelsDelayedByRestoreInProgressThenLocalDevice) { 224 local_device_->SetInitialized(false); 225 synced_window_delegate_->SetSessionRestoreInProgress(true); 226 Start(); 227 EXPECT_FALSE(load_finished_); 228 EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, 229 controller_->state()); 230 231 synced_window_delegate_->SetSessionRestoreInProgress(false); 232 EXPECT_FALSE(load_finished_); 233 EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, 234 controller_->state()); 235 236 local_device_->SetInitialized(true); 237 EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, 238 controller_->state()); 239 EXPECT_TRUE(LoadResult()); 240 } 241 242 } // namespace 243 244 } // namespace browser_sync 245