• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/browser_options_handler.h"
6 
7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/singleton.h"
10 #include "base/string_number_conversions.h"
11 #include "base/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "chrome/browser/autocomplete/autocomplete.h"
14 #include "chrome/browser/autocomplete/autocomplete_match.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/custom_home_pages_table_model.h"
17 #include "chrome/browser/instant/instant_confirm_dialog.h"
18 #include "chrome/browser/metrics/user_metrics.h"
19 #include "chrome/browser/net/url_fixer_upper.h"
20 #include "chrome/browser/prefs/pref_service.h"
21 #include "chrome/browser/prefs/session_startup_pref.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/search_engines/template_url.h"
24 #include "chrome/browser/search_engines/template_url_model.h"
25 #include "chrome/browser/ui/options/options_window.h"
26 #include "chrome/browser/ui/webui/favicon_source.h"
27 #include "chrome/browser/ui/webui/options/options_managed_banner_handler.h"
28 #include "chrome/common/pref_names.h"
29 #include "chrome/installer/util/browser_distribution.h"
30 #include "content/browser/browser_thread.h"
31 #include "content/common/notification_service.h"
32 #include "content/common/notification_source.h"
33 #include "content/common/notification_type.h"
34 #include "grit/chromium_strings.h"
35 #include "grit/generated_resources.h"
36 #include "ui/base/l10n/l10n_util.h"
37 
BrowserOptionsHandler()38 BrowserOptionsHandler::BrowserOptionsHandler()
39     : template_url_model_(NULL), startup_custom_pages_table_model_(NULL) {
40 #if !defined(OS_MACOSX)
41   default_browser_worker_ = new ShellIntegration::DefaultBrowserWorker(this);
42 #endif
43 }
44 
~BrowserOptionsHandler()45 BrowserOptionsHandler::~BrowserOptionsHandler() {
46   if (default_browser_worker_.get())
47     default_browser_worker_->ObserverDestroyed();
48   if (template_url_model_)
49     template_url_model_->RemoveObserver(this);
50 }
51 
GetLocalizedValues(DictionaryValue * localized_strings)52 void BrowserOptionsHandler::GetLocalizedValues(
53     DictionaryValue* localized_strings) {
54   DCHECK(localized_strings);
55 
56   static OptionsStringResource resources[] = {
57     { "startupGroupName", IDS_OPTIONS_STARTUP_GROUP_NAME },
58     { "startupShowDefaultAndNewTab",
59       IDS_OPTIONS_STARTUP_SHOW_DEFAULT_AND_NEWTAB},
60     { "startupShowLastSession", IDS_OPTIONS_STARTUP_SHOW_LAST_SESSION },
61     { "startupShowPages", IDS_OPTIONS_STARTUP_SHOW_PAGES },
62     { "startupAddLabel", IDS_OPTIONS_STARTUP_ADD_LABEL },
63     { "startupUseCurrent", IDS_OPTIONS_STARTUP_USE_CURRENT },
64     { "homepageGroupName", IDS_OPTIONS_HOMEPAGE_GROUP_NAME },
65     { "homepageUseNewTab", IDS_OPTIONS_HOMEPAGE_USE_NEWTAB },
66     { "homepageUseURL", IDS_OPTIONS_HOMEPAGE_USE_URL },
67     { "toolbarGroupName", IDS_OPTIONS_TOOLBAR_GROUP_NAME },
68     { "toolbarShowHomeButton", IDS_OPTIONS_TOOLBAR_SHOW_HOME_BUTTON },
69     { "toolbarShowBookmarksBar", IDS_OPTIONS_TOOLBAR_SHOW_BOOKMARKS_BAR },
70     { "defaultSearchGroupName", IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME },
71     { "defaultSearchManageEngines", IDS_OPTIONS_DEFAULTSEARCH_MANAGE_ENGINES },
72     { "instantName", IDS_INSTANT_PREF },
73     { "instantWarningText", IDS_INSTANT_PREF_WARNING },
74     { "instantConfirmTitle", IDS_INSTANT_OPT_IN_TITLE },
75     { "instantConfirmMessage", IDS_INSTANT_OPT_IN_MESSAGE },
76     { "defaultBrowserGroupName", IDS_OPTIONS_DEFAULTBROWSER_GROUP_NAME },
77   };
78 
79   RegisterStrings(localized_strings, resources, arraysize(resources));
80   RegisterTitle(localized_strings, "browserPage",
81                 IDS_OPTIONS_GENERAL_TAB_LABEL);
82 
83   localized_strings->SetString("instantLearnMoreLink",
84       ASCIIToUTF16(browser::InstantLearnMoreURL().spec()));
85   localized_strings->SetString("defaultBrowserUnknown",
86       l10n_util::GetStringFUTF16(IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN,
87           l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
88   localized_strings->SetString("defaultBrowserUseAsDefault",
89       l10n_util::GetStringFUTF16(IDS_OPTIONS_DEFAULTBROWSER_USEASDEFAULT,
90           l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
91 }
92 
RegisterMessages()93 void BrowserOptionsHandler::RegisterMessages() {
94   web_ui_->RegisterMessageCallback(
95       "setHomePage",
96       NewCallback(this, &BrowserOptionsHandler::SetHomePage));
97   web_ui_->RegisterMessageCallback(
98       "becomeDefaultBrowser",
99       NewCallback(this, &BrowserOptionsHandler::BecomeDefaultBrowser));
100   web_ui_->RegisterMessageCallback(
101       "setDefaultSearchEngine",
102       NewCallback(this, &BrowserOptionsHandler::SetDefaultSearchEngine));
103   web_ui_->RegisterMessageCallback(
104       "removeStartupPages",
105       NewCallback(this, &BrowserOptionsHandler::RemoveStartupPages));
106   web_ui_->RegisterMessageCallback(
107       "addStartupPage",
108       NewCallback(this, &BrowserOptionsHandler::AddStartupPage));
109   web_ui_->RegisterMessageCallback(
110       "editStartupPage",
111       NewCallback(this, &BrowserOptionsHandler::EditStartupPage));
112   web_ui_->RegisterMessageCallback(
113       "setStartupPagesToCurrentPages",
114       NewCallback(this, &BrowserOptionsHandler::SetStartupPagesToCurrentPages));
115   web_ui_->RegisterMessageCallback(
116       "requestAutocompleteSuggestions",
117       NewCallback(this,
118                   &BrowserOptionsHandler::RequestAutocompleteSuggestions));
119   web_ui_->RegisterMessageCallback(
120       "toggleShowBookmarksBar",
121       NewCallback(this, &BrowserOptionsHandler::ToggleShowBookmarksBar));
122 }
123 
Initialize()124 void BrowserOptionsHandler::Initialize() {
125   Profile* profile = web_ui_->GetProfile();
126 
127   // Create our favicon data source.
128   profile->GetChromeURLDataManager()->AddDataSource(
129       new FaviconSource(profile));
130 
131   homepage_.Init(prefs::kHomePage, profile->GetPrefs(), NULL);
132   default_browser_policy_.Init(prefs::kDefaultBrowserSettingEnabled,
133                                g_browser_process->local_state(),
134                                this);
135   UpdateDefaultBrowserState();
136   UpdateStartupPages();
137   UpdateSearchEngines();
138   banner_handler_.reset(
139       new OptionsManagedBannerHandler(web_ui_,
140                                       ASCIIToUTF16("BrowserOptions"),
141                                       OPTIONS_PAGE_GENERAL));
142 
143   autocomplete_controller_.reset(new AutocompleteController(profile, this));
144 }
145 
SetHomePage(const ListValue * args)146 void BrowserOptionsHandler::SetHomePage(const ListValue* args) {
147   std::string url_string;
148   std::string do_fixup_string;
149   int do_fixup;
150   CHECK_EQ(args->GetSize(), 2U);
151   CHECK(args->GetString(0, &url_string));
152   CHECK(args->GetString(1, &do_fixup_string));
153   CHECK(base::StringToInt(do_fixup_string, &do_fixup));
154 
155   if (do_fixup) {
156     GURL fixed_url = URLFixerUpper::FixupURL(url_string, std::string());
157     url_string = fixed_url.spec();
158   }
159   homepage_.SetValueIfNotManaged(url_string);
160 }
161 
UpdateDefaultBrowserState()162 void BrowserOptionsHandler::UpdateDefaultBrowserState() {
163 #if defined(OS_WIN)
164   // Check for side-by-side first.
165   if (!BrowserDistribution::GetDistribution()->CanSetAsDefault()) {
166     SetDefaultBrowserUIString(IDS_OPTIONS_DEFAULTBROWSER_SXS);
167     return;
168   }
169 #endif
170 
171 #if defined(OS_MACOSX)
172   ShellIntegration::DefaultBrowserState state =
173       ShellIntegration::IsDefaultBrowser();
174   int status_string_id;
175   if (state == ShellIntegration::IS_DEFAULT_BROWSER)
176     status_string_id = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
177   else if (state == ShellIntegration::NOT_DEFAULT_BROWSER)
178     status_string_id = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
179   else
180     status_string_id = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
181 
182   SetDefaultBrowserUIString(status_string_id);
183 #else
184   default_browser_worker_->StartCheckDefaultBrowser();
185 #endif
186 }
187 
BecomeDefaultBrowser(const ListValue * args)188 void BrowserOptionsHandler::BecomeDefaultBrowser(const ListValue* args) {
189   // If the default browser setting is managed then we should not be able to
190   // call this function.
191   if (default_browser_policy_.IsManaged())
192     return;
193 
194   UserMetricsRecordAction(UserMetricsAction("Options_SetAsDefaultBrowser"));
195 #if defined(OS_MACOSX)
196   if (ShellIntegration::SetAsDefaultBrowser())
197     UpdateDefaultBrowserState();
198 #else
199   default_browser_worker_->StartSetAsDefaultBrowser();
200   // Callback takes care of updating UI.
201 #endif
202 
203   // If the user attempted to make Chrome the default browser, then he/she
204   // arguably wants to be notified when that changes.
205   PrefService* prefs = web_ui_->GetProfile()->GetPrefs();
206   prefs->SetBoolean(prefs::kCheckDefaultBrowser, true);
207 }
208 
StatusStringIdForState(ShellIntegration::DefaultBrowserState state)209 int BrowserOptionsHandler::StatusStringIdForState(
210     ShellIntegration::DefaultBrowserState state) {
211   if (state == ShellIntegration::IS_DEFAULT_BROWSER)
212     return IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
213   if (state == ShellIntegration::NOT_DEFAULT_BROWSER)
214     return IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
215   return IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
216 }
217 
SetDefaultBrowserUIState(ShellIntegration::DefaultBrowserUIState state)218 void BrowserOptionsHandler::SetDefaultBrowserUIState(
219     ShellIntegration::DefaultBrowserUIState state) {
220   int status_string_id;
221   if (state == ShellIntegration::STATE_IS_DEFAULT)
222     status_string_id = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
223   else if (state == ShellIntegration::STATE_NOT_DEFAULT)
224     status_string_id = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
225   else if (state == ShellIntegration::STATE_UNKNOWN)
226     status_string_id = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
227   else
228     return;  // Still processing.
229 
230   SetDefaultBrowserUIString(status_string_id);
231 }
232 
SetDefaultBrowserUIString(int status_string_id)233 void BrowserOptionsHandler::SetDefaultBrowserUIString(int status_string_id) {
234   scoped_ptr<Value> status_string(Value::CreateStringValue(
235       l10n_util::GetStringFUTF16(status_string_id,
236                                  l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))));
237 
238   scoped_ptr<Value> is_default(Value::CreateBooleanValue(
239       status_string_id == IDS_OPTIONS_DEFAULTBROWSER_DEFAULT));
240 
241   scoped_ptr<Value> can_be_default(Value::CreateBooleanValue(
242       !default_browser_policy_.IsManaged() &&
243       (status_string_id == IDS_OPTIONS_DEFAULTBROWSER_DEFAULT ||
244        status_string_id == IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT)));
245 
246   web_ui_->CallJavascriptFunction("BrowserOptions.updateDefaultBrowserState",
247                                   *(status_string.get()),
248                                   *(is_default.get()),
249                                   *(can_be_default.get()));
250 }
251 
OnTemplateURLModelChanged()252 void BrowserOptionsHandler::OnTemplateURLModelChanged() {
253   if (!template_url_model_ || !template_url_model_->loaded())
254     return;
255 
256   const TemplateURL* default_url =
257       template_url_model_->GetDefaultSearchProvider();
258 
259   int default_index = 0;
260   ListValue search_engines;
261   std::vector<const TemplateURL*> model_urls =
262       template_url_model_->GetTemplateURLs();
263   for (size_t i = 0; i < model_urls.size(); ++i) {
264     if (!model_urls[i]->ShowInDefaultList())
265       continue;
266 
267     DictionaryValue* entry = new DictionaryValue();
268     entry->SetString("name", model_urls[i]->short_name());
269     entry->SetInteger("index", i);
270     search_engines.Append(entry);
271     if (model_urls[i] == default_url)
272       default_index = i;
273   }
274 
275   scoped_ptr<Value> default_value(Value::CreateIntegerValue(default_index));
276 
277   web_ui_->CallJavascriptFunction("BrowserOptions.updateSearchEngines",
278                                   search_engines, *(default_value.get()));
279 }
280 
SetDefaultSearchEngine(const ListValue * args)281 void BrowserOptionsHandler::SetDefaultSearchEngine(const ListValue* args) {
282   int selected_index = -1;
283   if (!ExtractIntegerValue(args, &selected_index)) {
284     NOTREACHED();
285     return;
286   }
287 
288   std::vector<const TemplateURL*> model_urls =
289       template_url_model_->GetTemplateURLs();
290   if (selected_index >= 0 &&
291       selected_index < static_cast<int>(model_urls.size()))
292     template_url_model_->SetDefaultSearchProvider(model_urls[selected_index]);
293 
294   UserMetricsRecordAction(UserMetricsAction("Options_SearchEngineChanged"));
295 }
296 
UpdateSearchEngines()297 void BrowserOptionsHandler::UpdateSearchEngines() {
298   template_url_model_ = web_ui_->GetProfile()->GetTemplateURLModel();
299   if (template_url_model_) {
300     template_url_model_->Load();
301     template_url_model_->AddObserver(this);
302     OnTemplateURLModelChanged();
303   }
304 }
305 
UpdateStartupPages()306 void BrowserOptionsHandler::UpdateStartupPages() {
307   Profile* profile = web_ui_->GetProfile();
308   startup_custom_pages_table_model_.reset(
309       new CustomHomePagesTableModel(profile));
310   startup_custom_pages_table_model_->SetObserver(this);
311 
312   const SessionStartupPref startup_pref =
313       SessionStartupPref::GetStartupPref(profile->GetPrefs());
314   startup_custom_pages_table_model_->SetURLs(startup_pref.urls);
315 }
316 
OnModelChanged()317 void BrowserOptionsHandler::OnModelChanged() {
318   ListValue startup_pages;
319   int page_count = startup_custom_pages_table_model_->RowCount();
320   std::vector<GURL> urls = startup_custom_pages_table_model_->GetURLs();
321   for (int i = 0; i < page_count; ++i) {
322     DictionaryValue* entry = new DictionaryValue();
323     entry->SetString("title", startup_custom_pages_table_model_->GetText(i, 0));
324     entry->SetString("url", urls[i].spec());
325     entry->SetString("tooltip",
326                      startup_custom_pages_table_model_->GetTooltip(i));
327     entry->SetString("modelIndex", base::IntToString(i));
328     startup_pages.Append(entry);
329   }
330 
331   web_ui_->CallJavascriptFunction("BrowserOptions.updateStartupPages",
332                                   startup_pages);
333 }
334 
OnItemsChanged(int start,int length)335 void BrowserOptionsHandler::OnItemsChanged(int start, int length) {
336   OnModelChanged();
337 }
338 
OnItemsAdded(int start,int length)339 void BrowserOptionsHandler::OnItemsAdded(int start, int length) {
340   OnModelChanged();
341 }
342 
OnItemsRemoved(int start,int length)343 void BrowserOptionsHandler::OnItemsRemoved(int start, int length) {
344   OnModelChanged();
345 }
346 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)347 void BrowserOptionsHandler::Observe(NotificationType type,
348                      const NotificationSource& source,
349                      const NotificationDetails& details) {
350   UpdateDefaultBrowserState();
351 }
352 
SetStartupPagesToCurrentPages(const ListValue * args)353 void BrowserOptionsHandler::SetStartupPagesToCurrentPages(
354     const ListValue* args) {
355   startup_custom_pages_table_model_->SetToCurrentlyOpenPages();
356   SaveStartupPagesPref();
357 }
358 
RemoveStartupPages(const ListValue * args)359 void BrowserOptionsHandler::RemoveStartupPages(const ListValue* args) {
360   for (int i = args->GetSize() - 1; i >= 0; --i) {
361     std::string string_value;
362     CHECK(args->GetString(i, &string_value));
363 
364     int selected_index;
365     base::StringToInt(string_value, &selected_index);
366     if (selected_index < 0 ||
367         selected_index >= startup_custom_pages_table_model_->RowCount()) {
368       NOTREACHED();
369       return;
370     }
371     startup_custom_pages_table_model_->Remove(selected_index);
372   }
373 
374   SaveStartupPagesPref();
375 }
376 
AddStartupPage(const ListValue * args)377 void BrowserOptionsHandler::AddStartupPage(const ListValue* args) {
378   std::string url_string;
379   CHECK_EQ(args->GetSize(), 1U);
380   CHECK(args->GetString(0, &url_string));
381 
382   GURL url = URLFixerUpper::FixupURL(url_string, std::string());
383   int index = startup_custom_pages_table_model_->RowCount();
384   startup_custom_pages_table_model_->Add(index, url);
385   SaveStartupPagesPref();
386 }
387 
EditStartupPage(const ListValue * args)388 void BrowserOptionsHandler::EditStartupPage(const ListValue* args) {
389   std::string url_string;
390   std::string index_string;
391   int index;
392   CHECK_EQ(args->GetSize(), 2U);
393   CHECK(args->GetString(0, &index_string));
394   CHECK(base::StringToInt(index_string, &index));
395   CHECK(args->GetString(1, &url_string));
396 
397   if (index < 0 || index > startup_custom_pages_table_model_->RowCount()) {
398     NOTREACHED();
399     return;
400   }
401 
402   std::vector<GURL> urls = startup_custom_pages_table_model_->GetURLs();
403   urls[index] = URLFixerUpper::FixupURL(url_string, std::string());
404   startup_custom_pages_table_model_->SetURLs(urls);
405 }
406 
SaveStartupPagesPref()407 void BrowserOptionsHandler::SaveStartupPagesPref() {
408   PrefService* prefs = web_ui_->GetProfile()->GetPrefs();
409 
410   SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs);
411   pref.urls = startup_custom_pages_table_model_->GetURLs();
412 
413   SessionStartupPref::SetStartupPref(prefs, pref);
414 }
415 
RequestAutocompleteSuggestions(const ListValue * args)416 void BrowserOptionsHandler::RequestAutocompleteSuggestions(
417     const ListValue* args) {
418   string16 input;
419   CHECK_EQ(args->GetSize(), 1U);
420   CHECK(args->GetString(0, &input));
421 
422   autocomplete_controller_->Start(input, string16(), true, false, false,
423                                   AutocompleteInput::ALL_MATCHES);
424 }
425 
ToggleShowBookmarksBar(const ListValue * args)426 void BrowserOptionsHandler::ToggleShowBookmarksBar(const ListValue* args) {
427   Source<Profile> source(web_ui_->GetProfile());
428   NotificationService::current()->Notify(
429       NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED,
430       source,
431       NotificationService::NoDetails());
432 }
433 
OnResultChanged(bool default_match_changed)434 void BrowserOptionsHandler::OnResultChanged(bool default_match_changed) {
435   const AutocompleteResult& result = autocomplete_controller_->result();
436   ListValue suggestions;
437   for (size_t i = 0; i < result.size(); ++i) {
438     const AutocompleteMatch& match = result.match_at(i);
439     AutocompleteMatch::Type type = match.type;
440     if (type != AutocompleteMatch::HISTORY_URL &&
441         type != AutocompleteMatch::HISTORY_TITLE &&
442         type != AutocompleteMatch::HISTORY_BODY &&
443         type != AutocompleteMatch::HISTORY_KEYWORD &&
444         type != AutocompleteMatch::NAVSUGGEST)
445       continue;
446     DictionaryValue* entry = new DictionaryValue();
447     entry->SetString("title", match.description);
448     entry->SetString("displayURL", match.contents);
449     entry->SetString("url", match.destination_url.spec());
450     suggestions.Append(entry);
451   }
452 
453   web_ui_->CallJavascriptFunction(
454       "BrowserOptions.updateAutocompleteSuggestions", suggestions);
455 }
456