Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / sync_ui_util.cc
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/sync/sync_ui_util.h"
6
7 #include "base/i18n/number_formatting.h"
8 #include "base/i18n/time_formatting.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/signin/signin_global_error.h"
15 #include "chrome/browser/signin/signin_manager_base.h"
16 #include "chrome/browser/signin/signin_ui_util.h"
17 #include "chrome/browser/sync/profile_sync_service.h"
18 #include "chrome/browser/sync/profile_sync_service_factory.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/browser/ui/browser_window.h"
21 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
22 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/common/url_constants.h"
26 #include "google_apis/gaia/google_service_auth_error.h"
27 #include "grit/browser_resources.h"
28 #include "grit/chromium_strings.h"
29 #include "grit/generated_resources.h"
30 #include "grit/locale_settings.h"
31 #include "sync/internal_api/public/base/model_type.h"
32 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
33 #include "sync/protocol/proto_enum_conversions.h"
34 #include "sync/protocol/sync_protocol_error.h"
35 #include "ui/base/l10n/l10n_util.h"
36 #include "ui/base/resource/resource_bundle.h"
37
38 #if defined(OS_CHROMEOS)
39 #include "chrome/browser/chromeos/login/user_manager.h"
40 #endif  // defined(OS_CHROMEOS)
41
42 typedef GoogleServiceAuthError AuthError;
43
44 namespace sync_ui_util {
45
46 namespace {
47
48 // Returns the message that should be displayed when the user is authenticated
49 // and can connect to the sync server. If the user hasn't yet authenticated, an
50 // empty string is returned.
51 base::string16 GetSyncedStateStatusLabel(ProfileSyncService* service,
52                                          const SigninManagerBase& signin,
53                                          StatusLabelStyle style) {
54   std::string user_display_name = signin.GetAuthenticatedUsername();
55
56 #if defined(OS_CHROMEOS)
57   if (chromeos::UserManager::IsInitialized()) {
58     // On CrOS user email is sanitized and then passed to the signin manager.
59     // Original email (containing dots) is stored as "display email".
60     user_display_name = chromeos::UserManager::Get()->
61         GetUserDisplayEmail(user_display_name);
62   }
63 #endif  // defined(OS_CHROMEOS)
64
65   base::string16 user_name = base::UTF8ToUTF16(user_display_name);
66
67   if (!user_name.empty()) {
68     if (!service || service->IsManaged()) {
69       // User is signed in, but sync is disabled.
70       return l10n_util::GetStringFUTF16(IDS_SIGNED_IN_WITH_SYNC_DISABLED,
71                                         user_name);
72     } else if (service->IsStartSuppressed()) {
73       // User is signed in, but sync has been stopped.
74       return l10n_util::GetStringFUTF16(IDS_SIGNED_IN_WITH_SYNC_SUPPRESSED,
75                                         user_name);
76     }
77   }
78
79   if (!service || !service->sync_initialized()) {
80     // User is not signed in, or sync is still initializing.
81     return base::string16();
82   }
83
84   DCHECK(!user_name.empty());
85
86   // Message may also carry additional advice with an HTML link, if acceptable.
87   switch (style) {
88     case PLAIN_TEXT:
89       return l10n_util::GetStringFUTF16(
90           IDS_SYNC_ACCOUNT_SYNCING_TO_USER,
91           user_name);
92     case WITH_HTML:
93       return l10n_util::GetStringFUTF16(
94           IDS_SYNC_ACCOUNT_SYNCING_TO_USER_WITH_MANAGE_LINK,
95           user_name,
96           base::ASCIIToUTF16(chrome::kSyncGoogleDashboardURL));
97     default:
98       NOTREACHED();
99       return NULL;
100   }
101 }
102
103 void GetStatusForActionableError(
104     const syncer::SyncProtocolError& error,
105     base::string16* status_label) {
106   DCHECK(status_label);
107   switch (error.action) {
108     case syncer::STOP_AND_RESTART_SYNC:
109        status_label->assign(
110            l10n_util::GetStringUTF16(IDS_SYNC_STOP_AND_RESTART_SYNC));
111       break;
112     case syncer::UPGRADE_CLIENT:
113        status_label->assign(
114            l10n_util::GetStringFUTF16(IDS_SYNC_UPGRADE_CLIENT,
115                l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
116       break;
117     case syncer::ENABLE_SYNC_ON_ACCOUNT:
118        status_label->assign(
119            l10n_util::GetStringUTF16(IDS_SYNC_ENABLE_SYNC_ON_ACCOUNT));
120     break;
121     case syncer::CLEAR_USER_DATA_AND_RESYNC:
122        status_label->assign(
123            l10n_util::GetStringUTF16(IDS_SYNC_CLEAR_USER_DATA));
124       break;
125     default:
126       NOTREACHED();
127   }
128 }
129
130 // TODO(akalin): Write unit tests for these three functions below.
131
132 // status_label and link_label must either be both NULL or both non-NULL.
133 MessageType GetStatusInfo(ProfileSyncService* service,
134                           const SigninManagerBase& signin,
135                           StatusLabelStyle style,
136                           base::string16* status_label,
137                           base::string16* link_label) {
138   DCHECK_EQ(status_label == NULL, link_label == NULL);
139
140   MessageType result_type(SYNCED);
141
142   if (signin.GetAuthenticatedUsername().empty())
143     return PRE_SYNCED;
144
145   if (!service || service->IsManaged() || service->HasSyncSetupCompleted() ||
146       service->IsStartSuppressed()) {
147     // The order or priority is going to be: 1. Unrecoverable errors.
148     // 2. Auth errors. 3. Protocol errors. 4. Passphrase errors.
149
150     if (service && service->HasUnrecoverableError()) {
151       if (status_label) {
152         status_label->assign(l10n_util::GetStringFUTF16(
153             IDS_SYNC_STATUS_UNRECOVERABLE_ERROR,
154             l10n_util::GetStringUTF16(IDS_SYNC_UNRECOVERABLE_ERROR_HELP_URL)));
155       }
156       return SYNC_ERROR;
157     }
158
159     // For auth errors first check if an auth is in progress.
160     if (signin.AuthInProgress()) {
161       if (status_label) {
162         status_label->assign(
163           l10n_util::GetStringUTF16(IDS_SYNC_AUTHENTICATING_LABEL));
164       }
165       return PRE_SYNCED;
166     }
167
168     // Check for sync errors if the sync service is enabled.
169     if (service) {
170       // Since there is no auth in progress, check for an auth error first.
171       AuthError auth_error =
172           SigninGlobalError::GetForProfile(service->profile())->
173               GetLastAuthError();
174       if (auth_error.state() != AuthError::NONE) {
175         if (status_label && link_label)
176           signin_ui_util::GetStatusLabelsForAuthError(
177               service->profile(), signin, status_label, link_label);
178         return SYNC_ERROR;
179       }
180
181       // We don't have an auth error. Check for an actionable error.
182       ProfileSyncService::Status status;
183       service->QueryDetailedSyncStatus(&status);
184       if (ShouldShowActionOnUI(status.sync_protocol_error)) {
185         if (status_label) {
186           GetStatusForActionableError(status.sync_protocol_error,
187                                       status_label);
188         }
189         return SYNC_ERROR;
190       }
191
192       // Check for a passphrase error.
193       if (service->IsPassphraseRequired()) {
194         if (service->IsPassphraseRequiredForDecryption()) {
195           // TODO(lipalani) : Ask tim if this is still needed.
196           // NOT first machine.
197           // Show a link ("needs attention"), but still indicate the
198           // current synced status.  Return SYNC_PROMO so that
199           // the configure link will still be shown.
200           if (status_label && link_label) {
201             status_label->assign(GetSyncedStateStatusLabel(
202                 service, signin, style));
203             link_label->assign(
204                 l10n_util::GetStringUTF16(IDS_SYNC_PASSWORD_SYNC_ATTENTION));
205           }
206           return SYNC_PROMO;
207         }
208       }
209
210       // Check to see if sync has been disabled via the dasboard and needs to be
211       // set up once again.
212       if (service->IsStartSuppressed() &&
213           status.sync_protocol_error.error_type == syncer::NOT_MY_BIRTHDAY) {
214         if (status_label) {
215           status_label->assign(GetSyncedStateStatusLabel(service,
216                                                          signin,
217                                                          style));
218         }
219         return PRE_SYNCED;
220       }
221     }
222
223     // There is no error. Display "Last synced..." message.
224     if (status_label)
225       status_label->assign(GetSyncedStateStatusLabel(service, signin, style));
226     return SYNCED;
227   } else {
228     // Either show auth error information with a link to re-login, auth in prog,
229     // or provide a link to continue with setup.
230     if (service->FirstSetupInProgress()) {
231       result_type = PRE_SYNCED;
232       ProfileSyncService::Status status;
233       service->QueryDetailedSyncStatus(&status);
234       AuthError auth_error =
235           SigninGlobalError::GetForProfile(
236               service->profile())->GetLastAuthError();
237       if (status_label) {
238         status_label->assign(
239             l10n_util::GetStringUTF16(IDS_SYNC_NTP_SETUP_IN_PROGRESS));
240       }
241       if (signin.AuthInProgress()) {
242         if (status_label) {
243           status_label->assign(
244               l10n_util::GetStringUTF16(IDS_SYNC_AUTHENTICATING_LABEL));
245         }
246       } else if (auth_error.state() != AuthError::NONE &&
247                  auth_error.state() != AuthError::TWO_FACTOR) {
248         if (status_label && link_label) {
249           status_label->clear();
250           signin_ui_util::GetStatusLabelsForAuthError(
251               service->profile(), signin, status_label, link_label);
252         }
253         result_type = SYNC_ERROR;
254       }
255     } else if (service->HasUnrecoverableError()) {
256       result_type = SYNC_ERROR;
257       ProfileSyncService::Status status;
258       service->QueryDetailedSyncStatus(&status);
259       if (ShouldShowActionOnUI(status.sync_protocol_error)) {
260         if (status_label) {
261           GetStatusForActionableError(status.sync_protocol_error,
262               status_label);
263         }
264       } else if (status_label) {
265         status_label->assign(l10n_util::GetStringUTF16(IDS_SYNC_SETUP_ERROR));
266       }
267     } else if (!signin.GetAuthenticatedUsername().empty()) {
268       // The user is signed in, but sync has been stopped.
269       if (status_label) {
270         base::string16 label = l10n_util::GetStringFUTF16(
271             IDS_SIGNED_IN_WITH_SYNC_SUPPRESSED,
272             base::UTF8ToUTF16(signin.GetAuthenticatedUsername()));
273         status_label->assign(label);
274         result_type = PRE_SYNCED;
275       }
276     }
277   }
278   return result_type;
279 }
280
281 // Returns the status info for use on the new tab page, where we want slightly
282 // different information than in the settings panel.
283 MessageType GetStatusInfoForNewTabPage(ProfileSyncService* service,
284                                        const SigninManagerBase& signin,
285                                        base::string16* status_label,
286                                        base::string16* link_label) {
287   DCHECK(status_label);
288   DCHECK(link_label);
289
290   if (service->HasSyncSetupCompleted() &&
291       service->IsPassphraseRequired()) {
292     if (service->passphrase_required_reason() == syncer::REASON_ENCRYPTION) {
293       // First machine migrating to passwords.  Show as a promotion.
294       if (status_label && link_label) {
295         status_label->assign(
296             l10n_util::GetStringFUTF16(
297                 IDS_SYNC_NTP_PASSWORD_PROMO,
298                 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
299         link_label->assign(
300             l10n_util::GetStringUTF16(IDS_SYNC_NTP_PASSWORD_ENABLE));
301       }
302       return SYNC_PROMO;
303     } else {
304       // NOT first machine.
305       // Show a link and present as an error ("needs attention").
306       if (status_label && link_label) {
307         status_label->assign(base::string16());
308         link_label->assign(
309             l10n_util::GetStringUTF16(IDS_SYNC_CONFIGURE_ENCRYPTION));
310       }
311       return SYNC_ERROR;
312     }
313   }
314
315   // Fallback to default.
316   return GetStatusInfo(service, signin, WITH_HTML, status_label, link_label);
317 }
318
319 }  // namespace
320
321 MessageType GetStatusLabels(ProfileSyncService* service,
322                             const SigninManagerBase& signin,
323                             StatusLabelStyle style,
324                             base::string16* status_label,
325                             base::string16* link_label) {
326   DCHECK(status_label);
327   DCHECK(link_label);
328   return sync_ui_util::GetStatusInfo(
329       service, signin, style, status_label, link_label);
330 }
331
332 MessageType GetStatusLabelsForNewTabPage(ProfileSyncService* service,
333                                          const SigninManagerBase& signin,
334                                          base::string16* status_label,
335                                          base::string16* link_label) {
336   DCHECK(status_label);
337   DCHECK(link_label);
338   return sync_ui_util::GetStatusInfoForNewTabPage(
339       service, signin, status_label, link_label);
340 }
341
342 void GetStatusLabelsForSyncGlobalError(ProfileSyncService* service,
343                                        const SigninManagerBase& signin,
344                                        base::string16* menu_label,
345                                        base::string16* bubble_message,
346                                        base::string16* bubble_accept_label) {
347   DCHECK(menu_label);
348   DCHECK(bubble_message);
349   DCHECK(bubble_accept_label);
350   *menu_label = base::string16();
351   *bubble_message = base::string16();
352   *bubble_accept_label = base::string16();
353
354   // Only display an error if we've completed sync setup.
355   if (!service->HasSyncSetupCompleted())
356     return;
357
358   // Display a passphrase error if we have one.
359   if (service->IsPassphraseRequired() &&
360       service->IsPassphraseRequiredForDecryption()) {
361     // This is not the first machine so ask user to enter passphrase.
362     *menu_label = l10n_util::GetStringUTF16(
363         IDS_SYNC_PASSPHRASE_ERROR_WRENCH_MENU_ITEM);
364     *bubble_message = l10n_util::GetStringUTF16(
365         IDS_SYNC_PASSPHRASE_ERROR_BUBBLE_VIEW_MESSAGE);
366     *bubble_accept_label = l10n_util::GetStringUTF16(
367         IDS_SYNC_PASSPHRASE_ERROR_BUBBLE_VIEW_ACCEPT);
368     return;
369   }
370 }
371
372 MessageType GetStatus(
373     ProfileSyncService* service, const SigninManagerBase& signin) {
374   return sync_ui_util::GetStatusInfo(service, signin, WITH_HTML, NULL, NULL);
375 }
376
377 base::string16 ConstructTime(int64 time_in_int) {
378   base::Time time = base::Time::FromInternalValue(time_in_int);
379
380   // If time is null the format function returns a time in 1969.
381   if (time.is_null())
382     return base::string16();
383   return base::TimeFormatFriendlyDateAndTime(time);
384 }
385
386 }  // namespace sync_ui_util