12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 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) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/signin/signin_ui_util.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/prefs/pref_service.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/sys_string_conversions.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/signin/account_tracker_service_factory.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/signin/signin_global_error.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/signin/signin_global_error_factory.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/sync_global_error.h" 19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/sync/sync_global_error_factory.h" 2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/browser/ui/browser_navigator.h" 216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/common/pref_names.h" 2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/chromium_strings.h" 2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h" 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/signin/core/browser/account_tracker_service.h" 25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/profile_oauth2_token_service.h" 26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h" 276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/signin/core/common/profile_management_switches.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/gfx/font_list.h" 3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/text_elider.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum width of a username - we trim emails that are wider than this so 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the wrench menu doesn't get ridiculously wide. 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kUsernameMaxWidth = 200; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace signin_ui_util { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GlobalError* GetSignedInServiceError(Profile* profile) { 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<GlobalError*> errors = GetSignedInServiceErrors(profile); 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (errors.empty()) 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return NULL; 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return errors[0]; 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::vector<GlobalError*> GetSignedInServiceErrors(Profile* profile) { 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<GlobalError*> errors; 49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Chrome OS doesn't use SigninGlobalError or SyncGlobalError. Other platforms 50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // may use these services to show auth and sync errors in the toolbar menu. 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if !defined(OS_CHROMEOS) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Auth errors have the highest priority - after that, individual service 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // errors. 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SigninGlobalError* signin_error = 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SigninGlobalErrorFactory::GetForProfile(profile); 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (signin_error && signin_error->HasError()) 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch errors.push_back(signin_error); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No auth error - now try other services. Currently the list is just hard- 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // coded but in the future if we add more we can create some kind of 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // registration framework. 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (profile->IsSyncAccessible()) { 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SyncGlobalError* error = SyncGlobalErrorFactory::GetForProfile(profile); 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (error && error->HasMenuItem()) 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch errors.push_back(error); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return errors; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 GetSigninMenuLabel(Profile* profile) { 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GlobalError* error = signin_ui_util::GetSignedInServiceError(profile); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (error) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return error->MenuItemLabel(); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No errors, so just display the signed in user, if any. 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ProfileSyncService* service = profile->IsSyncAccessible() ? 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ProfileSyncServiceFactory::GetForProfile(profile) : NULL; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Even if the user is signed in, don't display the "signed in as..." 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // label if we're still setting up sync. 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!service || !service->FirstSetupInProgress()) { 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string username; 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SigninManagerBase* signin_manager = 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SigninManagerFactory::GetForProfileIfExists(profile); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (signin_manager) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) username = signin_manager->GetAuthenticatedUsername(); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!username.empty() && !signin_manager->AuthInProgress()) { 9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::string16 elided = gfx::ElideText(base::UTF8ToUTF16(username), 9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) gfx::FontList(), kUsernameMaxWidth, gfx::ELIDE_EMAIL); 9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return l10n_util::GetStringFUTF16(IDS_SYNC_MENU_SYNCED_LABEL, elided); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return l10n_util::GetStringFUTF16(IDS_SYNC_MENU_PRE_SYNCED_LABEL, 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Given an authentication state this helper function returns various labels 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// that can be used to display information about the state. 1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid GetStatusLabelsForAuthError(Profile* profile, 1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const SigninManagerBase& signin_manager, 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16* status_label, 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16* link_label) { 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 username = 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(signin_manager.GetAuthenticatedUsername()); 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (link_label) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) link_label->assign(l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL)); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const GoogleServiceAuthError::State state = 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ProfileOAuth2TokenServiceFactory::GetForProfile(profile)-> 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) signin_error_controller()->auth_error().state(); 1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch switch (state) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case GoogleServiceAuthError::SERVICE_ERROR: 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GoogleServiceAuthError::ACCOUNT_DELETED: 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GoogleServiceAuthError::ACCOUNT_DISABLED: 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the user name is empty then the first login failed, otherwise the 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // credentials are out-of-date. 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (username.empty()) { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status_label) { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status_label->assign( 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_SYNC_INVALID_USER_CREDENTIALS)); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status_label) { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status_label->assign( 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_INFO_OUT_OF_DATE)); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GoogleServiceAuthError::SERVICE_UNAVAILABLE: 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status_label) { 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status_label->assign( 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_SYNC_SERVICE_UNAVAILABLE)); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (link_label) 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) link_label->clear(); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GoogleServiceAuthError::CONNECTION_FAILED: 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status_label) { 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status_label->assign( 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) l10n_util::GetStringFUTF16(IDS_SYNC_SERVER_IS_UNREACHABLE, 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) product_name)); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Note that there is little the user can do if the server is not 148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // reachable. Since attempting to re-connect is done automatically by 149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // the Syncer, we do not show the (re)login link. 150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (link_label) 151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) link_label->clear(); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status_label) { 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status_label->assign(l10n_util::GetStringUTF16( 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IDS_SYNC_ERROR_SIGNING_IN)); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void InitializePrefsForProfile(Profile* profile) { 1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Suppresses the upgrade tutorial for a new profile. 1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (profile->IsNewProfile() && switches::IsNewAvatarMenu()) { 1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) profile->GetPrefs()->SetInteger( 1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) prefs::kProfileAvatarTutorialShown, kUpgradeWelcomeTutorialShowMax + 1); 1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ShowSigninErrorLearnMorePage(Profile* profile) { 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static const char kSigninErrorLearnMoreUrl[] = 17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "https://support.google.com/chrome/answer/1181420?"; 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) chrome::NavigateParams params( 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profile, GURL(kSigninErrorLearnMoreUrl), ui::PAGE_TRANSITION_LINK); 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) params.disposition = NEW_FOREGROUND_TAB; 17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) chrome::Navigate(¶ms); 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string GetDisplayEmail(Profile* profile, const std::string& account_id) { 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AccountTrackerService* account_tracker = 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AccountTrackerServiceFactory::GetForProfile(profile); 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string email = account_tracker->GetAccountInfo(account_id).email; 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (email.empty()) { 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(AccountTrackerService::MIGRATION_NOT_STARTED, 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci account_tracker->GetMigrationState()); 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return account_id; 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return email; 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace signin_ui_util 192