OLD | NEW |
| (Empty) |
1 // Copyright 2014 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/extensions/api/synced_notifications_private/synced_noti
fications_shim.h" | |
6 | |
7 #include "extensions/browser/event_router.h" | |
8 #include "sync/api/sync_change.h" | |
9 #include "sync/api/sync_data.h" | |
10 #include "sync/api/sync_error_factory.h" | |
11 #include "sync/protocol/sync.pb.h" | |
12 | |
13 using namespace extensions; | |
14 using namespace extensions::api; | |
15 | |
16 namespace { | |
17 | |
18 synced_notifications_private::ChangeType SyncerChangeTypeToJS( | |
19 syncer::SyncChange::SyncChangeType change_type) { | |
20 switch (change_type) { | |
21 case syncer::SyncChange::ACTION_UPDATE: | |
22 return synced_notifications_private::CHANGE_TYPE_UPDATED; | |
23 case syncer::SyncChange::ACTION_DELETE: | |
24 return synced_notifications_private::CHANGE_TYPE_DELETED; | |
25 case syncer::SyncChange::ACTION_ADD: | |
26 return synced_notifications_private::CHANGE_TYPE_ADDED; | |
27 case syncer::SyncChange::ACTION_INVALID: | |
28 return synced_notifications_private::CHANGE_TYPE_NONE; | |
29 } | |
30 NOTREACHED(); | |
31 return synced_notifications_private::CHANGE_TYPE_NONE; | |
32 } | |
33 | |
34 syncer::ModelType JSDataTypeToSyncer( | |
35 synced_notifications_private::SyncDataType data_type) { | |
36 switch (data_type) { | |
37 case synced_notifications_private::SYNC_DATA_TYPE_APP_INFO: | |
38 return syncer::SYNCED_NOTIFICATION_APP_INFO; | |
39 case synced_notifications_private::SYNC_DATA_TYPE_SYNCED_NOTIFICATION: | |
40 return syncer::SYNCED_NOTIFICATIONS; | |
41 default: | |
42 NOTREACHED(); | |
43 return syncer::UNSPECIFIED; | |
44 } | |
45 } | |
46 | |
47 synced_notifications_private::SyncDataType SyncerModelTypeToJS( | |
48 syncer::ModelType model_type) { | |
49 switch (model_type) { | |
50 case syncer::SYNCED_NOTIFICATION_APP_INFO: | |
51 return synced_notifications_private::SYNC_DATA_TYPE_APP_INFO; | |
52 case syncer::SYNCED_NOTIFICATIONS: | |
53 return synced_notifications_private::SYNC_DATA_TYPE_SYNCED_NOTIFICATION; | |
54 default: | |
55 NOTREACHED(); | |
56 return synced_notifications_private::SYNC_DATA_TYPE_NONE; | |
57 } | |
58 } | |
59 | |
60 bool BuildNewSyncUpdate( | |
61 const tracked_objects::Location& from_here, | |
62 const std::string& changed_notification, | |
63 syncer::SyncChange* sync_change) { | |
64 sync_pb::EntitySpecifics specifics; | |
65 sync_pb::SyncedNotificationSpecifics* notification_specifics = | |
66 specifics.mutable_synced_notification(); | |
67 if (!notification_specifics->ParseFromArray( | |
68 changed_notification.c_str(), changed_notification.size())) { | |
69 return false; | |
70 } | |
71 | |
72 // TODO(synced notifications): pass the tag via the JS API. | |
73 const std::string& tag = | |
74 notification_specifics->coalesced_notification().key(); | |
75 syncer::SyncData sync_data = | |
76 syncer::SyncData::CreateLocalData(tag, tag, specifics); | |
77 *sync_change = syncer::SyncChange( | |
78 from_here, syncer::SyncChange::ACTION_UPDATE, sync_data); | |
79 return true; | |
80 } | |
81 | |
82 linked_ptr<synced_notifications_private::SyncChange> BuildNewJSSyncChange( | |
83 const syncer::SyncChange& change) { | |
84 linked_ptr<synced_notifications_private::SyncChange> js_change = | |
85 make_linked_ptr<synced_notifications_private::SyncChange>( | |
86 new synced_notifications_private::SyncChange()); | |
87 js_change->change_type = SyncerChangeTypeToJS(change.change_type()); | |
88 js_change->data.datatype = | |
89 SyncerModelTypeToJS(change.sync_data().GetDataType()); | |
90 if (change.sync_data().GetDataType() == syncer::SYNCED_NOTIFICATIONS) { | |
91 const sync_pb::SyncedNotificationSpecifics& specifics = | |
92 change.sync_data().GetSpecifics().synced_notification(); | |
93 js_change->data.data_item = specifics.SerializeAsString(); | |
94 } else { | |
95 DCHECK_EQ(change.sync_data().GetDataType(), | |
96 syncer::SYNCED_NOTIFICATION_APP_INFO); | |
97 const sync_pb::SyncedNotificationAppInfoSpecifics& specifics = | |
98 change.sync_data().GetSpecifics().synced_notification_app_info(); | |
99 js_change->data.data_item = specifics.SerializeAsString(); | |
100 } | |
101 return js_change; | |
102 } | |
103 | |
104 bool PopulateJSDataListFromSync( | |
105 const syncer::SyncDataList& sync_data_list, | |
106 std::vector<linked_ptr<synced_notifications_private::SyncData> >* | |
107 js_data_list) { | |
108 for (size_t i = 0; i < sync_data_list.size(); ++i) { | |
109 linked_ptr<synced_notifications_private::SyncData> js_data( | |
110 new synced_notifications_private::SyncData()); | |
111 syncer::ModelType data_type = sync_data_list[i].GetDataType(); | |
112 js_data->datatype = SyncerModelTypeToJS(data_type); | |
113 if (data_type == syncer::SYNCED_NOTIFICATIONS) { | |
114 const sync_pb::SyncedNotificationSpecifics& specifics = | |
115 sync_data_list[i].GetSpecifics().synced_notification(); | |
116 js_data->data_item = specifics.SerializeAsString(); | |
117 } else if (data_type == syncer::SYNCED_NOTIFICATION_APP_INFO) { | |
118 const sync_pb::SyncedNotificationAppInfoSpecifics& specifics = | |
119 sync_data_list[i].GetSpecifics().synced_notification_app_info(); | |
120 js_data->data_item = specifics.SerializeAsString(); | |
121 } else { | |
122 return false; | |
123 } | |
124 js_data_list->push_back(js_data); | |
125 } | |
126 return true; | |
127 } | |
128 | |
129 } // namespace | |
130 | |
131 SyncedNotificationsShim::SyncedNotificationsShim( | |
132 const EventLauncher& event_launcher, | |
133 const base::Closure& refresh_request) | |
134 : event_launcher_(event_launcher), | |
135 refresh_request_(refresh_request) { | |
136 } | |
137 | |
138 SyncedNotificationsShim::~SyncedNotificationsShim() { | |
139 } | |
140 | |
141 syncer::SyncMergeResult SyncedNotificationsShim::MergeDataAndStartSyncing( | |
142 syncer::ModelType type, | |
143 const syncer::SyncDataList& initial_sync_data, | |
144 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, | |
145 scoped_ptr<syncer::SyncErrorFactory> error_handler) { | |
146 if (type == syncer::SYNCED_NOTIFICATIONS) | |
147 notifications_change_processor_ = sync_processor.Pass(); | |
148 else if (type == syncer::SYNCED_NOTIFICATION_APP_INFO) | |
149 app_info_change_processor_ = sync_processor.Pass(); | |
150 else | |
151 NOTREACHED(); | |
152 | |
153 // Only wake up the extension if both sync data types are ready. | |
154 if (notifications_change_processor_ && app_info_change_processor_) { | |
155 scoped_ptr<Event> event(new Event( | |
156 synced_notifications_private::OnSyncStartup::kEventName, | |
157 synced_notifications_private::OnSyncStartup::Create())); | |
158 event_launcher_.Run(event.Pass()); | |
159 } | |
160 | |
161 return syncer::SyncMergeResult(type); | |
162 } | |
163 | |
164 void SyncedNotificationsShim::StopSyncing(syncer::ModelType type) { | |
165 if (type == syncer::SYNCED_NOTIFICATIONS) | |
166 notifications_change_processor_.reset(); | |
167 else if (type == syncer::SYNCED_NOTIFICATION_APP_INFO) | |
168 app_info_change_processor_.reset(); | |
169 else | |
170 NOTREACHED(); | |
171 } | |
172 | |
173 syncer::SyncError SyncedNotificationsShim::ProcessSyncChanges( | |
174 const tracked_objects::Location& from_here, | |
175 const syncer::SyncChangeList& changes) { | |
176 std::vector<linked_ptr<synced_notifications_private::SyncChange> > js_changes; | |
177 for (size_t i = 0; i < changes.size(); ++i) | |
178 js_changes.push_back(BuildNewJSSyncChange(changes[i])); | |
179 | |
180 scoped_ptr<base::ListValue> args( | |
181 synced_notifications_private::OnDataChanges::Create(js_changes)); | |
182 scoped_ptr<Event> event(new Event( | |
183 synced_notifications_private::OnDataChanges::kEventName, args.Pass())); | |
184 event_launcher_.Run(event.Pass()); | |
185 return syncer::SyncError(); | |
186 } | |
187 | |
188 syncer::SyncDataList SyncedNotificationsShim::GetAllSyncData( | |
189 syncer::ModelType type) const { | |
190 NOTIMPLEMENTED(); | |
191 return syncer::SyncDataList(); | |
192 } | |
193 | |
194 bool SyncedNotificationsShim::GetInitialData( | |
195 synced_notifications_private::SyncDataType data_type, | |
196 std::vector<linked_ptr<synced_notifications_private::SyncData> >* | |
197 js_data_list) const { | |
198 if (!IsSyncReady()) | |
199 return false; | |
200 | |
201 syncer::SyncDataList sync_data_list; | |
202 if (JSDataTypeToSyncer(data_type) == syncer::SYNCED_NOTIFICATIONS) { | |
203 sync_data_list = notifications_change_processor_->GetAllSyncData( | |
204 syncer::SYNCED_NOTIFICATIONS); | |
205 if (PopulateJSDataListFromSync(sync_data_list, js_data_list)) | |
206 return true; | |
207 } else if (JSDataTypeToSyncer(data_type) == | |
208 syncer::SYNCED_NOTIFICATION_APP_INFO) { | |
209 sync_data_list = app_info_change_processor_->GetAllSyncData( | |
210 syncer::SYNCED_NOTIFICATION_APP_INFO); | |
211 if (PopulateJSDataListFromSync(sync_data_list, js_data_list)) | |
212 return true; | |
213 } | |
214 return false; | |
215 } | |
216 | |
217 bool SyncedNotificationsShim::UpdateNotification( | |
218 const std::string& changed_notification) { | |
219 if (!IsSyncReady()) | |
220 return false; | |
221 | |
222 syncer::SyncChange sync_change; | |
223 if (!BuildNewSyncUpdate(FROM_HERE, changed_notification, &sync_change)) | |
224 return false; | |
225 syncer::SyncError error = notifications_change_processor_->ProcessSyncChanges( | |
226 FROM_HERE, | |
227 syncer::SyncChangeList(1, sync_change)); | |
228 return !error.IsSet(); | |
229 } | |
230 | |
231 bool SyncedNotificationsShim::SetRenderContext( | |
232 synced_notifications_private::RefreshRequest refresh_request, | |
233 const std::string& new_context) { | |
234 if (!IsSyncReady()) | |
235 return false; | |
236 | |
237 syncer::SyncChangeProcessor::ContextRefreshStatus sync_refresh_status = | |
238 refresh_request == | |
239 synced_notifications_private::REFRESH_REQUEST_REFRESH_NEEDED | |
240 ? syncer::SyncChangeProcessor::REFRESH_NEEDED | |
241 : syncer::SyncChangeProcessor::NO_REFRESH; | |
242 syncer::SyncError error = | |
243 notifications_change_processor_->UpdateDataTypeContext( | |
244 syncer::SYNCED_NOTIFICATIONS, sync_refresh_status, new_context); | |
245 | |
246 if (sync_refresh_status == syncer::SyncChangeProcessor::REFRESH_NEEDED && | |
247 !refresh_request_.is_null()) { | |
248 refresh_request_.Run(); | |
249 } | |
250 | |
251 return !error.IsSet(); | |
252 } | |
253 | |
254 bool SyncedNotificationsShim::IsSyncReady() const { | |
255 return notifications_change_processor_ && app_info_change_processor_; | |
256 } | |
OLD | NEW |