1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/all_status.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/port.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/net/server_connection_manager.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/service_constants.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/sessions/session_state.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/directory_manager.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync {
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic const sync_api::SyncManager::Status init_status =
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  { sync_api::SyncManager::Status::OFFLINE };
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickAllStatus::AllStatus() : status_(init_status) {
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status_.initial_sync_ended = true;
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status_.notifications_enabled = false;
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAllStatus::~AllStatus() {
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsensync_api::SyncManager::Status AllStatus::CreateBlankStatus() const {
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Status is initialized with the previous status value.  Variables
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // whose values accumulate (e.g. lifetime counters like updates_received)
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // are not to be cleared here.
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_api::SyncManager::Status status = status_;
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.syncing = true;
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.unsynced_count = 0;
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.conflicting_count = 0;
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.initial_sync_ended = false;
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.syncer_stuck = false;
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.max_consecutive_errors = 0;
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.server_broken = false;
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.updates_available = 0;
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return status;
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsensync_api::SyncManager::Status AllStatus::CalcSyncing(
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const SyncEngineEvent &event) const {
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_api::SyncManager::Status status = CreateBlankStatus();
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const sessions::SyncSessionSnapshot* snapshot = event.snapshot;
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.unsynced_count += static_cast<int>(snapshot->unsynced_count);
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.conflicting_count += snapshot->errors.num_conflicting_commits;
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The syncer may not be done yet, which could cause conflicting updates.
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // But this is only used for status, so it is better to have visibility.
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.conflicting_count += snapshot->num_conflicting_updates;
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.syncing |= snapshot->syncer_status.syncing;
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.syncing = snapshot->has_more_to_sync && snapshot->is_silenced;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.initial_sync_ended |= snapshot->is_share_usable;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.syncer_stuck |= snapshot->syncer_status.syncer_stuck;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const sessions::ErrorCounters& errors(snapshot->errors);
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (errors.consecutive_errors > status.max_consecutive_errors)
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    status.max_consecutive_errors = errors.consecutive_errors;
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 100 is an arbitrary limit.
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (errors.consecutive_transient_error_commits > 100)
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    status.server_broken = true;
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status.updates_available += snapshot->num_server_changes_remaining;
6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Accumulate update count only once per session to avoid double-counting.
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(ncarter): Make this realtime by having the syncer_status
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // counter preserve its value across sessions.  http://crbug.com/26339
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) {
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    status.updates_received +=
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        snapshot->syncer_status.num_updates_downloaded_total;
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    status.tombstone_updates_received +=
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        snapshot->syncer_status.num_tombstone_updates_downloaded_total;
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return status;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid AllStatus::CalcStatusChanges() {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool unsynced_changes = status_.unsynced_count > 0;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool online = status_.authenticated &&
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    status_.server_reachable && status_.server_up && !status_.server_broken;
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (online) {
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (status_.syncer_stuck)
8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      status_.summary = sync_api::SyncManager::Status::CONFLICT;
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else if (unsynced_changes || status_.syncing)
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      status_.summary = sync_api::SyncManager::Status::SYNCING;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      status_.summary = sync_api::SyncManager::Status::READY;
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (!status_.initial_sync_ended) {
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    status_.summary = sync_api::SyncManager::Status::OFFLINE_UNUSABLE;
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (unsynced_changes) {
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    status_.summary = sync_api::SyncManager::Status::OFFLINE_UNSYNCED;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    status_.summary = sync_api::SyncManager::Status::OFFLINE;
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid AllStatus::OnSyncEngineEvent(const SyncEngineEvent& event) {
103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ScopedStatusLock lock(this);
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (event.what_happened) {
105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    case SyncEngineEvent::SYNC_CYCLE_ENDED:
106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    case SyncEngineEvent::STATUS_CHANGED:
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      status_ = CalcSyncing(event);
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    case SyncEngineEvent::STOP_SYNCING_PERMANENTLY:
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case SyncEngineEvent::UPDATED_TOKEN:
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case SyncEngineEvent::CLEAR_SERVER_DATA_FAILED:
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case SyncEngineEvent::CLEAR_SERVER_DATA_SUCCEEDED:
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       break;
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(ERROR) << "Unrecognized Syncer Event: " << event.what_happened;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AllStatus::HandleServerConnectionEvent(
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ServerConnectionEvent& event) {
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ServerConnectionEvent::STATUS_CHANGED == event.what_happened) {
123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ScopedStatusLock lock(this);
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    status_.server_up = IsGoodReplyFromServer(event.connection_code);
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    status_.server_reachable = event.server_reachable;
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (event.connection_code == HttpResponse::SERVER_CONNECTION_OK) {
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      status_.authenticated = true;
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else {
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      status_.authenticated = false;
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsensync_api::SyncManager::Status AllStatus::status() const {
13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(mutex_);
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return status_;
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AllStatus::SetNotificationsEnabled(bool notifications_enabled) {
141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ScopedStatusLock lock(this);
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status_.notifications_enabled = notifications_enabled;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AllStatus::IncrementNotificationsSent() {
146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ScopedStatusLock lock(this);
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ++status_.notifications_sent;
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AllStatus::IncrementNotificationsReceived() {
151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ScopedStatusLock lock(this);
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ++status_.notifications_received;
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickScopedStatusLock::ScopedStatusLock(AllStatus* allstatus)
156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    : allstatus_(allstatus) {
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  allstatus->mutex_.Acquire();
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
160731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickScopedStatusLock::~ScopedStatusLock() {
161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  allstatus_->CalcStatusChanges();
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  allstatus_->mutex_.Release();
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace browser_sync
166