Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / options / search_engine_manager_handler.cc
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/ui/webui/options/search_engine_manager_handler.h"
6
7 #include "base/bind.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/extensions/extension_util.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/search_engines/template_url.h"
14 #include "chrome/browser/search_engines/template_url_service.h"
15 #include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
16 #include "chrome/browser/ui/search_engines/template_url_table_model.h"
17 #include "chrome/common/url_constants.h"
18 #include "content/public/browser/user_metrics.h"
19 #include "content/public/browser/web_ui.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/common/extension.h"
22 #include "grit/generated_resources.h"
23 #include "grit/locale_settings.h"
24 #include "ui/base/l10n/l10n_util.h"
25
26 namespace {
27
28 enum EngineInfoIndexes {
29   ENGINE_NAME,
30   ENGINE_KEYWORD,
31   ENGINE_URL,
32 };
33
34 };  // namespace
35
36 namespace options {
37
38 SearchEngineManagerHandler::SearchEngineManagerHandler() {
39 }
40
41 SearchEngineManagerHandler::~SearchEngineManagerHandler() {
42   if (list_controller_.get() && list_controller_->table_model())
43     list_controller_->table_model()->SetObserver(NULL);
44 }
45
46 void SearchEngineManagerHandler::InitializeHandler() {
47   list_controller_.reset(
48       new KeywordEditorController(Profile::FromWebUI(web_ui())));
49   DCHECK(list_controller_.get());
50   list_controller_->table_model()->SetObserver(this);
51 }
52
53 void SearchEngineManagerHandler::InitializePage() {
54   OnModelChanged();
55 }
56
57 void SearchEngineManagerHandler::GetLocalizedValues(
58     base::DictionaryValue* localized_strings) {
59   DCHECK(localized_strings);
60
61   RegisterTitle(localized_strings, "searchEngineManagerPage",
62                 IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE);
63   localized_strings->SetString("defaultSearchEngineListTitle",
64       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAIN_SEPARATOR));
65   localized_strings->SetString("otherSearchEngineListTitle",
66       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_OTHER_SEPARATOR));
67   localized_strings->SetString("extensionKeywordsListTitle",
68       l10n_util::GetStringUTF16(
69           IDS_SEARCH_ENGINES_EDITOR_EXTENSIONS_SEPARATOR));
70   localized_strings->SetString("makeDefaultSearchEngineButton",
71       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAKE_DEFAULT_BUTTON));
72   localized_strings->SetString("searchEngineTableNamePlaceholder",
73       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_NAME_PLACEHOLDER));
74   localized_strings->SetString("searchEngineTableKeywordPlaceholder",
75       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_KEYWORD_PLACEHOLDER));
76   localized_strings->SetString("searchEngineTableURLPlaceholder",
77       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_URL_PLACEHOLDER));
78   localized_strings->SetString("editSearchEngineInvalidTitleToolTip",
79       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_TITLE_TT));
80   localized_strings->SetString("editSearchEngineInvalidKeywordToolTip",
81       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT));
82   localized_strings->SetString("editSearchEngineInvalidURLToolTip",
83       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_URL_TT));
84 }
85
86 void SearchEngineManagerHandler::RegisterMessages() {
87   web_ui()->RegisterMessageCallback(
88       "managerSetDefaultSearchEngine",
89       base::Bind(&SearchEngineManagerHandler::SetDefaultSearchEngine,
90                  base::Unretained(this)));
91   web_ui()->RegisterMessageCallback(
92       "removeSearchEngine",
93       base::Bind(&SearchEngineManagerHandler::RemoveSearchEngine,
94                  base::Unretained(this)));
95   web_ui()->RegisterMessageCallback(
96       "editSearchEngine",
97       base::Bind(&SearchEngineManagerHandler::EditSearchEngine,
98                  base::Unretained(this)));
99   web_ui()->RegisterMessageCallback(
100       "checkSearchEngineInfoValidity",
101       base::Bind(&SearchEngineManagerHandler::CheckSearchEngineInfoValidity,
102                  base::Unretained(this)));
103   web_ui()->RegisterMessageCallback(
104       "searchEngineEditCancelled",
105       base::Bind(&SearchEngineManagerHandler::EditCancelled,
106                  base::Unretained(this)));
107   web_ui()->RegisterMessageCallback(
108       "searchEngineEditCompleted",
109       base::Bind(&SearchEngineManagerHandler::EditCompleted,
110                  base::Unretained(this)));
111 }
112
113 void SearchEngineManagerHandler::OnModelChanged() {
114   DCHECK(list_controller_.get());
115   if (!list_controller_->loaded())
116     return;
117
118   // Find the default engine.
119   const TemplateURL* default_engine =
120       list_controller_->url_model()->GetDefaultSearchProvider();
121   int default_index = list_controller_->table_model()->IndexOfTemplateURL(
122       default_engine);
123
124   // Build the first list (default search engine options).
125   base::ListValue defaults_list;
126   int last_default_engine_index =
127       list_controller_->table_model()->last_search_engine_index();
128   for (int i = 0; i < last_default_engine_index; ++i) {
129     // Third argument is false, as the engine is not from an extension.
130     defaults_list.Append(CreateDictionaryForEngine(
131         i, i == default_index, false));
132   }
133
134   // Build the second list (other search templates).
135   base::ListValue others_list;
136   int last_other_engine_index =
137       list_controller_->table_model()->last_other_engine_index();
138   if (last_default_engine_index < 0)
139     last_default_engine_index = 0;
140   for (int i = last_default_engine_index; i < last_other_engine_index; ++i) {
141     others_list.Append(CreateDictionaryForEngine(i, i == default_index, false));
142   }
143
144   // Build the extension keywords list.
145   base::ListValue keyword_list;
146   if (last_other_engine_index < 0)
147     last_other_engine_index = 0;
148   int engine_count = list_controller_->table_model()->RowCount();
149   for (int i = last_other_engine_index; i < engine_count; ++i) {
150     keyword_list.Append(CreateDictionaryForEngine(i, i == default_index, true));
151   }
152
153   web_ui()->CallJavascriptFunction("SearchEngineManager.updateSearchEngineList",
154                                    defaults_list, others_list, keyword_list);
155 }
156
157 void SearchEngineManagerHandler::OnItemsChanged(int start, int length) {
158   OnModelChanged();
159 }
160
161 void SearchEngineManagerHandler::OnItemsAdded(int start, int length) {
162   OnModelChanged();
163 }
164
165 void SearchEngineManagerHandler::OnItemsRemoved(int start, int length) {
166   OnModelChanged();
167 }
168
169 base::DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForEngine(
170     int index, bool is_default, bool is_extension) {
171   TemplateURLTableModel* table_model = list_controller_->table_model();
172   const TemplateURL* template_url = list_controller_->GetTemplateURL(index);
173
174   base::DictionaryValue* dict = new base::DictionaryValue();
175   dict->SetString("name",  template_url->short_name());
176   dict->SetString("displayName", table_model->GetText(
177     index, IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN));
178   dict->SetString("keyword", table_model->GetText(
179     index, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN));
180   dict->SetString("url", template_url->url_ref().DisplayURL());
181   dict->SetBoolean("urlLocked", template_url->prepopulate_id() > 0);
182   GURL icon_url = template_url->favicon_url();
183   if (icon_url.is_valid())
184     dict->SetString("iconURL", icon_url.spec());
185   dict->SetString("modelIndex", base::IntToString(index));
186
187   dict->SetBoolean("canBeRemoved",
188       list_controller_->CanRemove(template_url) && !is_extension);
189   dict->SetBoolean("canBeDefault",
190       list_controller_->CanMakeDefault(template_url) && !is_extension);
191   dict->SetBoolean("default", is_default);
192   dict->SetBoolean("canBeEdited", list_controller_->CanEdit(template_url));
193   dict->SetBoolean("isExtension", is_extension);
194   if (template_url->GetType() == TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION) {
195     const extensions::Extension* extension =
196         extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))
197             ->GetExtensionById(template_url->GetExtensionId(),
198                                extensions::ExtensionRegistry::EVERYTHING);
199     if (extension) {
200       dict->Set("extension",
201                 extensions::util::GetExtensionInfo(extension).release());
202     }
203   }
204   return dict;
205 }
206
207 void SearchEngineManagerHandler::SetDefaultSearchEngine(
208     const base::ListValue* args) {
209   int index;
210   if (!ExtractIntegerValue(args, &index)) {
211     NOTREACHED();
212     return;
213   }
214   if (index < 0 || index >= list_controller_->table_model()->RowCount())
215     return;
216
217   list_controller_->MakeDefaultTemplateURL(index);
218
219   content::RecordAction(
220       base::UserMetricsAction("Options_SearchEngineSetDefault"));
221 }
222
223 void SearchEngineManagerHandler::RemoveSearchEngine(
224     const base::ListValue* args) {
225   int index;
226   if (!ExtractIntegerValue(args, &index)) {
227     NOTREACHED();
228     return;
229   }
230   if (index < 0 || index >= list_controller_->table_model()->RowCount())
231     return;
232
233   if (list_controller_->CanRemove(list_controller_->GetTemplateURL(index))) {
234     list_controller_->RemoveTemplateURL(index);
235     content::RecordAction(
236         base::UserMetricsAction("Options_SearchEngineRemoved"));
237   }
238 }
239
240 void SearchEngineManagerHandler::EditSearchEngine(const base::ListValue* args) {
241   int index;
242   if (!ExtractIntegerValue(args, &index)) {
243     NOTREACHED();
244     return;
245   }
246
247   // Allow -1, which means we are adding a new engine.
248   if (index < -1 || index >= list_controller_->table_model()->RowCount())
249     return;
250
251   edit_controller_.reset(new EditSearchEngineController(
252       (index == -1) ? NULL : list_controller_->GetTemplateURL(index), this,
253       Profile::FromWebUI(web_ui())));
254 }
255
256 void SearchEngineManagerHandler::OnEditedKeyword(
257     TemplateURL* template_url,
258     const base::string16& title,
259     const base::string16& keyword,
260     const std::string& url) {
261   DCHECK(!url.empty());
262   if (template_url)
263     list_controller_->ModifyTemplateURL(template_url, title, keyword, url);
264   else
265     list_controller_->AddTemplateURL(title, keyword, url);
266   edit_controller_.reset();
267 }
268
269 void SearchEngineManagerHandler::CheckSearchEngineInfoValidity(
270     const base::ListValue* args)
271 {
272   if (!edit_controller_.get())
273     return;
274   base::string16 name;
275   base::string16 keyword;
276   std::string url;
277   std::string modelIndex;
278   if (!args->GetString(ENGINE_NAME, &name) ||
279       !args->GetString(ENGINE_KEYWORD, &keyword) ||
280       !args->GetString(ENGINE_URL, &url) ||
281       !args->GetString(3, &modelIndex)) {
282     NOTREACHED();
283     return;
284   }
285
286   base::DictionaryValue validity;
287   validity.SetBoolean("name", edit_controller_->IsTitleValid(name));
288   validity.SetBoolean("keyword", edit_controller_->IsKeywordValid(keyword));
289   validity.SetBoolean("url", edit_controller_->IsURLValid(url));
290   base::StringValue indexValue(modelIndex);
291   web_ui()->CallJavascriptFunction("SearchEngineManager.validityCheckCallback",
292                                    validity, indexValue);
293 }
294
295 void SearchEngineManagerHandler::EditCancelled(const base::ListValue* args) {
296   if (!edit_controller_.get())
297     return;
298   edit_controller_->CleanUpCancelledAdd();
299   edit_controller_.reset();
300 }
301
302 void SearchEngineManagerHandler::EditCompleted(const base::ListValue* args) {
303   if (!edit_controller_.get())
304     return;
305   base::string16 name;
306   base::string16 keyword;
307   std::string url;
308   if (!args->GetString(ENGINE_NAME, &name) ||
309       !args->GetString(ENGINE_KEYWORD, &keyword) ||
310       !args->GetString(ENGINE_URL, &url)) {
311     NOTREACHED();
312     return;
313   }
314
315   // Recheck validity.  It's possible to get here with invalid input if e.g. the
316   // user calls the right JS functions directly from the web inspector.
317   if (edit_controller_->IsTitleValid(name) &&
318       edit_controller_->IsKeywordValid(keyword) &&
319       edit_controller_->IsURLValid(url))
320     edit_controller_->AcceptAddOrEdit(name, keyword, url);
321 }
322
323 }  // namespace options