Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / sync / sync_ui_util.cc
blobb7f532233bb9ff4059b0735b2e4c896db0bcce65
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.
5 #include "chrome/browser/sync/sync_ui_util.h"
7 #include "base/i18n/number_formatting.h"
8 #include "base/i18n/time_formatting.h"
9 #include "base/string_util.h"
10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/prefs/pref_service.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/signin/signin_manager.h"
15 #include "chrome/browser/sync/profile_sync_service.h"
16 #include "chrome/browser/sync/profile_sync_service_factory.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_window.h"
19 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
20 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/common/url_constants.h"
24 #include "google_apis/gaia/google_service_auth_error.h"
25 #include "grit/browser_resources.h"
26 #include "grit/chromium_strings.h"
27 #include "grit/generated_resources.h"
28 #include "grit/locale_settings.h"
29 #include "sync/internal_api/public/base/model_type.h"
30 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
31 #include "sync/protocol/proto_enum_conversions.h"
32 #include "sync/protocol/sync_protocol_error.h"
33 #include "ui/base/l10n/l10n_util.h"
34 #include "ui/base/resource/resource_bundle.h"
36 typedef GoogleServiceAuthError AuthError;
38 namespace sync_ui_util {
40 namespace {
42 // Given an authentication state this helper function returns various labels
43 // that can be used to display information about the state.
44 void GetStatusLabelsForAuthError(const AuthError& auth_error,
45 const ProfileSyncService& service,
46 string16* status_label,
47 string16* link_label,
48 string16* global_error_menu_label,
49 string16* global_error_bubble_message,
50 string16* global_error_bubble_accept_label) {
51 string16 username = UTF8ToUTF16(service.profile()->GetPrefs()->GetString(
52 prefs::kGoogleServicesUsername));
53 string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
54 if (link_label)
55 link_label->assign(l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL));
57 switch (auth_error.state()) {
58 case AuthError::INVALID_GAIA_CREDENTIALS:
59 case AuthError::ACCOUNT_DELETED:
60 case AuthError::ACCOUNT_DISABLED:
61 // If the user name is empty then the first login failed, otherwise the
62 // credentials are out-of-date.
63 if (username.empty()) {
64 if (status_label) {
65 status_label->assign(
66 l10n_util::GetStringUTF16(IDS_SYNC_INVALID_USER_CREDENTIALS));
68 } else {
69 if (status_label) {
70 status_label->assign(
71 l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_INFO_OUT_OF_DATE));
73 if (global_error_menu_label) {
74 global_error_menu_label->assign(l10n_util::GetStringUTF16(
75 IDS_SYNC_SIGN_IN_ERROR_WRENCH_MENU_ITEM));
77 if (global_error_bubble_message) {
78 global_error_bubble_message->assign(l10n_util::GetStringFUTF16(
79 IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE, product_name));
81 if (global_error_bubble_accept_label) {
82 global_error_bubble_accept_label->assign(l10n_util::GetStringUTF16(
83 IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_ACCEPT));
86 break;
87 case AuthError::SERVICE_UNAVAILABLE:
88 if (status_label) {
89 status_label->assign(
90 l10n_util::GetStringUTF16(IDS_SYNC_SERVICE_UNAVAILABLE));
92 if (link_label)
93 link_label->clear();
94 if (global_error_menu_label) {
95 global_error_menu_label->assign(l10n_util::GetStringUTF16(
96 IDS_SYNC_SIGN_IN_ERROR_WRENCH_MENU_ITEM));
98 if (global_error_bubble_message) {
99 global_error_bubble_message->assign(l10n_util::GetStringFUTF16(
100 IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_MESSAGE, product_name));
102 if (global_error_bubble_accept_label) {
103 global_error_bubble_accept_label->assign(l10n_util::GetStringUTF16(
104 IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_ACCEPT));
106 break;
107 case AuthError::CONNECTION_FAILED:
108 // Note that there is little the user can do if the server is not
109 // reachable. Since attempting to re-connect is done automatically by
110 // the Syncer, we do not show the (re)login link.
111 if (status_label) {
112 status_label->assign(
113 l10n_util::GetStringFUTF16(IDS_SYNC_SERVER_IS_UNREACHABLE,
114 product_name));
116 break;
117 default:
118 if (status_label) {
119 status_label->assign(l10n_util::GetStringUTF16(
120 IDS_SYNC_ERROR_SIGNING_IN));
122 if (global_error_menu_label) {
123 global_error_menu_label->assign(l10n_util::GetStringUTF16(
124 IDS_SYNC_SIGN_IN_ERROR_WRENCH_MENU_ITEM));
126 if (global_error_bubble_message) {
127 global_error_bubble_message->assign(l10n_util::GetStringFUTF16(
128 IDS_SYNC_OTHER_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE, product_name));
130 if (global_error_bubble_accept_label) {
131 global_error_bubble_accept_label->assign(l10n_util::GetStringUTF16(
132 IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_ACCEPT));
134 break;
138 // Returns the message that should be displayed when the user is authenticated
139 // and can connect to the sync server. If the user hasn't yet authenticated, an
140 // empty string is returned.
141 string16 GetSyncedStateStatusLabel(ProfileSyncService* service,
142 StatusLabelStyle style) {
143 if (!service->sync_initialized())
144 return string16();
146 string16 user_name = UTF8ToUTF16(service->profile()->GetPrefs()->GetString(
147 prefs::kGoogleServicesUsername));
148 DCHECK(!user_name.empty());
150 // Message may also carry additional advice with an HTML link, if acceptable.
151 switch (style) {
152 case PLAIN_TEXT:
153 return l10n_util::GetStringFUTF16(
154 IDS_SYNC_ACCOUNT_SYNCING_TO_USER,
155 user_name);
156 case WITH_HTML:
157 return l10n_util::GetStringFUTF16(
158 IDS_SYNC_ACCOUNT_SYNCING_TO_USER_WITH_MANAGE_LINK,
159 user_name,
160 ASCIIToUTF16(chrome::kSyncGoogleDashboardURL));
161 default:
162 NOTREACHED();
163 return NULL;
167 void GetStatusForActionableError(
168 const syncer::SyncProtocolError& error,
169 string16* status_label) {
170 DCHECK(status_label);
171 switch (error.action) {
172 case syncer::STOP_AND_RESTART_SYNC:
173 status_label->assign(
174 l10n_util::GetStringUTF16(IDS_SYNC_STOP_AND_RESTART_SYNC));
175 break;
176 case syncer::UPGRADE_CLIENT:
177 status_label->assign(
178 l10n_util::GetStringFUTF16(IDS_SYNC_UPGRADE_CLIENT,
179 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
180 break;
181 case syncer::ENABLE_SYNC_ON_ACCOUNT:
182 status_label->assign(
183 l10n_util::GetStringUTF16(IDS_SYNC_ENABLE_SYNC_ON_ACCOUNT));
184 break;
185 case syncer::CLEAR_USER_DATA_AND_RESYNC:
186 status_label->assign(
187 l10n_util::GetStringUTF16(IDS_SYNC_CLEAR_USER_DATA));
188 break;
189 default:
190 NOTREACHED();
194 // TODO(akalin): Write unit tests for these three functions below.
196 // status_label and link_label must either be both NULL or both non-NULL.
197 MessageType GetStatusInfo(ProfileSyncService* service,
198 const SigninManager& signin,
199 StatusLabelStyle style,
200 string16* status_label,
201 string16* link_label) {
202 DCHECK_EQ(status_label == NULL, link_label == NULL);
204 MessageType result_type(SYNCED);
206 if (!service) {
207 return PRE_SYNCED;
210 if (service->HasSyncSetupCompleted()) {
211 ProfileSyncService::Status status;
212 service->QueryDetailedSyncStatus(&status);
213 const AuthError& auth_error = service->GetAuthError();
215 // The order or priority is going to be: 1. Unrecoverable errors.
216 // 2. Auth errors. 3. Protocol errors. 4. Passphrase errors.
218 if (service->HasUnrecoverableError()) {
219 if (status_label) {
220 status_label->assign(l10n_util::GetStringFUTF16(
221 IDS_SYNC_STATUS_UNRECOVERABLE_ERROR,
222 l10n_util::GetStringUTF16(IDS_SYNC_UNRECOVERABLE_ERROR_HELP_URL)));
224 return SYNC_ERROR;
227 // For auth errors first check if an auth is in progress.
228 if (signin.AuthInProgress()) {
229 if (status_label) {
230 status_label->assign(
231 l10n_util::GetStringUTF16(IDS_SYNC_AUTHENTICATING_LABEL));
233 return PRE_SYNCED;
236 // No auth in progress check for an auth error.
237 if (auth_error.state() != AuthError::NONE) {
238 if (status_label && link_label) {
239 GetStatusLabelsForAuthError(auth_error, *service,
240 status_label, link_label, NULL, NULL, NULL);
242 return SYNC_ERROR;
245 // We dont have an auth error. Check for protocol error.
246 if (ShouldShowActionOnUI(status.sync_protocol_error)) {
247 if (status_label) {
248 GetStatusForActionableError(status.sync_protocol_error,
249 status_label);
251 return SYNC_ERROR;
254 // Now finally passphrase error.
255 if (service->IsPassphraseRequired()) {
256 if (service->IsPassphraseRequiredForDecryption()) {
257 // TODO(lipalani) : Ask tim if this is still needed.
258 // NOT first machine.
259 // Show a link ("needs attention"), but still indicate the
260 // current synced status. Return SYNC_PROMO so that
261 // the configure link will still be shown.
262 if (status_label && link_label) {
263 status_label->assign(GetSyncedStateStatusLabel(service, style));
264 link_label->assign(
265 l10n_util::GetStringUTF16(IDS_SYNC_PASSWORD_SYNC_ATTENTION));
267 return SYNC_PROMO;
271 // There is no error. Display "Last synced..." message.
272 if (status_label)
273 status_label->assign(GetSyncedStateStatusLabel(service, style));
274 return SYNCED;
275 } else {
276 // Either show auth error information with a link to re-login, auth in prog,
277 // or provide a link to continue with setup.
278 result_type = PRE_SYNCED;
279 if (service->FirstSetupInProgress()) {
280 ProfileSyncService::Status status;
281 service->QueryDetailedSyncStatus(&status);
282 const AuthError& auth_error = service->GetAuthError();
283 if (status_label) {
284 status_label->assign(
285 l10n_util::GetStringUTF16(IDS_SYNC_NTP_SETUP_IN_PROGRESS));
287 if (signin.AuthInProgress()) {
288 if (status_label) {
289 status_label->assign(
290 l10n_util::GetStringUTF16(IDS_SYNC_AUTHENTICATING_LABEL));
292 } else if (auth_error.state() != AuthError::NONE &&
293 auth_error.state() != AuthError::TWO_FACTOR) {
294 if (status_label) {
295 status_label->clear();
296 GetStatusLabelsForAuthError(auth_error, *service, status_label, NULL,
297 NULL, NULL, NULL);
299 result_type = SYNC_ERROR;
301 } else if (service->HasUnrecoverableError()) {
302 result_type = SYNC_ERROR;
303 ProfileSyncService::Status status;
304 service->QueryDetailedSyncStatus(&status);
305 if (ShouldShowActionOnUI(status.sync_protocol_error)) {
306 if (status_label) {
307 GetStatusForActionableError(status.sync_protocol_error,
308 status_label);
310 } else if (status_label) {
311 status_label->assign(l10n_util::GetStringUTF16(IDS_SYNC_SETUP_ERROR));
315 return result_type;
318 // Returns the status info for use on the new tab page, where we want slightly
319 // different information than in the settings panel.
320 MessageType GetStatusInfoForNewTabPage(ProfileSyncService* service,
321 const SigninManager& signin,
322 string16* status_label,
323 string16* link_label) {
324 DCHECK(status_label);
325 DCHECK(link_label);
327 if (service->HasSyncSetupCompleted() &&
328 service->IsPassphraseRequired()) {
329 if (service->passphrase_required_reason() == syncer::REASON_ENCRYPTION) {
330 // First machine migrating to passwords. Show as a promotion.
331 if (status_label && link_label) {
332 status_label->assign(
333 l10n_util::GetStringFUTF16(
334 IDS_SYNC_NTP_PASSWORD_PROMO,
335 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
336 link_label->assign(
337 l10n_util::GetStringUTF16(IDS_SYNC_NTP_PASSWORD_ENABLE));
339 return SYNC_PROMO;
340 } else {
341 // NOT first machine.
342 // Show a link and present as an error ("needs attention").
343 if (status_label && link_label) {
344 status_label->assign(string16());
345 link_label->assign(
346 l10n_util::GetStringUTF16(IDS_SYNC_CONFIGURE_ENCRYPTION));
348 return SYNC_ERROR;
352 // Fallback to default.
353 return GetStatusInfo(service, signin, WITH_HTML, status_label, link_label);
356 } // namespace
358 MessageType GetStatusLabels(ProfileSyncService* service,
359 const SigninManager& signin,
360 StatusLabelStyle style,
361 string16* status_label,
362 string16* link_label) {
363 DCHECK(status_label);
364 DCHECK(link_label);
365 return sync_ui_util::GetStatusInfo(
366 service, signin, style, status_label, link_label);
369 MessageType GetStatusLabelsForNewTabPage(ProfileSyncService* service,
370 const SigninManager& signin,
371 string16* status_label,
372 string16* link_label) {
373 DCHECK(status_label);
374 DCHECK(link_label);
375 return sync_ui_util::GetStatusInfoForNewTabPage(
376 service, signin, status_label, link_label);
379 void GetStatusLabelsForSyncGlobalError(ProfileSyncService* service,
380 const SigninManager& signin,
381 string16* menu_label,
382 string16* bubble_message,
383 string16* bubble_accept_label) {
384 DCHECK(menu_label);
385 DCHECK(bubble_message);
386 DCHECK(bubble_accept_label);
387 *menu_label = string16();
388 *bubble_message = string16();
389 *bubble_accept_label = string16();
391 if (!service->HasSyncSetupCompleted())
392 return;
394 MessageType status = GetStatus(service, signin);
395 if (status == SYNC_ERROR) {
396 const AuthError& auth_error = service->GetAuthError();
397 if (auth_error.state() != AuthError::NONE) {
398 GetStatusLabelsForAuthError(auth_error, *service, NULL, NULL,
399 menu_label, bubble_message, bubble_accept_label);
400 // If we have an actionable auth error, display it.
401 if (!menu_label->empty())
402 return;
406 // No actionable auth error - display the passphrase error.
407 if (service->IsPassphraseRequired() &&
408 service->IsPassphraseRequiredForDecryption()) {
409 // This is not the first machine so ask user to enter passphrase.
410 *menu_label = l10n_util::GetStringUTF16(
411 IDS_SYNC_PASSPHRASE_ERROR_WRENCH_MENU_ITEM);
412 string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
413 *bubble_message = l10n_util::GetStringFUTF16(
414 IDS_SYNC_PASSPHRASE_ERROR_BUBBLE_VIEW_MESSAGE, product_name);
415 *bubble_accept_label = l10n_util::GetStringUTF16(
416 IDS_SYNC_PASSPHRASE_ERROR_BUBBLE_VIEW_ACCEPT);
417 return;
421 MessageType GetStatus(
422 ProfileSyncService* service, const SigninManager& signin) {
423 return sync_ui_util::GetStatusInfo(service, signin, WITH_HTML, NULL, NULL);
426 string16 GetSyncMenuLabel(
427 ProfileSyncService* service, const SigninManager& signin) {
428 MessageType type = GetStatus(service, signin);
430 if (type == sync_ui_util::SYNCED)
431 return l10n_util::GetStringUTF16(IDS_SYNC_MENU_SYNCED_LABEL);
432 else if (type == sync_ui_util::SYNC_ERROR)
433 return l10n_util::GetStringUTF16(IDS_SYNC_MENU_SYNC_ERROR_LABEL);
434 else
435 return l10n_util::GetStringUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL);
438 string16 ConstructTime(int64 time_in_int) {
439 base::Time time = base::Time::FromInternalValue(time_in_int);
441 // If time is null the format function returns a time in 1969.
442 if (time.is_null())
443 return string16();
444 return base::TimeFormatFriendlyDateAndTime(time);
447 std::string MakeSyncAuthErrorText(
448 const GoogleServiceAuthError::State& state) {
449 switch (state) {
450 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
451 case GoogleServiceAuthError::ACCOUNT_DELETED:
452 case GoogleServiceAuthError::ACCOUNT_DISABLED:
453 case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
454 return "INVALID_GAIA_CREDENTIALS";
455 case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
456 return "USER_NOT_SIGNED_UP";
457 case GoogleServiceAuthError::CONNECTION_FAILED:
458 return "CONNECTION_FAILED";
459 default:
460 return std::string();
464 } // namespace sync_ui_util