1// Copyright (c) 2011 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// A class representing an attempt to synchronize the local syncable data
6// store with a sync server. A SyncSession instance is passed as a stateful
7// bundle to and from various SyncerCommands with the goal of converging the
8// client view of data with that of the server. The commands twiddle with
9// session status in response to events and hiccups along the way, set and
10// query session progress with regards to conflict resolution and applying
11// server updates, and access the SyncSessionContext for the current session
12// via SyncSession instances.
13
14#ifndef CHROME_BROWSER_SYNC_SESSIONS_SYNC_SESSION_H_
15#define CHROME_BROWSER_SYNC_SESSIONS_SYNC_SESSION_H_
16#pragma once
17
18#include <map>
19#include <string>
20#include <utility>
21#include <vector>
22
23#include "base/basictypes.h"
24#include "base/memory/scoped_ptr.h"
25#include "base/time.h"
26#include "chrome/browser/sync/engine/model_safe_worker.h"
27#include "chrome/browser/sync/sessions/ordered_commit_set.h"
28#include "chrome/browser/sync/sessions/session_state.h"
29#include "chrome/browser/sync/sessions/status_controller.h"
30#include "chrome/browser/sync/sessions/sync_session_context.h"
31#include "chrome/browser/sync/syncable/model_type.h"
32#include "chrome/browser/sync/util/extensions_activity_monitor.h"
33
34namespace syncable {
35class WriteTransaction;
36}
37
38namespace browser_sync {
39class ModelSafeWorker;
40
41namespace sessions {
42
43class SyncSession {
44 public:
45  // The Delegate services events that occur during the session requiring an
46  // explicit (and session-global) action, as opposed to events that are simply
47  // recorded in per-session state.
48  class Delegate {
49   public:
50    // The client was throttled and should cease-and-desist syncing activity
51    // until the specified time.
52    virtual void OnSilencedUntil(const base::TimeTicks& silenced_until) = 0;
53
54    // Silenced intervals can be out of phase with individual sessions, so the
55    // delegate is the only thing that can give an authoritative answer for
56    // "is syncing silenced right now". This shouldn't be necessary very often
57    // as the delegate ensures no session is started if syncing is silenced.
58    // ** Note **  This will return true if silencing commenced during this
59    // session and the interval has not yet elapsed, but the contract here is
60    // solely based on absolute time values. So, this cannot be used to infer
61    // that any given session _instance_ is silenced.  An example of reasonable
62    // use is for UI reporting.
63    virtual bool IsSyncingCurrentlySilenced() = 0;
64
65    // The client has been instructed to change its short poll interval.
66    virtual void OnReceivedShortPollIntervalUpdate(
67        const base::TimeDelta& new_interval) = 0;
68
69    // The client has been instructed to change its long poll interval.
70    virtual void OnReceivedLongPollIntervalUpdate(
71        const base::TimeDelta& new_interval) = 0;
72
73    // The client needs to cease and desist syncing at once.  This occurs when
74    // the Syncer detects that the backend store has fundamentally changed or
75    // is a different instance altogether (e.g. swapping from a test instance
76    // to production, or a global stop syncing operation has wiped the store).
77    virtual void OnShouldStopSyncingPermanently() = 0;
78
79   protected:
80    virtual ~Delegate() {}
81  };
82
83  SyncSession(SyncSessionContext* context,
84              Delegate* delegate,
85              const SyncSourceInfo& source,
86              const ModelSafeRoutingInfo& routing_info,
87              const std::vector<ModelSafeWorker*>& workers);
88  ~SyncSession();
89
90  // Builds a thread-safe and read-only copy of the current session state.
91  SyncSessionSnapshot TakeSnapshot() const;
92
93  // Returns true if this session contains data that should go through the sync
94  // engine again.
95  bool HasMoreToSync() const;
96
97  // Collects all state pertaining to how and why |s| originated and unions it
98  // with corresponding state in |this|, leaving |s| unchanged.  Allows |this|
99  // to take on the responsibilities |s| had (e.g. certain data types) in the
100  // next SyncShare operation using |this|, rather than needed two separate
101  // sessions.
102  void Coalesce(const SyncSession& session);
103
104  // Should be called any time |this| is being re-used in a new call to
105  // SyncShare (e.g., HasMoreToSync returned true).
106  void ResetTransientState();
107
108  SyncSessionContext* context() const { return context_; }
109  Delegate* delegate() const { return delegate_; }
110  syncable::WriteTransaction* write_transaction() { return write_transaction_; }
111  StatusController* status_controller() { return status_controller_.get(); }
112
113  const ExtensionsActivityMonitor::Records& extensions_activity() const {
114    return extensions_activity_;
115  }
116  ExtensionsActivityMonitor::Records* mutable_extensions_activity() {
117    return &extensions_activity_;
118  }
119
120  // Volatile reader for the source member of the sync session object.  The
121  // value is set to the SYNC_CYCLE_CONTINUATION value to signal that it has
122  // been read.
123  SyncSourceInfo TestAndSetSource();
124
125  const std::vector<ModelSafeWorker*>& workers() const { return workers_; }
126  const ModelSafeRoutingInfo& routing_info() const { return routing_info_; }
127  const SyncSourceInfo& source() const { return source_; }
128
129 private:
130  // Extend the encapsulation boundary to utilities for internal member
131  // assignments. This way, the scope of these actions is explicit, they can't
132  // be overridden, and assigning is always accompanied by unassigning.
133  friend class ScopedSetSessionWriteTransaction;
134
135  // The context for this session, guaranteed to outlive |this|.
136  SyncSessionContext* const context_;
137
138  // The source for initiating this sync session.
139  SyncSourceInfo source_;
140
141  // Information about extensions activity since the last successful commit.
142  ExtensionsActivityMonitor::Records extensions_activity_;
143
144  // Used to allow various steps to share a transaction. Can be NULL.
145  syncable::WriteTransaction* write_transaction_;
146
147  // The delegate for this session, must never be NULL.
148  Delegate* delegate_;
149
150  // Our controller for various status and error counters.
151  scoped_ptr<StatusController> status_controller_;
152
153  // The set of active ModelSafeWorkers for the duration of this session.
154  // This can change if this session is Coalesce()'d with another.
155  std::vector<ModelSafeWorker*> workers_;
156
157  // The routing info for the duration of this session, dictating which
158  // datatypes should be synced and which workers should be used when working
159  // on those datatypes.
160  ModelSafeRoutingInfo routing_info_;
161
162  DISALLOW_COPY_AND_ASSIGN(SyncSession);
163};
164
165// Installs a WriteTransaction to a given session and later clears it when the
166// utility falls out of scope. Transactions are not nestable, so it is an error
167// to try and use one of these if the session already has a transaction.
168class ScopedSetSessionWriteTransaction {
169 public:
170  ScopedSetSessionWriteTransaction(SyncSession* session,
171                                   syncable::WriteTransaction* trans)
172      : session_(session) {
173    DCHECK(!session_->write_transaction_);
174    session_->write_transaction_ = trans;
175  }
176  ~ScopedSetSessionWriteTransaction() { session_->write_transaction_ = NULL; }
177
178 private:
179  SyncSession* session_;
180  DISALLOW_COPY_AND_ASSIGN(ScopedSetSessionWriteTransaction);
181};
182
183}  // namespace sessions
184}  // namespace browser_sync
185
186#endif  // CHROME_BROWSER_SYNC_SESSIONS_SYNC_SESSION_H_
187