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

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

Powered by Google App Engine
This is Rietveld 408576698