12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/about_signin_internals.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/command_line.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/trace_event.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/hash.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/i18n/time_formatting.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/stringprintf.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
15effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/profile_oauth2_token_service.h"
16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_client.h"
17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/signin_internals_util.h"
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h"
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/signin/core/common/profile_management_switches.h"
200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/signin/core/common/signin_switches.h"
216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_fetcher.h"
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_util.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "google_apis/gaia/gaia_urls.h"
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/cookies/canonical_cookie.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::Time;
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace signin_internals_util;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GetTimeStr(base::Time time) {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF16ToUTF8(base::TimeFormatShortDateAndTime(time));
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::ListValue* AddSection(base::ListValue* parent_list,
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            const std::string& title) {
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> section(new base::DictionaryValue());
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_contents = new base::ListValue();
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  section->SetString("title", title);
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  section->Set("data", section_contents);
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  parent_list->Append(section.release());
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return section_contents;
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AddSectionEntry(base::ListValue* section_list,
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const std::string& field_name,
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     const std::string& field_status,
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     const std::string& field_time = "") {
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue());
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry->SetString("label", field_name);
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  entry->SetString("status", field_status);
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  entry->SetString("time", field_time);
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  section_list->Append(entry.release());
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void AddCookieEntry(base::ListValue* accounts_list,
596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                     const std::string& field_email,
606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                     const std::string& field_valid) {
616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue());
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  entry->SetString("email", field_email);
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  entry->SetString("valid", field_valid);
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  accounts_list->Append(entry.release());
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string SigninStatusFieldToLabel(UntimedSigninStatusField field) {
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (field) {
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case USERNAME:
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "User Id";
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case UNTIMED_FIELDS_END:
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NOTREACHED();
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return std::string();
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NOTREACHED();
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return std::string();
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if !defined (OS_CHROMEOS)
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustd::string SigninStatusFieldToLabel(TimedSigninStatusField field) {
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (field) {
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case SIGNIN_TYPE:
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return "Type";
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case AUTHENTICATION_RESULT_RECEIVED:
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return "Last Authentication Result Received";
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case REFRESH_TOKEN_RECEIVED:
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return "Last RefreshToken Received";
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case GET_USER_INFO_STATUS:
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return "Last OnGetUserInfo Received";
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case UBER_TOKEN_STATUS:
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return "Last OnUberToken Received";
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case MERGE_SESSION_STATUS:
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return "Last OnMergeSession Received";
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case TIMED_FIELDS_END:
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NOTREACHED();
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return "Error";
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NOTREACHED();
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return "Error";
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif // !defined (OS_CHROMEOS)
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // anonymous namespace
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochAboutSigninInternals::AboutSigninInternals(
106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    ProfileOAuth2TokenService* token_service,
107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    SigninManagerBase* signin_manager)
108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    : token_service_(token_service),
109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      signin_manager_(signin_manager),
110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      client_(NULL) {}
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochAboutSigninInternals::~AboutSigninInternals() {}
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AboutSigninInternals::AddSigninObserver(
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AboutSigninInternals::Observer* observer) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  signin_observers_.AddObserver(observer);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AboutSigninInternals::RemoveSigninObserver(
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AboutSigninInternals::Observer* observer) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  signin_observers_.RemoveObserver(observer);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AboutSigninInternals::NotifySigninValueChanged(
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const UntimedSigninStatusField& field,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& value) {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int field_index = field - UNTIMED_FIELDS_BEGIN;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(field_index >= 0 &&
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         field_index < signin_status_.untimed_signin_fields.size());
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  signin_status_.untimed_signin_fields[field_index] = value;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Also persist these values in the prefs.
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string pref_path = SigninStatusFieldToString(field);
135e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  client_->GetPrefs()->SetString(pref_path.c_str(), value);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyObservers();
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AboutSigninInternals::NotifySigninValueChanged(
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const TimedSigninStatusField& field,
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& value) {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int field_index = field - TIMED_FIELDS_BEGIN;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(field_index >= 0 &&
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         field_index < signin_status_.timed_signin_fields.size());
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Time now = Time::NowFromSystemTime();
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string time_as_str =
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::UTF16ToUTF8(base::TimeFormatShortDateAndTime(now));
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TimedSigninStatusValue timed_value(value, time_as_str);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  signin_status_.timed_signin_fields[field_index] = timed_value;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Also persist these values in the prefs.
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string value_pref = SigninStatusFieldToString(field) + ".value";
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string time_pref = SigninStatusFieldToString(field) + ".time";
157e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  client_->GetPrefs()->SetString(value_pref.c_str(), value);
158e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  client_->GetPrefs()->SetString(time_pref.c_str(), time_as_str);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyObservers();
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AboutSigninInternals::RefreshSigninPrefs() {
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Since the AboutSigninInternals has a dependency on the SigninManager
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // (as seen in the AboutSigninInternalsFactory) the SigninManager can have
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the AuthenticatedUsername set before AboutSigninInternals can observe it.
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // For that scenario, read the AuthenticatedUsername if it exists.
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (signin_manager_->IsAuthenticated()) {
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    signin_status_.untimed_signin_fields[USERNAME] =
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        signin_manager_->GetAuthenticatedUsername();
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
173e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Return if no client exists. Can occur in unit tests.
174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!client_)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
177e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  PrefService* pref_service = client_->GetPrefs();
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = UNTIMED_FIELDS_BEGIN; i < UNTIMED_FIELDS_END; ++i) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string pref_path =
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SigninStatusFieldToString(static_cast<UntimedSigninStatusField>(i));
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    signin_status_.untimed_signin_fields[i - UNTIMED_FIELDS_BEGIN] =
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pref_service->GetString(pref_path.c_str());
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
185e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (int i = TIMED_FIELDS_BEGIN; i < TIMED_FIELDS_END; ++i) {
186e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const std::string value_pref =
187e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        SigninStatusFieldToString(static_cast<TimedSigninStatusField>(i)) +
188e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        ".value";
189e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const std::string time_pref =
190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        SigninStatusFieldToString(static_cast<TimedSigninStatusField>(i)) +
191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        ".time";
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TimedSigninStatusValue value(pref_service->GetString(value_pref.c_str()),
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 pref_service->GetString(time_pref.c_str()));
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    signin_status_.timed_signin_fields[i - TIMED_FIELDS_BEGIN] = value;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // TODO(rogerta): Get status and timestamps for oauth2 tokens.
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyObservers();
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
203e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid AboutSigninInternals::Initialize(SigninClient* client) {
204e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK(!client_);
205e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  client_ = client;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RefreshSigninPrefs();
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
209e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  signin_manager_->AddSigninDiagnosticsObserver(this);
210e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  token_service_->AddDiagnosticsObserver(this);
2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  cookie_changed_subscription_ = client_->AddCookieChangedCallback(
2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     base::Bind(&AboutSigninInternals::OnCookieChanged,
2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     base::Unretained(this)));
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AboutSigninInternals::Shutdown() {
217e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  signin_manager_->RemoveSigninDiagnosticsObserver(this);
218e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  token_service_->RemoveDiagnosticsObserver(this);
2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  cookie_changed_subscription_.reset();
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AboutSigninInternals::NotifyObservers() {
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<base::DictionaryValue> signin_status_value =
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      signin_status_.ToValue(client_->GetProductVersion());
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(AboutSigninInternals::Observer,
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    signin_observers_,
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    OnSigninStateChanged(signin_status_value.get()));
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<base::DictionaryValue> AboutSigninInternals::GetSigninStatus() {
231e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return signin_status_.ToValue(client_->GetProductVersion()).Pass();
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AboutSigninInternals::OnAccessTokenRequested(
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& account_id,
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& consumer_id,
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const OAuth2TokenService::ScopeSet& scopes) {
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TokenInfo* token = signin_status_.FindToken(account_id, consumer_id, scopes);
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (token) {
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *token = TokenInfo(consumer_id, scopes);
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    token = new TokenInfo(consumer_id, scopes);
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    signin_status_.token_info_map[account_id].push_back(token);
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotifyObservers();
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AboutSigninInternals::OnFetchAccessTokenComplete(
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& account_id,
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& consumer_id,
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const OAuth2TokenService::ScopeSet& scopes,
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GoogleServiceAuthError error,
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::Time expiration_time) {
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TokenInfo* token = signin_status_.FindToken(account_id, consumer_id, scopes);
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!token) {
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(1) << "Can't find token: " << account_id << ", " << consumer_id;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  token->receive_time = base::Time::Now();
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  token->error = error;
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  token->expiration_time = expiration_time;
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotifyObservers();
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AboutSigninInternals::OnTokenRemoved(
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& account_id,
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const OAuth2TokenService::ScopeSet& scopes) {
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < signin_status_.token_info_map[account_id].size();
272e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       ++i) {
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TokenInfo* token = signin_status_.token_info_map[account_id][i];
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (token->scopes == scopes)
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      token->Invalidate();
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotifyObservers();
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void AboutSigninInternals::OnRefreshTokenReceived(std::string status) {
281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  NotifySigninValueChanged(REFRESH_TOKEN_RECEIVED, status);
282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void AboutSigninInternals::OnAuthenticationResultReceived(std::string status) {
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  NotifySigninValueChanged(AUTHENTICATION_RESULT_RECEIVED, status);
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void AboutSigninInternals::OnCookieChanged(
2896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const net::CanonicalCookie* cookie) {
2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (cookie->Name() == "LSID" &&
2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      cookie->Domain() == GaiaUrls::GetInstance()->gaia_url().host() &&
2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      cookie->IsSecure() &&
2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      cookie->IsHttpOnly()) {
2946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    GetCookieAccountsAsync();
2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void AboutSigninInternals::GetCookieAccountsAsync() {
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Don't bother calling /ListAccounts if no one will observe the response.
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!gaia_fetcher_ && signin_observers_.might_have_observers()) {
3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // There is no list account request in flight.
3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    gaia_fetcher_.reset(new GaiaAuthFetcher(
3036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        this, GaiaConstants::kChromeSource, client_->GetURLRequestContext()));
3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    gaia_fetcher_->StartListAccounts();
3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void AboutSigninInternals::OnListAccountsSuccess(const std::string& data) {
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  gaia_fetcher_.reset();
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Get account information from response data.
3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::vector<std::pair<std::string, bool> > gaia_accounts;
3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  bool valid_json = gaia::ParseListAccountsData(data, &gaia_accounts);
3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!valid_json) {
3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    VLOG(1) << "AboutSigninInternals::OnListAccountsSuccess: parsing error";
3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else {
3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    OnListAccountsComplete(gaia_accounts);
3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
3196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void AboutSigninInternals::OnListAccountsFailure(
3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const GoogleServiceAuthError& error) {
3236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  gaia_fetcher_.reset();
3246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  VLOG(1) << "AboutSigninInternals::OnListAccountsFailure:" << error.ToString();
3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
3266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void AboutSigninInternals::OnListAccountsComplete(
3286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    std::vector<std::pair<std::string, bool> >& gaia_accounts) {
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::DictionaryValue signin_status;
3306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::ListValue* cookie_info = new base::ListValue();
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  signin_status.Set("cookie_info", cookie_info);
3326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  for (size_t i = 0; i < gaia_accounts.size(); ++i) {
3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    AddCookieEntry(cookie_info,
3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   gaia_accounts[i].first,
3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   gaia_accounts[i].second ? "Valid" : "Invalid");
3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (gaia_accounts.size() == 0)
3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    AddCookieEntry(cookie_info, "No Accounts Present.", "");
3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Update the observers that the cookie's accounts are updated.
3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  FOR_EACH_OBSERVER(AboutSigninInternals::Observer,
3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    signin_observers_,
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    OnCookieAccountsFetched(&signin_status));
3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AboutSigninInternals::TokenInfo::TokenInfo(
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& consumer_id,
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const OAuth2TokenService::ScopeSet& scopes)
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : consumer_id(consumer_id),
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scopes(scopes),
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request_time(base::Time::Now()),
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error(GoogleServiceAuthError::AuthErrorNone()),
355e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      removed_(false) {}
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AboutSigninInternals::TokenInfo::~TokenInfo() {}
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AboutSigninInternals::TokenInfo::LessThan(const TokenInfo* a,
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               const TokenInfo* b) {
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return a->consumer_id < b->consumer_id || a->scopes < b->scopes;
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
364e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid AboutSigninInternals::TokenInfo::Invalidate() { removed_ = true; }
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::DictionaryValue* AboutSigninInternals::TokenInfo::ToValue() const {
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> token_info(new base::DictionaryValue());
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  token_info->SetString("service", consumer_id);
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string scopes_str;
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (OAuth2TokenService::ScopeSet::const_iterator it = scopes.begin();
372e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       it != scopes.end();
373e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       ++it) {
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scopes_str += *it + "<br/>";
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  token_info->SetString("scopes", scopes_str);
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  token_info->SetString("request_time", GetTimeStr(request_time).c_str());
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (removed_) {
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    token_info->SetString("status", "Token was revoked.");
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (!receive_time.is_null()) {
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error == GoogleServiceAuthError::AuthErrorNone()) {
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool token_expired = expiration_time < base::Time::Now();
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::string status_str = "";
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (token_expired)
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        status_str = "<p style=\"color: #ffffff; background-color: #ff0000\">";
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::StringAppendF(&status_str,
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          "Received token at %s. Expire at %s",
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          GetTimeStr(receive_time).c_str(),
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          GetTimeStr(expiration_time).c_str());
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (token_expired)
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::StringAppendF(&status_str, "</p>");
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      token_info->SetString("status", status_str);
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      token_info->SetString(
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          "status",
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          base::StringPrintf("Failure: %s", error.ToString().c_str()));
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    token_info->SetString("status", "Waiting for response");
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return token_info.release();
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AboutSigninInternals::SigninStatus::SigninStatus()
407e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    : untimed_signin_fields(UNTIMED_FIELDS_COUNT),
408e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      timed_signin_fields(TIMED_FIELDS_COUNT) {}
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AboutSigninInternals::SigninStatus::~SigninStatus() {
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (TokenInfoMap::iterator it = token_info_map.begin();
412e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       it != token_info_map.end();
413e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       ++it) {
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    STLDeleteElements(&it->second);
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
418e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochAboutSigninInternals::TokenInfo* AboutSigninInternals::SigninStatus::FindToken(
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& account_id,
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& consumer_id,
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const OAuth2TokenService::ScopeSet& scopes) {
422e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (size_t i = 0; i < token_info_map[account_id].size(); ++i) {
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TokenInfo* tmp = token_info_map[account_id][i];
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (tmp->consumer_id == consumer_id && tmp->scopes == scopes)
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return tmp;
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return NULL;
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
430e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochscoped_ptr<base::DictionaryValue> AboutSigninInternals::SigninStatus::ToValue(
431e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::string product_version) {
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> signin_status(new base::DictionaryValue());
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* signin_info = new base::ListValue();
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  signin_status->Set("signin_info", signin_info);
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // A summary of signin related info first.
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* basic_info = AddSection(signin_info, "Basic Information");
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::string signin_status_string =
439e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      untimed_signin_fields[USERNAME - UNTIMED_FIELDS_BEGIN].empty()
440e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          ? "Not Signed In"
441e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          : "Signed In";
442e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  AddSectionEntry(basic_info, "Chrome Version", product_version);
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddSectionEntry(basic_info, "Signin Status", signin_status_string);
4440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  AddSectionEntry(basic_info, "Web Based Signin Enabled?",
4450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      switches::IsEnableWebBasedSignin() == true ? "True" : "False");
4460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  AddSectionEntry(basic_info, "New Avatar Menu Enabled?",
4470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      switches::IsNewAvatarMenu() == true ? "True" : "False");
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  AddSectionEntry(basic_info, "New Profile Management Enabled?",
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      switches::IsNewProfileManagement() == true ? "True" : "False");
4506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  AddSectionEntry(basic_info, "Account Consistency Enabled?",
4516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      switches::IsEnableAccountConsistency() == true ? "True" : "False");
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Only add username.  SID and LSID have moved to tokens section.
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::string field =
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SigninStatusFieldToLabel(static_cast<UntimedSigninStatusField>(USERNAME));
456e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  AddSectionEntry(basic_info,
457e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                  field,
458e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                  untimed_signin_fields[USERNAME - UNTIMED_FIELDS_BEGIN]);
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
460116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if !defined(OS_CHROMEOS)
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Time and status information of the possible sign in types.
462e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::ListValue* detailed_info =
463e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      AddSection(signin_info, "Last Signin Details");
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = TIMED_FIELDS_BEGIN; i < TIMED_FIELDS_END; ++i) {
4655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string status_field_label =
4665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        SigninStatusFieldToLabel(static_cast<TimedSigninStatusField>(i));
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
468e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    AddSectionEntry(detailed_info,
4695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    status_field_label,
4705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    timed_signin_fields[i - TIMED_FIELDS_BEGIN].first,
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    timed_signin_fields[i - TIMED_FIELDS_BEGIN].second);
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif // !defined(OS_CHROMEOS)
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Token information for all services.
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* token_info = new base::ListValue();
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  signin_status->Set("token_info", token_info);
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (TokenInfoMap::iterator it = token_info_map.begin();
479e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       it != token_info_map.end();
480e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       ++it) {
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue* token_details = AddSection(token_info, it->first);
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::sort(it->second.begin(), it->second.end(), TokenInfo::LessThan);
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::vector<TokenInfo*>& tokens = it->second;
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (size_t i = 0; i < tokens.size(); ++i) {
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::DictionaryValue* token_info = tokens[i]->ToValue();
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      token_details->Append(token_info);
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return signin_status.Pass();
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
493