Logo Search packages:      
Sourcecode: chromium-browser version File versions  Download package

advanced_contents_gtk.cc

// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/gtk/options/advanced_contents_gtk.h"

#include <sys/types.h>
#include <sys/wait.h>

#include <string>
#include <vector>

#include "app/gtk_signal.h"
#include "app/gtk_util.h"
#include "app/l10n_util.h"
#include "base/basictypes.h"
#include "base/env_var.h"
#include "base/file_util.h"
#include "base/linux_util.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_tokenizer.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/fonts_languages_window.h"
#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
#include "chrome/browser/gtk/clear_browsing_data_dialog_gtk.h"
#include "chrome/browser/gtk/gtk_chrome_link_button.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/gtk/options/content_settings_window_gtk.h"
#include "chrome/browser/gtk/options/options_layout_gtk.h"
#include "chrome/browser/net/dns_global.h"
#include "chrome/browser/options_page_base.h"
#include "chrome/browser/options_util.h"
#include "chrome/browser/pref_member.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/process_watcher.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"

namespace {

// Command used to configure GNOME proxy settings. The command was renamed
// in January 2009, so both are used to work on both old and new systems.
const char* kOldGNOMEProxyConfigCommand[] = {"gnome-network-preferences", NULL};
const char* kGNOMEProxyConfigCommand[] = {"gnome-network-properties", NULL};
// KDE3 and KDE4 are only slightly different, but incompatible. Go figure.
const char* kKDE3ProxyConfigCommand[] = {"kcmshell", "proxy", NULL};
const char* kKDE4ProxyConfigCommand[] = {"kcmshell4", "proxy", NULL};

// The URL for Linux ssl certificate configuration help.
const char* const kLinuxCertificatesConfigUrl =
    "http://code.google.com/p/chromium/wiki/LinuxCertManagement";

// The URL for Linux proxy configuration help when not running under a
// supported desktop environment.
const char kLinuxProxyConfigUrl[] = "about:linux-proxy-config";

// The pixel width we wrap labels at.
// TODO(evanm): make the labels wrap at the appropriate width.
const int kWrapWidth = 475;

GtkWidget* CreateWrappedLabel(int string_id) {
  GtkWidget* label = gtk_label_new(
      l10n_util::GetStringUTF8(string_id).c_str());
  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
  gtk_widget_set_size_request(label, kWrapWidth, -1);
  return label;
}

GtkWidget* CreateCheckButtonWithWrappedLabel(int string_id) {
  GtkWidget* checkbox = gtk_check_button_new();
  gtk_container_add(GTK_CONTAINER(checkbox),
                    CreateWrappedLabel(string_id));
  return checkbox;
}

GtkWidget* AddCheckButtonWithWrappedLabel(int string_id,
                                          GtkWidget* container,
                                          GCallback handler,
                                          gpointer data) {
  GtkWidget* checkbox = CreateCheckButtonWithWrappedLabel(string_id);
  gtk_box_pack_start(GTK_BOX(container), checkbox, FALSE, FALSE, 0);
  g_signal_connect(checkbox, "toggled", handler, data);

  return checkbox;
}

// Don't let the widget handle scroll events. Instead, pass it on to the
// parent widget.
gboolean PassScrollToParent(GtkWidget* widget, GdkEvent* event,
                            gpointer unused) {
  if (widget->parent)
    gtk_propagate_event(widget->parent, event);

  return TRUE;
}

// Recursively search for a combo box among the children of |widget|.
void SearchForComboBox(GtkWidget* widget, gpointer data) {
  if (GTK_IS_COMBO_BOX(widget)) {
    *reinterpret_cast<GtkWidget**>(data) = widget;
  } else if (GTK_IS_CONTAINER(widget)) {
    gtk_container_foreach(GTK_CONTAINER(widget), SearchForComboBox, data);
  }
}

// Letting the combo boxes in the advanced options page handle scroll events is
// annoying because they fight with the scrolled window. Also,
// GtkFileChooserButton is buggy in that if you scroll on it very quickly it
// spews Gtk-WARNINGs, which causes us to crash in debug. This function disables
// scrolling for the combo box in |widget| (the first one it finds in a DFS).
void DisableScrolling(GtkWidget* widget) {
  gpointer combo_box_ptr = NULL;
  SearchForComboBox(widget, &combo_box_ptr);

  if (!combo_box_ptr) {
    NOTREACHED() << " Did not find a combo box in this widget.";
    return;
  }

  g_signal_connect(GTK_WIDGET(combo_box_ptr), "scroll-event",
                   G_CALLBACK(PassScrollToParent), NULL);
}

}  // anonymous namespace


///////////////////////////////////////////////////////////////////////////////
// DownloadSection

class DownloadSection : public OptionsPageBase {
 public:
  explicit DownloadSection(Profile* profile);
  virtual ~DownloadSection() {}

  GtkWidget* get_page_widget() const {
    return page_;
  }

 private:
  // Overridden from OptionsPageBase.
  virtual void NotifyPrefChanged(const std::wstring* pref_name);

  // Callbacks for the widgets.
  static void OnDownloadLocationChanged(GtkFileChooser* widget,
                                        DownloadSection* section);
  static void OnDownloadAskForSaveLocationChanged(GtkWidget* widget,
                                                  DownloadSection* section);
  static void OnResetFileHandlersClicked(GtkButton *button,
                                         DownloadSection* section);

  // The widgets for the download options.
  GtkWidget* download_location_button_;
  GtkWidget* download_ask_for_save_location_checkbox_;
  GtkWidget* reset_file_handlers_label_;
  GtkWidget* reset_file_handlers_button_;

  // The widget containing the options for this section.
  GtkWidget* page_;

  // Pref members.
  StringPrefMember default_download_location_;
  BooleanPrefMember ask_for_save_location_;
  StringPrefMember auto_open_files_;

  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
  // then turning around and saving them again.
  bool pref_changing_;

  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;

