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

Side by Side Diff: chrome/browser/sync/glue/app_change_processor.cc

Issue 7564037: Apps/Extensions Sync refactoring -- delete most of the old glue, implement new sync API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years, 4 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) 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 #include "chrome/browser/sync/glue/app_change_processor.h"
6
7 #include <sstream>
8 #include <string>
9
10 #include "base/logging.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_sync_data.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/sync/glue/extension_sync.h"
15 #include "chrome/browser/sync/glue/extension_util.h"
16 #include "chrome/browser/sync/protocol/extension_specifics.pb.h"
17 #include "chrome/browser/sync/unrecoverable_error_handler.h"
18 #include "chrome/common/chrome_notification_types.h"
19 #include "chrome/common/extensions/extension.h"
20 #include "content/browser/browser_thread.h"
21 #include "content/common/notification_details.h"
22 #include "content/common/notification_source.h"
23
24 namespace browser_sync {
25
26 AppChangeProcessor::AppChangeProcessor(
27 UnrecoverableErrorHandler* error_handler)
28 : ChangeProcessor(error_handler),
29 traits_(GetAppSyncTraits()),
30 profile_(NULL),
31 extension_service_(NULL) {
32 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
33 DCHECK(error_handler);
34 }
35
36 AppChangeProcessor::~AppChangeProcessor() {
37 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
38 }
39
40 // TODO(akalin): We need to make sure events we receive from either
41 // the browser or the syncapi are done in order; this is tricky since
42 // some events (e.g., extension installation) are done asynchronously.
43
44 void AppChangeProcessor::Observe(int type,
45 const NotificationSource& source,
46 const NotificationDetails& details) {
47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
48 DCHECK(running());
49 DCHECK(profile_);
50 if ((type != chrome::NOTIFICATION_EXTENSION_LOADED) &&
51 (type != chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED) &&
52 (type != chrome::NOTIFICATION_EXTENSION_UNLOADED)) {
53 LOG(DFATAL) << "Received unexpected notification of type "
54 << type;
55 return;
56 }
57
58 // Filter out unhandled extensions first.
59 DCHECK_EQ(Source<Profile>(source).ptr(), profile_);
60 const Extension& extension =
61 (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) ?
62 *Details<UnloadedExtensionInfo>(details)->extension :
63 *Details<const Extension>(details).ptr();
64 if (!traits_.is_valid_and_syncable(extension)) {
65 return;
66 }
67
68 const std::string& id = extension.id();
69
70 // Then handle extension uninstalls.
71 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) {
72 const UnloadedExtensionInfo& info =
73 *Details<UnloadedExtensionInfo>(details).ptr();
74 if (info.reason == UnloadedExtensionInfo::UNINSTALL) {
75 VLOG(1) << "Removing server data for uninstalled extension " << id
76 << " of type " << info.extension->GetType();
77 RemoveServerData(traits_, id, share_handle());
78 return;
79 }
80 }
81
82 VLOG(1) << "Updating server data for extension " << id
83 << " (notification type = " << type << ")";
84 std::string error;
85 if (!UpdateServerData(traits_, extension, *extension_service_,
86 share_handle(), &error)) {
87 error_handler()->OnUnrecoverableError(FROM_HERE, error);
88 }
89 }
90
91 void AppChangeProcessor::ApplyChangesFromSyncModel(
92 const sync_api::BaseTransaction* trans,
93 const sync_api::SyncManager::ChangeRecord* changes,
94 int change_count) {
95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
96 if (!running()) {
97 return;
98 }
99 for (int i = 0; i < change_count; ++i) {
100 const sync_api::SyncManager::ChangeRecord& change = changes[i];
101 sync_pb::ExtensionSpecifics specifics;
102 switch (change.action) {
103 case sync_api::SyncManager::ChangeRecord::ACTION_ADD:
104 case sync_api::SyncManager::ChangeRecord::ACTION_UPDATE: {
105 sync_api::ReadNode node(trans);
106 if (!node.InitByIdLookup(change.id)) {
107 std::stringstream error;
108 error << "Extension node lookup failed for change " << change.id
109 << " of action type " << change.action;
110 error_handler()->OnUnrecoverableError(FROM_HERE, error.str());
111 return;
112 }
113 DCHECK_EQ(node.GetModelType(), traits_.model_type);
114 specifics = (*traits_.extension_specifics_getter)(node);
115 break;
116 }
117 case sync_api::SyncManager::ChangeRecord::ACTION_DELETE: {
118 if (!(*traits_.extension_specifics_entity_getter)(
119 change.specifics, &specifics)) {
120 std::stringstream error;
121 error << "Could not get extension specifics from deleted node "
122 << change.id;
123 error_handler()->OnUnrecoverableError(FROM_HERE, error.str());
124 LOG(DFATAL) << error.str();
125 }
126 break;
127 }
128 }
129 ExtensionSyncData sync_data;
130 if (!SpecificsToSyncData(specifics, &sync_data)) {
131 // TODO(akalin): Should probably recover or drop.
132 std::string error =
133 std::string("Invalid server specifics: ") +
134 ExtensionSpecificsToString(specifics);
135 error_handler()->OnUnrecoverableError(FROM_HERE, error);
136 return;
137 }
138 sync_data.uninstalled =
139 (change.action == sync_api::SyncManager::ChangeRecord::ACTION_DELETE);
140 StopObserving();
141 extension_service_->ProcessSyncData(sync_data,
142 traits_.is_valid_and_syncable);
143 StartObserving();
144 }
145 }
146
147 void AppChangeProcessor::StartImpl(Profile* profile) {
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
149 profile_ = profile;
150 extension_service_ = profile_->GetExtensionService();
151 DCHECK(profile_);
152 DCHECK(extension_service_);
153 StartObserving();
154 }
155
156 void AppChangeProcessor::StopImpl() {
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
158 StopObserving();
159 profile_ = NULL;
160 extension_service_ = NULL;
161 }
162
163 void AppChangeProcessor::StartObserving() {
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
165 DCHECK(profile_);
166
167 notification_registrar_.Add(
168 this, chrome::NOTIFICATION_EXTENSION_LOADED,
169 Source<Profile>(profile_));
170 // Despite the name, this notification is exactly like
171 // EXTENSION_LOADED but with an initial state of DISABLED.
172 notification_registrar_.Add(
173 this, chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED,
174 Source<Profile>(profile_));
175
176 notification_registrar_.Add(
177 this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
178 Source<Profile>(profile_));
179 }
180
181 void AppChangeProcessor::StopObserving() {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
183 DCHECK(profile_);
184 VLOG(1) << "Unobserving all notifications";
185 notification_registrar_.RemoveAll();
186 }
187
188 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698