template_url_service_test_util.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright (c) 2012 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 "chrome/browser/search_engines/template_url_service_test_util.h" 6 7#include "base/bind.h" 8#include "base/message_loop.h" 9#include "base/path_service.h" 10#include "base/synchronization/waitable_event.h" 11#include "base/threading/thread.h" 12#include "chrome/browser/google/google_url_tracker.h" 13#include "chrome/browser/search_engines/search_terms_data.h" 14#include "chrome/browser/search_engines/template_url_service.h" 15#include "chrome/browser/search_engines/template_url_service_factory.h" 16#include "chrome/browser/webdata/web_data_service_factory.h" 17#include "chrome/common/chrome_notification_types.h" 18#include "chrome/common/pref_names.h" 19#include "chrome/test/automation/value_conversion_util.h" 20#include "chrome/test/base/testing_pref_service_syncable.h" 21#include "chrome/test/base/testing_profile.h" 22#include "content/public/browser/notification_service.h" 23#include "content/public/test/test_browser_thread.h" 24#include "testing/gtest/include/gtest/gtest.h" 25 26 27#if defined(OS_CHROMEOS) 28#include "chrome/browser/google/google_util_chromeos.h" 29#endif 30 31using content::BrowserThread; 32 33namespace { 34 35// A callback used to coordinate when the database has finished processing 36// requests. See note in BlockTillServiceProcessesRequests for details. 37// 38// Schedules a QuitClosure on the message loop it was created with. 39void QuitCallback(MessageLoop* message_loop) { 40 message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); 41} 42 43// Blocks the caller until thread has finished servicing all pending 44// requests. 45static void WaitForThreadToProcessRequests(BrowserThread::ID identifier) { 46 // Schedule a task on the thread that is processed after all 47 // pending requests on the thread. 48 BrowserThread::PostTask(identifier, FROM_HERE, 49 base::Bind(&QuitCallback, MessageLoop::current())); 50 MessageLoop::current()->Run(); 51} 52 53} // namespace 54 55// Trivial subclass of TemplateURLService that records the last invocation of 56// SetKeywordSearchTermsForURL. 57class TestingTemplateURLService : public TemplateURLService { 58 public: 59 static ProfileKeyedService* Build(content::BrowserContext* profile) { 60 return new TestingTemplateURLService(static_cast<Profile*>(profile)); 61 } 62 63 explicit TestingTemplateURLService(Profile* profile) 64 : TemplateURLService(profile) { 65 } 66 67 string16 GetAndClearSearchTerm() { 68 string16 search_term; 69 search_term.swap(search_term_); 70 return search_term; 71 } 72 73 protected: 74 virtual void SetKeywordSearchTermsForURL(const TemplateURL* t_url, 75 const GURL& url, 76 const string16& term) OVERRIDE { 77 search_term_ = term; 78 } 79 80 private: 81 string16 search_term_; 82 83 DISALLOW_COPY_AND_ASSIGN(TestingTemplateURLService); 84}; 85 86TemplateURLServiceTestUtil::TemplateURLServiceTestUtil() 87 : ui_thread_(BrowserThread::UI, &message_loop_), 88 db_thread_(BrowserThread::DB), 89 io_thread_(BrowserThread::IO), 90 changed_count_(0) { 91} 92 93TemplateURLServiceTestUtil::~TemplateURLServiceTestUtil() { 94} 95 96void TemplateURLServiceTestUtil::SetUp() { 97 // Make unique temp directory. 98 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 99 profile_.reset(new TestingProfile(temp_dir_.path())); 100 db_thread_.Start(); 101 profile_->CreateWebDataService(); 102 103 TemplateURLService* service = static_cast<TemplateURLService*>( 104 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( 105 profile_.get(), TestingTemplateURLService::Build)); 106 service->AddObserver(this); 107 108#if defined(OS_CHROMEOS) 109 google_util::chromeos::ClearBrandForCurrentSession(); 110#endif 111} 112 113void TemplateURLServiceTestUtil::TearDown() { 114 if (profile_.get()) { 115 // Clear the request context so it will get deleted. This should be done 116 // before shutting down the I/O thread to avoid memory leaks. 117 profile_->ResetRequestContext(); 118 profile_.reset(); 119 } 120 121 // Wait for the delete of the request context to happen. 122 if (io_thread_.IsRunning()) 123 TemplateURLServiceTestUtil::BlockTillIOThreadProcessesRequests(); 124 125 // The I/O thread must be shutdown before the DB thread. 126 io_thread_.Stop(); 127 128 // Note that we must ensure the DB thread is stopped after WDS 129 // shutdown (so it can commit pending transactions) but before 130 // deleting the test profile directory, otherwise we may not be 131 // able to delete it due to an open transaction. 132 // Schedule another task on the DB thread to notify us that it's safe to 133 // carry on with the test. 134 base::WaitableEvent done(false, false); 135 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 136 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done))); 137 done.Wait(); 138 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); 139 MessageLoop::current()->Run(); 140 db_thread_.Stop(); 141 142 UIThreadSearchTermsData::SetGoogleBaseURL(std::string()); 143 144 // Flush the message loop to make application verifiers happy. 145 message_loop_.RunUntilIdle(); 146} 147 148void TemplateURLServiceTestUtil::OnTemplateURLServiceChanged() { 149 changed_count_++; 150} 151 152int TemplateURLServiceTestUtil::GetObserverCount() { 153 return changed_count_; 154} 155 156void TemplateURLServiceTestUtil::ResetObserverCount() { 157 changed_count_ = 0; 158} 159 160void TemplateURLServiceTestUtil::BlockTillServiceProcessesRequests() { 161 WaitForThreadToProcessRequests(BrowserThread::DB); 162} 163 164void TemplateURLServiceTestUtil::BlockTillIOThreadProcessesRequests() { 165 WaitForThreadToProcessRequests(BrowserThread::IO); 166} 167 168void TemplateURLServiceTestUtil::VerifyLoad() { 169 ASSERT_FALSE(model()->loaded()); 170 model()->Load(); 171 BlockTillServiceProcessesRequests(); 172 EXPECT_EQ(1, GetObserverCount()); 173 ResetObserverCount(); 174} 175 176void TemplateURLServiceTestUtil::ChangeModelToLoadState() { 177 model()->ChangeToLoadedState(); 178 // Initialize the web data service so that the database gets updated with 179 // any changes made. 180 181 model()->service_ = WebDataService::FromBrowserContext(profile_.get()); 182 BlockTillServiceProcessesRequests(); 183} 184 185void TemplateURLServiceTestUtil::ClearModel() { 186 TemplateURLServiceFactory::GetInstance()->SetTestingFactory( 187 profile_.get(), NULL); 188} 189 190void TemplateURLServiceTestUtil::ResetModel(bool verify_load) { 191 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( 192 profile_.get(), TestingTemplateURLService::Build); 193 model()->AddObserver(this); 194 changed_count_ = 0; 195 if (verify_load) 196 VerifyLoad(); 197} 198 199string16 TemplateURLServiceTestUtil::GetAndClearSearchTerm() { 200 return 201 static_cast<TestingTemplateURLService*>(model())->GetAndClearSearchTerm(); 202} 203 204void TemplateURLServiceTestUtil::SetGoogleBaseURL(const GURL& base_url) const { 205 DCHECK(base_url.is_valid()); 206 UIThreadSearchTermsData data(profile_.get()); 207 GoogleURLTracker::UpdatedDetails urls(GURL(data.GoogleBaseURLValue()), 208 base_url); 209 UIThreadSearchTermsData::SetGoogleBaseURL(base_url.spec()); 210 content::NotificationService::current()->Notify( 211 chrome::NOTIFICATION_GOOGLE_URL_UPDATED, 212 content::Source<Profile>(profile_.get()), 213 content::Details<GoogleURLTracker::UpdatedDetails>(&urls)); 214} 215 216void TemplateURLServiceTestUtil::SetManagedDefaultSearchPreferences( 217 bool enabled, 218 const std::string& name, 219 const std::string& keyword, 220 const std::string& search_url, 221 const std::string& suggest_url, 222 const std::string& icon_url, 223 const std::string& encodings, 224 const std::string& alternate_url, 225 const std::string& search_terms_replacement_key) { 226 TestingPrefServiceSyncable* pref_service = profile_->GetTestingPrefService(); 227 pref_service->SetManagedPref(prefs::kDefaultSearchProviderEnabled, 228 Value::CreateBooleanValue(enabled)); 229 pref_service->SetManagedPref(prefs::kDefaultSearchProviderName, 230 Value::CreateStringValue(name)); 231 pref_service->SetManagedPref(prefs::kDefaultSearchProviderKeyword, 232 Value::CreateStringValue(keyword)); 233 pref_service->SetManagedPref(prefs::kDefaultSearchProviderSearchURL, 234 Value::CreateStringValue(search_url)); 235 pref_service->SetManagedPref(prefs::kDefaultSearchProviderSuggestURL, 236 Value::CreateStringValue(suggest_url)); 237 pref_service->SetManagedPref(prefs::kDefaultSearchProviderIconURL, 238 Value::CreateStringValue(icon_url)); 239 pref_service->SetManagedPref(prefs::kDefaultSearchProviderEncodings, 240 Value::CreateStringValue(encodings)); 241 pref_service->SetManagedPref(prefs::kDefaultSearchProviderAlternateURLs, 242 alternate_url.empty() ? new base::ListValue() : 243 CreateListValueFrom(alternate_url)); 244 pref_service->SetManagedPref( 245 prefs::kDefaultSearchProviderSearchTermsReplacementKey, 246 Value::CreateStringValue(search_terms_replacement_key)); 247 model()->Observe(chrome::NOTIFICATION_DEFAULT_SEARCH_POLICY_CHANGED, 248 content::NotificationService::AllSources(), 249 content::NotificationService::NoDetails()); 250} 251 252void TemplateURLServiceTestUtil::RemoveManagedDefaultSearchPreferences() { 253 TestingPrefServiceSyncable* pref_service = profile_->GetTestingPrefService(); 254 pref_service->RemoveManagedPref(prefs::kDefaultSearchProviderEnabled); 255 pref_service->RemoveManagedPref(prefs::kDefaultSearchProviderName); 256 pref_service->RemoveManagedPref(prefs::kDefaultSearchProviderKeyword); 257 pref_service->RemoveManagedPref(prefs::kDefaultSearchProviderSearchURL); 258 pref_service->RemoveManagedPref(prefs::kDefaultSearchProviderSuggestURL); 259 pref_service->RemoveManagedPref(prefs::kDefaultSearchProviderIconURL); 260 pref_service->RemoveManagedPref(prefs::kDefaultSearchProviderEncodings); 261 pref_service->RemoveManagedPref(prefs::kDefaultSearchProviderAlternateURLs); 262 pref_service->RemoveManagedPref( 263 prefs::kDefaultSearchProviderSearchTermsReplacementKey); 264 pref_service->RemoveManagedPref(prefs::kDefaultSearchProviderID); 265 pref_service->RemoveManagedPref(prefs::kDefaultSearchProviderPrepopulateID); 266 model()->Observe(chrome::NOTIFICATION_DEFAULT_SEARCH_POLICY_CHANGED, 267 content::NotificationService::AllSources(), 268 content::NotificationService::NoDetails()); 269} 270 271TemplateURLService* TemplateURLServiceTestUtil::model() const { 272 return TemplateURLServiceFactory::GetForProfile(profile_.get()); 273} 274 275TestingProfile* TemplateURLServiceTestUtil::profile() const { 276 return profile_.get(); 277} 278 279void TemplateURLServiceTestUtil::StartIOThread() { 280 io_thread_.StartIOThread(); 281} 282 283void TemplateURLServiceTestUtil::PumpLoop() { 284 message_loop_.RunUntilIdle(); 285} 286