  DISALLOW_COPY_AND_ASSIGN(DownloadSection);
};

DownloadSection::DownloadSection(Profile* profile)
    : OptionsPageBase(profile),
      pref_changing_(true) {
  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);

  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
      page_, profile));

  // Download location options.
  download_location_button_ = gtk_file_chooser_button_new(
      l10n_util::GetStringUTF8(
          IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_WINDOW_TITLE).c_str(),
      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
  g_signal_connect(download_location_button_, "selection-changed",
                   G_CALLBACK(OnDownloadLocationChanged), this);
  DisableScrolling(download_location_button_);

  // Add the default download path to the list of shortcuts in the selector.
  FilePath default_download_path;
  if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS,
                        &default_download_path)) {
    NOTREACHED();
  } else {
    if (!gtk_file_chooser_add_shortcut_folder(
        GTK_FILE_CHOOSER(download_location_button_),
        default_download_path.value().c_str(),
        NULL)) {
      NOTREACHED();
    }
  }

  GtkWidget* download_location_control = gtk_util::CreateLabeledControlsGroup(
      NULL,
      l10n_util::GetStringUTF8(
          IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE).c_str(),
      download_location_button_,
      NULL);
  gtk_box_pack_start(GTK_BOX(page_), download_location_control,
                     FALSE, FALSE, 0);

  download_ask_for_save_location_checkbox_ = CreateCheckButtonWithWrappedLabel(
      IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION);
  gtk_box_pack_start(GTK_BOX(page_), download_ask_for_save_location_checkbox_,
                     FALSE, FALSE, 0);
  g_signal_connect(download_ask_for_save_location_checkbox_, "clicked",
                   G_CALLBACK(OnDownloadAskForSaveLocationChanged), this);
  accessible_widget_helper_->SetWidgetName(
      download_ask_for_save_location_checkbox_,
      IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION);

  // Option for resetting file handlers.
  reset_file_handlers_label_ = CreateWrappedLabel(
      IDS_OPTIONS_AUTOOPENFILETYPES_INFO);
  gtk_misc_set_alignment(GTK_MISC(reset_file_handlers_label_), 0, 0);
  gtk_box_pack_start(GTK_BOX(page_), reset_file_handlers_label_,
                     FALSE, FALSE, 0);

  reset_file_handlers_button_ = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(
          IDS_OPTIONS_AUTOOPENFILETYPES_RESETTODEFAULT).c_str());
  g_signal_connect(reset_file_handlers_button_, "clicked",
                   G_CALLBACK(OnResetFileHandlersClicked), this);
  // Stick it in an hbox so it doesn't expand to the whole width.
  GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(button_hbox),
                     reset_file_handlers_button_,
                     FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(page_),
                     gtk_util::IndentWidget(button_hbox),
                     FALSE, FALSE, 0);

  // Init prefs watchers.
  default_download_location_.Init(prefs::kDownloadDefaultDirectory,
                                  profile->GetPrefs(), this);
  ask_for_save_location_.Init(prefs::kPromptForDownload,
                              profile->GetPrefs(), this);
  auto_open_files_.Init(prefs::kDownloadExtensionsToOpen, profile->GetPrefs(),
                        this);

  NotifyPrefChanged(NULL);
}

void DownloadSection::NotifyPrefChanged(const std::wstring* pref_name) {
  pref_changing_ = true;
  if (!pref_name || *pref_name == prefs::kDownloadDefaultDirectory) {
    gtk_file_chooser_set_current_folder(
        GTK_FILE_CHOOSER(download_location_button_),
        FilePath::FromWStringHack(
            default_download_location_.GetValue()).value().c_str());
  }

  if (!pref_name || *pref_name == prefs::kPromptForDownload) {
    gtk_toggle_button_set_active(
        GTK_TOGGLE_BUTTON(download_ask_for_save_location_checkbox_),
        ask_for_save_location_.GetValue());
  }

  if (!pref_name || *pref_name == prefs::kDownloadExtensionsToOpen) {
    bool enabled =
        profile()->GetDownloadManager()->HasAutoOpenFileTypesRegistered();
    gtk_widget_set_sensitive(reset_file_handlers_label_, enabled);
    gtk_widget_set_sensitive(reset_file_handlers_button_, enabled);
  }
  pref_changing_ = false;
}

// static
void DownloadSection::OnDownloadLocationChanged(GtkFileChooser* widget,
                                                DownloadSection* section) {
  if (section->pref_changing_)
    return;

  gchar* folder = gtk_file_chooser_get_filename(widget);
  FilePath path(folder);
  g_free(folder);
  // Gtk seems to call this signal multiple times, so we only set the pref and
  // metric if something actually changed.
  if (path.ToWStringHack() != section->default_download_location_.GetValue()) {
    section->default_download_location_.SetValue(path.ToWStringHack());
    section->UserMetricsRecordAction(
        UserMetricsAction("Options_SetDownloadDirectory"),
        section->profile()->GetPrefs());
  }
}

// static
void DownloadSection::OnDownloadAskForSaveLocationChanged(
    GtkWidget* widget, DownloadSection* section) {
  if (section->pref_changing_)
    return;
  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  if (enabled) {
    section->UserMetricsRecordAction(
        UserMetricsAction("Options_AskForSaveLocation_Enable"),
        section->profile()->GetPrefs());
  } else {
    section->UserMetricsRecordAction(
        UserMetricsAction("Options_AskForSaveLocation_Disable"),
        section->profile()->GetPrefs());
  }
  section->ask_for_save_location_.SetValue(enabled);
}

