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 "components/wifi_sync/wifi_credential_syncable_service.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include <utility> | |
10 #include <vector> | |
11 | |
12 #include "base/logging.h" | |
13 #include "components/sync/model/sync_change.h" | |
14 #include "components/sync/model/sync_data.h" | |
15 #include "components/sync/model/sync_error.h" | |
16 #include "components/sync/model/sync_error_factory.h" | |
17 #include "components/sync/model/sync_merge_result.h" | |
18 #include "components/sync/protocol/sync.pb.h" | |
19 #include "components/wifi_sync/wifi_credential.h" | |
20 #include "components/wifi_sync/wifi_security_class.h" | |
21 | |
22 namespace wifi_sync { | |
23 | |
24 namespace { | |
25 | |
26 struct RawCredentialData { | |
27 std::vector<uint8_t> ssid; | |
28 WifiSecurityClass security_class; | |
29 std::string passphrase; | |
30 }; | |
31 | |
32 void BuildSpecifics(const WifiCredential& credential, | |
33 sync_pb::EntitySpecifics* out_buffer) { | |
34 DCHECK(out_buffer); | |
35 sync_pb::WifiCredentialSpecifics* credential_specifics = | |
36 out_buffer->mutable_wifi_credential(); | |
37 DCHECK(credential_specifics); | |
38 credential_specifics->set_ssid(credential.ssid().data(), | |
39 credential.ssid().size()); | |
40 credential_specifics->set_security_class( | |
41 WifiSecurityClassToSyncSecurityClass(credential.security_class())); | |
42 if (WifiSecurityClassSupportsPassphrases(credential.security_class())) { | |
43 credential_specifics->set_passphrase(credential.passphrase().data(), | |
44 credential.passphrase().size()); | |
45 } | |
46 } | |
47 | |
48 bool ParseSpecifics(const sync_pb::EntitySpecifics& specifics, | |
49 RawCredentialData* raw_credential) { | |
50 DCHECK(raw_credential); | |
51 if (!specifics.has_wifi_credential()) { | |
52 LOG(ERROR) << "Specifics with missing wifi_credential; skipping"; | |
53 return false; | |
54 } | |
55 | |
56 const sync_pb::WifiCredentialSpecifics& credential_specifics = | |
57 specifics.wifi_credential(); | |
58 if (!credential_specifics.has_ssid()) { | |
59 LOG(ERROR) << "Specifics with missing SSID; skipping"; | |
60 return false; | |
61 } | |
62 if (!credential_specifics.has_security_class()) { | |
63 LOG(ERROR) << "Specifics with missing security class; skipping"; | |
64 return false; | |
65 } | |
66 | |
67 const WifiSecurityClass security_class = | |
68 WifiSecurityClassFromSyncSecurityClass( | |
69 credential_specifics.security_class()); | |
70 if (WifiSecurityClassSupportsPassphrases(security_class) && | |
71 !credential_specifics.has_passphrase()) { | |
72 LOG(ERROR) << "Specifics for security class " | |
73 << credential_specifics.security_class() | |
74 << " is missing passphrase; skipping"; | |
75 return false; | |
76 } | |
77 | |
78 raw_credential->ssid.assign(credential_specifics.ssid().begin(), | |
79 credential_specifics.ssid().end()); | |
80 raw_credential->security_class = security_class; | |
81 raw_credential->passphrase = credential_specifics.passphrase(); | |
82 return true; | |
83 } | |
84 | |
85 // TODO(quiche): Separate SyncData validation from parsing of | |
86 // WifiCredentialSpecifics. | |
87 bool ParseSyncData(const syncer::SyncData& sync_data, | |
88 RawCredentialData* raw_credential) { | |
89 DCHECK(raw_credential); | |
90 if (!sync_data.IsValid()) { | |
91 LOG(WARNING) << "Invalid SyncData; skipping item"; | |
92 return false; | |
93 } | |
94 | |
95 if (sync_data.GetDataType() != syncer::WIFI_CREDENTIALS) { | |
96 LOG(WARNING) << "Unexpected SyncData of type " | |
97 << syncer::ModelTypeToString(sync_data.GetDataType()) | |
98 << "; skipping item"; | |
99 return false; | |
100 } | |
101 | |
102 return ParseSpecifics(sync_data.GetSpecifics(), raw_credential); | |
103 } | |
104 | |
105 } // namespace | |
106 | |
107 const syncer::ModelType WifiCredentialSyncableService::kModelType = | |
108 syncer::WIFI_CREDENTIALS; | |
109 | |
110 WifiCredentialSyncableService::WifiCredentialSyncableService( | |
111 std::unique_ptr<WifiConfigDelegate> network_config_delegate) | |
112 : network_config_delegate_(std::move(network_config_delegate)) { | |
113 DCHECK(network_config_delegate_); | |
114 } | |
115 | |
116 WifiCredentialSyncableService::~WifiCredentialSyncableService() { | |
117 } | |
118 | |
119 syncer::SyncMergeResult WifiCredentialSyncableService::MergeDataAndStartSyncing( | |
120 syncer::ModelType type, | |
121 const syncer::SyncDataList& initial_sync_data, | |
122 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, | |
123 std::unique_ptr<syncer::SyncErrorFactory> /* error_handler */) { | |
124 DCHECK(!sync_processor_.get()); | |
125 DCHECK(sync_processor.get()); | |
126 DCHECK_EQ(kModelType, type); | |
127 | |
128 sync_processor_ = std::move(sync_processor); | |
129 | |
130 // TODO(quiche): Update local WiFi configuration from |initial_sync_data|. | |
131 // TODO(quiche): Notify upper layers that sync is ready. | |
132 NOTIMPLEMENTED(); | |
133 | |
134 return syncer::SyncMergeResult(type); | |
135 } | |
136 | |
137 void WifiCredentialSyncableService::StopSyncing(syncer::ModelType type) { | |
138 DCHECK_EQ(kModelType, type); | |
139 sync_processor_.reset(); | |
140 } | |
141 | |
142 syncer::SyncDataList WifiCredentialSyncableService::GetAllSyncData( | |
143 syncer::ModelType type) const { | |
144 DCHECK_EQ(kModelType, type); | |
145 NOTIMPLEMENTED(); | |
146 return syncer::SyncDataList(); | |
147 } | |
148 | |
149 syncer::SyncError WifiCredentialSyncableService::ProcessSyncChanges( | |
150 const tracked_objects::Location& /* caller_location */, | |
151 const syncer::SyncChangeList& change_list) { | |
152 if (!sync_processor_.get()) { | |
153 return syncer::SyncError( | |
154 FROM_HERE, syncer::SyncError::UNREADY_ERROR, | |
155 "ProcessSyncChanges called before MergeDataAndStartSyncing", | |
156 kModelType); | |
157 } | |
158 | |
159 for (const syncer::SyncChange& sync_change : change_list) { | |
160 DCHECK(sync_change.IsValid()); | |
161 RawCredentialData raw_credential; | |
162 if (!ParseSyncData(sync_change.sync_data(), &raw_credential)) { | |
163 LOG(WARNING) << "Failed to parse item; skipping " | |
164 << syncer::SyncChange::ChangeTypeToString( | |
165 sync_change.change_type()); | |
166 continue; | |
167 } | |
168 | |
169 std::unique_ptr<WifiCredential> credential; | |
170 switch (sync_change.change_type()) { | |
171 case syncer::SyncChange::ACTION_ADD: | |
172 credential = WifiCredential::Create(raw_credential.ssid, | |
173 raw_credential.security_class, | |
174 raw_credential.passphrase); | |
175 if (!credential) | |
176 LOG(WARNING) << "Failed to create credential; skipping"; | |
177 else | |
178 network_config_delegate_->AddToLocalNetworks(*credential); | |
179 break; | |
180 case syncer::SyncChange::ACTION_UPDATE: | |
181 // TODO(quiche): Implement update, and add appropriate tests. | |
182 NOTIMPLEMENTED(); | |
183 break; | |
184 case syncer::SyncChange::ACTION_DELETE: | |
185 // TODO(quiche): Implement delete, and add appropriate tests. | |
186 NOTIMPLEMENTED(); | |
187 break; | |
188 default: | |
189 return syncer::SyncError( | |
190 FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | |
191 "ProcessSyncChanges given invalid SyncChangeType", kModelType); | |
192 } | |
193 } | |
194 | |
195 return syncer::SyncError(); | |
196 } | |
197 | |
198 bool WifiCredentialSyncableService::AddToSyncedNetworks( | |
199 const std::string& item_id, | |
200 const WifiCredential& credential) { | |
201 if (!sync_processor_.get()) { | |
202 // Callers must queue updates until MergeDataAndStartSyncing has | |
203 // been called on this SyncableService. | |
204 LOG(WARNING) << "WifiCredentials syncable service is not started."; | |
205 return false; | |
206 } | |
207 | |
208 const SsidAndSecurityClass network_id( | |
209 credential.ssid(), credential.security_class()); | |
210 if (synced_networks_and_passphrases_.find(network_id) != | |
211 synced_networks_and_passphrases_.end()) { | |
212 // TODO(quiche): If passphrase has changed, submit this to sync as | |
213 // an ACTION_UPDATE. crbug.com/431436 | |
214 return false; | |
215 } | |
216 | |
217 syncer::SyncChangeList change_list; | |
218 syncer::SyncError sync_error; | |
219 sync_pb::EntitySpecifics wifi_credential_specifics; | |
220 BuildSpecifics(credential, &wifi_credential_specifics); | |
221 change_list.push_back( | |
222 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, | |
223 syncer::SyncData::CreateLocalData( | |
224 item_id, item_id, wifi_credential_specifics))); | |
225 sync_error = sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); | |
226 if (sync_error.IsSet()) { | |
227 LOG(ERROR) << sync_error.ToString(); | |
228 return false; | |
229 } | |
230 | |
231 synced_networks_and_passphrases_[network_id] = credential.passphrase(); | |
232 return true; | |
233 } | |
234 | |
235 } // namespace wifi_sync | |
OLD | NEW |