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

Side by Side Diff: chrome/browser/invalidation_service.cc

Issue 13197004: Draft: InvalidationService (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Passes tests Created 7 years, 8 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 (c) 2013 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/invalidation_service.h"
6
7 #include "base/base64.h"
8 #include "base/command_line.h"
9 #include "base/rand_util.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/signin/signin_manager.h"
12 #include "chrome/browser/signin/token_service.h"
13 #include "chrome/common/chrome_notification_types.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "content/public/browser/notification_service.h"
16 #include "google_apis/gaia/gaia_constants.h"
17 #include "google_apis/gaia/google_service_auth_error.h"
18 #include "sync/notifier/invalidator.h"
19 #include "sync/notifier/invalidator_state.h"
20 #include "sync/notifier/non_blocking_invalidator.h"
21
22 namespace {
23 // Parses the given command line for notifier options.
24 notifier::NotifierOptions ParseNotifierOptions(
25 const CommandLine& command_line,
26 const scoped_refptr<net::URLRequestContextGetter>&
27 request_context_getter) {
28 notifier::NotifierOptions notifier_options;
29 notifier_options.request_context_getter = request_context_getter;
30
31 if (command_line.HasSwitch(switches::kSyncNotificationHostPort)) {
32 notifier_options.xmpp_host_port =
33 net::HostPortPair::FromString(
34 command_line.GetSwitchValueASCII(
35 switches::kSyncNotificationHostPort));
36 DVLOG(1) << "Using " << notifier_options.xmpp_host_port.ToString()
37 << " for test sync notification server.";
38 }
39
40 notifier_options.try_ssltcp_first =
41 command_line.HasSwitch(switches::kSyncTrySsltcpFirstForXmpp);
42 DVLOG_IF(1, notifier_options.try_ssltcp_first)
43 << "Trying SSL/TCP port before XMPP port for notifications.";
44
45 notifier_options.invalidate_xmpp_login =
46 command_line.HasSwitch(switches::kSyncInvalidateXmppLogin);
47 DVLOG_IF(1, notifier_options.invalidate_xmpp_login)
48 << "Invalidating sync XMPP login.";
49
50 notifier_options.allow_insecure_connection =
51 command_line.HasSwitch(switches::kSyncAllowInsecureXmppConnection);
52 DVLOG_IF(1, notifier_options.allow_insecure_connection)
53 << "Allowing insecure XMPP connections.";
54
55 if (command_line.HasSwitch(switches::kSyncNotificationMethod)) {
56 const std::string notification_method_str(
57 command_line.GetSwitchValueASCII(switches::kSyncNotificationMethod));
58 notifier_options.notification_method =
59 notifier::StringToNotificationMethod(notification_method_str);
60 }
61
62 return notifier_options;
63 }
64
65 std::string GenerateInvalidatorClientId() {
66 // Generate a GUID with 128 bits worth of base64-encoded randomness.
67 // This format is similar to that of sync's cache_guid.
68 const int kGuidBytes = 128 / 8;
69 std::string guid;
70 base::Base64Encode(base::RandBytesAsString(kGuidBytes), &guid);
71 return guid;
72 }
73
74 } // namespace
75
76 InvalidationService::InvalidationService(SigninManager* signin,
77 TokenService* token_service)
78 : signin_manager_(signin),
79 token_service_(token_service),
80 invalidator_registrar_(new syncer::InvalidatorRegistrar()) { }
81
82 InvalidationService::~InvalidationService() {
83 DCHECK(CalledOnValidThread());
84 }
85
86 void InvalidationService::Init(Profile* profile) {
87 DCHECK(CalledOnValidThread());
88
89 profile_ = profile;
90
91 invalidator_storage_.reset(
92 new browser_sync::InvalidatorStorage(profile_->GetPrefs()));
93 if (invalidator_storage_->GetInvalidatorClientId().empty()) {
94 // This also clears any existing state. We can't reuse old invalidator
95 // state with the new ID anyway.
96 invalidator_storage_->SetInvalidatorClientId(
97 GenerateInvalidatorClientId());
98 }
99
100 if (IsReadyToStart()) {
101 Start();
102 }
103
104 notification_registrar_.Add(this,
105 chrome::NOTIFICATION_TOKEN_AVAILABLE,
106 content::Source<TokenService>(token_service_));
107 notification_registrar_.Add(this,
108 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
109 content::NotificationService::AllSources());
110 }
111
112 void InvalidationService::RegisterInvalidationHandler(
113 syncer::InvalidationHandler* handler) {
114 DCHECK(CalledOnValidThread());
115 DVLOG(2) << "Registering";
116 invalidator_registrar_->RegisterHandler(handler);
117 }
118
119 void InvalidationService::UpdateRegisteredInvalidationIds(
120 syncer::InvalidationHandler* handler,
121 const syncer::ObjectIdSet& ids) {
122 DCHECK(CalledOnValidThread());
123 DVLOG(2) << "Registering ids: " << ids.size();
124 invalidator_registrar_->UpdateRegisteredIds(handler, ids);
125 if (invalidator_) {
126 invalidator_->UpdateRegisteredIds(
127 this,
128 invalidator_registrar_->GetAllRegisteredIds());
129 }
130 }
131
132 void InvalidationService::UnregisterInvalidationHandler(
133 syncer::InvalidationHandler* handler) {
134 DCHECK(CalledOnValidThread());
135 DVLOG(2) << "Unregistering";
136 invalidator_registrar_->UnregisterHandler(handler);
137 // FIXME: Should unregistering the handler also unregister the IDs?
138 // I don't see why not...
139 if (invalidator_) {
140 invalidator_->UpdateRegisteredIds(
141 this,
142 invalidator_registrar_->GetAllRegisteredIds());
143 }
144 }
145
146 void InvalidationService::AcknowledgeInvalidation(
147 const invalidation::ObjectId& id,
148 const syncer::AckHandle& ack_handle) {
149 DCHECK(CalledOnValidThread());
150 if (invalidator_) {
151 invalidator_->Acknowledge(id, ack_handle);
152 }
153 }
154
155 syncer::InvalidatorState InvalidationService::GetInvalidatorState() const {
156 DCHECK(CalledOnValidThread());
157 if (invalidator_) {
158 DVLOG(2) << "GetInvalidatorState returning " << GetInvalidatorState();
159 return invalidator_->GetInvalidatorState();
160 } else {
161 DVLOG(2) << "Invalidator currently stopped";
162 return syncer::TRANSIENT_INVALIDATION_ERROR;
163 }
164 }
165
166 std::string InvalidationService::GetInvalidatorClientId() const {
167 DCHECK(CalledOnValidThread());
168 if (!invalidator_storage_) { // NULL in some unit tests.
169 return "TESTING_ONLY_ID";
170 }
171
172 return invalidator_storage_->GetInvalidatorClientId();
173 }
174
175 void InvalidationService::Observe(
176 int type,
177 const content::NotificationSource& source,
178 const content::NotificationDetails& details) {
179 DCHECK(CalledOnValidThread());
180
181 switch (type) {
182 case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
tim (not reviewing) 2013/04/15 16:48:24 I forget, do we always send TOKEN_AVAILABLE from T
rlarocque 2013/04/22 21:47:15 I think that's always guaranteed. I was a bit sus
tim (not reviewing) 2013/04/22 22:13:56 More likely is at one time TOKEN_AVAILABLE was act
183 const TokenService::TokenAvailableDetails& token_details =
184 *(content::Details<const TokenService::TokenAvailableDetails>(
185 details).ptr());
186 if (token_details.service() == GaiaConstants::kSyncService) {
187 DCHECK(IsReadyToStart());
188 if (!IsStarted()) {
189 Start();
tim (not reviewing) 2013/04/15 16:48:24 You should check with atwilson@ and rogerta@ about
rlarocque 2013/04/22 21:47:15 I'm not sure that we want to go in that direction.
tim (not reviewing) 2013/04/22 22:13:56 As I said, just make sure you check with Drew (at
190 } else {
191 UpdateToken();
192 }
193 }
194 break;
195 }
196 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
tim (not reviewing) 2013/04/15 16:48:24 This may get interesting when we have service acco
197 Stop();
198 break;
199 }
200 }
201
202 void InvalidationService::OnInvalidatorStateChange(
203 syncer::InvalidatorState state) {
204 invalidator_registrar_->UpdateInvalidatorState(state);
205 }
206
207 void InvalidationService::OnIncomingInvalidation(
208 const syncer::ObjectIdInvalidationMap& invalidation_map) {
209 invalidator_registrar_->DispatchInvalidationsToHandlers(invalidation_map);
210 }
211
212 void InvalidationService::Shutdown() {
213 DCHECK(CalledOnValidThread());
214 Stop();
215 invalidator_registrar_.reset();
216 }
217
218 bool InvalidationService::IsReadyToStart() {
219 if (signin_manager_->GetAuthenticatedUsername().empty()) {
220 DVLOG(2) << "Not starting InvalidationService: user is not signed in.";
221 return false;
222 }
223
224 if (!token_service_) {
225 DVLOG(2) << "Not starting InvalidationService: TokenService unavailable.";
226 return false;
227 }
228
229 if (!token_service_->HasTokenForService(GaiaConstants::kSyncService)) {
230 DVLOG(2) << "Not starting InvalidationService: Sync token unavailable.";
231 return false;
232 }
233
234 return true;
235 }
236
237 bool InvalidationService::IsStarted() {
238 return !!invalidator_;
239 }
240
241 void InvalidationService::Start() {
242 DCHECK(CalledOnValidThread());
243
244 DCHECK(!invalidator_);
245
246 invalidator_.reset(new syncer::NonBlockingInvalidator(
247 ParseNotifierOptions(*CommandLine::ForCurrentProcess(),
248 profile_->GetRequestContext()),
249 invalidator_storage_->GetInvalidatorClientId(),
250 invalidator_storage_->GetAllInvalidationStates(),
251 invalidator_storage_->GetBootstrapData(),
252 syncer::WeakHandle<syncer::InvalidationStateTracker>(
253 invalidator_storage_->AsWeakPtr()),
254 content::GetUserAgent(GURL())));
255
256 UpdateToken();
257
258 invalidator_->RegisterHandler(this);
259 invalidator_->UpdateRegisteredIds(
260 this,
261 invalidator_registrar_->GetAllRegisteredIds());
262 }
263
264 void InvalidationService::UpdateToken() {
265 std::string email = signin_manager_->GetAuthenticatedUsername();
266 DCHECK(!email.empty()) << "Expected user to be signed in.";
267
268 // FIXME: Is it right to use the sync token here?
tim (not reviewing) 2013/04/15 16:48:24 Yes, this seems correct and equivalent to before t
rlarocque 2013/04/22 21:47:15 OK. Just to be clear, my intent with this patch i
tim (not reviewing) 2013/04/22 22:13:56 So, yes. I think we're in agreement? In the futur
269 DCHECK(token_service_->HasTokenForService(GaiaConstants::kSyncService));
270 std::string sync_token = token_service_->GetTokenForService(
271 GaiaConstants::kSyncService);
272
273 DVLOG(2) << "UpdateCredentials: " << email;
274 invalidator_->UpdateCredentials(email, sync_token);
275 }
276
277 void InvalidationService::Stop() {
278 if (invalidator_) {
279 invalidator_->UnregisterHandler(this);
280 invalidator_.reset();
281 }
282 if (invalidator_storage_) {
283 invalidator_storage_->Clear();
284 invalidator_storage_.reset();
285 }
286 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698