1 // Copyright (c) 2011 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 <string> 6 7 #include "base/basictypes.h" 8 #include "base/memory/ref_counted.h" 9 #include "base/message_loop.h" 10 #include "base/task.h" 11 #include "base/utf_string_conversions.h" 12 #include "chrome/browser/search_engines/search_provider_install_data.h" 13 #include "chrome/browser/search_engines/template_url.h" 14 #include "chrome/browser/search_engines/template_url_model.h" 15 #include "chrome/browser/search_engines/template_url_model_test_util.h" 16 #include "chrome/common/pref_names.h" 17 #include "chrome/test/testing_pref_service.h" 18 #include "chrome/test/testing_profile.h" 19 #include "content/browser/browser_thread.h" 20 #include "content/common/notification_service.h" 21 #include "content/common/notification_source.h" 22 #include "content/common/notification_type.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 25 // Create a TemplateURL. The caller owns the returned TemplateURL*. 26 static TemplateURL* CreateTemplateURL(const std::string& url, 27 const std::string& keyword) { 28 TemplateURL* t_url = new TemplateURL(); 29 t_url->SetURL(url, 0, 0); 30 t_url->set_keyword(UTF8ToUTF16(keyword)); 31 t_url->set_short_name(UTF8ToUTF16(keyword)); 32 return t_url; 33 } 34 35 // Test the SearchProviderInstallData::GetInstallState. 36 class TestGetInstallState : 37 public base::RefCountedThreadSafe<TestGetInstallState> { 38 public: 39 explicit TestGetInstallState(SearchProviderInstallData* install_data) 40 : install_data_(install_data), 41 main_loop_(NULL), 42 passed_(false) { 43 } 44 45 void set_search_provider_host( 46 const std::string& search_provider_host) { 47 search_provider_host_ = search_provider_host; 48 } 49 50 void set_default_search_provider_host( 51 const std::string& default_search_provider_host) { 52 default_search_provider_host_ = default_search_provider_host; 53 } 54 55 // Runs the test. Returns true if all passed. False if any failed. 56 bool RunTests(); 57 58 private: 59 friend class base::RefCountedThreadSafe<TestGetInstallState>; 60 ~TestGetInstallState(); 61 62 // Starts the test run on the IO thread. 63 void StartTestOnIOThread(); 64 65 // Callback for when SearchProviderInstallData is ready to have 66 // GetInstallState called. Runs all of the test cases. 67 void DoInstallStateTests(); 68 69 // Does a verification for one url and its expected state. 70 void VerifyInstallState(SearchProviderInstallData::State expected_state, 71 const std::string& url); 72 73 SearchProviderInstallData* install_data_; 74 MessageLoop* main_loop_; 75 76 // A host which should be a search provider but not the default. 77 std::string search_provider_host_; 78 79 // A host which should be a search provider but not the default. 80 std::string default_search_provider_host_; 81 82 // Used to indicate if DoInstallStateTests passed all test. 83 bool passed_; 84 85 DISALLOW_COPY_AND_ASSIGN(TestGetInstallState); 86 }; 87 88 bool TestGetInstallState::RunTests() { 89 passed_ = true; 90 91 main_loop_ = MessageLoop::current(); 92 93 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)->PostTask( 94 FROM_HERE, 95 NewRunnableMethod(this, &TestGetInstallState::StartTestOnIOThread)); 96 // Run the current message loop. When the test is finished on the I/O thread, 97 // it invokes Quit, which unblocks this. 98 MessageLoop::current()->Run(); 99 main_loop_ = NULL; 100 101 // Let the testing code know what the result is. 102 return passed_; 103 } 104 105 TestGetInstallState::~TestGetInstallState() { 106 } 107 108 void TestGetInstallState::StartTestOnIOThread() { 109 install_data_->CallWhenLoaded( 110 NewRunnableMethod(this, 111 &TestGetInstallState::DoInstallStateTests)); 112 } 113 114 void TestGetInstallState::DoInstallStateTests() { 115 // Installed but not default. 116 VerifyInstallState(SearchProviderInstallData::INSTALLED_BUT_NOT_DEFAULT, 117 "http://" + search_provider_host_ + "/"); 118 VerifyInstallState(SearchProviderInstallData::INSTALLED_BUT_NOT_DEFAULT, 119 "http://" + search_provider_host_ + ":80/"); 120 121 // Not installed. 122 VerifyInstallState(SearchProviderInstallData::NOT_INSTALLED, 123 "http://" + search_provider_host_ + ":96/"); 124 125 // Not installed due to different scheme. 126 VerifyInstallState(SearchProviderInstallData::NOT_INSTALLED, 127 "https://" + search_provider_host_ + "/"); 128 129 // Not installed. 130 VerifyInstallState(SearchProviderInstallData::NOT_INSTALLED, 131 "http://a" + search_provider_host_ + "/"); 132 133 // Installed as default. 134 if (!default_search_provider_host_.empty()) { 135 VerifyInstallState(SearchProviderInstallData::INSTALLED_AS_DEFAULT, 136 "http://" + default_search_provider_host_ + "/"); 137 } 138 139 // All done. 140 main_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); 141 } 142 143 void TestGetInstallState::VerifyInstallState( 144 SearchProviderInstallData::State expected_state, 145 const std::string& url) { 146 147 SearchProviderInstallData::State actual_state = 148 install_data_->GetInstallState(GURL(url)); 149 if (expected_state == actual_state) 150 return; 151 152 passed_ = false; 153 LOG(ERROR) << "GetInstallState for " << url << " failed. Expected " << 154 expected_state << ". Actual " << actual_state << "."; 155 } 156 157 // Provides basic test set-up/tear-down functionality needed by all tests 158 // that use TemplateURLModelTestUtil. 159 class SearchProviderInstallDataTest : public testing::Test { 160 public: 161 SearchProviderInstallDataTest() 162 : install_data_(NULL) {} 163 164 virtual void SetUp() { 165 testing::Test::SetUp(); 166 util_.SetUp(); 167 util_.StartIOThread(); 168 install_data_ = new SearchProviderInstallData( 169 util_.GetWebDataService(), 170 NotificationType::RENDERER_PROCESS_TERMINATED, 171 Source<SearchProviderInstallDataTest>(this)); 172 } 173 174 virtual void TearDown() { 175 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)->PostTask( 176 FROM_HERE, 177 new DeleteTask<SearchProviderInstallData>(install_data_)); 178 install_data_ = NULL; 179 180 // Make sure that the install data class on the UI thread gets cleaned up. 181 // It doesn't matter that this happens after install_data_ is deleted. 182 NotificationService::current()->Notify( 183 NotificationType::RENDERER_PROCESS_TERMINATED, 184 Source<SearchProviderInstallDataTest>(this), 185 NotificationService::NoDetails()); 186 187 util_.TearDown(); 188 testing::Test::TearDown(); 189 } 190 191 void SimulateDefaultSearchIsManaged(const std::string& url) { 192 ASSERT_FALSE(url.empty()); 193 TestingPrefService* service = util_.profile()->GetTestingPrefService(); 194 service->SetManagedPref( 195 prefs::kDefaultSearchProviderEnabled, 196 Value::CreateBooleanValue(true)); 197 service->SetManagedPref( 198 prefs::kDefaultSearchProviderSearchURL, 199 Value::CreateStringValue(url)); 200 service->SetManagedPref( 201 prefs::kDefaultSearchProviderName, 202 Value::CreateStringValue("managed")); 203 // Clear the IDs that are not specified via policy. 204 service->SetManagedPref( 205 prefs::kDefaultSearchProviderID, new StringValue("")); 206 service->SetManagedPref( 207 prefs::kDefaultSearchProviderPrepopulateID, new StringValue("")); 208 util_.model()->Observe( 209 NotificationType::PREF_CHANGED, 210 Source<PrefService>(util_.profile()->GetTestingPrefService()), 211 Details<std::string>(NULL)); 212 } 213 214 protected: 215 TemplateURLModelTestUtil util_; 216 217 // Provides the search provider install state on the I/O thread. It must be 218 // deleted on the I/O thread, which is why it isn't a scoped_ptr. 219 SearchProviderInstallData* install_data_; 220 221 DISALLOW_COPY_AND_ASSIGN(SearchProviderInstallDataTest); 222 }; 223 224 TEST_F(SearchProviderInstallDataTest, GetInstallState) { 225 // Set up the database. 226 util_.ChangeModelToLoadState(); 227 std::string host = "www.unittest.com"; 228 TemplateURL* t_url = CreateTemplateURL("http://" + host + "/path", 229 "unittest"); 230 util_.model()->Add(t_url); 231 232 // Wait for the changes to be saved. 233 TemplateURLModelTestUtil::BlockTillServiceProcessesRequests(); 234 235 // Verify the search providers install state (with no default set). 236 scoped_refptr<TestGetInstallState> test_get_install_state( 237 new TestGetInstallState(install_data_)); 238 test_get_install_state->set_search_provider_host(host); 239 EXPECT_TRUE(test_get_install_state->RunTests()); 240 241 // Set-up a default and try it all one more time. 242 std::string default_host = "www.mmm.com"; 243 TemplateURL* default_url = CreateTemplateURL("http://" + default_host + "/", 244 "mmm"); 245 util_.model()->Add(default_url); 246 util_.model()->SetDefaultSearchProvider(default_url); 247 test_get_install_state->set_default_search_provider_host(default_host); 248 EXPECT_TRUE(test_get_install_state->RunTests()); 249 } 250 251 252 TEST_F(SearchProviderInstallDataTest, ManagedDefaultSearch) { 253 // Set up the database. 254 util_.ChangeModelToLoadState(); 255 std::string host = "www.unittest.com"; 256 TemplateURL* t_url = CreateTemplateURL("http://" + host + "/path", 257 "unittest"); 258 util_.model()->Add(t_url); 259 260 // Set a managed preference that establishes a default search provider. 261 std::string host2 = "www.managedtest.com"; 262 std::string url2 = "http://" + host2 + "/p{searchTerms}"; 263 SimulateDefaultSearchIsManaged(url2); 264 EXPECT_TRUE(util_.model()->is_default_search_managed()); 265 266 // Wait for the changes to be saved. 267 util_.BlockTillServiceProcessesRequests(); 268 269 // Verify the search providers install state. The default search should be 270 // the managed one we previously set. 271 scoped_refptr<TestGetInstallState> test_get_install_state( 272 new TestGetInstallState(install_data_)); 273 test_get_install_state->set_search_provider_host(host); 274 test_get_install_state->set_default_search_provider_host(host2); 275 EXPECT_TRUE(test_get_install_state->RunTests()); 276 } 277 278 279 TEST_F(SearchProviderInstallDataTest, GoogleBaseUrlChange) { 280 scoped_refptr<TestGetInstallState> test_get_install_state( 281 new TestGetInstallState(install_data_)); 282 283 // Set up the database. 284 util_.ChangeModelToLoadState(); 285 std::string google_host = "w.com"; 286 util_.SetGoogleBaseURL("http://" + google_host + "/"); 287 // Wait for the I/O thread to process the update notification. 288 TemplateURLModelTestUtil::BlockTillIOThreadProcessesRequests(); 289 290 TemplateURL* t_url = CreateTemplateURL("{google:baseURL}?q={searchTerms}", 291 "t"); 292 util_.model()->Add(t_url); 293 TemplateURL* default_url = CreateTemplateURL("http://d.com/", 294 "d"); 295 util_.model()->Add(default_url); 296 util_.model()->SetDefaultSearchProvider(default_url); 297 298 // Wait for the changes to be saved. 299 TemplateURLModelTestUtil::BlockTillServiceProcessesRequests(); 300 301 // Verify the search providers install state (with no default set). 302 test_get_install_state->set_search_provider_host(google_host); 303 EXPECT_TRUE(test_get_install_state->RunTests()); 304 305 // Change the Google base url. 306 google_host = "foo.com"; 307 util_.SetGoogleBaseURL("http://" + google_host + "/"); 308 // Wait for the I/O thread to process the update notification. 309 TemplateURLModelTestUtil::BlockTillIOThreadProcessesRequests(); 310 311 // Verify that the change got picked up. 312 test_get_install_state->set_search_provider_host(google_host); 313 EXPECT_TRUE(test_get_install_state->RunTests()); 314 } 315