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 "chrome/browser/ui/webui/options/search_engine_manager_handler.h"
6
7 #include "base/callback.h"
8 #include "base/string_number_conversions.h"
9 #include "base/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/search_engines/template_url.h"
13 #include "chrome/browser/search_engines/template_url_model.h"
14 #include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
15 #include "chrome/browser/ui/search_engines/template_url_table_model.h"
16 #include "chrome/common/url_constants.h"
17 #include "grit/generated_resources.h"
18 #include "grit/locale_settings.h"
19 #include "ui/base/l10n/l10n_util.h"
20
21 namespace {
22
23 enum EngineInfoIndexes {
24 ENGINE_NAME,
25 ENGINE_KEYWORD,
26 ENGINE_URL,
27 };
28
29 }; // namespace
30
SearchEngineManagerHandler()31 SearchEngineManagerHandler::SearchEngineManagerHandler() {
32 }
33
~SearchEngineManagerHandler()34 SearchEngineManagerHandler::~SearchEngineManagerHandler() {
35 if (list_controller_.get() && list_controller_->table_model())
36 list_controller_->table_model()->SetObserver(NULL);
37 }
38
Initialize()39 void SearchEngineManagerHandler::Initialize() {
40 list_controller_.reset(new KeywordEditorController(web_ui_->GetProfile()));
41 if (list_controller_.get()) {
42 list_controller_->table_model()->SetObserver(this);
43 OnModelChanged();
44 }
45 }
46
GetLocalizedValues(DictionaryValue * localized_strings)47 void SearchEngineManagerHandler::GetLocalizedValues(
48 DictionaryValue* localized_strings) {
49 DCHECK(localized_strings);
50
51 RegisterTitle(localized_strings, "searchEngineManagerPage",
52 IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE);
53 localized_strings->SetString("defaultSearchEngineListTitle",
54 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAIN_SEPARATOR));
55 localized_strings->SetString("otherSearchEngineListTitle",
56 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_OTHER_SEPARATOR));
57 localized_strings->SetString("searchEngineTableNameHeader",
58 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN));
59 localized_strings->SetString("searchEngineTableKeywordHeader",
60 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN));
61 localized_strings->SetString("searchEngineTableURLHeader",
62 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_EDIT_BUTTON));
63 localized_strings->SetString("makeDefaultSearchEngineButton",
64 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAKE_DEFAULT_BUTTON));
65 localized_strings->SetString("searchEngineTableNamePlaceholder",
66 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_NAME_PLACEHOLDER));
67 localized_strings->SetString("searchEngineTableKeywordPlaceholder",
68 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_KEYWORD_PLACEHOLDER));
69 localized_strings->SetString("searchEngineTableURLPlaceholder",
70 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_URL_PLACEHOLDER));
71 localized_strings->SetString("editSearchEngineInvalidTitleToolTip",
72 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_TITLE_TT));
73 localized_strings->SetString("editSearchEngineInvalidKeywordToolTip",
74 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT));
75 localized_strings->SetString("editSearchEngineInvalidURLToolTip",
76 l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_URL_TT));
77 }
78
RegisterMessages()79 void SearchEngineManagerHandler::RegisterMessages() {
80 web_ui_->RegisterMessageCallback(
81 "managerSetDefaultSearchEngine",
82 NewCallback(this, &SearchEngineManagerHandler::SetDefaultSearchEngine));
83 web_ui_->RegisterMessageCallback(
84 "removeSearchEngine",
85 NewCallback(this, &SearchEngineManagerHandler::RemoveSearchEngine));
86 web_ui_->RegisterMessageCallback(
87 "editSearchEngine",
88 NewCallback(this, &SearchEngineManagerHandler::EditSearchEngine));
89 web_ui_->RegisterMessageCallback(
90 "checkSearchEngineInfoValidity",
91 NewCallback(this,
92 &SearchEngineManagerHandler::CheckSearchEngineInfoValidity));
93 web_ui_->RegisterMessageCallback(
94 "searchEngineEditCancelled",
95 NewCallback(this, &SearchEngineManagerHandler::EditCancelled));
96 web_ui_->RegisterMessageCallback(
97 "searchEngineEditCompleted",
98 NewCallback(this, &SearchEngineManagerHandler::EditCompleted));
99 }
100
OnModelChanged()101 void SearchEngineManagerHandler::OnModelChanged() {
102 if (!list_controller_->loaded())
103 return;
104
105 // Find the default engine.
106 const TemplateURL* default_engine =
107 list_controller_->url_model()->GetDefaultSearchProvider();
108 int default_index = list_controller_->table_model()->IndexOfTemplateURL(
109 default_engine);
110
111 // Build the first list (default search engine options).
112 ListValue defaults_list;
113 int last_default_engine_index =
114 list_controller_->table_model()->last_search_engine_index();
115 for (int i = 0; i < last_default_engine_index; ++i) {
116 defaults_list.Append(CreateDictionaryForEngine(i, i == default_index));
117 }
118
119 // Build the second list (other search templates).
120 ListValue others_list;
121 if (last_default_engine_index < 0)
122 last_default_engine_index = 0;
123 int engine_count = list_controller_->table_model()->RowCount();
124 for (int i = last_default_engine_index; i < engine_count; ++i) {
125 others_list.Append(CreateDictionaryForEngine(i, i == default_index));
126 }
127
128 web_ui_->CallJavascriptFunction("SearchEngineManager.updateSearchEngineList",
129 defaults_list, others_list);
130 }
131
OnItemsChanged(int start,int length)132 void SearchEngineManagerHandler::OnItemsChanged(int start, int length) {
133 OnModelChanged();
134 }
135
OnItemsAdded(int start,int length)136 void SearchEngineManagerHandler::OnItemsAdded(int start, int length) {
137 OnModelChanged();
138 }
139
OnItemsRemoved(int start,int length)140 void SearchEngineManagerHandler::OnItemsRemoved(int start, int length) {
141 OnModelChanged();
142 }
143
CreateDictionaryForEngine(int index,bool is_default)144 DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForEngine(
145 int index, bool is_default) {
146 TemplateURLTableModel* table_model = list_controller_->table_model();
147 const TemplateURL* template_url = list_controller_->GetTemplateURL(index);
148
149 DictionaryValue* dict = new DictionaryValue();
150 dict->SetString("name", template_url->short_name());
151 dict->SetString("displayName", table_model->GetText(
152 index, IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN));
153 dict->SetString("keyword", table_model->GetText(
154 index, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN));
155 dict->SetString("url", template_url->url()->DisplayURL());
156 dict->SetBoolean("urlLocked", template_url->prepopulate_id() > 0);
157 GURL icon_url = template_url->GetFaviconURL();
158 if (icon_url.is_valid())
159 dict->SetString("iconURL", icon_url.spec());
160 dict->SetString("modelIndex", base::IntToString(index));
161
162 if (list_controller_->CanRemove(template_url))
163 dict->SetString("canBeRemoved", "1");
164 if (list_controller_->CanMakeDefault(template_url))
165 dict->SetString("canBeDefault", "1");
166 if (is_default)
167 dict->SetString("default", "1");
168
169 return dict;
170 }
171
SetDefaultSearchEngine(const ListValue * args)172 void SearchEngineManagerHandler::SetDefaultSearchEngine(const ListValue* args) {
173 int index;
174 if (!ExtractIntegerValue(args, &index)) {
175 NOTREACHED();
176 return;
177 }
178 if (index < 0 || index >= list_controller_->table_model()->RowCount())
179 return;
180
181 list_controller_->MakeDefaultTemplateURL(index);
182 }
183
RemoveSearchEngine(const ListValue * args)184 void SearchEngineManagerHandler::RemoveSearchEngine(const ListValue* args) {
185 int index;
186 if (!ExtractIntegerValue(args, &index)) {
187 NOTREACHED();
188 return;
189 }
190 if (index < 0 || index >= list_controller_->table_model()->RowCount())
191 return;
192
193 if (list_controller_->CanRemove(list_controller_->GetTemplateURL(index)))
194 list_controller_->RemoveTemplateURL(index);
195 }
196
EditSearchEngine(const ListValue * args)197 void SearchEngineManagerHandler::EditSearchEngine(const ListValue* args) {
198 int index;
199 if (!ExtractIntegerValue(args, &index)) {
200 NOTREACHED();
201 return;
202 }
203 // Allow -1, which means we are adding a new engine.
204 if (index < -1 || index >= list_controller_->table_model()->RowCount())
205 return;
206
207 const TemplateURL* edit_url = NULL;
208 if (index != -1)
209 edit_url = list_controller_->GetTemplateURL(index);
210 edit_controller_.reset(
211 new EditSearchEngineController(edit_url, this, web_ui_->GetProfile()));
212 }
213
OnEditedKeyword(const TemplateURL * template_url,const string16 & title,const string16 & keyword,const std::string & url)214 void SearchEngineManagerHandler::OnEditedKeyword(
215 const TemplateURL* template_url,
216 const string16& title,
217 const string16& keyword,
218 const std::string& url) {
219 if (template_url) {
220 list_controller_->ModifyTemplateURL(template_url, title, keyword, url);
221 } else {
222 list_controller_->AddTemplateURL(title, keyword, url);
223 }
224 edit_controller_.reset();
225 }
226
CheckSearchEngineInfoValidity(const ListValue * args)227 void SearchEngineManagerHandler::CheckSearchEngineInfoValidity(
228 const ListValue* args)
229 {
230 if (!edit_controller_.get())
231 return;
232 string16 name;
233 string16 keyword;
234 std::string url;
235 std::string modelIndex;
236 if (!args->GetString(ENGINE_NAME, &name) ||
237 !args->GetString(ENGINE_KEYWORD, &keyword) ||
238 !args->GetString(ENGINE_URL, &url) ||
239 !args->GetString(3, &modelIndex)) {
240 NOTREACHED();
241 return;
242 }
243
244 DictionaryValue validity;
245 validity.SetBoolean("name", edit_controller_->IsTitleValid(name));
246 validity.SetBoolean("keyword", edit_controller_->IsKeywordValid(keyword));
247 validity.SetBoolean("url", edit_controller_->IsURLValid(url));
248 StringValue indexValue(modelIndex);
249 web_ui_->CallJavascriptFunction("SearchEngineManager.validityCheckCallback",
250 validity, indexValue);
251 }
252
EditCancelled(const ListValue * args)253 void SearchEngineManagerHandler::EditCancelled(const ListValue* args) {
254 if (!edit_controller_.get())
255 return;
256 edit_controller_->CleanUpCancelledAdd();
257 edit_controller_.reset();
258 }
259
EditCompleted(const ListValue * args)260 void SearchEngineManagerHandler::EditCompleted(const ListValue* args) {
261 if (!edit_controller_.get())
262 return;
263 string16 name;
264 string16 keyword;
265 std::string url;
266 if (!args->GetString(ENGINE_NAME, &name) ||
267 !args->GetString(ENGINE_KEYWORD, &keyword) ||
268 !args->GetString(ENGINE_URL, &url)) {
269 NOTREACHED();
270 return;
271 }
272 edit_controller_->AcceptAddOrEdit(name, keyword, url);
273 }
274