Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: chrome/browser/ui/sync/one_click_signin_helper.cc

Issue 9453035: Implement one click login. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Addressing review comments Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
6
7 #include "base/metrics/histogram.h"
8 #include "base/string_split.h"
9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/infobars/infobar_tab_helper.h"
11 #include "chrome/browser/prefs/pref_service.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/signin/signin_manager.h"
14 #include "chrome/browser/signin/signin_manager_factory.h"
15 #include "chrome/browser/sync/profile_sync_service.h"
16 #include "chrome/browser/sync/profile_sync_service_factory.h"
17 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
18 #include "chrome/browser/tab_contents/tab_util.h"
19 #include "chrome/browser/ui/one_click_signin_dialog.h"
20 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
21 #include "chrome/common/pref_names.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/page_navigator.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/common/frame_navigate_params.h"
26 #include "grit/chromium_strings.h"
27 #include "grit/generated_resources.h"
28 #include "grit/theme_resources_standard.h"
29 #include "net/base/cookie_monster.h"
30 #include "net/url_request/url_request.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/base/resource/resource_bundle.h"
33 #include "webkit/forms/password_form.h"
34 #include "webkit/forms/password_form_dom_manager.h"
35
36 namespace {
37 // Enum values used for UMA histograms.
38 enum {
39 // The infobar was shown to the user.
40 HISTOGRAM_SHOWN,
41
42 // The user pressed the accept button to perform the suggested action.
43 HISTOGRAM_ACCEPTED,
44
45 // The user pressed the reject to turn off the feature.
46 HISTOGRAM_REJECTED,
47
48 // The user pressed the X button to dismiss the infobar this time.
49 HISTOGRAM_DISMISSED,
50
51 // The user completely ignored the infoar. Either they navigated away, or
52 // they used the page as is.
53 HISTOGRAM_IGNORED,
54
55 // The user clicked on the learn more link in the infobar.
56 HISTOGRAM_LEARN_MORE,
57
58 HISTOGRAM_MAX
59 };
60
61 // The infobar asking the user if they want to use one-click sign in.
62 class OneClickLoginInfoBarDelegate : public ConfirmInfoBarDelegate {
63 public:
64 OneClickLoginInfoBarDelegate(InfoBarTabHelper* owner,
65 const std::string& email,
66 const std::string& password);
67 virtual ~OneClickLoginInfoBarDelegate();
68
69 private:
70 // ConfirmInfoBarDelegate overrides.
71 virtual void InfoBarDismissed() OVERRIDE;
72 virtual gfx::Image* GetIcon() const OVERRIDE;
73 virtual Type GetInfoBarType() const OVERRIDE;
74 virtual string16 GetMessageText() const OVERRIDE;
75 virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
76 virtual bool Accept() OVERRIDE;
77 virtual bool Cancel() OVERRIDE;
78
79 void RecordHistogramAction(int action);
80
81 Profile* profile_;
82
83 // Email address and password of the account that has just logged in.
84 std::string email_;
85 std::string password_;
86
87 // Whether any UI controls in the infobar were pressed or not.
88 bool button_pressed_;
89
90 DISALLOW_COPY_AND_ASSIGN(OneClickLoginInfoBarDelegate);
91 };
92
93 OneClickLoginInfoBarDelegate::OneClickLoginInfoBarDelegate(
94 InfoBarTabHelper* owner,
95 const std::string& email,
96 const std::string& password)
97 : ConfirmInfoBarDelegate(owner),
98 profile_(Profile::FromBrowserContext(
99 owner->web_contents()->GetBrowserContext())),
100 email_(email),
101 password_(password),
102 button_pressed_(false) {
103 DCHECK(profile_);
104 RecordHistogramAction(HISTOGRAM_SHOWN);
105 }
106
107 OneClickLoginInfoBarDelegate::~OneClickLoginInfoBarDelegate() {
108 if (!button_pressed_)
109 RecordHistogramAction(HISTOGRAM_IGNORED);
110 }
111
112 void OneClickLoginInfoBarDelegate::InfoBarDismissed() {
113 RecordHistogramAction(HISTOGRAM_DISMISSED);
114 button_pressed_ = true;
115 }
116
117 gfx::Image* OneClickLoginInfoBarDelegate::GetIcon() const {
118 return &ResourceBundle::GetSharedInstance().GetNativeImageNamed(
119 IDR_INFOBAR_AUTOLOGIN);
120 }
121
122 InfoBarDelegate::Type OneClickLoginInfoBarDelegate::GetInfoBarType() const {
123 return PAGE_ACTION_TYPE;
124 }
125
126 string16 OneClickLoginInfoBarDelegate::GetMessageText() const {
127 return l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_INFOBAR_MESSAGE);
128 }
129
130 string16 OneClickLoginInfoBarDelegate::GetButtonLabel(
131 InfoBarButton button) const {
132 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
133 IDS_OK : IDS_ONE_CLICK_SIGNIN_INFOBAR_CANCEL_BUTTON);
134 }
135
136 bool OneClickLoginInfoBarDelegate::Accept() {
137 RecordHistogramAction(HISTOGRAM_ACCEPTED);
138 ShowOneClickSigninDialog(profile_, email_, password_);
139 button_pressed_ = true;
140 return true;
141 }
142
143 bool OneClickLoginInfoBarDelegate::Cancel() {
144 PrefService* pref_service =
145 TabContentsWrapper::GetCurrentWrapperForContents(
146 owner()->web_contents())->profile()->GetPrefs();
147 pref_service->SetBoolean(prefs::kReverseAutologinEnabled, false);
148 RecordHistogramAction(HISTOGRAM_REJECTED);
149 button_pressed_ = true;
150 return true;
151 }
152
153 void OneClickLoginInfoBarDelegate::RecordHistogramAction(int action) {
154 UMA_HISTOGRAM_ENUMERATION("AutoLogin.Reverse", action, HISTOGRAM_MAX);
155 }
156
157 } // namespace
158
159 // static
160 bool OneClickSigninHelper::CanOffer(content::WebContents* web_contents) {
161 return !web_contents->GetBrowserContext()->IsOffTheRecord();
162 }
163
164 // static
165 void OneClickSigninHelper::ShowInfoBarIfPossible(net::URLRequest* request,
166 int child_id,
167 int route_id) {
168 // See if the response contains the X-Google-Accounts-SignIn header.
169 std::string value;
170 request->GetResponseHeaderByName("X-Google-Accounts-SignIn", &value);
171 if (value.empty())
172 return;
173
174 std::vector<std::pair<std::string, std::string> > pairs;
175 if (!base::SplitStringIntoKeyValuePairs(value, '=', ',', &pairs))
176 return;
177
178 // Parse the information from the value string.
179 std::string email;
180 for (size_t i = 0; i < pairs.size(); ++i) {
181 const std::pair<std::string, std::string>& pair = pairs[i];
182 if (pair.first == "email")
183 TrimString(pair.second, "\"", &email);
184 }
185
186 if (email.empty())
187 return;
188
189 content::BrowserThread::PostTask(
190 content::BrowserThread::UI, FROM_HERE,
191 base::Bind(&OneClickSigninHelper::ShowInfoBarUIThread, email,
192 child_id, route_id));
193 }
194
195 OneClickSigninHelper::OneClickSigninHelper(content::WebContents* web_contents)
196 : content::WebContentsObserver(web_contents) {
197 }
198
199 OneClickSigninHelper::~OneClickSigninHelper() {
200 }
201
202 // static
203 void OneClickSigninHelper::ShowInfoBarUIThread(
204 const std::string& email,
205 int child_id,
206 int route_id) {
207 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
208
209 content::WebContents* web_contents = tab_util::GetWebContentsByID(child_id,
210 route_id);
211 if (!web_contents)
212 return;
213
214 Profile* profile =
215 Profile::FromBrowserContext(web_contents->GetBrowserContext());
216
217 if (!ProfileSyncService::IsSyncEnabled())
218 return;
219
220 ProfileSyncService* service =
221 ProfileSyncServiceFactory::GetForProfile(profile);
222
223 if (!profile->GetPrefs()->GetBoolean(prefs::kReverseAutologinEnabled) ||
224 service->AreCredentialsAvailable())
225 return;
226
227 TabContentsWrapper* wrapper =
228 TabContentsWrapper::GetCurrentWrapperForContents(web_contents);
229 if (!wrapper)
230 return;
231
232 // TODO(rogerta): remove this #if once the dialog is fully implemented for
233 // mac and linux.
234 #if defined(ENABLE_ONE_CLICK_SIGNIN)
235 // Save the email in the one-click signin manager. The manager may
236 // not exist if the contents is incognito or if the profile is already
237 // connected to a Google account.
238 OneClickSigninHelper* helper = wrapper->one_click_signin_helper();
239 if (helper)
240 helper->SaveEmail(email);
241 #endif
242 }
243
244 void OneClickSigninHelper::DidNavigateAnyFrame(
245 const content::LoadCommittedDetails& details,
246 const content::FrameNavigateParams& params) {
247 if (params.password_form.origin.is_valid())
248 SavePassword(UTF16ToUTF8(params.password_form.password_value));
249 }
250
251 void OneClickSigninHelper::DidStopLoading() {
252 if (email_.empty() || password_.empty())
253 return;
254
255 TabContentsWrapper* wrapper =
256 TabContentsWrapper::GetCurrentWrapperForContents(web_contents());
257
258 wrapper->infobar_tab_helper()->AddInfoBar(
259 new OneClickLoginInfoBarDelegate(wrapper->infobar_tab_helper(),
260 email_, password_));
261
262 email_.clear();
263 password_.clear();
264 }
265
266 void OneClickSigninHelper::SaveEmail(const std::string& email) {
267 // TODO(rogerta): validate that the email address is the same as set in
268 // the form?
269 email_ = email;
270 }
271
272 void OneClickSigninHelper::SavePassword(const std::string& password) {
273 // TODO(rogerta): in the case of a 2-factor or captcha or some other type of
274 // challenge, its possible for the user to never complete the signin.
275 // Should have a way to detect this and clear the password member.
276 password_ = password;
277 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698