// static
void DownloadSection::OnResetFileHandlersClicked(GtkButton *button,
                                                 DownloadSection* section) {
  section->profile()->GetDownloadManager()->ResetAutoOpenFiles();
  section->UserMetricsRecordAction(
      UserMetricsAction("Options_ResetAutoOpenFiles"),
      section->profile()->GetPrefs());
}

///////////////////////////////////////////////////////////////////////////////
// NetworkSection

class NetworkSection : public OptionsPageBase {
 public:
  explicit NetworkSection(Profile* profile);
  virtual ~NetworkSection() {}

  GtkWidget* get_page_widget() const {
    return page_;
  }

 private:
  struct ProxyConfigCommand {
    std::string binary;
    const char** argv;
  };
  // The callback functions for invoking the proxy config dialog.
  static void OnChangeProxiesButtonClicked(GtkButton *button,
                                           NetworkSection* section);
  // Search $PATH to find one of the commands. Store the full path to
  // it in the |binary| field and the command array index in in |index|.
  static bool SearchPATH(ProxyConfigCommand* commands, size_t ncommands,
                         size_t* index);
  // Start the given proxy configuration utility.
  static void StartProxyConfigUtil(const ProxyConfigCommand& command);

  // The widget containing the options for this section.
  GtkWidget* page_;

  DISALLOW_COPY_AND_ASSIGN(NetworkSection);
};

NetworkSection::NetworkSection(Profile* profile)
    : OptionsPageBase(profile) {
  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);

  GtkWidget* proxy_description_label = CreateWrappedLabel(
      IDS_OPTIONS_PROXIES_LABEL);
  gtk_misc_set_alignment(GTK_MISC(proxy_description_label), 0, 0);
  gtk_box_pack_start(GTK_BOX(page_), proxy_description_label,
                     FALSE, FALSE, 0);

  GtkWidget* change_proxies_button = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(
          IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON).c_str());
  g_signal_connect(change_proxies_button, "clicked",
                   G_CALLBACK(OnChangeProxiesButtonClicked), this);

  // Stick it in an hbox so it doesn't expand to the whole width.
  GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(button_hbox),
                     change_proxies_button,
                     FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(page_),
                     gtk_util::IndentWidget(button_hbox),
                     FALSE, FALSE, 0);
}

// static
void NetworkSection::OnChangeProxiesButtonClicked(GtkButton *button,
                                                  NetworkSection* section) {
  section->UserMetricsRecordAction(UserMetricsAction("Options_ChangeProxies"),
                                   NULL);

  scoped_ptr<base::EnvVarGetter> env_getter(base::EnvVarGetter::Create());

  ProxyConfigCommand command;
  bool found_command = false;
  switch (base::GetDesktopEnvironment(env_getter.get())) {
    case base::DESKTOP_ENVIRONMENT_GNOME: {
      size_t index;
      ProxyConfigCommand commands[2];
      commands[0].argv = kGNOMEProxyConfigCommand;
      commands[1].argv = kOldGNOMEProxyConfigCommand;
      found_command = SearchPATH(commands, 2, &index);
      if (found_command)
        command = commands[index];
      break;
    }

    case base::DESKTOP_ENVIRONMENT_KDE3:
      command.argv = kKDE3ProxyConfigCommand;
      found_command = SearchPATH(&command, 1, NULL);
      break;

    case base::DESKTOP_ENVIRONMENT_KDE4:
      command.argv = kKDE4ProxyConfigCommand;
      found_command = SearchPATH(&command, 1, NULL);
      break;

    case base::DESKTOP_ENVIRONMENT_XFCE:
    case base::DESKTOP_ENVIRONMENT_OTHER:
      break;
  }

  if (found_command) {
    StartProxyConfigUtil(command);
  } else {
    const char* name = base::GetDesktopEnvironmentName(env_getter.get());
    if (name)
      LOG(ERROR) << "Could not find " << name << " network settings in $PATH";
    BrowserList::GetLastActive()->
        OpenURL(GURL(kLinuxProxyConfigUrl),
                GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
  }
}

// static
bool NetworkSection::SearchPATH(ProxyConfigCommand* commands, size_t ncommands,
                                size_t* index) {
  const char* path = getenv("PATH");
  if (!path)
    return false;
  FilePath bin_path;
  CStringTokenizer tk(path, path + strlen(path), ":");
  // Search $PATH looking for the commands in order.
  while (tk.GetNext()) {
    for (size_t i = 0; i < ncommands; i++) {
      bin_path = FilePath(tk.token()).Append(commands[i].argv[0]);
      if (file_util::PathExists(bin_path)) {
        commands[i].binary = bin_path.value();
        if (index)
          *index = i;
        return true;
      }
    }
  }
  // Did not find any of the binaries in $PATH.
  return false;
}

// static
void NetworkSection::StartProxyConfigUtil(const ProxyConfigCommand& command) {
  std::vector<std::string> argv;
  argv.push_back(command.binary);
  for (size_t i = 1; command.argv[i]; i++)
    argv.push_back(command.argv[i]);
  base::file_handle_mapping_vector no_files;
  base::ProcessHandle handle;
  if (!base::LaunchApp(argv, no_files, false, &handle)) {
    LOG(ERROR) << "StartProxyConfigUtil failed to start " << command.binary;
    BrowserList::GetLastActive()->
        OpenURL(GURL(kLinuxProxyConfigUrl), GURL(), NEW_FOREGROUND_TAB,
                PageTransition::LINK);
    return;
  }
  ProcessWatcher::EnsureProcessGetsReaped(handle);
}

///////////////////////////////////////////////////////////////////////////////
// TranslateSection

class TranslateSection : public OptionsPageBase {
 public:
  explicit TranslateSection(Profile* profile);
  virtual ~TranslateSection() {}

  GtkWidget* get_page_widget() const {
    return page_;
  }

 private:
  // Overridden from OptionsPageBase.
  virtual void NotifyPrefChanged(const std::wstring* pref_name);

  CHROMEGTK_CALLBACK_0(TranslateSection, void, OnTranslateClicked);

  // Preferences for this section:
  BooleanPrefMember enable_translate_;

  // The widget containing the options for this section.
  GtkWidget* page_;

  // The checkbox.
  GtkWidget* translate_checkbox_;

  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
  // then turning around and saving them again.
  bool pref_changing_;

  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;

  DISALLOW_COPY_AND_ASSIGN(TranslateSection);
};

TranslateSection::TranslateSection(Profile* profile)
    : OptionsPageBase(profile),
      pref_changing_(true) {
  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);

  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
      page_, profile));

  translate_checkbox_ = CreateCheckButtonWithWrappedLabel(
      IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE);
  gtk_box_pack_start(GTK_BOX(page_), translate_checkbox_,
                     FALSE, FALSE, 0);
  g_signal_connect(translate_checkbox_, "clicked",
                   G_CALLBACK(OnTranslateClickedThunk), this);
  accessible_widget_helper_->SetWidgetName(
      translate_checkbox_,
      IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE);

  // Init member prefs so we can update the controls if prefs change.
  enable_translate_.Init(prefs::kEnableTranslate, profile->GetPrefs(), this);

  NotifyPrefChanged(NULL);
}

