1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// Use of this source code is governed by a BSD-style license that can be 3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// found in the LICENSE file. 4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "base/compiler_specific.h" 6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "base/strings/string16.h" 7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "base/strings/utf_string_conversions.h" 8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "chrome/browser/profiles/profile.h" 9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "chrome/browser/search_engines/template_url_service_factory_test_util.h" 10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "chrome/browser/ui/search_engines/keyword_editor_controller.h" 11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "chrome/browser/ui/search_engines/template_url_table_model.h" 12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "chrome/test/base/testing_pref_service_syncable.h" 13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "chrome/test/base/testing_profile.h" 14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "components/search_engines/template_url.h" 15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "components/search_engines/template_url_service.h" 16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "content/public/test/test_browser_thread_bundle.h" 17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "testing/gtest/include/gtest/gtest.h" 18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "ui/base/models/table_model_observer.h" 19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 20baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing base::ASCIIToUTF16; 21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 22baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const base::string16 kA(ASCIIToUTF16("a")); 23baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const base::string16 kA1(ASCIIToUTF16("a1")); 24baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const base::string16 kB(ASCIIToUTF16("b")); 25baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const base::string16 kB1(ASCIIToUTF16("b1")); 26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// Base class for keyword editor tests. Creates a profile containing an 28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// empty TemplateURLService. 29baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass KeywordEditorControllerTest : public testing::Test, 30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync public ui::TableModelObserver { 31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync public: 32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync KeywordEditorControllerTest() 33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync : util_(&profile_), 34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync simulate_load_failure_(false), 35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync model_changed_count_(0), 36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync items_changed_count_(0), 37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync added_count_(0), 38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync removed_count_(0) {} 39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync explicit KeywordEditorControllerTest(bool simulate_load_failure) 41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync : util_(&profile_), 42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync simulate_load_failure_(simulate_load_failure), 43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync model_changed_count_(0), 44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync items_changed_count_(0), 45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync added_count_(0), 46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync removed_count_(0) {} 47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync virtual void SetUp() OVERRIDE { 49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (simulate_load_failure_) 50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync util_.model()->OnWebDataServiceRequestDone(0, NULL); 51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync util_.VerifyLoad(); 53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync controller_.reset(new KeywordEditorController(&profile_)); 55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync controller_->table_model()->SetObserver(this); 56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync virtual void TearDown() OVERRIDE { 59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync controller_.reset(); 60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync virtual void OnModelChanged() OVERRIDE { 63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync model_changed_count_++; 64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync virtual void OnItemsChanged(int start, int length) OVERRIDE { 67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync items_changed_count_++; 68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync virtual void OnItemsAdded(int start, int length) OVERRIDE { 71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync added_count_++; 72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync virtual void OnItemsRemoved(int start, int length) OVERRIDE { 75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync removed_count_++; 76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync void VerifyChangeCount(int model_changed_count, int item_changed_count, 79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int added_count, int removed_count) { 80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync ASSERT_EQ(model_changed_count, model_changed_count_); 81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync ASSERT_EQ(item_changed_count, items_changed_count_); 82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync ASSERT_EQ(added_count, added_count_); 83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync ASSERT_EQ(removed_count, removed_count_); 84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync ClearChangeCount(); 85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync void ClearChangeCount() { 88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync model_changed_count_ = items_changed_count_ = added_count_ = 89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync removed_count_ = 0; 90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync void SimulateDefaultSearchIsManaged(const std::string& url) { 93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync util_.SetManagedDefaultSearchPreferences(true, 94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync "managed", 95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync "managed", 96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync url, 97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync std::string(), 98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync std::string(), 99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync std::string(), 100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync std::string(), 101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync std::string()); 102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync TemplateURLTableModel* table_model() { return controller_->table_model(); } 105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync KeywordEditorController* controller() { return controller_.get(); } 106 const TemplateURLServiceFactoryTestUtil* util() const { return &util_; } 107 108 int items_changed_count() const { return items_changed_count_; } 109 int added_count() const { return added_count_; } 110 int removed_count() const { return removed_count_; } 111 112 private: 113 content::TestBrowserThreadBundle thread_bundle_; 114 TestingProfile profile_; 115 scoped_ptr<KeywordEditorController> controller_; 116 TemplateURLServiceFactoryTestUtil util_; 117 bool simulate_load_failure_; 118 119 int model_changed_count_; 120 int items_changed_count_; 121 int added_count_; 122 int removed_count_; 123}; 124 125class KeywordEditorControllerNoWebDataTest 126 : public KeywordEditorControllerTest { 127 public: 128 KeywordEditorControllerNoWebDataTest() : KeywordEditorControllerTest(true) {} 129}; 130 131// Tests adding a TemplateURL. 132TEST_F(KeywordEditorControllerTest, Add) { 133 int original_row_count = table_model()->RowCount(); 134 controller()->AddTemplateURL(kA, kB, "http://c"); 135 136 // Verify the observer was notified. 137 VerifyChangeCount(0, 0, 1, 0); 138 if (HasFatalFailure()) 139 return; 140 141 // Verify the TableModel has the new data. 142 ASSERT_EQ(original_row_count + 1, table_model()->RowCount()); 143 144 // Verify the TemplateURLService has the new data. 145 const TemplateURL* turl = util()->model()->GetTemplateURLForKeyword(kB); 146 ASSERT_TRUE(turl); 147 EXPECT_EQ(ASCIIToUTF16("a"), turl->short_name()); 148 EXPECT_EQ(ASCIIToUTF16("b"), turl->keyword()); 149 EXPECT_EQ("http://c", turl->url()); 150} 151 152// Tests modifying a TemplateURL. 153TEST_F(KeywordEditorControllerTest, Modify) { 154 controller()->AddTemplateURL(kA, kB, "http://c"); 155 ClearChangeCount(); 156 157 // Modify the entry. 158 TemplateURL* turl = util()->model()->GetTemplateURLs()[0]; 159 controller()->ModifyTemplateURL(turl, kA1, kB1, "http://c1"); 160 161 // Make sure it was updated appropriately. 162 VerifyChangeCount(0, 1, 0, 0); 163 EXPECT_EQ(ASCIIToUTF16("a1"), turl->short_name()); 164 EXPECT_EQ(ASCIIToUTF16("b1"), turl->keyword()); 165 EXPECT_EQ("http://c1", turl->url()); 166} 167 168// Tests making a TemplateURL the default search provider. 169TEST_F(KeywordEditorControllerTest, MakeDefault) { 170 int index = controller()->AddTemplateURL(kA, kB, "http://c{searchTerms}"); 171 ClearChangeCount(); 172 173 const TemplateURL* turl = util()->model()->GetTemplateURLForKeyword(kB); 174 int new_default = controller()->MakeDefaultTemplateURL(index); 175 EXPECT_EQ(index, new_default); 176 // Making an item the default sends a handful of changes. Which are sent isn't 177 // important, what is important is 'something' is sent. 178 ASSERT_TRUE(items_changed_count() > 0 || added_count() > 0 || 179 removed_count() > 0); 180 ASSERT_TRUE(util()->model()->GetDefaultSearchProvider() == turl); 181 182 // Making it default a second time should fail. 183 new_default = controller()->MakeDefaultTemplateURL(index); 184 EXPECT_EQ(-1, new_default); 185} 186 187// Tests that a TemplateURL can't be made the default if the default search 188// provider is managed via policy. 189TEST_F(KeywordEditorControllerTest, CannotSetDefaultWhileManaged) { 190 controller()->AddTemplateURL(kA, kB, "http://c{searchTerms}"); 191 controller()->AddTemplateURL(kA1, kB1, "http://d{searchTerms}"); 192 ClearChangeCount(); 193 194 const TemplateURL* turl1 = 195 util()->model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")); 196 ASSERT_TRUE(turl1 != NULL); 197 const TemplateURL* turl2 = 198 util()->model()->GetTemplateURLForKeyword(ASCIIToUTF16("b1")); 199 ASSERT_TRUE(turl2 != NULL); 200 201 EXPECT_TRUE(controller()->CanMakeDefault(turl1)); 202 EXPECT_TRUE(controller()->CanMakeDefault(turl2)); 203 204 SimulateDefaultSearchIsManaged(turl2->url()); 205 EXPECT_TRUE(util()->model()->is_default_search_managed()); 206 207 EXPECT_FALSE(controller()->CanMakeDefault(turl1)); 208 EXPECT_FALSE(controller()->CanMakeDefault(turl2)); 209} 210 211// Tests that a TemplateURL can't be edited if it is the managed default search 212// provider. 213TEST_F(KeywordEditorControllerTest, EditManagedDefault) { 214 controller()->AddTemplateURL(kA, kB, "http://c{searchTerms}"); 215 controller()->AddTemplateURL(kA1, kB1, "http://d{searchTerms}"); 216 ClearChangeCount(); 217 218 const TemplateURL* turl1 = 219 util()->model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")); 220 ASSERT_TRUE(turl1 != NULL); 221 const TemplateURL* turl2 = 222 util()->model()->GetTemplateURLForKeyword(ASCIIToUTF16("b1")); 223 ASSERT_TRUE(turl2 != NULL); 224 225 EXPECT_TRUE(controller()->CanEdit(turl1)); 226 EXPECT_TRUE(controller()->CanEdit(turl2)); 227 228 // Simulate setting a managed default. This will add another template URL to 229 // the model. 230 SimulateDefaultSearchIsManaged(turl2->url()); 231 EXPECT_TRUE(util()->model()->is_default_search_managed()); 232 EXPECT_TRUE(controller()->CanEdit(turl1)); 233 EXPECT_TRUE(controller()->CanEdit(turl2)); 234 EXPECT_FALSE( 235 controller()->CanEdit(util()->model()->GetDefaultSearchProvider())); 236} 237 238TEST_F(KeywordEditorControllerNoWebDataTest, MakeDefaultNoWebData) { 239 int index = controller()->AddTemplateURL(kA, kB, "http://c{searchTerms}"); 240 ClearChangeCount(); 241 242 // This should not result in a crash. 243 int new_default = controller()->MakeDefaultTemplateURL(index); 244 EXPECT_EQ(index, new_default); 245} 246 247// Mutates the TemplateURLService and make sure table model is updating 248// appropriately. 249TEST_F(KeywordEditorControllerTest, MutateTemplateURLService) { 250 int original_row_count = table_model()->RowCount(); 251 252 TemplateURLData data; 253 data.short_name = ASCIIToUTF16("b"); 254 data.SetKeyword(ASCIIToUTF16("a")); 255 TemplateURL* turl = new TemplateURL(data); 256 util()->model()->Add(turl); 257 258 // Table model should have updated. 259 VerifyChangeCount(1, 0, 0, 0); 260 261 // And should contain the newly added TemplateURL. 262 ASSERT_EQ(original_row_count + 1, table_model()->RowCount()); 263 ASSERT_GE(table_model()->IndexOfTemplateURL(turl), 0); 264} 265