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