void TranslateSection::NotifyPrefChanged(const std::wstring* pref_name) {
  pref_changing_ = true;
  if (!pref_name || *pref_name == prefs::kEnableTranslate) {
    gtk_toggle_button_set_active(
        GTK_TOGGLE_BUTTON(translate_checkbox_), enable_translate_.GetValue());
  }
  pref_changing_ = false;
}

void TranslateSection::OnTranslateClicked(GtkWidget* widget) {
  if (pref_changing_)
    return;
  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  UserMetricsRecordAction(
      enabled ?
      UserMetricsAction("Options_Translate_Enable") :
      UserMetricsAction("Options_Translate_Disable"),
      profile()->GetPrefs());
  enable_translate_.SetValue(enabled);
}

///////////////////////////////////////////////////////////////////////////////
// PrivacySection

class PrivacySection : public OptionsPageBase {
 public:
  explicit PrivacySection(Profile* profile);
  virtual ~PrivacySection() {}

  GtkWidget* get_page_widget() const {
    return page_;
  }

 private:
  // Overridden from OptionsPageBase.
  virtual void NotifyPrefChanged(const std::wstring* pref_name);

  // Try to make the the crash stats consent and the metrics upload
  // permission match the |reporting_enabled_checkbox_|.
  void ResolveMetricsReportingEnabled();

  // Inform the user that the browser must be restarted for changes to take
  // effect.
  void ShowRestartMessageBox() const;

  // The callback functions for the options widgets.
  static void OnContentSettingsClicked(GtkButton* button,
                                       PrivacySection* privacy_section);
  static void OnClearBrowsingDataButtonClicked(GtkButton* widget,
                                               PrivacySection* page);
  static void OnLearnMoreLinkClicked(GtkButton *button,
                                     PrivacySection* privacy_section);
  static void OnEnableLinkDoctorChange(GtkWidget* widget,
                                       PrivacySection* options_window);
  static void OnEnableSuggestChange(GtkWidget* widget,
                                    PrivacySection* options_window);
  static void OnDNSPrefetchingChange(GtkWidget* widget,
                                     PrivacySection* options_window);
  static void OnSafeBrowsingChange(GtkWidget* widget,
                                   PrivacySection* options_window);
  static void OnLoggingChange(GtkWidget* widget,
                              PrivacySection* options_window);

  // The widget containing the options for this section.
  GtkWidget* page_;

  // The widgets for the privacy options.
  GtkWidget* enable_link_doctor_checkbox_;
  GtkWidget* enable_suggest_checkbox_;
  GtkWidget* enable_dns_prefetching_checkbox_;
  GtkWidget* enable_safe_browsing_checkbox_;
#if defined(GOOGLE_CHROME_BUILD)
  GtkWidget* reporting_enabled_checkbox_;
#endif

  // Preferences for this section:
  BooleanPrefMember alternate_error_pages_;
  BooleanPrefMember use_suggest_;
  BooleanPrefMember dns_prefetch_enabled_;
  BooleanPrefMember safe_browsing_;
  BooleanPrefMember enable_metrics_recording_;

  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
  // then turning around and saving them again.
  bool pref_changing_;

  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;

  DISALLOW_COPY_AND_ASSIGN(PrivacySection);
};

