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

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

Powered by Google App Engine
This is Rietveld 408576698