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

Side by Side Diff: chrome/browser/signin/one_click_signin.cc

Issue 9453035: Implement one click login. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Added missing grd files 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/signin/one_click_signin.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/google/google_util.h"
11 #include "chrome/browser/infobars/infobar_tab_helper.h"
12 #include "chrome/browser/prefs/pref_service.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/signin/signin_manager.h"
15 #include "chrome/browser/signin/signin_manager_factory.h"
16 #include "chrome/browser/sync/profile_sync_service.h"
17 #include "chrome/browser/sync/profile_sync_service_factory.h"
18 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
19 #include "chrome/browser/tab_contents/tab_util.h"
20 #include "chrome/browser/ui/one_click_signin_dialog.h"
21 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
22 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
23 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
24 #include "chrome/common/chrome_notification_types.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/common/url_constants.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/notification_source.h"
29 #include "content/public/browser/page_navigator.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/common/frame_navigate_params.h"
32 #include "grit/chromium_strings.h"
33 #include "grit/generated_resources.h"
34 #include "grit/theme_resources_standard.h"
35 #include "net/base/cookie_monster.h"
36 #include "net/http/http_response_headers.h"
37 #include "net/url_request/url_request.h"
38 #include "ui/base/l10n/l10n_util.h"
39 #include "ui/base/resource/resource_bundle.h"
40
41 namespace {
42 // Enum values used for UMA histograms.
43 enum {
44 // The infobar was shown to the user.
45 HISTOGRAM_SHOWN,
46
47 // The user pressed the accept button to perform the suggested action.
48 HISTOGRAM_ACCEPTED,
49
50 // The user pressed the reject to turn off the feature.
51 HISTOGRAM_REJECTED,
52
53 // The user pressed the X button to dismiss the infobar this time.
54 HISTOGRAM_DISMISSED,
55
56 // The user completely ignored the infoar. Either they navigated away, or
57 // they used the page as is.
58 HISTOGRAM_IGNORED,
59
60 // The user clicked on the learn more link in the infobar.
61 HISTOGRAM_LEARN_MORE,
62
63 HISTOGRAM_MAX
64 };
65
66 // The infobar asking the user if they want to use one-click sign in.
67 class OneClickLoginInfoBarDelegate : public ConfirmInfoBarDelegate {
68 public:
69 OneClickLoginInfoBarDelegate(InfoBarTabHelper* owner,
70 const std::string& email,
71 const std::string& password);
72 virtual ~OneClickLoginInfoBarDelegate();
73
74 private:
75 // ConfirmInfoBarDelegate overrides.
76 virtual void InfoBarDismissed() OVERRIDE;
77 virtual gfx::Image* GetIcon() const OVERRIDE;
78 virtual Type GetInfoBarType() const OVERRIDE;
79 virtual string16 GetMessageText() const OVERRIDE;
80 virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
81 virtual bool Accept() OVERRIDE;
82 virtual bool Cancel() OVERRIDE;
83
84 void RecordHistogramAction(int action);
85
86 Profile* profile_;
87
88 // Email address and password of the account that has just logged in.
89 std::string email_;
90 std::string password_;
91
92 // Whether any UI controls in the infobar were pressed or not.
93 bool button_pressed_;
94
95 DISALLOW_COPY_AND_ASSIGN(OneClickLoginInfoBarDelegate);
96 };
97
98 OneClickLoginInfoBarDelegate::OneClickLoginInfoBarDelegate(
99 InfoBarTabHelper* owner,
100 const std::string& email,
101 const std::string& password)
102 : ConfirmInfoBarDelegate(owner),
103 profile_(Profile::FromBrowserContext(
104 owner->web_contents()->GetBrowserContext())),
105 email_(email),
106 password_(password),
107 button_pressed_(false) {
108 DCHECK(profile_);
109 RecordHistogramAction(HISTOGRAM_SHOWN);
110 }
111
112 OneClickLoginInfoBarDelegate::~OneClickLoginInfoBarDelegate() {
113 if (!button_pressed_)
114 RecordHistogramAction(HISTOGRAM_IGNORED);
115 }
116
117 void OneClickLoginInfoBarDelegate::InfoBarDismissed() {
118 RecordHistogramAction(HISTOGRAM_DISMISSED);
119 button_pressed_ = true;
120 }
121
122 gfx::Image* OneClickLoginInfoBarDelegate::GetIcon() const {
123 return &ResourceBundle::GetSharedInstance().GetNativeImageNamed(
124 IDR_INFOBAR_AUTOLOGIN);
125 }
126
127 InfoBarDelegate::Type OneClickLoginInfoBarDelegate::GetInfoBarType() const {
128 return PAGE_ACTION_TYPE;
129 }
130
131 string16 OneClickLoginInfoBarDelegate::GetMessageText() const {
132 return l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_INFOBAR_MESSAGE);
133 }
134
135 string16 OneClickLoginInfoBarDelegate::GetButtonLabel(
136 InfoBarButton button) const {
137 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
138 IDS_OK : IDS_ONE_CLICK_SIGNIN_INFOBAR_CANCEL_BUTTON);
139 }
140
141 bool OneClickLoginInfoBarDelegate::Accept() {
142 RecordHistogramAction(HISTOGRAM_ACCEPTED);
143 ShowOneClickSigninDialog(profile_, email_, password_);
144 button_pressed_ = true;
145 return true;
146 }
147
148 bool OneClickLoginInfoBarDelegate::Cancel() {
149 PrefService* pref_service =
150 TabContentsWrapper::GetCurrentWrapperForContents(
151 owner()->web_contents())->profile()->GetPrefs();
152 pref_service->SetBoolean(prefs::kReverseAutologinEnabled, false);
153 RecordHistogramAction(HISTOGRAM_REJECTED);
154 button_pressed_ = true;
155 return true;
156 }
157
158 void OneClickLoginInfoBarDelegate::RecordHistogramAction(int action) {
159 UMA_HISTOGRAM_ENUMERATION("AutoLogin.Reverse", action, HISTOGRAM_MAX);
160 }
161
162 } // namespace
163
164 // static
165 bool OneClickSigninManager::CanOffer(content::WebContents* web_contents) {
166 return !web_contents->GetBrowserContext()->IsOffTheRecord();
167 }
168
169 // static
170 void OneClickSigninManager::ShowInfoBarIfPossible(net::URLRequest* request,
171 int child_id,
172 int route_id) {
173 // See if the response contains the X-Google-Accounts-SignIn header.
174 std::string value;
175 request->GetResponseHeaderByName("X-Google-Accounts-SignIn", &value);
176 if (value.empty())
177 return;
178
179 std::vector<std::pair<std::string, std::string> > pairs;
180 if (!base::SplitStringIntoKeyValuePairs(value, '=', ',', &pairs))
181 return;
182
183 // Parse the information from the value string.
184 std::string email;
185 for (size_t i = 0; i < pairs.size(); ++i) {
186 const std::pair<std::string, std::string>& pair = pairs[i];
187 if (pair.first == "email")
188 TrimString(pair.second, "\"", &email);
189 }
190
191 if (email.empty())
192 return;
193
194 content::BrowserThread::PostTask(
195 content::BrowserThread::UI, FROM_HERE,
196 base::Bind(&OneClickSigninManager::ShowInfoBarUIThread, email,
197 child_id, route_id));
198 }
199
200 OneClickSigninManager::OneClickSigninManager(content::WebContents* web_contents)
201 : content::WebContentsObserver(web_contents) {
202 }
203
204 OneClickSigninManager::~OneClickSigninManager() {
205 }
206
207 // static
208 void OneClickSigninManager::ShowInfoBarUIThread(
209 const std::string& email,
210 int child_id,
211 int route_id) {
212 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
213
214 content::WebContents* web_contents = tab_util::GetWebContentsByID(child_id,
215 route_id);
216 if (!web_contents)
217 return;
218
219 Profile* profile =
220 Profile::FromBrowserContext(web_contents->GetBrowserContext());
221
222 if (!ProfileSyncService::IsSyncEnabled())
223 return;
224
225 ProfileSyncService* service =
226 ProfileSyncServiceFactory::GetForProfile(profile);
227
228 if (!profile->GetPrefs()->GetBoolean(prefs::kReverseAutologinEnabled) ||
229 service->AreCredentialsAvailable())
230 return;
231
232 TabContentsWrapper* wrapper =
233 TabContentsWrapper::GetCurrentWrapperForContents(web_contents);
234 if (!wrapper)
235 return;
236
237 // TODO(rogerta): remove this #if once the dialog is fully implemented for
238 // mac and linux.
239 #if defined(ENABLE_ONE_CLICK_SIGNIN)
240 // Save the email in the one-click signin manager. The manager may
241 // not exist if the contents is incognito or if the profile is already
242 // connected to a Google account.
243 OneClickSigninManager* manager = wrapper->one_click_signin_manager();
244 if (manager)
245 manager->SaveEmail(email);
246 #endif
247 }
248
249 void OneClickSigninManager::DidNavigateAnyFrame(
250 const content::LoadCommittedDetails& details,
251 const content::FrameNavigateParams& params) {
252 if (params.password_form.origin.is_valid())
253 SavePassword(params.password_form);
254 }
255
256 void OneClickSigninManager::DidStopLoading() {
257 if (email_.empty() || password_.empty())
258 return;
259
260 TabContentsWrapper* wrapper =
261 TabContentsWrapper::GetCurrentWrapperForContents(web_contents());
262
263 wrapper->infobar_tab_helper()->AddInfoBar(
264 new OneClickLoginInfoBarDelegate(wrapper->infobar_tab_helper(),
265 email_, password_));
266
267 email_.clear();
268 password_.clear();
269 }
270
271 void OneClickSigninManager::SaveEmail(const std::string& email) {
272 // TODO(rogerta): validate that the email address is the same as set in
273 // the form?
274 email_ = email;
275 }
276
277 void OneClickSigninManager::SavePassword(
278 const webkit::forms::PasswordForm& form) {
279 // TODO(rogerta): validate that the email address in the form is the same
280 // as set by SaveEmail?
281
282 // TODO(rogerta): in the case of a 2-factor or captcha or some other type of
283 // challenge, its possible for the user to never complete the signin.
284 // Should have a way to detect this and clear the password member.
285
286 // TODO(rogerta): need to make sure this works with multi-login enabled
287 // accounts. In particular, of the user is already longged into one
288 // account, adds a second account to the session and decides to connect
289 // his profile with that one, make sure we use the right account.
290 password_ = UTF16ToUTF8(form.password_value);
291 }
292
293
294 OneClickSigninSyncStarter::OneClickSigninSyncStarter(
295 const std::string& email,
296 const std::string& password,
297 Profile* profile,
298 bool use_default_settings)
299 : profile_(profile),
300 signin_tracker_(profile, this),
301 use_default_settings_(use_default_settings) {
302 DCHECK(profile_);
303
304 SigninManager* manager = SigninManagerFactory::GetForProfile(profile_);
305 manager->StartSignInWithCredentials(email, password);
306 }
307
308 OneClickSigninSyncStarter::~OneClickSigninSyncStarter() {
309 }
310
311 void OneClickSigninSyncStarter::GaiaCredentialsValid() {
312 }
313
314 void OneClickSigninSyncStarter::SigninFailed() {
315 delete this;
316 }
317
318 void OneClickSigninSyncStarter::SigninSuccess() {
319 ProfileSyncService* profile_sync_service =
320 ProfileSyncServiceFactory::GetForProfile(profile_);
321 profile_sync_service->SetSyncSetupCompleted();
322
323 if (use_default_settings_) {
324 // Just kick off the sync machine, no need to configure it first.
325 profile_sync_service->UnsuppressAndStart();
326 } else {
327 // Give the user a chance to configure things.
328 LoginUIService* login_ui_service =
329 LoginUIServiceFactory::GetForProfile(profile_);
330 login_ui_service->ShowLoginUI();
Andrew T Wilson (Slow) 2012/03/02 19:14:01 BTW, I think there's going to be a bug here, if yo
Roger Tawa OOO till Jul 10th 2012/03/02 22:32:47 Done.
331 }
332
333 delete this;
334 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698