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