1// Copyright (c) 2012 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/storage/setting_sync_data.h"
6
7#include "base/json/json_reader.h"
8#include "base/json/json_writer.h"
9#include "sync/api/sync_data.h"
10#include "sync/protocol/app_setting_specifics.pb.h"
11#include "sync/protocol/extension_setting_specifics.pb.h"
12#include "sync/protocol/sync.pb.h"
13
14namespace extensions {
15
16SettingSyncData::SettingSyncData(
17    const syncer::SyncChange& sync_change) {
18  Init(sync_change.change_type(), sync_change.sync_data());
19}
20
21SettingSyncData::SettingSyncData(
22    const syncer::SyncData& sync_data) {
23  Init(syncer::SyncChange::ACTION_INVALID, sync_data);
24}
25
26void SettingSyncData::Init(
27    syncer::SyncChange::SyncChangeType change_type,
28    const syncer::SyncData& sync_data) {
29  DCHECK(!internal_.get());
30  sync_pb::EntitySpecifics specifics = sync_data.GetSpecifics();
31  // The data must only be either extension or app specfics.
32  DCHECK_NE(specifics.has_extension_setting(),
33            specifics.has_app_setting());
34  if (specifics.has_extension_setting()) {
35    InitFromExtensionSettingSpecifics(
36        change_type,
37        specifics.extension_setting());
38  } else if (specifics.has_app_setting()) {
39    InitFromExtensionSettingSpecifics(
40        change_type,
41        specifics.app_setting().extension_setting());
42  }
43}
44
45void SettingSyncData::InitFromExtensionSettingSpecifics(
46    syncer::SyncChange::SyncChangeType change_type,
47    const sync_pb::ExtensionSettingSpecifics& specifics) {
48  DCHECK(!internal_.get());
49  scoped_ptr<Value> value(
50      base::JSONReader::Read(specifics.value()));
51  if (!value.get()) {
52    LOG(WARNING) << "Specifics for " << specifics.extension_id() << "/" <<
53        specifics.key() << " had bad JSON for value: " << specifics.value();
54    value.reset(new base::DictionaryValue());
55  }
56  internal_ = new Internal(
57      change_type,
58      specifics.extension_id(),
59      specifics.key(),
60      value.Pass());
61}
62
63SettingSyncData::SettingSyncData(
64    syncer::SyncChange::SyncChangeType change_type,
65    const std::string& extension_id,
66    const std::string& key,
67    scoped_ptr<Value> value)
68    : internal_(new Internal(change_type, extension_id, key, value.Pass())) {}
69
70SettingSyncData::~SettingSyncData() {}
71
72syncer::SyncChange::SyncChangeType SettingSyncData::change_type() const {
73  return internal_->change_type_;
74}
75
76const std::string& SettingSyncData::extension_id() const {
77  return internal_->extension_id_;
78}
79
80const std::string& SettingSyncData::key() const {
81  return internal_->key_;
82}
83
84const Value& SettingSyncData::value() const {
85  return *internal_->value_;
86}
87
88SettingSyncData::Internal::Internal(
89    syncer::SyncChange::SyncChangeType change_type,
90    const std::string& extension_id,
91    const std::string& key,
92    scoped_ptr<Value> value)
93    : change_type_(change_type),
94      extension_id_(extension_id),
95      key_(key),
96      value_(value.Pass()) {
97  DCHECK(value_.get());
98}
99
100SettingSyncData::Internal::~Internal() {}
101
102}  // namespace extensions
103