Home | History | Annotate | Download | only in signin
      1 // Copyright (c) 2012 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/about_signin_internals.h"
      6 
      7 #include "base/debug/trace_event.h"
      8 #include "base/hash.h"
      9 #include "base/i18n/time_formatting.h"
     10 #include "base/logging.h"
     11 #include "base/prefs/pref_service.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "chrome/browser/profiles/profile.h"
     14 #include "chrome/browser/signin/signin_internals_util.h"
     15 #include "chrome/browser/signin/signin_manager.h"
     16 #include "chrome/browser/signin/token_service.h"
     17 #include "chrome/browser/signin/token_service_factory.h"
     18 #include "chrome/browser/ui/webui/signin_internals_ui.h"
     19 #include "google_apis/gaia/gaia_constants.h"
     20 
     21 using base::Time;
     22 using namespace signin_internals_util;
     23 
     24 AboutSigninInternals::AboutSigninInternals() : profile_(NULL) {
     25   // Initialize default values for tokens.
     26   for (size_t i = 0; i < kNumTokenPrefs; ++i) {
     27     signin_status_.token_info_map.insert(std::pair<std::string, TokenInfo>(
     28         kTokenPrefsArray[i],
     29         TokenInfo(std::string(), "Not Loaded", std::string(), 0,
     30                   kTokenPrefsArray[i])));
     31   }
     32 }
     33 
     34 AboutSigninInternals::~AboutSigninInternals() {
     35 }
     36 
     37 void AboutSigninInternals::AddSigninObserver(
     38     AboutSigninInternals::Observer* observer) {
     39   signin_observers_.AddObserver(observer);
     40 }
     41 
     42 void AboutSigninInternals::RemoveSigninObserver(
     43     AboutSigninInternals::Observer* observer) {
     44   signin_observers_.RemoveObserver(observer);
     45 }
     46 
     47 void AboutSigninInternals::NotifySigninValueChanged(
     48     const UntimedSigninStatusField& field,
     49     const std::string& value) {
     50   unsigned int field_index = field - UNTIMED_FIELDS_BEGIN;
     51   DCHECK(field_index >= 0 &&
     52          field_index < signin_status_.untimed_signin_fields.size());
     53 
     54   signin_status_.untimed_signin_fields[field_index] = value;
     55 
     56   // Also persist these values in the prefs.
     57   const std::string pref_path = SigninStatusFieldToString(field);
     58   profile_->GetPrefs()->SetString(pref_path.c_str(), value);
     59 
     60   NotifyObservers();
     61 }
     62 
     63 void AboutSigninInternals::NotifySigninValueChanged(
     64     const TimedSigninStatusField& field,
     65     const std::string& value) {
     66   unsigned int field_index = field - TIMED_FIELDS_BEGIN;
     67   DCHECK(field_index >= 0 &&
     68          field_index < signin_status_.timed_signin_fields.size());
     69 
     70   Time now = Time::NowFromSystemTime();
     71   std::string time_as_str = UTF16ToUTF8(base::TimeFormatFriendlyDate(now));
     72   TimedSigninStatusValue timed_value(value, time_as_str);
     73 
     74   signin_status_.timed_signin_fields[field_index] = timed_value;
     75 
     76   // Also persist these values in the prefs.
     77   const std::string value_pref = SigninStatusFieldToString(field) + ".value";
     78   const std::string time_pref = SigninStatusFieldToString(field) + ".time";
     79   profile_->GetPrefs()->SetString(value_pref.c_str(), value);
     80   profile_->GetPrefs()->SetString(time_pref.c_str(), time_as_str);
     81 
     82   NotifyObservers();
     83 }
     84 
     85 void AboutSigninInternals::RefreshSigninPrefs() {
     86   // Return if no profile exists. Can occur in unit tests.
     87   if (!profile_)
     88     return;
     89 
     90   PrefService* pref_service = profile_->GetPrefs();
     91   for (int i = UNTIMED_FIELDS_BEGIN; i < UNTIMED_FIELDS_END; ++i) {
     92     const std::string pref_path =
     93         SigninStatusFieldToString(static_cast<UntimedSigninStatusField>(i));
     94 
     95     signin_status_.untimed_signin_fields[i - UNTIMED_FIELDS_BEGIN] =
     96         pref_service->GetString(pref_path.c_str());
     97   }
     98   for (int i = TIMED_FIELDS_BEGIN ; i < TIMED_FIELDS_END; ++i) {
     99     const std::string value_pref = SigninStatusFieldToString(
    100         static_cast<TimedSigninStatusField>(i)) + ".value";
    101     const std::string time_pref = SigninStatusFieldToString(
    102         static_cast<TimedSigninStatusField>(i)) + ".time";
    103 
    104     TimedSigninStatusValue value(pref_service->GetString(value_pref.c_str()),
    105                                  pref_service->GetString(time_pref.c_str()));
    106     signin_status_.timed_signin_fields[i - TIMED_FIELDS_BEGIN] = value;
    107   }
    108 
    109   // Get status and timestamps for all token services.
    110   for (size_t i = 0; i < kNumTokenPrefs; i++) {
    111     const std::string pref = TokenPrefPath(kTokenPrefsArray[i]);
    112     const std::string value = pref + ".value";
    113     const std::string status = pref + ".status";
    114     const std::string time = pref + ".time";
    115     const std::string time_internal = pref + ".time_internal";
    116 
    117     TokenInfo token_info(pref_service->GetString(value.c_str()),
    118                          pref_service->GetString(status.c_str()),
    119                          pref_service->GetString(time.c_str()),
    120                          pref_service->GetInt64(time_internal.c_str()),
    121                          kTokenPrefsArray[i]);
    122 
    123     signin_status_.token_info_map[kTokenPrefsArray[i]] = token_info;
    124   }
    125 
    126   NotifyObservers();
    127 }
    128 
    129 void AboutSigninInternals::NotifyTokenReceivedSuccess(
    130     const std::string& token_name,
    131     const std::string& token,
    132     bool update_time) {
    133   // This should have been initialized already.
    134   DCHECK(signin_status_.token_info_map.count(token_name));
    135 
    136   const std::string status_success = "Successful";
    137   signin_status_.token_info_map[token_name].token = token;
    138   signin_status_.token_info_map[token_name].status = status_success;
    139 
    140   // Also update preferences.
    141   const std::string value_pref = TokenPrefPath(token_name) + ".value";
    142   const std::string time_pref = TokenPrefPath(token_name) + ".time";
    143   const std::string time_internal_pref =
    144       TokenPrefPath(token_name) + ".time_internal";
    145   const std::string status_pref = TokenPrefPath(token_name) + ".status";
    146   profile_->GetPrefs()->SetString(value_pref.c_str(), token);
    147   profile_->GetPrefs()->SetString(status_pref.c_str(), "Successful");
    148 
    149   // Update timestamp if needed.
    150   if (update_time) {
    151     Time now = Time::NowFromSystemTime();
    152     int64 time_as_int = now.ToInternalValue();
    153     const std::string time_as_str =
    154         UTF16ToUTF8(base::TimeFormatFriendlyDate(now));
    155     signin_status_.token_info_map[token_name].time = time_as_str;
    156     signin_status_.token_info_map[token_name].time_internal = time_as_int;
    157     profile_->GetPrefs()->SetString(time_pref.c_str(), time_as_str);
    158     profile_->GetPrefs()->SetInt64(time_internal_pref.c_str(), time_as_int);
    159   }
    160 
    161   NotifyObservers();
    162 }
    163 
    164 
    165 void AboutSigninInternals::NotifyTokenReceivedFailure(
    166     const std::string& token_name,
    167     const std::string& error) {
    168   Time now = Time::NowFromSystemTime();
    169   int64 time_as_int = now.ToInternalValue();
    170   const std::string time_as_str =
    171       UTF16ToUTF8(base::TimeFormatFriendlyDate(now));
    172 
    173   // This should have been initialized already.
    174   DCHECK(signin_status_.token_info_map.count(token_name));
    175 
    176   signin_status_.token_info_map[token_name].token.clear();
    177   signin_status_.token_info_map[token_name].status = error;
    178   signin_status_.token_info_map[token_name].time = time_as_str;
    179   signin_status_.token_info_map[token_name].time_internal = time_as_int;
    180 
    181   // Also update preferences.
    182   const std::string value_pref = TokenPrefPath(token_name) + ".value";
    183   const std::string time_pref = TokenPrefPath(token_name) + ".time";
    184   const std::string time_internal_pref =
    185       TokenPrefPath(token_name) + ".time_internal";
    186   const std::string status_pref = TokenPrefPath(token_name) + ".status";
    187   profile_->GetPrefs()->SetString(value_pref.c_str(), std::string());
    188   profile_->GetPrefs()->SetString(time_pref.c_str(), time_as_str);
    189     profile_->GetPrefs()->SetInt64(time_internal_pref.c_str(), time_as_int);
    190   profile_->GetPrefs()->SetString(status_pref.c_str(), error);
    191 
    192   NotifyObservers();
    193 }
    194 
    195 // While clearing tokens, we don't update the time or status.
    196 void AboutSigninInternals::NotifyClearStoredToken(
    197     const std::string& token_name) {
    198   // This should have been initialized already.
    199   DCHECK(signin_status_.token_info_map.count(token_name));
    200 
    201   signin_status_.token_info_map[token_name].token.clear();
    202 
    203   const std::string value_pref = TokenPrefPath(token_name) + ".value";
    204   profile_->GetPrefs()->SetString(value_pref.c_str(), std::string());
    205 
    206   NotifyObservers();
    207 }
    208 
    209 void AboutSigninInternals::Initialize(Profile* profile) {
    210   DCHECK(!profile_);
    211   profile_ = profile;
    212 
    213   RefreshSigninPrefs();
    214 
    215   SigninManagerFactory::GetForProfile(profile)->
    216       AddSigninDiagnosticsObserver(this);
    217   TokenServiceFactory::GetForProfile(profile)->
    218       AddSigninDiagnosticsObserver(this);
    219 }
    220 
    221 void AboutSigninInternals::Shutdown() {
    222   SigninManagerFactory::GetForProfile(profile_)->
    223       RemoveSigninDiagnosticsObserver(this);
    224   TokenServiceFactory::GetForProfile(profile_)->
    225       RemoveSigninDiagnosticsObserver(this);
    226 }
    227 
    228 void AboutSigninInternals::NotifyObservers() {
    229   FOR_EACH_OBSERVER(AboutSigninInternals::Observer,
    230                     signin_observers_,
    231                     OnSigninStateChanged(signin_status_.ToValue()));
    232 }
    233 
    234 scoped_ptr<DictionaryValue> AboutSigninInternals::GetSigninStatus() {
    235   return signin_status_.ToValue().Pass();
    236 }
    237 
    238 Time AboutSigninInternals::GetTokenTime(
    239     const std::string& token_name) const {
    240   TokenInfoMap::const_iterator iter =
    241       signin_status_.token_info_map.find(token_name);
    242   if (iter == signin_status_.token_info_map.end())
    243     return base::Time();
    244   return base::Time::FromInternalValue(iter->second.time_internal);
    245 }
    246