PrivacySection::PrivacySection(Profile* profile)
    : OptionsPageBase(profile),
      pref_changing_(true) {
  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);

  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
      page_, profile));

  GtkWidget* content_button = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(
          IDS_OPTIONS_PRIVACY_CONTENT_SETTINGS_BUTTON).c_str());
  g_signal_connect(content_button, "clicked",
                   G_CALLBACK(OnContentSettingsClicked), this);

  GtkWidget* clear_data_button = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_OPTIONS_PRIVACY_CLEAR_DATA_BUTTON).c_str());
  g_signal_connect(clear_data_button, "clicked",
                   G_CALLBACK(OnClearBrowsingDataButtonClicked), this);

  // Stick it in an hbox so it doesn't expand to the whole width.
  GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_box_pack_start(GTK_BOX(button_hbox), content_button, FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(button_hbox), clear_data_button, FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(page_), gtk_util::IndentWidget(button_hbox),
                     FALSE, FALSE, 0);

  GtkWidget* section_description_label = CreateWrappedLabel(
      IDS_OPTIONS_DISABLE_SERVICES);
  gtk_misc_set_alignment(GTK_MISC(section_description_label), 0, 0);
  gtk_box_pack_start(GTK_BOX(page_), section_description_label,
                     FALSE, FALSE, 0);

  GtkWidget* learn_more_link = gtk_chrome_link_button_new(
      l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str());
  // Stick it in an hbox so it doesn't expand to the whole width.
  GtkWidget* learn_more_hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(learn_more_hbox), learn_more_link,
                     FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(page_), learn_more_hbox,
                     FALSE, FALSE, 0);
  g_signal_connect(learn_more_link, "clicked",
                   G_CALLBACK(OnLearnMoreLinkClicked), this);

  enable_link_doctor_checkbox_ = CreateCheckButtonWithWrappedLabel(
      IDS_OPTIONS_LINKDOCTOR_PREF);
  gtk_box_pack_start(GTK_BOX(page_), enable_link_doctor_checkbox_,
                     FALSE, FALSE, 0);
  g_signal_connect(enable_link_doctor_checkbox_, "clicked",
                   G_CALLBACK(OnEnableLinkDoctorChange), this);
  accessible_widget_helper_->SetWidgetName(
      enable_link_doctor_checkbox_, IDS_OPTIONS_LINKDOCTOR_PREF);

  enable_suggest_checkbox_ = CreateCheckButtonWithWrappedLabel(
      IDS_OPTIONS_SUGGEST_PREF);
  gtk_box_pack_start(GTK_BOX(page_), enable_suggest_checkbox_,
                     FALSE, FALSE, 0);
  g_signal_connect(enable_suggest_checkbox_, "clicked",
                   G_CALLBACK(OnEnableSuggestChange), this);
  accessible_widget_helper_->SetWidgetName(
      enable_suggest_checkbox_, IDS_OPTIONS_SUGGEST_PREF);

  enable_dns_prefetching_checkbox_ = CreateCheckButtonWithWrappedLabel(
      IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION);
  gtk_box_pack_start(GTK_BOX(page_), enable_dns_prefetching_checkbox_,
                     FALSE, FALSE, 0);
  g_signal_connect(enable_dns_prefetching_checkbox_, "clicked",
                   G_CALLBACK(OnDNSPrefetchingChange), this);
  accessible_widget_helper_->SetWidgetName(
      enable_dns_prefetching_checkbox_,
      IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION);

  enable_safe_browsing_checkbox_ = CreateCheckButtonWithWrappedLabel(
      IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION);
  gtk_box_pack_start(GTK_BOX(page_), enable_safe_browsing_checkbox_,
                     FALSE, FALSE, 0);
  g_signal_connect(enable_safe_browsing_checkbox_, "clicked",
                   G_CALLBACK(OnSafeBrowsingChange), this);
  accessible_widget_helper_->SetWidgetName(
      enable_safe_browsing_checkbox_,
      IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION);

#if defined(GOOGLE_CHROME_BUILD)
  reporting_enabled_checkbox_ = CreateCheckButtonWithWrappedLabel(
      IDS_OPTIONS_ENABLE_LOGGING);
  gtk_box_pack_start(GTK_BOX(page_), reporting_enabled_checkbox_,
                     FALSE, FALSE, 0);
  g_signal_connect(reporting_enabled_checkbox_, "clicked",
                   G_CALLBACK(OnLoggingChange), this);
  accessible_widget_helper_->SetWidgetName(
      reporting_enabled_checkbox_, IDS_OPTIONS_ENABLE_LOGGING);
#endif

  // Init member prefs so we can update the controls if prefs change.
  alternate_error_pages_.Init(prefs::kAlternateErrorPagesEnabled,
                              profile->GetPrefs(), this);
  use_suggest_.Init(prefs::kSearchSuggestEnabled,
                    profile->GetPrefs(), this);
  dns_prefetch_enabled_.Init(prefs::kDnsPrefetchingEnabled,
                             profile->GetPrefs(), this);
  safe_browsing_.Init(prefs::kSafeBrowsingEnabled, profile->GetPrefs(), this);
  enable_metrics_recording_.Init(prefs::kMetricsReportingEnabled,
                                 g_browser_process->local_state(), this);

  NotifyPrefChanged(NULL);
}

// static
void PrivacySection::OnContentSettingsClicked(GtkButton* button,
                                              PrivacySection* privacy_section) {
  ContentSettingsWindowGtk::Show(
      GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
      CONTENT_SETTINGS_TYPE_DEFAULT,
      privacy_section->profile());
}

// static
void PrivacySection::OnClearBrowsingDataButtonClicked(GtkButton* widget,
                                                      PrivacySection* section) {
  ClearBrowsingDataDialogGtk::Show(
      GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(widget))),
      section->profile());
}

// static
void PrivacySection::OnLearnMoreLinkClicked(GtkButton *button,
                                            PrivacySection* privacy_section) {
  BrowserList::GetLastActive()->
      OpenURL(GURL(l10n_util::GetStringUTF8(IDS_LEARN_MORE_PRIVACY_URL)),
              GURL(), NEW_WINDOW, PageTransition::LINK);
}

// static
void PrivacySection::OnEnableLinkDoctorChange(GtkWidget* widget,
                                              PrivacySection* privacy_section) {
  if (privacy_section->pref_changing_)
    return;
  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  privacy_section->UserMetricsRecordAction(
      enabled ?
          UserMetricsAction("Options_LinkDoctorCheckbox_Enable") :
          UserMetricsAction("Options_LinkDoctorCheckbox_Disable"),
      privacy_section->profile()->GetPrefs());
  privacy_section->alternate_error_pages_.SetValue(enabled);
}

// static
void PrivacySection::OnEnableSuggestChange(GtkWidget* widget,
                                           PrivacySection* privacy_section) {
  if (privacy_section->pref_changing_)
    return;
  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  privacy_section->UserMetricsRecordAction(
      enabled ?
          UserMetricsAction("Options_UseSuggestCheckbox_Enable") :
          UserMetricsAction("Options_UseSuggestCheckbox_Disable"),
      privacy_section->profile()->GetPrefs());
  privacy_section->use_suggest_.SetValue(enabled);
}

