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// A class to run the syncer on a thread.
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/callback.h"
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/linked_ptr.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/observer_list.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/task.h"
153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/timer.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/engine/nudge_source.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/engine/polling_constants.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/engine/syncer.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/syncable/model_type_payload_map.h"
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/engine/net/server_connection_manager.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/sessions/sync_session.h"
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/sessions/sync_session_context.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync {
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct ServerConnectionEvent;
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass SyncerThread : public sessions::SyncSession::Delegate,
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                     public ServerConnectionEventListener {
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  enum Mode {
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // In this mode, the thread only performs configuration tasks.  This is
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // designed to make the case where we want to download updates for a
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // specific type only, and not continue syncing until we are moved into
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // normal mode.
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CONFIGURATION_MODE,
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Resumes polling and allows nudges, drops configuration tasks.  Runs
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // through entire sync cycle.
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NORMAL_MODE,
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Takes ownership of both |context| and |syncer|.
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SyncerThread(sessions::SyncSessionContext* context, Syncer* syncer);
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual ~SyncerThread();
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  typedef Callback0::Type ModeChangeCallback;
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Change the mode of operation.
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // We don't use a lock when changing modes, so we won't cause currently
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // scheduled jobs to adhere to the new mode.  We could protect it, but it
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // doesn't buy very much as a) a session could already be in progress and it
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // will continue no matter what, b) the scheduled sessions already contain
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // all their required state and won't be affected by potential change at
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // higher levels (i.e. the registrar), and c) we service tasks FIFO, so once
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // the mode changes all future jobs will be run against the updated mode.
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If supplied, |callback| will be invoked when the mode has been
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // changed to |mode| *from the SyncerThread*, and not from the caller
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // thread.
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void Start(Mode mode, ModeChangeCallback* callback);
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Joins on the thread as soon as possible (currently running session
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // completes).
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void Stop();
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The meat and potatoes.
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ScheduleNudge(const base::TimeDelta& delay, NudgeSource source,
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                     const syncable::ModelTypeBitSet& types,
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                     const tracked_objects::Location& nudge_location);
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ScheduleNudgeWithPayloads(
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const base::TimeDelta& delay, NudgeSource source,
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const syncable::ModelTypePayloadMap& types_with_payloads,
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const tracked_objects::Location& nudge_location);
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ScheduleConfig(const syncable::ModelTypeBitSet& types);
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ScheduleClearUserData();
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Change status of notifications in the SyncSessionContext.
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void set_notifications_enabled(bool notifications_enabled);
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // DDOS avoidance function.  Calculates how long we should wait before trying
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // again after a failed sync attempt, where the last delay was |base_delay|.
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(tim): Look at URLRequestThrottlerEntryInterface.
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static base::TimeDelta GetRecommendedDelay(const base::TimeDelta& base_delay);
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // SyncSession::Delegate implementation.
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void OnSilencedUntil(const base::TimeTicks& silenced_until);
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual bool IsSyncingCurrentlySilenced();
89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void OnReceivedShortPollIntervalUpdate(
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const base::TimeDelta& new_interval);
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void OnReceivedLongPollIntervalUpdate(
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const base::TimeDelta& new_interval);
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void OnShouldStopSyncingPermanently();
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // ServerConnectionEventListener implementation.
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(tim): schedule a nudge when valid connection detected? in 1 minute?
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void OnServerConnectionEvent(const ServerConnectionEvent2& event);
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private:
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  enum JobProcessDecision {
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Indicates we should continue with the current job.
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CONTINUE,
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Indicates that we should save it to be processed later.
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SAVE,
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Indicates we should drop this job.
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DROP,
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct SyncSessionJob {
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // An enum used to describe jobs for scheduling purposes.
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    enum SyncSessionJobPurpose {
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Our poll timer schedules POLL jobs periodically based on a server
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // assigned poll interval.
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      POLL,
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // A nudge task can come from a variety of components needing to force
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // a sync.  The source is inferable from |session.source()|.
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NUDGE,
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // The user invoked a function in the UI to clear their entire account
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // and stop syncing (globally).
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CLEAR_USER_DATA,
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Typically used for fetching updates for a subset of the enabled types
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // during initial sync or reconfiguration.  We don't run all steps of
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // the sync cycle for these (e.g. CleanupDisabledTypes is skipped).
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONFIGURATION,
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    };
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SyncSessionJob();
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SyncSessionJob(SyncSessionJobPurpose purpose, base::TimeTicks start,
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        linked_ptr<sessions::SyncSession> session, bool is_canary_job,
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        const tracked_objects::Location& nudge_location);
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ~SyncSessionJob();
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SyncSessionJobPurpose purpose;
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::TimeTicks scheduled_start;
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    linked_ptr<sessions::SyncSession> session;
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bool is_canary_job;
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // This is the location the nudge came from. used for debugging purpose.
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // In case of multiple nudges getting coalesced this stores the first nudge
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // that came in.
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    tracked_objects::Location nudge_location;
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  friend class SyncerThread2Test;
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  friend class SyncerThread2WhiteboxTest;
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DropNudgeWhileExponentialBackOff);
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, SaveNudge);
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueNudge);
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, DropPoll);
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinuePoll);
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueConfiguration);
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           SaveConfigurationWhileThrottled);
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           SaveNudgeWhileThrottled);
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           ContinueClearUserDataUnderAllCircumstances);
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           ContinueCanaryJobConfig);
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ContinueNudgeWhileExponentialBackOff);
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // A component used to get time delays associated with exponential backoff.
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Encapsulated into a class to facilitate testing.
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  class DelayProvider {
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   public:
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DelayProvider();
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    virtual base::TimeDelta GetDelay(const base::TimeDelta& last_delay);
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    virtual ~DelayProvider();
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   private:
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DISALLOW_COPY_AND_ASSIGN(DelayProvider);
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct WaitInterval {
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    enum Mode {
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // A wait interval whose duration has been affected by exponential
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // backoff.
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // EXPONENTIAL_BACKOFF intervals are nudge-rate limited to 1 per interval.
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPONENTIAL_BACKOFF,
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // A server-initiated throttled interval.  We do not allow any syncing
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // during such an interval.
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      THROTTLED,
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WaitInterval();
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ~WaitInterval();
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Mode mode;
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // This bool is set to true if we have observed a nudge during this
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // interval and mode == EXPONENTIAL_BACKOFF.
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bool had_nudge;
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::TimeDelta length;
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::OneShotTimer<SyncerThread> timer;
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Configure jobs are saved only when backing off or throttling. So we
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // expose the pointer here.
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    scoped_ptr<SyncSessionJob> pending_configure_job;
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WaitInterval(Mode mode, base::TimeDelta length);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Helper to assemble a job and post a delayed task to sync.
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ScheduleSyncSessionJob(
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const base::TimeDelta& delay,
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SyncSessionJob::SyncSessionJobPurpose purpose,
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      sessions::SyncSession* session,
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const tracked_objects::Location& nudge_location);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Invoke the Syncer to perform a sync.
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void DoSyncSessionJob(const SyncSessionJob& job);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Called after the Syncer has performed the sync represented by |job|, to
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // reset our state.
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void FinishSyncSessionJob(const SyncSessionJob& job);
21372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Record important state that might be needed in future syncs, such as which
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // data types may require cleanup.
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void UpdateCarryoverSessionState(const SyncSessionJob& old_job);
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Helper to FinishSyncSessionJob to schedule the next sync operation.
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ScheduleNextSync(const SyncSessionJob& old_job);
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Helper to configure polling intervals. Used by Start and ScheduleNextSync.
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void AdjustPolling(const SyncSessionJob* old_job);
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Helper to ScheduleNextSync in case of consecutive sync errors.
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void HandleConsecutiveContinuationError(const SyncSessionJob& old_job);
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Determines if it is legal to run |job| by checking current
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // operational mode, backoff or throttling, freshness
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // (so we don't make redundant syncs), and connection.
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool ShouldRunJob(const SyncSessionJob& job);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Decide whether we should CONTINUE, SAVE or DROP the job.
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  JobProcessDecision DecideOnJob(const SyncSessionJob& job);
2344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Decide on whether to CONTINUE, SAVE or DROP the job when we are in
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // backoff mode.
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job);
2384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Saves the job for future execution. Note: It drops all the poll jobs.
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void SaveJob(const SyncSessionJob& job);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Coalesces the current job with the pending nudge.
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void InitOrCoalescePendingJob(const SyncSessionJob& job);
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 'Impl' here refers to real implementation of public functions, running on
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // |thread_|.
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void StartImpl(Mode mode, ModeChangeCallback* callback);
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ScheduleNudgeImpl(
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const base::TimeDelta& delay,
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const syncable::ModelTypePayloadMap& types_with_payloads,
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bool is_canary_job, const tracked_objects::Location& nudge_location);
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ScheduleConfigImpl(const ModelSafeRoutingInfo& routing_info,
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const std::vector<ModelSafeWorker*>& workers,
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source);
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ScheduleClearUserDataImpl();
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Returns true if the client is currently in exponential backoff.
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool IsBackingOff() const;
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Helper to signal all listeners registered with |session_context_|.
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void Notify(SyncEngineEvent::EventCause cause);
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Callback to change backoff state.
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void DoCanaryJob();
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void Unthrottle();
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Executes the pending job. Called whenever an event occurs that may
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // change conditions permitting a job to run. Like when network connection is
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // re-established, mode changes etc.
271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void DoPendingJobIfPossible(bool is_canary_job);
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The pointer is owned by the caller.
274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  browser_sync::sessions::SyncSession* CreateSyncSession(
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const browser_sync::sessions::SyncSourceInfo& info);
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Creates a session for a poll and performs the sync.
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void PollTimerCallback();
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Assign |start| and |end| to appropriate SyncerStep values for the
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // specified |purpose|.
282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void SetSyncerStepsForPurpose(SyncSessionJob::SyncSessionJobPurpose purpose,
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                SyncerStep* start,
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                SyncerStep* end);
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Initializes the hookup between the ServerConnectionManager and us.
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void WatchConnectionManager();
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Used to update |server_connection_ok_|, see below.
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void CheckServerConnectionManagerStatus(
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      HttpResponse::ServerConnectionCode code);
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Called once the first time thread_ is started to broadcast an initial
294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // session snapshot containing data like initial_sync_ended.  Important when
295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // the client starts up and does not need to perform an initial sync.
296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void SendInitialSnapshot();
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::Thread thread_;
299201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Modifiable versions of kDefaultLongPollIntervalSeconds which can be
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // updated by the server.
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::TimeDelta syncer_short_poll_interval_seconds_;
303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::TimeDelta syncer_long_poll_interval_seconds_;
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Periodic timer for polling.  See AdjustPolling.
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::RepeatingTimer<SyncerThread> poll_timer_;
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The mode of operation. We don't use a lock, see Start(...) comment.
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Mode mode_;
310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(tim): Bug 26339. This needs to track more than just time I think,
312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // since the nudges could be for different types. Current impl doesn't care.
313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::TimeTicks last_sync_session_end_time_;
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Have we observed a valid server connection?
316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool server_connection_ok_;
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Tracks in-flight nudges so we can coalesce.
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<SyncSessionJob> pending_nudge_;
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Current wait state.  Null if we're not in backoff and not throttled.
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<WaitInterval> wait_interval_;
323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<DelayProvider> delay_provider_;
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Invoked to run through the sync cycle.
327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<Syncer> syncer_;
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<sessions::SyncSessionContext> session_context_;
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(SyncerThread);
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace browser_sync
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// The SyncerThread manages its own internal thread and thus outlives it. We
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// don't need refcounting for posting tasks to this internal thread.
339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::SyncerThread);
340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
342