Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: chrome/browser/sync/startup_controller.cc

Issue 162443004: sync: final pieces to sync deferred initialization (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix test leak Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 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/startup_controller.h"
6
7 #include "base/command_line.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/metrics/histogram.h"
10 #include "chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h"
11 #include "chrome/browser/signin/profile_oauth2_token_service.h"
12 #include "chrome/browser/sync/sync_prefs.h"
13 #include "chrome/common/chrome_switches.h"
14
15 namespace browser_sync {
16
17 namespace {
18
19 // The amount of time we'll wait to initialize sync if no data type triggers
20 // initialization via a StartSyncFlare.
21 const int kDeferredInitFallbackSeconds = 10;
22
23 // Enum (for UMA, primarily) defining different events that cause us to
24 // exit the "deferred" state of initialization and invoke start_backend.
25 enum DeferredInitTrigger {
26 // We have received a signal from a SyncableService requesting that sync
27 // starts as soon as possible.
28 TRIGGER_DATA_TYPE_REQUEST,
29 // No data type requested sync to start and our fallback timer expired.
30 TRIGGER_FALLBACK_TIMER,
31 MAX_TRIGGER_VALUE
32 };
33
34 } // namespace
35
36 StartupController::StartupController(
37 ProfileSyncServiceStartBehavior start_behavior,
38 ProfileOAuth2TokenService* token_service,
39 const browser_sync::SyncPrefs* sync_prefs,
40 const ManagedUserSigninManagerWrapper* signin,
41 base::Closure start_backend)
42 : received_start_request_(false),
43 setup_in_progress_(false),
44 auto_start_enabled_(start_behavior == AUTO_START),
45 sync_prefs_(sync_prefs),
46 token_service_(token_service),
47 signin_(signin),
48 start_backend_(start_backend),
49 fallback_timeout_(
50 base::TimeDelta::FromSeconds(kDeferredInitFallbackSeconds)),
51 weak_factory_(this) {}
52
53 StartupController::~StartupController() {}
54
55 void StartupController::Reset() {
56 received_start_request_ = false;
57 setup_in_progress_ = false;
58 start_up_time_ = base::Time();
59 start_backend_time_ = base::Time();
60 // Don't let previous timers affect us post-reset.
61 weak_factory_.InvalidateWeakPtrs();
62 }
63
64 void StartupController::set_setup_in_progress(bool in_progress) {
65 setup_in_progress_ = in_progress;
66 }
67
68 void StartupController::StartUp(StartUpDeferredOption deferred_option) {
69 const bool first_start = start_up_time_.is_null();
70 if (first_start)
71 start_up_time_ = base::Time::Now();
72
73 if (deferred_option == STARTUP_BACKEND_DEFERRED &&
haitaol1 2014/02/20 00:01:06 I think the code can be simplified if this block i
tim (not reviewing) 2014/02/20 22:52:52 I played around with this and it gets a little mes
haitaol1 2014/02/25 00:53:01 fair enough On 2014/02/20 22:52:52, timsteele wro
74 CommandLine::ForCurrentProcess()->
75 HasSwitch(switches::kSyncEnableDeferredStartup)) {
76 if (first_start) {
77 base::MessageLoop::current()->PostDelayedTask(
78 FROM_HERE,
79 base::Bind(&StartupController::OnFallbackStartupTimerExpired,
80 weak_factory_.GetWeakPtr()), fallback_timeout_);
81 }
82 return;
83 }
84
85 start_backend_time_ = base::Time::Now();
86 start_backend_.Run();
87 }
88
89 void StartupController::OverrideFallbackTimeoutForTest(
90 const base::TimeDelta& timeout) {
91 fallback_timeout_ = timeout;
92 }
93
94 void StartupController::TryStart() {
haitaol1 2014/02/20 00:01:06 can you return a bool to indicate whether the cond
tim (not reviewing) 2014/02/20 22:52:52 Done.
95 if (sync_prefs_->IsManaged())
96 return;
97
98 if (sync_prefs_->IsStartSuppressed())
99 return;
100
101 if (signin_->GetEffectiveUsername().empty())
102 return;
103
104 if (!token_service_)
105 return;
106
107 if (!token_service_->RefreshTokenIsAvailable(
108 signin_->GetAccountIdToUse())) {
109 return;
110 }
111
112 // TODO(tim): Seems wrong to always record this histogram here...
113 // If we got here then tokens are loaded and user logged in and sync is
114 // enabled. If OAuth refresh token is not available then something is wrong.
115 // When PSS requests access token, OAuth2TokenService will return error and
116 // PSS will show error to user asking to reauthenticate.
117 UMA_HISTOGRAM_BOOLEAN("Sync.RefreshTokenAvailable", true);
118
119 // If sync setup has completed we always start the backend. If the user is in
120 // the process of setting up now, we should start the backend to download
121 // account control state / encryption information). If autostart is enabled,
122 // but we haven't completed sync setup, we try to start sync anyway, since
123 // it's possible we crashed/shutdown after logging in but before the backend
124 // finished initializing the last time.
125 //
126 // However, the only time we actually need to start sync _immediately_ is if
127 // we haven't completed sync setup and the user is in the process of setting
128 // up - either they just signed in (for the first time) on an auto-start
129 // platform or they explicitly kicked off sync setup, and e.g we need to
130 // fetch account details like encryption state to populate UI. Otherwise,
131 // for performance reasons and maximizing parallelism at chrome startup, we
132 // defer the heavy lifting for sync init until things have calmed down.
133 if (sync_prefs_->HasSyncSetupCompleted()) {
134 if (!received_start_request_)
135 StartUp(STARTUP_BACKEND_DEFERRED);
136 else
137 StartUp(STARTUP_IMMEDIATE);
138 } else if (setup_in_progress_ || auto_start_enabled_) {
139 // We haven't completed sync setup. Start immediately if the user explicitly
140 // kicked this off or we're supposed to automatically start syncing.
141 StartUp(STARTUP_IMMEDIATE);
142 }
143 }
144
145 void StartupController::OnFallbackStartupTimerExpired() {
146 DCHECK(CommandLine::ForCurrentProcess()->HasSwitch(
147 switches::kSyncEnableDeferredStartup));
148
149 if (!start_backend_time_.is_null())
150 return;
151
152 DVLOG(2) << "Sync deferred init fallback timer expired, starting backend.";
153 DCHECK(!start_up_time_.is_null());
154 base::TimeDelta time_deferred = base::Time::Now() - start_up_time_;
155 UMA_HISTOGRAM_TIMES("Sync.Startup.TimeDeferred", time_deferred);
156 UMA_HISTOGRAM_ENUMERATION("Sync.Startup.DeferredInitTrigger",
157 TRIGGER_FALLBACK_TIMER,
158 MAX_TRIGGER_VALUE);
159 received_start_request_ = true;
160 TryStart();
haitaol1 2014/02/20 00:01:06 can you call StartUp() here?
tim (not reviewing) 2014/02/20 22:52:52 The current model and one I'd like to stick to is
161 }
162
163 std::string StartupController::GetBackendInitializationStateString() const {
164 if (!start_backend_time_.is_null())
165 return "Started";
166 else if (!start_up_time_.is_null())
167 return "Deferred";
168 else
169 return "Not started";
170 }
171
172 void StartupController::OnDataTypeRequestsSyncStartup(syncer::ModelType type) {
173 if (!CommandLine::ForCurrentProcess()->HasSwitch(
174 switches::kSyncEnableDeferredStartup)) {
175 DVLOG(2) << "Ignoring data type request for sync startup: "
176 << syncer::ModelTypeToString(type);
177 return;
178 }
179
180 if (!start_backend_time_.is_null())
181 return;
182
183 DVLOG(2) << "Data type requesting sync startup: "
184 << syncer::ModelTypeToString(type);
185 // Measure the time spent waiting for init and the type that triggered it.
186 // We could measure the time spent deferred on a per-datatype basis, but
187 // for now this is probably sufficient.
188 if (!start_up_time_.is_null()) {
189 base::TimeDelta time_deferred = base::Time::Now() - start_up_time_;
190 UMA_HISTOGRAM_TIMES("Sync.Startup.TimeDeferred", time_deferred);
191 UMA_HISTOGRAM_ENUMERATION("Sync.Startup.TypeTriggeringInit",
haitaol1 2014/02/20 00:01:06 This UMA and the one below don't have to be in if{
tim (not reviewing) 2014/02/20 22:52:52 That data-type filtering is handled by the caller.
haitaol1 2014/02/25 00:53:01 I'm more concerned that backend is started by disa
tim (not reviewing) 2014/02/25 01:17:44 No, I don't believe so, because the caller (PSS) i
192 ModelTypeToHistogramInt(type),
193 syncer::MODEL_TYPE_COUNT);
194 UMA_HISTOGRAM_ENUMERATION("Sync.Startup.DeferredInitTrigger",
195 TRIGGER_DATA_TYPE_REQUEST,
196 MAX_TRIGGER_VALUE);
197 }
198 received_start_request_ = true;
199 TryStart();
200 }
201
202 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698