1// Copyright 2013 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/password_manager_handler.h"
6
7#include "base/bind.h"
8#include "base/prefs/pref_service.h"
9#include "base/strings/string_number_conversions.h"
10#include "base/strings/utf_string_conversions.h"
11#include "base/values.h"
12#include "chrome/browser/chrome_notification_types.h"
13#include "chrome/browser/profiles/profile.h"
14#if defined(OS_WIN) && defined(USE_ASH)
15#include "chrome/browser/ui/ash/ash_util.h"
16#endif
17#include "chrome/common/pref_names.h"
18#include "chrome/common/url_constants.h"
19#include "chrome/grit/generated_resources.h"
20#include "components/autofill/core/common/password_form.h"
21#include "content/public/browser/notification_details.h"
22#include "content/public/browser/notification_source.h"
23#include "content/public/browser/user_metrics.h"
24#include "content/public/browser/web_contents.h"
25#include "content/public/browser/web_ui.h"
26#include "net/base/net_util.h"
27
28namespace options {
29
30PasswordManagerHandler::PasswordManagerHandler()
31    : password_manager_presenter_(this) {}
32
33PasswordManagerHandler::~PasswordManagerHandler() {}
34
35Profile* PasswordManagerHandler::GetProfile() {
36  return Profile::FromWebUI(web_ui());
37}
38
39#if !defined(OS_ANDROID)
40gfx::NativeWindow PasswordManagerHandler::GetNativeWindow() {
41  return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
42}
43#endif
44
45void PasswordManagerHandler::GetLocalizedValues(
46    base::DictionaryValue* localized_strings) {
47  DCHECK(localized_strings);
48
49  static const OptionsStringResource resources[] = {
50    { "savedPasswordsTitle",
51      IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE },
52    { "passwordExceptionsTitle",
53      IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE },
54    { "passwordSearchPlaceholder",
55      IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS },
56    { "passwordShowButton",
57      IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON },
58    { "passwordHideButton",
59      IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON },
60    { "passwordsNoPasswordsDescription",
61      IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION },
62    { "passwordsNoExceptionsDescription",
63      IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION },
64  };
65
66  RegisterStrings(localized_strings, resources, arraysize(resources));
67  RegisterTitle(localized_strings, "passwordsPage",
68                IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE);
69
70  localized_strings->SetString("passwordManagerLearnMoreURL",
71                               chrome::kPasswordManagerLearnMoreURL);
72  bool disable_show_passwords = false;
73
74#if defined(OS_WIN) && defined(USE_ASH)
75  // We disable the ability to show passwords when running in Windows Metro
76  // interface.  This is because we cannot pop native Win32 dialogs from the
77  // Metro process.
78  // TODO(wfh): Revisit this if Metro usage grows.
79  if (chrome::IsNativeWindowInAsh(GetNativeWindow()))
80    disable_show_passwords = true;
81#endif
82
83  localized_strings->SetBoolean("disableShowPasswords", disable_show_passwords);
84}
85
86void PasswordManagerHandler::RegisterMessages() {
87  web_ui()->RegisterMessageCallback(
88      "updatePasswordLists",
89      base::Bind(&PasswordManagerHandler::HandleUpdatePasswordLists,
90                 base::Unretained(this)));
91  web_ui()->RegisterMessageCallback(
92      "removeSavedPassword",
93      base::Bind(&PasswordManagerHandler::HandleRemoveSavedPassword,
94                 base::Unretained(this)));
95  web_ui()->RegisterMessageCallback(
96      "removePasswordException",
97      base::Bind(&PasswordManagerHandler::HandleRemovePasswordException,
98                 base::Unretained(this)));
99  web_ui()->RegisterMessageCallback(
100      "requestShowPassword",
101      base::Bind(&PasswordManagerHandler::HandleRequestShowPassword,
102                 base::Unretained(this)));
103}
104
105void PasswordManagerHandler::InitializeHandler() {
106  password_manager_presenter_.Initialize();
107}
108
109void PasswordManagerHandler::HandleRemoveSavedPassword(
110    const base::ListValue* args) {
111  std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args));
112  int index;
113  if (base::StringToInt(string_value, &index) && index >= 0) {
114    password_manager_presenter_.RemoveSavedPassword(static_cast<size_t>(index));
115  }
116}
117
118void PasswordManagerHandler::HandleRemovePasswordException(
119    const base::ListValue* args) {
120  std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args));
121  int index;
122  if (base::StringToInt(string_value, &index) && index >= 0) {
123    password_manager_presenter_.RemovePasswordException(
124        static_cast<size_t>(index));
125  }
126}
127
128void PasswordManagerHandler::HandleRequestShowPassword(
129    const base::ListValue* args) {
130  int index;
131  if (!ExtractIntegerValue(args, &index))
132    NOTREACHED();
133
134  password_manager_presenter_.RequestShowPassword(static_cast<size_t>(index));
135}
136
137void PasswordManagerHandler::ShowPassword(
138    size_t index,
139    const base::string16& password_value) {
140  // Call back the front end to reveal the password.
141  web_ui()->CallJavascriptFunction(
142      "PasswordManager.showPassword",
143      base::FundamentalValue(static_cast<int>(index)),
144      base::StringValue(password_value));
145}
146
147void PasswordManagerHandler::HandleUpdatePasswordLists(
148    const base::ListValue* args) {
149  password_manager_presenter_.UpdatePasswordLists();
150}
151
152void PasswordManagerHandler::SetPasswordList(
153    const ScopedVector<autofill::PasswordForm>& password_list,
154    bool show_passwords) {
155  base::ListValue entries;
156  languages_ = GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
157  base::string16 placeholder(base::ASCIIToUTF16("        "));
158  for (size_t i = 0; i < password_list.size(); ++i) {
159    base::ListValue* entry = new base::ListValue();
160    entry->Append(new base::StringValue(net::FormatUrl(password_list[i]->origin,
161                                                       languages_)));
162    entry->Append(new base::StringValue(password_list[i]->username_value));
163    if (show_passwords) {
164      entry->Append(new base::StringValue(password_list[i]->password_value));
165    } else {
166      // Use a placeholder value with the same length as the password.
167      entry->Append(new base::StringValue(
168          base::string16(password_list[i]->password_value.length(), ' ')));
169    }
170    entries.Append(entry);
171  }
172
173  web_ui()->CallJavascriptFunction("PasswordManager.setSavedPasswordsList",
174                                   entries);
175}
176
177void PasswordManagerHandler::SetPasswordExceptionList(
178    const ScopedVector<autofill::PasswordForm>& password_exception_list) {
179  base::ListValue entries;
180  for (size_t i = 0; i < password_exception_list.size(); ++i) {
181    entries.Append(new base::StringValue(
182        net::FormatUrl(password_exception_list[i]->origin, languages_)));
183  }
184
185  web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList",
186                                   entries);
187}
188
189}  // namespace options
190