summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/options
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-15 20:43:44 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-15 20:43:44 +0000
commit3ee88ee11b8fd2092ca1287e7c48f9f6c4ed886e (patch)
tree951a04950724ccc925f45e5a9d264b7ee49d09b3 /chrome/browser/views/options
parent7f858d1032720f471991db19c383e1af19c24088 (diff)
downloadchromium_src-3ee88ee11b8fd2092ca1287e7c48f9f6c4ed886e.zip
chromium_src-3ee88ee11b8fd2092ca1287e7c48f9f6c4ed886e.tar.gz
chromium_src-3ee88ee11b8fd2092ca1287e7c48f9f6c4ed886e.tar.bz2
Use tab to group "Show saved passwords" and "Exceptions"
BUG=9026 "Show saved passwords" and "Exceptions" were splited into 2 dialogs, group together in one single dialog with different pages by tabbing. Review URL: http://codereview.chromium.org/67055 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13786 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views/options')
-rw-r--r--chrome/browser/views/options/content_page_view.cc16
-rw-r--r--chrome/browser/views/options/content_page_view.h1
-rw-r--r--chrome/browser/views/options/exceptions_page_view.cc179
-rw-r--r--chrome/browser/views/options/exceptions_page_view.h69
-rw-r--r--chrome/browser/views/options/fonts_page_view.cc3
-rw-r--r--chrome/browser/views/options/languages_page_view.cc2
-rw-r--r--chrome/browser/views/options/passwords_exceptions_window_view.cc99
-rw-r--r--chrome/browser/views/options/passwords_exceptions_window_view.h64
-rw-r--r--chrome/browser/views/options/passwords_page_view.cc328
-rw-r--r--chrome/browser/views/options/passwords_page_view.h179
10 files changed, 924 insertions, 16 deletions
diff --git a/chrome/browser/views/options/content_page_view.cc b/chrome/browser/views/options/content_page_view.cc
index 10feabc9..7263505 100644
--- a/chrome/browser/views/options/content_page_view.cc
+++ b/chrome/browser/views/options/content_page_view.cc
@@ -15,8 +15,7 @@
#include "chrome/browser/shell_dialogs.h"
#include "chrome/browser/views/options/fonts_languages_window_view.h"
#include "chrome/browser/views/options/options_group_view.h"
-#include "chrome/browser/views/password_manager_view.h"
-#include "chrome/browser/views/password_manager_exceptions_view.h"
+#include "chrome/browser/views/options/passwords_exceptions_window_view.h"
#include "chrome/browser/views/standard_layout.h"
#include "chrome/common/gfx/chrome_canvas.h"
#include "chrome/common/l10n_util.h"
@@ -180,7 +179,6 @@ ContentPageView::ContentPageView(Profile* profile)
passwords_group_(NULL),
passwords_asktosave_radio_(NULL),
passwords_neversave_radio_(NULL),
- passwords_show_passwords_button_(NULL),
fonts_lang_group_(NULL),
fonts_and_languages_label_(NULL),
change_content_fonts_button_(NULL),
@@ -242,11 +240,8 @@ void ContentPageView::ButtonPressed(views::Button* sender) {
}
ask_to_save_passwords_.SetValue(enabled);
} else if (sender == passwords_exceptions_button_) {
- UserMetricsRecordAction(L"Options_ShowPasswordManagerExceptions", NULL);
- PasswordManagerExceptionsView::Show(profile());
- }else if (sender == passwords_show_passwords_button_) {
- UserMetricsRecordAction(L"Options_ShowPasswordManager", NULL);
- PasswordManagerView::Show(profile());
+ UserMetricsRecordAction(L"Options_ShowPasswordsExceptions", NULL);
+ PasswordsExceptionsWindowView::Show(profile());
} else if (sender == form_autofill_checkbox_) {
bool enabled = form_autofill_checkbox_->checked();
if (enabled) {
@@ -413,8 +408,6 @@ void ContentPageView::InitPasswordSavingGroup() {
kPasswordSavingRadioGroup);
passwords_neversave_radio_->set_listener(this);
passwords_neversave_radio_->SetMultiLine(true);
- passwords_show_passwords_button_ = new views::NativeButton(
- this, l10n_util::GetString(IDS_OPTIONS_PASSWORDS_SHOWPASSWORDS));
passwords_exceptions_button_ = new views::NativeButton(
this, l10n_util::GetString(IDS_OPTIONS_PASSWORDS_EXCEPTIONS));
@@ -444,8 +437,7 @@ void ContentPageView::InitPasswordSavingGroup() {
layout->StartRow(0, single_column_view_set_id);
layout->AddView(passwords_neversave_radio_);
layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
- layout->StartRow(0, double_column_view_set_id);
- layout->AddView(passwords_show_passwords_button_);
+ layout->StartRow(0, single_column_view_set_id);
layout->AddView(passwords_exceptions_button_);
passwords_group_ = new OptionsGroupView(
diff --git a/chrome/browser/views/options/content_page_view.h b/chrome/browser/views/options/content_page_view.h
index 98d2030..7102f63 100644
--- a/chrome/browser/views/options/content_page_view.h
+++ b/chrome/browser/views/options/content_page_view.h
@@ -70,7 +70,6 @@ class ContentPageView : public OptionsPageView,
OptionsGroupView* passwords_group_;
views::RadioButton* passwords_asktosave_radio_;
views::RadioButton* passwords_neversave_radio_;
- views::NativeButton* passwords_show_passwords_button_;
// Controls for the Form Autofill group
OptionsGroupView* form_autofill_group_;
diff --git a/chrome/browser/views/options/exceptions_page_view.cc b/chrome/browser/views/options/exceptions_page_view.cc
new file mode 100644
index 0000000..b4c580c
--- /dev/null
+++ b/chrome/browser/views/options/exceptions_page_view.cc
@@ -0,0 +1,179 @@
+// Copyright (c) 2009 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/views/options/exceptions_page_view.h"
+
+#include "base/string_util.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/views/standard_layout.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/pref_service.h"
+#include "chrome/views/background.h"
+#include "chrome/views/controls/button/native_button.h"
+#include "chrome/views/grid_layout.h"
+#include "grit/generated_resources.h"
+
+using views::ColumnSet;
+using views::GridLayout;
+
+///////////////////////////////////////////////////////////////////////////////
+// ExceptionsTableModel
+ExceptionsTableModel::ExceptionsTableModel(Profile* profile)
+ : PasswordsTableModel(profile) {
+}
+
+ExceptionsTableModel::~ExceptionsTableModel() {
+}
+
+std::wstring ExceptionsTableModel::GetText(int row, int col_id) {
+ DCHECK_EQ(col_id, IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN);
+ return PasswordsTableModel::GetText(row, col_id);
+}
+
+int ExceptionsTableModel::CompareValues(int row1, int row2,
+ int col_id) {
+ DCHECK_EQ(col_id, IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN);
+ return PasswordsTableModel::CompareValues(row1, row2, col_id);
+}
+
+void ExceptionsTableModel::GetAllExceptionsForProfile() {
+ DCHECK(!pending_login_query_);
+ pending_login_query_ = web_data_service()->GetAllLogins(this);
+}
+
+void ExceptionsTableModel::OnWebDataServiceRequestDone(
+ WebDataService::Handle h,
+ const WDTypedResult* result) {
+ DCHECK_EQ(pending_login_query_, h);
+ pending_login_query_ = NULL;
+
+ if (!result)
+ return;
+
+ DCHECK(result->GetType() == PASSWORD_RESULT);
+
+ // Get the result from the database into a useable form.
+ const WDResult<std::vector<PasswordForm*> >* r =
+ static_cast<const WDResult<std::vector<PasswordForm*> >*>(result);
+ std::vector<PasswordForm*> rows = r->GetValue();
+ STLDeleteElements<PasswordRows>(&saved_signons_);
+ std::wstring languages =
+ profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
+ for (size_t i = 0; i < rows.size(); ++i) {
+ if (rows[i]->blacklisted_by_user) {
+ saved_signons_.push_back(new PasswordRow(
+ gfx::SortedDisplayURL(rows[i]->origin, languages), rows[i]));
+ }
+ }
+ if (observer_)
+ observer_->OnModelChanged();
+ if (row_count_observer_)
+ row_count_observer_->OnRowCountChanged(RowCount());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ExceptionsPageView, public
+ExceptionsPageView::ExceptionsPageView(Profile* profile)
+ : OptionsPageView(profile),
+ remove_button_(this, l10n_util::GetString(
+ IDS_EXCEPTIONS_PAGE_VIEW_REMOVE_BUTTON)),
+ remove_all_button_(this, l10n_util::GetString(
+ IDS_EXCEPTIONS_PAGE_VIEW_REMOVE_ALL_BUTTON)),
+ table_model_(profile),
+ table_view_(NULL) {
+}
+
+void ExceptionsPageView::OnSelectionChanged() {
+ bool has_selection = table_view_->SelectedRowCount() > 0;
+ remove_button_.SetEnabled(has_selection);
+}
+
+void ExceptionsPageView::ButtonPressed(views::Button* sender) {
+ // Close will result in our destruction.
+ if (sender == &remove_all_button_) {
+ table_model_.ForgetAndRemoveAllSignons();
+ return;
+ }
+
+ // The following require a selection (and only one, since table is single-
+ // select only).
+ views::TableSelectionIterator iter = table_view_->SelectionBegin();
+ int row = *iter;
+ PasswordForm* selected = table_model_.GetPasswordFormAt(row);
+ DCHECK(++iter == table_view_->SelectionEnd());
+
+ if (sender == &remove_button_) {
+ table_model_.ForgetAndRemoveSignon(row);
+ } else {
+ NOTREACHED() << "Invalid button.";
+ }
+}
+
+void ExceptionsPageView::OnRowCountChanged(size_t rows) {
+ remove_all_button_.SetEnabled(rows > 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ExceptionsPageView, protected
+void ExceptionsPageView::InitControlLayout() {
+ SetupButtons();
+ SetupTable();
+
+ // Do the layout thing.
+ const int column_set_id = 0;
+ GridLayout* layout = CreatePanelGridLayout(this);
+ SetLayoutManager(layout);
+
+ // Design the grid.
+ ColumnSet* column_set = layout->AddColumnSet(column_set_id);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
+ GridLayout::FIXED, 300, 0);
+ column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 0,
+ GridLayout::USE_PREF, 0, 0);
+
+ // Fill the grid.
+ layout->StartRow(0.05f, column_set_id);
+ layout->AddView(table_view_, 1, 2);
+ layout->AddView(&remove_button_);
+ layout->StartRow(0.80f, column_set_id);
+ layout->SkipColumns(1);
+ layout->AddView(&remove_all_button_);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ // Ask the database for exception data.
+ table_model_.GetAllExceptionsForProfile();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ExceptionsPageView, private
+void ExceptionsPageView::SetupButtons() {
+ remove_button_.SetParentOwned(false);
+ remove_button_.SetEnabled(false);
+
+ remove_all_button_.SetParentOwned(false);
+ remove_all_button_.SetEnabled(false);
+}
+
+void ExceptionsPageView::SetupTable() {
+ // Tell the table model we are concerned about how many rows it has.
+ table_model_.set_row_count_observer(this);
+
+ // Creates the different columns for the table.
+ // The float resize values are the result of much tinkering.
+ std::vector<views::TableColumn> columns;
+ columns.push_back(views::TableColumn(
+ IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN,
+ views::TableColumn::LEFT, -1, 0.55f));
+ columns.back().sortable = true;
+ table_view_ = new views::TableView(&table_model_, columns, views::TEXT_ONLY,
+ true, true, true);
+ // Make the table initially sorted by host.
+ views::TableView::SortDescriptors sort;
+ sort.push_back(views::TableView::SortDescriptor(
+ IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN, true));
+ table_view_->SetSortDescriptors(sort);
+ table_view_->SetObserver(this);
+}
diff --git a/chrome/browser/views/options/exceptions_page_view.h b/chrome/browser/views/options/exceptions_page_view.h
new file mode 100644
index 0000000..e0abe67
--- /dev/null
+++ b/chrome/browser/views/options/exceptions_page_view.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2009 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.
+
+#ifndef CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTIONS_PAGE_VIEW_H_
+#define CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTIONS_PAGE_VIEW_H_
+
+#include "chrome/browser/views/options/options_page_view.h"
+#include "chrome/browser/views/options/passwords_page_view.h"
+
+class Profile;
+
+///////////////////////////////////////////////////////////////////////////////
+// ExceptionsTableModel
+class ExceptionsTableModel : public PasswordsTableModel {
+ public:
+ explicit ExceptionsTableModel(Profile* profile);
+ virtual ~ExceptionsTableModel();
+
+ // TableModel methods.
+ virtual std::wstring GetText(int row, int column);
+ virtual int CompareValues(int row1, int row2, int col_id);
+
+ // WebDataServiceConsumer implementation.
+ virtual void OnWebDataServiceRequestDone(WebDataService::Handle h,
+ const WDTypedResult* result);
+ // Request all logins data.
+ void GetAllExceptionsForProfile();
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ExceptionsPageView
+class ExceptionsPageView : public OptionsPageView,
+ public views::TableViewObserver,
+ public views::ButtonListener,
+ public PasswordsTableModelObserver {
+ public:
+ explicit ExceptionsPageView(Profile* profile);
+
+ // views::TableViewObserverImplementation.
+ virtual void OnSelectionChanged();
+
+ // views::ButtonListener implementation.
+ virtual void ButtonPressed(views::Button* sender);
+
+ // PasswordsTableModelObserver implementation.
+ virtual void OnRowCountChanged(size_t rows);
+
+ protected:
+ virtual void InitControlLayout();
+
+ private:
+ // Helper to configure our buttons and labels.
+ void SetupButtons();
+
+ // Helper to configure our table view.
+ void SetupTable();
+
+ ExceptionsTableModel table_model_;
+ views::TableView* table_view_;
+
+ // The buttons and labels.
+ views::NativeButton remove_button_;
+ views::NativeButton remove_all_button_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExceptionsPageView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTIONS_PAGE_VIEW_H_
diff --git a/chrome/browser/views/options/fonts_page_view.cc b/chrome/browser/views/options/fonts_page_view.cc
index 7433a65..b05941f 100644
--- a/chrome/browser/views/options/fonts_page_view.cc
+++ b/chrome/browser/views/options/fonts_page_view.cc
@@ -16,7 +16,6 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/character_encoding.h"
#include "chrome/browser/shell_dialogs.h"
-#include "chrome/browser/views/password_manager_view.h"
#include "chrome/browser/views/standard_layout.h"
#include "chrome/common/gfx/chrome_canvas.h"
#include "chrome/common/gfx/chrome_font.h"
@@ -402,7 +401,7 @@ void FontsPageView::InitFontLayout() {
this,
l10n_util::GetString(
IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_BUTTON_LABEL));
-
+
sans_serif_font_label_ = new views::Label(
l10n_util::GetString(
IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SANS_SERIF_LABEL));
diff --git a/chrome/browser/views/options/languages_page_view.cc b/chrome/browser/views/options/languages_page_view.cc
index 2634639..40a427f 100644
--- a/chrome/browser/views/options/languages_page_view.cc
+++ b/chrome/browser/views/options/languages_page_view.cc
@@ -16,7 +16,6 @@
#include "chrome/browser/shell_dialogs.h"
#include "chrome/browser/spellchecker.h"
#include "chrome/browser/views/options/language_combobox_model.h"
-#include "chrome/browser/views/password_manager_view.h"
#include "chrome/browser/views/restart_message_box.h"
#include "chrome/browser/views/standard_layout.h"
#include "chrome/common/gfx/chrome_canvas.h"
@@ -31,6 +30,7 @@
#include "chrome/views/controls/text_field.h"
#include "chrome/views/grid_layout.h"
#include "chrome/views/widget/widget.h"
+#include "chrome/views/window/window.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
diff --git a/chrome/browser/views/options/passwords_exceptions_window_view.cc b/chrome/browser/views/options/passwords_exceptions_window_view.cc
new file mode 100644
index 0000000..9bf44b4
--- /dev/null
+++ b/chrome/browser/views/options/passwords_exceptions_window_view.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2009 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/views/options/passwords_exceptions_window_view.h"
+
+#include "chrome/browser/views/options/passwords_page_view.h"
+#include "chrome/browser/views/options/exceptions_page_view.h"
+#include "chrome/common/l10n_util.h"
+#include "grit/generated_resources.h"
+
+// static
+PasswordsExceptionsWindowView* PasswordsExceptionsWindowView::instance_ = NULL;
+
+static const int kDefaultWindowWidth = 530;
+static const int kDefaultWindowHeight = 240;
+static const int kDialogPadding = 7;
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsExceptionsWindowView, public
+
+PasswordsExceptionsWindowView::PasswordsExceptionsWindowView(Profile* profile)
+ : tabs_(NULL),
+ passwords_page_view_(NULL),
+ exceptions_page_view_(NULL),
+ profile_(profile) {
+}
+
+// static
+void PasswordsExceptionsWindowView::Show(Profile* profile) {
+ DCHECK(profile);
+ if (!instance_) {
+ instance_ = new PasswordsExceptionsWindowView(profile);
+
+ // instances_ will get deleted once Close() is called.
+ views::Window::CreateChromeWindow(NULL, gfx::Rect(), instance_);
+ }
+ if (!instance_->window()->IsVisible()) {
+ instance_->window()->Show();
+ } else {
+ instance_->window()->Activate();
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// PasswordsExceptionsWindowView, views::View implementations
+
+void PasswordsExceptionsWindowView::Layout() {
+ tabs_->SetBounds(kDialogPadding, kDialogPadding,
+ width() - (2 * kDialogPadding),
+ height() - (2 * kDialogPadding));
+}
+
+gfx::Size PasswordsExceptionsWindowView::GetPreferredSize() {
+ return gfx::Size(kDefaultWindowWidth, kDefaultWindowHeight);
+}
+
+void PasswordsExceptionsWindowView::ViewHierarchyChanged(
+ bool is_add, views::View* parent, views::View* child) {
+ if (is_add && child == this)
+ Init();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// PasswordsExceptionsWindowView, views::DisloagDelegate implementations
+
+int PasswordsExceptionsWindowView::GetDialogButtons() const {
+ return DIALOGBUTTON_CANCEL;
+}
+
+std::wstring PasswordsExceptionsWindowView::GetWindowTitle() const {
+ return l10n_util::GetString(IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE);
+}
+
+void PasswordsExceptionsWindowView::WindowClosing() {
+ // |instnace_| is deleted once the window is closed, so we just have to set
+ // it to NULL.
+ instance_ = NULL;
+}
+
+views::View* PasswordsExceptionsWindowView::GetContentsView() {
+ return this;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// PasswordsExceptionsWindowView, private
+
+void PasswordsExceptionsWindowView::Init() {
+ tabs_ = new views::TabbedPane();
+ AddChildView(tabs_);
+
+ passwords_page_view_ = new PasswordsPageView(profile_);
+ tabs_->AddTab(l10n_util::GetString(
+ IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE), passwords_page_view_);
+
+ exceptions_page_view_ = new ExceptionsPageView(profile_);
+ tabs_->AddTab(l10n_util::GetString(
+ IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE), exceptions_page_view_);
+}
diff --git a/chrome/browser/views/options/passwords_exceptions_window_view.h b/chrome/browser/views/options/passwords_exceptions_window_view.h
new file mode 100644
index 0000000..e3e8705
--- /dev/null
+++ b/chrome/browser/views/options/passwords_exceptions_window_view.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2009 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.
+
+#ifndef CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_VIEW_H_
+#define CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_VIEW_H_
+
+#include "chrome/views/controls/tabbed_pane.h"
+#include "chrome/views/view.h"
+#include "chrome/views/window/dialog_delegate.h"
+#include "chrome/views/window/window.h"
+
+class Profile;
+class PasswordsPageView;
+class ExceptionsPageView;
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsExceptionsWindowView
+//
+// The contents of the "Save passwords and exceptions" dialog window.
+//
+class PasswordsExceptionsWindowView : public views::View,
+ public views::DialogDelegate {
+ public:
+ explicit PasswordsExceptionsWindowView(Profile* profile);
+ virtual ~PasswordsExceptionsWindowView() {}
+
+ // Show the PasswordManagerExceptionsView for the given profile.
+ static void Show(Profile* profile);
+
+ // views::View methods.
+ virtual void Layout();
+ virtual gfx::Size GetPreferredSize();
+ virtual void ViewHierarchyChanged(bool is_add, views::View* parent,
+ views::View* child);
+
+ // views::DialogDelegate methods:
+ virtual int GetDialogButtons() const;
+ virtual bool CanResize() const { return true; }
+ virtual bool CanMaximize() const { return false; }
+ virtual bool IsAlwaysOnTop() const { return false; }
+ virtual bool HasAlwaysOnTopMenu() const { return false; }
+ virtual std::wstring GetWindowTitle() const;
+ virtual void WindowClosing();
+ virtual views::View* GetContentsView();
+
+ private:
+ void Init();
+
+ // The Tab view that contains all of the options pages.
+ views::TabbedPane* tabs_;
+
+ PasswordsPageView* passwords_page_view_;
+
+ ExceptionsPageView* exceptions_page_view_;
+
+ Profile* profile_;
+
+ static PasswordsExceptionsWindowView* instance_;
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordsExceptionsWindowView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_VIEW_H_
diff --git a/chrome/browser/views/options/passwords_page_view.cc b/chrome/browser/views/options/passwords_page_view.cc
new file mode 100644
index 0000000..7325dd4
--- /dev/null
+++ b/chrome/browser/views/options/passwords_page_view.cc
@@ -0,0 +1,328 @@
+// Copyright (c) 2009 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/views/options/passwords_page_view.h"
+
+#include "base/string_util.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/views/standard_layout.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/pref_service.h"
+#include "chrome/views/background.h"
+#include "chrome/views/controls/button/native_button.h"
+#include "chrome/views/grid_layout.h"
+#include "grit/generated_resources.h"
+
+using views::ColumnSet;
+using views::GridLayout;
+
+///////////////////////////////////////////////////////////////////////////////
+// MultiLabelButtons
+MultiLabelButtons::MultiLabelButtons(views::ButtonListener* listener,
+ const std::wstring& label,
+ const std::wstring& alt_label)
+ : NativeButton(listener, label),
+ label_(label),
+ alt_label_(alt_label),
+ pref_size_(-1, -1) {
+}
+
+gfx::Size MultiLabelButtons::GetPreferredSize() {
+ if (pref_size_.width() == -1 && pref_size_.height() == -1) {
+ // Let's compute our preferred size.
+ std::wstring current_label = label();
+ SetLabel(label_);
+ pref_size_ = NativeButton::GetPreferredSize();
+ SetLabel(alt_label_);
+ gfx::Size alt_pref_size = NativeButton::GetPreferredSize();
+ // Revert to the original label.
+ SetLabel(current_label);
+ pref_size_.SetSize(std::max(pref_size_.width(), alt_pref_size.width()),
+ std::max(pref_size_.height(), alt_pref_size.height()));
+ }
+ return gfx::Size(pref_size_.width(), pref_size_.height());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsTableModel, public
+PasswordsTableModel::PasswordsTableModel(Profile* profile)
+ : observer_(NULL),
+ row_count_observer_(NULL),
+ pending_login_query_(NULL),
+ saved_signons_cleanup_(&saved_signons_),
+ profile_(profile) {
+ DCHECK(profile && profile->GetWebDataService(Profile::EXPLICIT_ACCESS));
+}
+
+PasswordsTableModel::~PasswordsTableModel() {
+ CancelLoginsQuery();
+}
+
+int PasswordsTableModel::RowCount() {
+ return static_cast<int>(saved_signons_.size());
+}
+
+std::wstring PasswordsTableModel::GetText(int row,
+ int col_id) {
+ switch (col_id) {
+ case IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN: { // Site.
+ const std::wstring& url = saved_signons_[row]->display_url.display_url();
+ // Force URL to have LTR directionality.
+ if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) {
+ std::wstring localized_url = url;
+ l10n_util::WrapStringWithLTRFormatting(&localized_url);
+ return localized_url;
+ }
+ return url;
+ }
+ case IDS_PASSWORDS_PAGE_VIEW_USERNAME_COLUMN: { // Username.
+ std::wstring username = GetPasswordFormAt(row)->username_value;
+ l10n_util::AdjustStringForLocaleDirection(username, &username);
+ return username;
+ }
+ default:
+ NOTREACHED() << "Invalid column.";
+ return std::wstring();
+ }
+}
+
+int PasswordsTableModel::CompareValues(int row1, int row2,
+ int column_id) {
+ if (column_id == IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN) {
+ return saved_signons_[row1]->display_url.Compare(
+ saved_signons_[row2]->display_url, GetCollator());
+ }
+ return TableModel::CompareValues(row1, row2, column_id);
+}
+
+void PasswordsTableModel::SetObserver(
+ views::TableModelObserver* observer) {
+ observer_ = observer;
+}
+
+void PasswordsTableModel::GetAllSavedLoginsForProfile() {
+ DCHECK(!pending_login_query_);
+ pending_login_query_ = web_data_service()->GetAllAutofillableLogins(this);
+}
+
+void PasswordsTableModel::OnWebDataServiceRequestDone(
+ WebDataService::Handle h,
+ const WDTypedResult* result) {
+ DCHECK_EQ(pending_login_query_, h);
+ pending_login_query_ = NULL;
+
+ if (!result)
+ return;
+
+ DCHECK(result->GetType() == PASSWORD_RESULT);
+
+ // Get the result from the database into a useable form.
+ const WDResult<std::vector<PasswordForm*> >* r =
+ static_cast<const WDResult<std::vector<PasswordForm*> >*>(result);
+ std::vector<PasswordForm*> rows = r->GetValue();
+ STLDeleteElements<PasswordRows>(&saved_signons_);
+ saved_signons_.resize(rows.size(), NULL);
+ std::wstring languages =
+ profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
+ for (size_t i = 0; i < rows.size(); ++i) {
+ saved_signons_[i] = new PasswordRow(
+ gfx::SortedDisplayURL(rows[i]->origin, languages), rows[i]);
+ }
+ if (observer_)
+ observer_->OnModelChanged();
+ if (row_count_observer_)
+ row_count_observer_->OnRowCountChanged(RowCount());
+}
+
+PasswordForm* PasswordsTableModel::GetPasswordFormAt(int row) {
+ DCHECK(row >= 0 && row < RowCount());
+ return saved_signons_[row]->form.get();
+}
+
+void PasswordsTableModel::ForgetAndRemoveSignon(int row) {
+ DCHECK(row >= 0 && row < RowCount());
+ PasswordRows::iterator target_iter = saved_signons_.begin() + row;
+ // Remove from DB, memory, and vector.
+ PasswordRow* password_row = *target_iter;
+ web_data_service()->RemoveLogin(*(password_row->form.get()));
+ delete password_row;
+ saved_signons_.erase(target_iter);
+ if (observer_)
+ observer_->OnItemsRemoved(row, 1);
+ if (row_count_observer_)
+ row_count_observer_->OnRowCountChanged(RowCount());
+}
+
+void PasswordsTableModel::ForgetAndRemoveAllSignons() {
+ PasswordRows::iterator iter = saved_signons_.begin();
+ while (iter != saved_signons_.end()) {
+ // Remove from DB, memory, and vector.
+ PasswordRow* row = *iter;
+ web_data_service()->RemoveLogin(*(row->form.get()));
+ delete row;
+ iter = saved_signons_.erase(iter);
+ }
+ if (observer_)
+ observer_->OnModelChanged();
+ if (row_count_observer_)
+ row_count_observer_->OnRowCountChanged(RowCount());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsTableModel, private
+void PasswordsTableModel::CancelLoginsQuery() {
+ if (pending_login_query_) {
+ web_data_service()->CancelRequest(pending_login_query_);
+ pending_login_query_ = NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsPageView, public
+PasswordsPageView::PasswordsPageView(Profile* profile)
+ : OptionsPageView(profile),
+ show_button_(
+ this,
+ l10n_util::GetString(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON),
+ l10n_util::GetString(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON)),
+ remove_button_(this, l10n_util::GetString(
+ IDS_PASSWORDS_PAGE_VIEW_REMOVE_BUTTON)),
+ remove_all_button_(this, l10n_util::GetString(
+ IDS_PASSWORDS_PAGE_VIEW_REMOVE_ALL_BUTTON)),
+ table_model_(profile),
+ table_view_(NULL) {
+}
+
+void PasswordsPageView::OnSelectionChanged() {
+ bool has_selection = table_view_->SelectedRowCount() > 0;
+ remove_button_.SetEnabled(has_selection);
+ // Reset the password related views.
+ show_button_.SetLabel(
+ l10n_util::GetString(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON));
+ show_button_.SetEnabled(has_selection);
+ password_label_.SetText(std::wstring());
+}
+
+void PasswordsPageView::ButtonPressed(views::Button* sender) {
+ // Close will result in our destruction.
+ if (sender == &remove_all_button_) {
+ table_model_.ForgetAndRemoveAllSignons();
+ return;
+ }
+
+ // The following require a selection (and only one, since table is single-
+ // select only).
+ views::TableSelectionIterator iter = table_view_->SelectionBegin();
+ int row = *iter;
+ PasswordForm* selected = table_model_.GetPasswordFormAt(row);
+ DCHECK(++iter == table_view_->SelectionEnd());
+
+ if (sender == &remove_button_) {
+ table_model_.ForgetAndRemoveSignon(row);
+ } else if (sender == &show_button_) {
+ if (password_label_.GetText().length() == 0) {
+ password_label_.SetText(selected->password_value);
+ show_button_.SetLabel(
+ l10n_util::GetString(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON));
+ } else {
+ password_label_.SetText(L"");
+ show_button_.SetLabel(
+ l10n_util::GetString(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON));
+ }
+ } else {
+ NOTREACHED() << "Invalid button.";
+ }
+}
+
+void PasswordsPageView::OnRowCountChanged(size_t rows) {
+ remove_all_button_.SetEnabled(rows > 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsPageView, protected
+void PasswordsPageView::InitControlLayout() {
+ SetupButtonsAndLabels();
+ SetupTable();
+
+ // Do the layout thing.
+ const int top_column_set_id = 0;
+ const int lower_column_set_id = 1;
+ GridLayout* layout = CreatePanelGridLayout(this);
+ SetLayoutManager(layout);
+
+ // Design the grid.
+ ColumnSet* column_set = layout->AddColumnSet(top_column_set_id);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
+ GridLayout::FIXED, 300, 0);
+ column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 0,
+ GridLayout::USE_PREF, 0, 0);
+
+ column_set = layout->AddColumnSet(lower_column_set_id);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 0,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(1, kRelatedControlHorizontalSpacing);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 0,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->LinkColumnSizes(0, 2, -1);
+
+ // Fill the grid.
+ layout->StartRow(0.05f, top_column_set_id);
+ layout->AddView(table_view_, 1, 4);
+ layout->AddView(&remove_button_);
+ layout->StartRow(0.05f, top_column_set_id);
+ layout->SkipColumns(1);
+ layout->AddView(&remove_all_button_);
+ layout->StartRow(0.05f, top_column_set_id);
+ layout->SkipColumns(1);
+ layout->AddView(&show_button_);
+ layout->StartRow(0.80f, top_column_set_id);
+ layout->SkipColumns(1);
+ layout->AddView(&password_label_);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ // Ask the database for saved password data.
+ table_model_.GetAllSavedLoginsForProfile();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsPageView, private
+void PasswordsPageView::SetupButtonsAndLabels() {
+ // Disable all buttons in the first place.
+ show_button_.SetParentOwned(false);
+ show_button_.SetEnabled(false);
+
+ remove_button_.SetParentOwned(false);
+ remove_button_.SetEnabled(false);
+
+ remove_all_button_.SetParentOwned(false);
+ remove_all_button_.SetEnabled(false);
+
+ password_label_.SetParentOwned(false);
+}
+
+void PasswordsPageView::SetupTable() {
+ // Tell the table model we are concern about how many rows it has.
+ table_model_.set_row_count_observer(this);
+
+ // Creates the different columns for the table.
+ // The float resize values are the result of much tinkering.
+ std::vector<views::TableColumn> columns;
+ columns.push_back(views::TableColumn(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN,
+ views::TableColumn::LEFT, -1, 0.55f));
+ columns.back().sortable = true;
+ columns.push_back(views::TableColumn(
+ IDS_PASSWORDS_PAGE_VIEW_USERNAME_COLUMN, views::TableColumn::RIGHT,
+ -1, 0.37f));
+ columns.back().sortable = true;
+ table_view_ = new views::TableView(&table_model_, columns, views::TEXT_ONLY,
+ true, true, true);
+ // Make the table initially sorted by host.
+ views::TableView::SortDescriptors sort;
+ sort.push_back(views::TableView::SortDescriptor(
+ IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN, true));
+ table_view_->SetSortDescriptors(sort);
+ table_view_->SetObserver(this);
+}
diff --git a/chrome/browser/views/options/passwords_page_view.h b/chrome/browser/views/options/passwords_page_view.h
new file mode 100644
index 0000000..dca2b1e
--- /dev/null
+++ b/chrome/browser/views/options/passwords_page_view.h
@@ -0,0 +1,179 @@
+// Copyright (c) 2009 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.
+
+#ifndef CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_PAGE_VIEW_H_
+#define CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_PAGE_VIEW_H_
+
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/views/options/options_page_view.h"
+#include "chrome/browser/webdata/web_data_service.h"
+#include "chrome/common/gfx/text_elider.h"
+#include "chrome/common/stl_util-inl.h"
+#include "chrome/views/controls/button/native_button.h"
+#include "chrome/views/controls/label.h"
+#include "chrome/views/controls/table/table_view.h"
+#include "chrome/views/window/dialog_delegate.h"
+#include "chrome/views/window/window.h"
+#include "webkit/glue/password_form.h"
+
+class Profile;
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordTableModelObserver
+// An observer interface to notify change of row count in a table model. This
+// allow the container view of TableView(i.e. PasswordsPageView and
+// ExceptionsPageView), to be notified of row count changes directly
+// from the TableModel. We have two different observers in
+// PasswordsTableModel, namely views::TableModelObserver and
+// PasswordsTableModelObserver, rather than adding this event to
+// views::TableModelObserver because only container view of
+// PasswordsTableModel cares about this event.
+class PasswordsTableModelObserver {
+ public:
+ virtual void OnRowCountChanged(size_t rows) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// MultiLabelButtons
+// A button that can have 2 different labels set on it and for which the
+// preferred size is the size of the widest string.
+class MultiLabelButtons : public views::NativeButton {
+ public:
+ MultiLabelButtons(views::ButtonListener* listener,
+ const std::wstring& label,
+ const std::wstring& alt_label);
+
+ virtual gfx::Size GetPreferredSize();
+
+ private:
+ std::wstring label_;
+ std::wstring alt_label_;
+ gfx::Size pref_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(MultiLabelButtons);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsTableModel
+class PasswordsTableModel : public views::TableModel,
+ public WebDataServiceConsumer {
+ public:
+ explicit PasswordsTableModel(Profile* profile);
+ virtual ~PasswordsTableModel();
+
+ // TableModel methods.
+ virtual int RowCount();
+ virtual std::wstring GetText(int row, int column);
+ virtual int CompareValues(int row1, int row2, int column_id);
+ virtual void SetObserver(views::TableModelObserver* observer);
+
+ // Delete the PasswordForm at specified row from the database (and remove
+ // from view).
+ void ForgetAndRemoveSignon(int row);
+
+ // Delete all saved signons for the active profile (via web data service),
+ // and clear the view.
+ void ForgetAndRemoveAllSignons();
+
+ // WebDataServiceConsumer implementation.
+ virtual void OnWebDataServiceRequestDone(WebDataService::Handle h,
+ const WDTypedResult* result);
+ // Request saved logins data.
+ void GetAllSavedLoginsForProfile();
+
+ // Return the PasswordForm at the specified index.
+ PasswordForm* GetPasswordFormAt(int row);
+
+ // Set the observer who concerns about how many rows are in the table.
+ void set_row_count_observer(PasswordsTableModelObserver* observer) {
+ row_count_observer_ = observer;
+ }
+
+ protected:
+ // Wraps the PasswordForm from the database and caches the display URL for
+ // quick sorting.
+ struct PasswordRow {
+ PasswordRow(const gfx::SortedDisplayURL& url, PasswordForm* password_form)
+ : display_url(url), form(password_form) {
+ }
+
+ // Contains the URL that is displayed along with the
+ gfx::SortedDisplayURL display_url;
+
+ // The underlying PasswordForm. We own this.
+ scoped_ptr<PasswordForm> form;
+ };
+
+ // The web data service associated with the currently active profile.
+ WebDataService* web_data_service() {
+ return profile_->GetWebDataService(Profile::EXPLICIT_ACCESS);
+ }
+
+ // The TableView observing this model.
+ views::TableModelObserver* observer_;
+
+ // Dispatching row count events specific to this password manager table model
+ // to this observer.
+ PasswordsTableModelObserver* row_count_observer_;
+
+ // Handle to any pending WebDataService::GetLogins query.
+ WebDataService::Handle pending_login_query_;
+
+ // The set of passwords we're showing.
+ typedef std::vector<PasswordRow*> PasswordRows;
+ PasswordRows saved_signons_;
+ STLElementDeleter<PasswordRows> saved_signons_cleanup_;
+
+ Profile* profile_;
+
+ private:
+ // Cancel any pending login query involving a callback.
+ void CancelLoginsQuery();
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordsTableModel);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsPageView
+class PasswordsPageView : public OptionsPageView,
+ public views::TableViewObserver,
+ public views::ButtonListener,
+ public PasswordsTableModelObserver {
+ public:
+ explicit PasswordsPageView(Profile* profile);
+
+ // views::TableViewObserverImplementation.
+ virtual void OnSelectionChanged();
+
+ // views::ButtonListener implementation.
+ virtual void ButtonPressed(views::Button* sender);
+
+ // PasswordsTableModelObserver implementation.
+ virtual void OnRowCountChanged(size_t rows);
+
+ protected:
+ virtual void InitControlLayout();
+
+ private:
+ // Helper to configure our buttons and labels.
+ void SetupButtonsAndLabels();
+
+ // Helper to configure our table view.
+ void SetupTable();
+
+ PasswordsTableModel table_model_;
+ views::TableView* table_view_;
+
+ // The buttons and labels.
+ MultiLabelButtons show_button_;
+ views::NativeButton remove_button_;
+ views::NativeButton remove_all_button_;
+ views::Label password_label_;
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordsPageView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_PAGE_VIEW_H_