// static
void PrivacySection::OnDNSPrefetchingChange(GtkWidget* widget,
                                           PrivacySection* privacy_section) {
  if (privacy_section->pref_changing_)
    return;
  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  privacy_section->UserMetricsRecordAction(
      enabled ?
          UserMetricsAction("Options_DnsPrefetchCheckbox_Enable") :
          UserMetricsAction("Options_DnsPrefetchCheckbox_Disable"),
      privacy_section->profile()->GetPrefs());
  privacy_section->dns_prefetch_enabled_.SetValue(enabled);
  chrome_browser_net::EnableDnsPrefetch(enabled);
}

// static
void PrivacySection::OnSafeBrowsingChange(GtkWidget* widget,
                                          PrivacySection* privacy_section) {
  if (privacy_section->pref_changing_)
    return;
  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  privacy_section->UserMetricsRecordAction(
      enabled ?
          UserMetricsAction("Options_SafeBrowsingCheckbox_Enable") :
          UserMetricsAction("Options_SafeBrowsingCheckbox_Disable"),
      privacy_section->profile()->GetPrefs());
  privacy_section->safe_browsing_.SetValue(enabled);
  SafeBrowsingService* safe_browsing_service =
      g_browser_process->resource_dispatcher_host()->safe_browsing_service();
  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
      safe_browsing_service, &SafeBrowsingService::OnEnable, enabled));
}

// static
void PrivacySection::OnLoggingChange(GtkWidget* widget,
                                     PrivacySection* privacy_section) {
  if (privacy_section->pref_changing_)
    return;
  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  privacy_section->UserMetricsRecordAction(
      enabled ?
          UserMetricsAction("Options_MetricsReportingCheckbox_Enable") :
          UserMetricsAction("Options_MetricsReportingCheckbox_Disable"),
      privacy_section->profile()->GetPrefs());
  // Prevent us from being called again by ResolveMetricsReportingEnabled
  // resetting the checkbox if there was a problem.
  g_signal_handlers_block_by_func(widget,
                                  reinterpret_cast<gpointer>(OnLoggingChange),
                                  privacy_section);
  privacy_section->ResolveMetricsReportingEnabled();
  if (enabled == gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
    privacy_section->ShowRestartMessageBox();
  g_signal_handlers_unblock_by_func(widget,
                                    reinterpret_cast<gpointer>(OnLoggingChange),
                                    privacy_section);
  privacy_section->enable_metrics_recording_.SetValue(enabled);
}

void PrivacySection::NotifyPrefChanged(const std::wstring* pref_name) {
  pref_changing_ = true;
  if (!pref_name || *pref_name == prefs::kAlternateErrorPagesEnabled) {
    gtk_toggle_button_set_active(
        GTK_TOGGLE_BUTTON(enable_link_doctor_checkbox_),
        alternate_error_pages_.GetValue());
  }
  if (!pref_name || *pref_name == prefs::kSearchSuggestEnabled) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_suggest_checkbox_),
                                 use_suggest_.GetValue());
  }
  if (!pref_name || *pref_name == prefs::kDnsPrefetchingEnabled) {
    bool enabled = dns_prefetch_enabled_.GetValue();
    gtk_toggle_button_set_active(
        GTK_TOGGLE_BUTTON(enable_dns_prefetching_checkbox_), enabled);
    chrome_browser_net::EnableDnsPrefetch(enabled);
  }
  if (!pref_name || *pref_name == prefs::kSafeBrowsingEnabled) {
    gtk_toggle_button_set_active(
        GTK_TOGGLE_BUTTON(enable_safe_browsing_checkbox_),
        safe_browsing_.GetValue());
  }
#if defined(GOOGLE_CHROME_BUILD)
  if (!pref_name || *pref_name == prefs::kMetricsReportingEnabled) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_),
                                 enable_metrics_recording_.GetValue());
    ResolveMetricsReportingEnabled();
  }
#endif
  pref_changing_ = false;
}

void PrivacySection::ResolveMetricsReportingEnabled() {
#if defined(GOOGLE_CHROME_BUILD)
  bool enabled = gtk_toggle_button_get_active(
      GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_));

  enabled = OptionsUtil::ResolveMetricsReportingEnabled(enabled);

  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_),
                               enabled);
#endif
}

void PrivacySection::ShowRestartMessageBox() const {
  GtkWidget* dialog = gtk_message_dialog_new(
      GTK_WINDOW(gtk_widget_get_toplevel(page_)),
      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL),
      GTK_MESSAGE_INFO,
      GTK_BUTTONS_OK,
      "%s",
      l10n_util::GetStringUTF8(IDS_OPTIONS_RESTART_REQUIRED).c_str());
  gtk_util::ApplyMessageDialogQuirks(dialog);
  gtk_window_set_title(GTK_WINDOW(dialog),
      l10n_util::GetStringUTF8(IDS_PRODUCT_NAME).c_str());
  g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_destroy),
                           dialog);
  gtk_widget_show_all(dialog);
}

///////////////////////////////////////////////////////////////////////////////
// SecuritySection

class SecuritySection : public OptionsPageBase {
 public:
  explicit SecuritySection(Profile* profile);
  virtual ~SecuritySection() {}

  GtkWidget* get_page_widget() const {
    return page_;
  }

 private:
  // Overridden from OptionsPageBase.
  virtual void NotifyPrefChanged(const std::wstring* pref_name);

