Home | History | Annotate | Download | only in options
      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    335 void BrowserOptionsHandler::OnItemsChanged(int start, int length) {
    336   OnModelChanged();
    337 }
    338 
    339 void BrowserOptionsHandler::OnItemsAdded(int start, int length) {
    340   OnModelChanged();
    341 }
    342 
    343 void BrowserOptionsHandler::OnItemsRemoved(int start, int length) {
    344   OnModelChanged();
    345 }
    346 
    347 void BrowserOptionsHandler::Observe(NotificationType type,
    348                      const NotificationSource& source,
    349                      const NotificationDetails& details) {
    350   UpdateDefaultBrowserState();
    351 }
    352 
    353 void BrowserOptionsHandler::SetStartupPagesToCurrentPages(
    354     const ListValue* args) {
    355   startup_custom_pages_table_model_->SetToCurrentlyOpenPages();
    356   SaveStartupPagesPref();
    357 }
    358 
    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 
    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 
    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 
    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 
    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 
    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 
    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