session_change_processor.cc revision bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293
1// Copyright (c) 2010 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/glue/session_change_processor.h"
6
7#include <sstream>
8#include <string>
9
10#include "base/logging.h"
11#include "chrome/browser/chrome_thread.h"
12#include "chrome/browser/sync/engine/syncapi.h"
13#include "chrome/browser/sync/glue/session_model_associator.h"
14#include "chrome/common/notification_details.h"
15#include "chrome/common/notification_source.h"
16
17namespace browser_sync {
18
19SessionChangeProcessor::SessionChangeProcessor(
20    UnrecoverableErrorHandler* error_handler,
21    SessionModelAssociator* session_model_associator)
22    : ChangeProcessor(error_handler),
23      session_model_associator_(session_model_associator),
24      profile_(NULL) {
25  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
26  DCHECK(error_handler);
27  DCHECK(session_model_associator_);
28}
29
30SessionChangeProcessor::~SessionChangeProcessor() {
31  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
32}
33
34void SessionChangeProcessor::Observe(NotificationType type,
35                                     const NotificationSource& source,
36                                     const NotificationDetails& details) {
37  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
38  DCHECK(running());
39  DCHECK(profile_);
40  switch (type.value) {
41    case NotificationType::SESSION_SERVICE_SAVED: {
42      std::string tag = session_model_associator_->GetCurrentMachineTag();
43      DCHECK_EQ(Source<Profile>(source).ptr(), profile_);
44      LOG(INFO) << "Got change notification of type " << type.value
45                << " for session " << tag;
46      session_model_associator_->UpdateSyncModelDataFromClient();
47      break;
48    }
49    default:
50      LOG(DFATAL) << "Received unexpected notification of type "
51                  << type.value;
52      break;
53  }
54}
55
56void SessionChangeProcessor::ApplyChangesFromSyncModel(
57    const sync_api::BaseTransaction* trans,
58    const sync_api::SyncManager::ChangeRecord* changes,
59    int change_count) {
60  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
61  if (!running()) {
62    return;
63  }
64  for (int i = 0; i < change_count; ++i) {
65    const sync_api::SyncManager::ChangeRecord& change = changes[i];
66    switch (change.action) {
67      case sync_api::SyncManager::ChangeRecord::ACTION_ADD:
68        UpdateModel(trans, change, true);
69        break;
70      case sync_api::SyncManager::ChangeRecord::ACTION_UPDATE:
71        UpdateModel(trans, change, true);
72        break;
73      case sync_api::SyncManager::ChangeRecord::ACTION_DELETE:
74        UpdateModel(trans, change, false);
75        break;
76    }
77  }
78}
79
80void SessionChangeProcessor::UpdateModel(const sync_api::BaseTransaction* trans,
81    const sync_api::SyncManager::ChangeRecord& change, bool associate) {
82  sync_api::ReadNode node(trans);
83  if (!node.InitByIdLookup(change.id)) {
84    std::stringstream error;
85    error << "Session node lookup failed for change " << change.id
86      << " of action type " << change.action;
87    error_handler()->OnUnrecoverableError(FROM_HERE, error.str());
88    return;
89  }
90  DCHECK_EQ(node.GetModelType(), syncable::SESSIONS);
91  StopObserving();
92  if (associate) {
93    session_model_associator_->Associate(
94      (const sync_pb::SessionSpecifics *) NULL, node.GetId());
95  } else {
96    session_model_associator_->Disassociate(node.GetId());
97  }
98  StartObserving();
99}
100
101void SessionChangeProcessor::StartImpl(Profile* profile) {
102  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
103  DCHECK(profile);
104  DCHECK(profile_ == NULL);
105  profile_ = profile;
106  StartObserving();
107}
108
109void SessionChangeProcessor::StopImpl() {
110  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
111  StopObserving();
112  profile_ = NULL;
113}
114
115void SessionChangeProcessor::StartObserving() {
116  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
117  DCHECK(profile_);
118  LOG(INFO) << "Observing SESSION_SERVICE_SAVED";
119  notification_registrar_.Add(
120      this, NotificationType::SESSION_SERVICE_SAVED,
121      Source<Profile>(profile_));
122}
123
124void SessionChangeProcessor::StopObserving() {
125  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
126  DCHECK(profile_);
127  LOG(INFO) << "removing observation of all notifications";
128  notification_registrar_.RemoveAll();
129}
130
131}  // namespace browser_sync
132
133