  // The callback functions for the options widgets.
  static void OnManageCertificatesClicked(GtkButton* button,
                                          SecuritySection* section);
  static void OnRevCheckingEnabledToggled(GtkToggleButton* togglebutton,
                                          SecuritySection* section);
  static void OnSSL2EnabledToggled(GtkToggleButton* togglebutton,
                                   SecuritySection* section);
  static void OnSSL3EnabledToggled(GtkToggleButton* togglebutton,
                                   SecuritySection* section);
  static void OnTLS1EnabledToggled(GtkToggleButton* togglebutton,
                                   SecuritySection* section);

  // The widget containing the options for this section.
  GtkWidget* page_;
  GtkWidget* rev_checking_enabled_checkbox_;
  GtkWidget* ssl2_enabled_checkbox_;
  GtkWidget* ssl3_enabled_checkbox_;
  GtkWidget* tls1_enabled_checkbox_;

  // SSLConfigService prefs.
  BooleanPrefMember rev_checking_enabled_;
  BooleanPrefMember ssl2_enabled_;
  BooleanPrefMember ssl3_enabled_;
  BooleanPrefMember tls1_enabled_;

  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
  // then turning around and saving them again.
  bool pref_changing_;

  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;

  DISALLOW_COPY_AND_ASSIGN(SecuritySection);
};

SecuritySection::SecuritySection(Profile* profile)
    : OptionsPageBase(profile),
      pref_changing_(true) {
  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);

  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
      page_, profile));

  GtkWidget* manage_certificates_label = CreateWrappedLabel(
      IDS_OPTIONS_CERTIFICATES_LABEL);
  gtk_misc_set_alignment(GTK_MISC(manage_certificates_label), 0, 0);
  gtk_box_pack_start(GTK_BOX(page_), manage_certificates_label,
                     FALSE, FALSE, 0);

  // TODO(mattm): change this to a button to launch the system certificate
  // manager, when one exists.
  GtkWidget* manage_certificates_link = gtk_chrome_link_button_new(
      l10n_util::GetStringUTF8(IDS_OPTIONS_CERTIFICATES_MANAGE_BUTTON).c_str());
  // Stick it in an hbox so it doesn't expand to the whole width.
  GtkWidget* manage_certificates_hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(manage_certificates_hbox),
                     manage_certificates_link, FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(page_),
                     gtk_util::IndentWidget(manage_certificates_hbox),
                     FALSE, FALSE, 0);
  g_signal_connect(manage_certificates_link, "clicked",
                   G_CALLBACK(OnManageCertificatesClicked), this);

  // TODO(mattm): should have a description label here and have the checkboxes
  // indented, but IDS_OPTIONS_SSL_GROUP_DESCRIPTION isn't appropriate and
  // didn't think of adding a Linux specific one before the string freeze.
  rev_checking_enabled_checkbox_ = AddCheckButtonWithWrappedLabel(
      IDS_OPTIONS_SSL_CHECKREVOCATION, page_,
      G_CALLBACK(OnRevCheckingEnabledToggled), this);
  accessible_widget_helper_->SetWidgetName(
      rev_checking_enabled_checkbox_, IDS_OPTIONS_SSL_CHECKREVOCATION);
  ssl2_enabled_checkbox_ = AddCheckButtonWithWrappedLabel(
      IDS_OPTIONS_SSL_USESSL2, page_, G_CALLBACK(OnSSL2EnabledToggled), this);
  accessible_widget_helper_->SetWidgetName(
      ssl2_enabled_checkbox_, IDS_OPTIONS_SSL_USESSL2);
  ssl3_enabled_checkbox_ = AddCheckButtonWithWrappedLabel(
      IDS_OPTIONS_SSL_USESSL3, page_, G_CALLBACK(OnSSL3EnabledToggled), this);
  accessible_widget_helper_->SetWidgetName(
      ssl3_enabled_checkbox_, IDS_OPTIONS_SSL_USESSL3);
  tls1_enabled_checkbox_ = AddCheckButtonWithWrappedLabel(
      IDS_OPTIONS_SSL_USETLS1, page_, G_CALLBACK(OnTLS1EnabledToggled), this);
  accessible_widget_helper_->SetWidgetName(
      tls1_enabled_checkbox_, IDS_OPTIONS_SSL_USETLS1);

  rev_checking_enabled_.Init(prefs::kCertRevocationCheckingEnabled,
                             profile->GetPrefs(), this);
  ssl2_enabled_.Init(prefs::kSSL2Enabled, profile->GetPrefs(), this);
  ssl3_enabled_.Init(prefs::kSSL3Enabled, profile->GetPrefs(), this);
  tls1_enabled_.Init(prefs::kTLS1Enabled, profile->GetPrefs(), this);

  NotifyPrefChanged(NULL);
}

void SecuritySection::NotifyPrefChanged(const std::wstring* pref_name) {
  pref_changing_ = true;
  if (!pref_name || *pref_name == prefs::kCertRevocationCheckingEnabled) {
    gtk_toggle_button_set_active(
        GTK_TOGGLE_BUTTON(rev_checking_enabled_checkbox_),
        rev_checking_enabled_.GetValue());
  }
  if (!pref_name || *pref_name == prefs::kSSL2Enabled) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ssl2_enabled_checkbox_),
                                 ssl2_enabled_.GetValue());
  }
  if (!pref_name || *pref_name == prefs::kSSL3Enabled) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ssl3_enabled_checkbox_),
                                 ssl3_enabled_.GetValue());
  }
  if (!pref_name || *pref_name == prefs::kTLS1Enabled) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tls1_enabled_checkbox_),
                                 tls1_enabled_.GetValue());
  }
  pref_changing_ = false;
}


// static
void SecuritySection::OnManageCertificatesClicked(GtkButton* button,
                                                  SecuritySection* section) {
  BrowserList::GetLastActive()->
      OpenURL(GURL(kLinuxCertificatesConfigUrl), GURL(), NEW_WINDOW,
              PageTransition::LINK);
}

// static
void SecuritySection::OnRevCheckingEnabledToggled(GtkToggleButton* togglebutton,
                                                  SecuritySection* section) {
  if (section->pref_changing_)
    return;

  bool enabled = gtk_toggle_button_get_active(togglebutton);
  if (enabled) {
    section->UserMetricsRecordAction(
        UserMetricsAction("Options_CheckCertRevocation_Enable"),
        NULL);
  } else {
    section->UserMetricsRecordAction(
        UserMetricsAction("Options_CheckCertRevocation_Disable"),
        NULL);
  }
  section->rev_checking_enabled_.SetValue(enabled);
}

// static
void SecuritySection::OnSSL2EnabledToggled(GtkToggleButton* togglebutton,
                                           SecuritySection* section) {
  if (section->pref_changing_)
    return;

  bool enabled = gtk_toggle_button_get_active(togglebutton);
  if (enabled) {
    section->UserMetricsRecordAction(UserMetricsAction("Options_SSL2_Enable"),
                                     NULL);
  } else {
    section->UserMetricsRecordAction(UserMetricsAction("Options_SSL2_Disable"),
                                     NULL);
  }
  section->ssl2_enabled_.SetValue(enabled);
}

// static
void SecuritySection::OnSSL3EnabledToggled(GtkToggleButton* togglebutton,
                                           SecuritySection* section) {
  if (section->pref_changing_)
    return;

  bool enabled = gtk_toggle_button_get_active(togglebutton);
  if (enabled) {
    section->UserMetricsRecordAction(UserMetricsAction("Options_SSL3_Enable"),
                                     NULL);
  } else {
    section->UserMetricsRecordAction(UserMetricsAction("Options_SSL3_Disable"),
                                     NULL);
  }
  section->ssl3_enabled_.SetValue(enabled);
}

// static
void SecuritySection::OnTLS1EnabledToggled(GtkToggleButton* togglebutton,
                                           SecuritySection* section) {
  if (section->pref_changing_)
    return;

  bool enabled = gtk_toggle_button_get_active(togglebutton);
  if (enabled) {
    section->UserMetricsRecordAction(UserMetricsAction("Options_TLS1_Enable"),
                                     NULL);
  } else {
    section->UserMetricsRecordAction(UserMetricsAction("Options_TLS1_Disable"),
                                     NULL);
  }
  section->tls1_enabled_.SetValue(enabled);
}

///////////////////////////////////////////////////////////////////////////////
// WebContentSection

class WebContentSection : public OptionsPageBase {
 public:
  explicit WebContentSection(Profile* profile);
  virtual ~WebContentSection() {}

  GtkWidget* get_page_widget() const {
    return page_;
  }

 private:
  // The callback functions for the options widgets.
  static void OnFontsAndLanguagesButtonClicked(GtkButton *button,
                                               WebContentSection* section);

  // The widget containing the options for this section.
  GtkWidget* page_;

  DISALLOW_COPY_AND_ASSIGN(WebContentSection);
};

WebContentSection::WebContentSection(Profile* profile)
    : OptionsPageBase(profile) {
  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);

  GtkWidget* fonts_and_languages_label = CreateWrappedLabel(
      IDS_OPTIONS_FONTSETTINGS_INFO);
  gtk_misc_set_alignment(GTK_MISC(fonts_and_languages_label), 0, 0);
  gtk_box_pack_start(GTK_BOX(page_), fonts_and_languages_label,
                     FALSE, FALSE, 0);

  GtkWidget* fonts_and_languages_button = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(
          IDS_OPTIONS_FONTSETTINGS_CONFIGUREFONTS_BUTTON).c_str());
  g_signal_connect(fonts_and_languages_button, "clicked",
                   G_CALLBACK(OnFontsAndLanguagesButtonClicked), this);
  // Stick it in an hbox so it doesn't expand to the whole width.
  GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(button_hbox),
                     fonts_and_languages_button,
                     FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(page_),
                     gtk_util::IndentWidget(button_hbox),
                     FALSE, FALSE, 0);

  // TODO(mattm): gears options would go here if we supported gears
}

// static
void WebContentSection::OnFontsAndLanguagesButtonClicked(
    GtkButton *button, WebContentSection* section) {
  ShowFontsLanguagesWindow(GTK_WINDOW(gtk_widget_get_toplevel(section->page_)),
                           FONTS_ENCODING_PAGE,
                           section->profile());
}

///////////////////////////////////////////////////////////////////////////////
// AdvancedContentsGtk

AdvancedContentsGtk::AdvancedContentsGtk(Profile* profile)
    : profile_(profile) {
  Init();
}

AdvancedContentsGtk::~AdvancedContentsGtk() {
}

void AdvancedContentsGtk::Init() {
  OptionsLayoutBuilderGtk options_builder;

  privacy_section_.reset(new PrivacySection(profile_));
  options_builder.AddOptionGroup(
      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY),
      privacy_section_->get_page_widget(), false);

  network_section_.reset(new NetworkSection(profile_));
  options_builder.AddOptionGroup(
      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_NETWORK),
      network_section_->get_page_widget(), false);

  translate_section_.reset(new TranslateSection(profile_));
  options_builder.AddOptionGroup(
      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_TRANSLATE),
      translate_section_->get_page_widget(), false);

  download_section_.reset(new DownloadSection(profile_));
  options_builder.AddOptionGroup(
      l10n_util::GetStringUTF8(IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME),
      download_section_->get_page_widget(), false);

  web_content_section_.reset(new WebContentSection(profile_));
  options_builder.AddOptionGroup(
      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_CONTENT),
      web_content_section_->get_page_widget(), false);

  security_section_.reset(new SecuritySection(profile_));
  options_builder.AddOptionGroup(
      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_SECURITY),
      security_section_->get_page_widget(), false);

  page_ = options_builder.get_page_widget();
}

Generated by  Doxygen 1.6.0   Back to index