summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/sync/glue/synced_device_tracker.cc55
-rw-r--r--chrome/browser/sync/glue/synced_device_tracker.h10
-rw-r--r--chrome/browser/sync/glue/synced_device_tracker_unittest.cc47
-rw-r--r--chrome/browser/sync/profile_sync_service.cc58
-rw-r--r--chrome/browser/sync/profile_sync_service.h12
-rw-r--r--chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc31
-rw-r--r--sync/internal_api/DEPS1
-rw-r--r--sync/internal_api/public/util/sync_db_util.h30
-rw-r--r--sync/internal_api/sync_db_util.cc38
-rw-r--r--sync/protocol/DEPS1
-rw-r--r--sync/protocol/device_info_specifics.proto4
-rw-r--r--sync/protocol/proto_value_conversions.cc10
-rw-r--r--sync/sync_internal_api.gypi2
13 files changed, 267 insertions, 32 deletions
diff --git a/chrome/browser/sync/glue/synced_device_tracker.cc b/chrome/browser/sync/glue/synced_device_tracker.cc
index bf7fa92..e77463e 100644
--- a/chrome/browser/sync/glue/synced_device_tracker.cc
+++ b/chrome/browser/sync/glue/synced_device_tracker.cc
@@ -13,6 +13,7 @@
#include "sync/internal_api/public/user_share.h"
#include "sync/internal_api/public/write_node.h"
#include "sync/internal_api/public/write_transaction.h"
+#include "sync/util/time.h"
namespace browser_sync {
@@ -157,25 +158,28 @@ void SyncedDeviceTracker::InitLocalDeviceInfoContinuation(
}
void SyncedDeviceTracker::WriteLocalDeviceInfo(const DeviceInfo& info) {
- sync_pb::DeviceInfoSpecifics specifics;
DCHECK_EQ(cache_guid_, info.guid());
- specifics.set_cache_guid(cache_guid_);
- specifics.set_client_name(info.client_name());
- specifics.set_chrome_version(info.chrome_version());
- specifics.set_sync_user_agent(info.sync_user_agent());
- specifics.set_device_type(info.device_type());
-
- WriteDeviceInfo(specifics, local_device_info_tag_);
+ WriteDeviceInfo(info, local_device_info_tag_);
}
-void SyncedDeviceTracker::WriteDeviceInfo(
- const sync_pb::DeviceInfoSpecifics& specifics,
- const std::string& tag) {
+void SyncedDeviceTracker::WriteDeviceInfo(const DeviceInfo& info,
+ const std::string& tag) {
syncer::WriteTransaction trans(FROM_HERE, user_share_);
syncer::WriteNode node(&trans);
+ sync_pb::DeviceInfoSpecifics specifics;
+ specifics.set_cache_guid(info.guid());
+ specifics.set_client_name(info.client_name());
+ specifics.set_chrome_version(info.chrome_version());
+ specifics.set_sync_user_agent(info.sync_user_agent());
+ specifics.set_device_type(info.device_type());
+
if (node.InitByClientTagLookup(syncer::DEVICE_INFO, tag) ==
syncer::BaseNode::INIT_OK) {
+ const sync_pb::DeviceInfoSpecifics& sync_specifics =
+ node.GetDeviceInfoSpecifics();
+ if (sync_specifics.has_backup_timestamp())
+ specifics.set_backup_timestamp(sync_specifics.backup_timestamp());
node.SetDeviceInfoSpecifics(specifics);
node.SetTitle(specifics.client_name());
} else {
@@ -195,4 +199,33 @@ void SyncedDeviceTracker::WriteDeviceInfo(
}
}
+void SyncedDeviceTracker::UpdateLocalDeviceBackupTime(base::Time backup_time) {
+ syncer::WriteTransaction trans(FROM_HERE, user_share_);
+ syncer::WriteNode node(&trans);
+
+ if (node.InitByClientTagLookup(syncer::DEVICE_INFO, local_device_info_tag_)
+ == syncer::BaseNode::INIT_OK) {
+ sync_pb::DeviceInfoSpecifics specifics = node.GetDeviceInfoSpecifics();
+ int64 new_backup_timestamp = syncer::TimeToProtoTime(backup_time);
+ if (!specifics.has_backup_timestamp() ||
+ specifics.backup_timestamp() != new_backup_timestamp) {
+ specifics.set_backup_timestamp(new_backup_timestamp);
+ node.SetDeviceInfoSpecifics(specifics);
+ }
+ }
+}
+
+base::Time SyncedDeviceTracker::GetLocalDeviceBackupTime() const {
+ syncer::ReadTransaction trans(FROM_HERE, user_share_);
+ syncer::ReadNode node(&trans);
+ if (node.InitByClientTagLookup(syncer::DEVICE_INFO, local_device_info_tag_)
+ == syncer::BaseNode::INIT_OK &&
+ node.GetDeviceInfoSpecifics().has_backup_timestamp()) {
+ return syncer::ProtoTimeToTime(
+ node.GetDeviceInfoSpecifics().backup_timestamp());
+ } else {
+ return base::Time();
+ }
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/synced_device_tracker.h b/chrome/browser/sync/glue/synced_device_tracker.h
index 3f0844a..1bc2d66 100644
--- a/chrome/browser/sync/glue/synced_device_tracker.h
+++ b/chrome/browser/sync/glue/synced_device_tracker.h
@@ -61,6 +61,13 @@ class SyncedDeviceTracker : public ChangeProcessor {
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
+ // Update |backup_timestamp| in local device info specifics to |backup_time|
+ // if different.
+ void UpdateLocalDeviceBackupTime(base::Time backup_time);
+
+ // Return time derived from |backup_timestamp| in local device info specifics.
+ base::Time GetLocalDeviceBackupTime() const;
+
private:
friend class SyncedDeviceTrackerTest;
@@ -72,8 +79,7 @@ class SyncedDeviceTracker : public ChangeProcessor {
// Helper to write arbitrary device info. Useful for writing local device
// info and also used by test cases to write arbitrary device infos.
- void WriteDeviceInfo(const sync_pb::DeviceInfoSpecifics& specifics,
- const std::string& tag);
+ void WriteDeviceInfo(const DeviceInfo& info, const std::string& tag);
syncer::UserShare* user_share_;
const std::string cache_guid_;
diff --git a/chrome/browser/sync/glue/synced_device_tracker_unittest.cc b/chrome/browser/sync/glue/synced_device_tracker_unittest.cc
index 4596b5a1..267d047 100644
--- a/chrome/browser/sync/glue/synced_device_tracker_unittest.cc
+++ b/chrome/browser/sync/glue/synced_device_tracker_unittest.cc
@@ -20,20 +20,6 @@
namespace browser_sync {
-namespace {
-
-void ConvertDeviceInfoSpecifics(
- const DeviceInfo& device_info,
- sync_pb::DeviceInfoSpecifics* specifics) {
- specifics->set_cache_guid(device_info.guid());
- specifics->set_client_name(device_info.client_name());
- specifics->set_chrome_version(device_info.chrome_version());
- specifics->set_sync_user_agent(device_info.sync_user_agent());
- specifics->set_device_type(device_info.device_type());
-}
-
-} // namespace
-
class SyncedDeviceTrackerTest : public ::testing::Test {
protected:
SyncedDeviceTrackerTest() : transaction_count_baseline_(0) { }
@@ -69,9 +55,7 @@ class SyncedDeviceTrackerTest : public ::testing::Test {
}
void WriteDeviceInfo(const DeviceInfo& device_info) {
- sync_pb::DeviceInfoSpecifics specifics;
- ConvertDeviceInfoSpecifics(device_info, &specifics);
- synced_device_tracker_->WriteDeviceInfo(specifics, device_info.guid());
+ synced_device_tracker_->WriteDeviceInfo(device_info, device_info.guid());
}
void ResetObservedChangesCounter() {
@@ -208,6 +192,35 @@ TEST_F(SyncedDeviceTrackerTest, GetAllDeviceInfo) {
EXPECT_TRUE(device_info[1]->Equals(device_info2));
}
+TEST_F(SyncedDeviceTrackerTest, DeviceBackupTime) {
+ DeviceInfo device_info(
+ user_share()->directory->cache_guid(),
+ "John’s Device", "XYZ v1", "XYZ SyncAgent v1",
+ sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
+ const base::Time test_backup_time =
+ base::Time::UnixEpoch() + base::TimeDelta::FromDays(10000);
+
+ WriteLocalDeviceInfo(device_info);
+ synced_device_tracker_->UpdateLocalDeviceBackupTime(test_backup_time);
+
+ // Verify read of device info and backup time.
+ EXPECT_EQ(test_backup_time,
+ synced_device_tracker_->GetLocalDeviceBackupTime());
+ scoped_ptr<DeviceInfo> device_info_out(
+ synced_device_tracker_->ReadLocalDeviceInfo());
+ ASSERT_TRUE(device_info_out);
+ EXPECT_TRUE(device_info.Equals(*device_info_out.get()));
+
+ // Verify backup time is not lost after updating device info.
+ DeviceInfo device_info2(
+ user_share()->directory->cache_guid(),
+ "def Device", "XYZ v2", "XYZ SyncAgent v2",
+ sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
+ WriteLocalDeviceInfo(device_info2);
+ EXPECT_EQ(test_backup_time,
+ synced_device_tracker_->GetLocalDeviceBackupTime());
+}
+
} // namespace
} // namespace browser_sync
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index cd24db0e..9102c4a 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -76,6 +76,7 @@
#include "components/sync_driver/pref_names.h"
#include "components/sync_driver/system_encryptor.h"
#include "components/sync_driver/user_selectable_sync_type.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
@@ -90,6 +91,7 @@
#include "sync/internal_api/public/sync_context_proxy.h"
#include "sync/internal_api/public/sync_encryption_handler.h"
#include "sync/internal_api/public/util/experiments.h"
+#include "sync/internal_api/public/util/sync_db_util.h"
#include "sync/internal_api/public/util/sync_string_conversions.h"
#include "sync/js/js_event_details.h"
#include "sync/util/cryptographer.h"
@@ -658,6 +660,8 @@ void ProfileSyncService::StartUpSlowBackendComponents(
if (backend_mode_ == ROLLBACK)
ClearBrowsingDataSinceFirstSync();
+ else if (backend_mode_ == SYNC)
+ CheckSyncBackupIfNeeded();
base::FilePath sync_folder = backend_mode_ == SYNC ?
base::FilePath(kSyncDataFolderName) :
@@ -1022,6 +1026,13 @@ void ProfileSyncService::PostBackendInitialization() {
// Never get here for backup / restore.
DCHECK_EQ(backend_mode_, SYNC);
+ if (last_backup_time_) {
+ browser_sync::SyncedDeviceTracker* device_tracker =
+ backend_->GetSyncedDeviceTracker();
+ if (device_tracker)
+ device_tracker->UpdateLocalDeviceBackupTime(*last_backup_time_);
+ }
+
if (protocol_event_observers_.might_have_observers()) {
backend_->RequestBufferedProtocolEventsAndEnableForwarding();
}
@@ -2597,3 +2608,50 @@ void ProfileSyncService::StartStopBackupForTesting() {
else
backup_rollback_controller_.Start(base::TimeDelta());
}
+
+void ProfileSyncService::CheckSyncBackupIfNeeded() {
+ DCHECK_EQ(backend_mode_, SYNC);
+
+#if defined(ENABLE_PRE_SYNC_BACKUP)
+ // Check backup once a day.
+ if (!last_backup_time_ &&
+ (last_synced_time_.is_null() ||
+ base::Time::Now() - last_synced_time_ >=
+ base::TimeDelta::FromDays(1))) {
+ // If sync thread is set, need to serialize check on sync thread after
+ // closing backup DB.
+ if (sync_thread_) {
+ sync_thread_->message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(syncer::CheckSyncDbLastModifiedTime,
+ profile_->GetPath().Append(kSyncBackupDataFolderName),
+ base::MessageLoopProxy::current(),
+ base::Bind(&ProfileSyncService::CheckSyncBackupCallback,
+ weak_factory_.GetWeakPtr())));
+ } else {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::FILE, FROM_HERE,
+ base::Bind(syncer::CheckSyncDbLastModifiedTime,
+ profile_->GetPath().Append(kSyncBackupDataFolderName),
+ base::MessageLoopProxy::current(),
+ base::Bind(&ProfileSyncService::CheckSyncBackupCallback,
+ weak_factory_.GetWeakPtr())));
+ }
+ }
+#endif
+}
+
+void ProfileSyncService::CheckSyncBackupCallback(base::Time backup_time) {
+ last_backup_time_.reset(new base::Time(backup_time));
+
+ if (HasSyncingBackend() && backend_initialized_) {
+ browser_sync::SyncedDeviceTracker* device_tracker =
+ backend_->GetSyncedDeviceTracker();
+ if (device_tracker)
+ device_tracker->UpdateLocalDeviceBackupTime(*last_backup_time_);
+ }
+}
+
+base::Time ProfileSyncService::GetDeviceBackupTimeForTesting() const {
+ return backend_->GetSyncedDeviceTracker()->GetLocalDeviceBackupTime();
+}
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 5b695fb..ccb4606 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -782,6 +782,8 @@ class ProfileSyncService : public ProfileSyncServiceBase,
void StartStopBackupForTesting();
+ base::Time GetDeviceBackupTimeForTesting() const;
+
protected:
// Helper to configure the priority data types.
void ConfigurePriorityDataTypes();
@@ -957,6 +959,12 @@ class ProfileSyncService : public ProfileSyncServiceBase,
// Clear browsing data since first sync during rollback.
void ClearBrowsingDataSinceFirstSync();
+ // Post background task to check sync backup DB state if needed.
+ void CheckSyncBackupIfNeeded();
+
+ // Callback to receive backup DB check result.
+ void CheckSyncBackupCallback(base::Time backup_time);
+
// Factory used to create various dependent objects.
scoped_ptr<ProfileSyncComponentsFactory> factory_;
@@ -1124,6 +1132,10 @@ class ProfileSyncService : public ProfileSyncServiceBase,
base::Callback<void(Profile*, base::Time, base::Time)> clear_browsing_data_;
+ // Last time when pre-sync data was saved. NULL pointer means backup data
+ // state is unknown. If time value is null, backup data doesn't exist.
+ scoped_ptr<base::Time> last_backup_time_;
+
DISALLOW_COPY_AND_ASSIGN(ProfileSyncService);
};
diff --git a/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc b/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc
index 3321669..6de9eb2 100644
--- a/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc
@@ -5,6 +5,7 @@
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_service.h"
+#include "base/run_loop.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/test/integration/bookmarks_helper.h"
@@ -14,7 +15,9 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/bookmarks/browser/bookmark_model.h"
+#include "sync/internal_api/public/util/sync_db_util.h"
#include "sync/test/fake_server/fake_server_verifier.h"
+#include "sync/util/time.h"
using bookmarks_helper::AddFolder;
using bookmarks_helper::AddURL;
@@ -45,7 +48,26 @@ class SingleClientBackupRollbackTest : public SyncTest {
switches::kSyncEnableRollback);
}
+ base::Time GetBackupDbLastModified() {
+ base::RunLoop run_loop;
+
+ base::Time backup_time;
+ syncer::CheckSyncDbLastModifiedTime(
+ GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup")),
+ base::MessageLoopProxy::current(),
+ base::Bind(&SingleClientBackupRollbackTest::CheckDbCallback,
+ base::Unretained(this), &backup_time));
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ return backup_time;
+ }
+
private:
+ void CheckDbCallback(base::Time* time_out, base::Time time_in) {
+ *time_out = syncer::ProtoTimeToTime(syncer::TimeToProtoTime(time_in));
+ }
+
DISALLOW_COPY_AND_ASSIGN(SingleClientBackupRollbackTest);
};
@@ -188,16 +210,21 @@ IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
// Setup sync, wait for its completion, and make sure changes were synced.
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
- ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
+ ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Made bookmark changes while sync is on.
Move(0, tier1_a->GetChild(0), tier1_b, 1);
Remove(0, tier1_b, 0);
ASSERT_TRUE(AddFolder(0, tier1_b, 1, "tier2_c"));
- ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
+ ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
ASSERT_TRUE(ModelMatchesVerifier(0));
+ // Verify backup time is set on device info.
+ base::Time backup_time = GetBackupDbLastModified();
+ ASSERT_FALSE(backup_time.is_null());
+ ASSERT_EQ(backup_time, GetSyncService(0)->GetDeviceBackupTimeForTesting());
+
// Let server to return rollback command on next sync request.
GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
diff --git a/sync/internal_api/DEPS b/sync/internal_api/DEPS
index 13e6b8a..42ab18e 100644
--- a/sync/internal_api/DEPS
+++ b/sync/internal_api/DEPS
@@ -4,6 +4,7 @@ include_rules = [
"+net/http",
"+net/test",
"+net/url_request",
+ "+sql",
"+sync/base",
"+sync/engine",
"+sync/js",
diff --git a/sync/internal_api/public/util/sync_db_util.h b/sync/internal_api/public/util/sync_db_util.h
new file mode 100644
index 0000000..3784a10
--- /dev/null
+++ b/sync/internal_api/public/util/sync_db_util.h
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_INTERNAL_API_PUBLIC_UTIL_SYNC_DB_UTIL_H_
+#define SYNC_INTERNAL_API_PUBLIC_UTIL_SYNC_DB_UTIL_H_
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
+#include "sync/base/sync_export.h"
+
+namespace base {
+class FilePath;
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace syncer {
+
+// Check integrity of sync DB under |sync_dir|. Invoke |callback| with last
+// modified time if integrity check passes, with NULL time otherwise. This
+// is called on either sync thread or IO thread.
+SYNC_EXPORT void CheckSyncDbLastModifiedTime(
+ const base::FilePath& sync_dir,
+ scoped_refptr<base::SingleThreadTaskRunner> callback_runner,
+ base::Callback<void(base::Time)> callback);
+
+} // namesapce syncer
+
+#endif // SYNC_INTERNAL_API_PUBLIC_UTIL_SYNC_DB_UTIL_H_
diff --git a/sync/internal_api/sync_db_util.cc b/sync/internal_api/sync_db_util.cc
new file mode 100644
index 0000000..c12889d
--- /dev/null
+++ b/sync/internal_api/sync_db_util.cc
@@ -0,0 +1,38 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/internal_api/public/util/sync_db_util.h"
+
+#include "base/files/file_path.h"
+#include "base/single_thread_task_runner.h"
+#include "sql/connection.h"
+#include "sync/syncable/directory.h"
+
+namespace syncer {
+
+void CheckSyncDbLastModifiedTime(
+ const base::FilePath& sync_dir,
+ scoped_refptr<base::SingleThreadTaskRunner> callback_runner,
+ base::Callback<void(base::Time)> callback) {
+ const base::FilePath sync_db =
+ sync_dir.Append(syncable::Directory::kSyncDatabaseFilename);
+
+ base::File f(sync_db, base::File::FLAG_OPEN | base::File::FLAG_READ);
+ base::File::Info info;
+ if (!f.IsValid() || !f.GetInfo(&info)) {
+ callback_runner->PostTask(FROM_HERE, base::Bind(callback, base::Time()));
+ return;
+ }
+ f.Close();
+
+ sql::Connection db;
+ if (!db.Open(sync_db) || !db.QuickIntegrityCheck()) {
+ callback_runner->PostTask(FROM_HERE, base::Bind(callback, base::Time()));
+ } else {
+ callback_runner->PostTask(FROM_HERE,
+ base::Bind(callback, info.last_modified));
+ }
+}
+
+} // namespace syncer
diff --git a/sync/protocol/DEPS b/sync/protocol/DEPS
index f8f9de5..d623db8 100644
--- a/sync/protocol/DEPS
+++ b/sync/protocol/DEPS
@@ -1,4 +1,5 @@
include_rules = [
"+sync/base",
"+sync/internal_api/public/base",
+ "+sync/util",
]
diff --git a/sync/protocol/device_info_specifics.proto b/sync/protocol/device_info_specifics.proto
index 67eb469..f87b361 100644
--- a/sync/protocol/device_info_specifics.proto
+++ b/sync/protocol/device_info_specifics.proto
@@ -34,4 +34,8 @@ message DeviceInfoSpecifics {
// The Chrome instance's version. Updated (if necessary) on every startup.
optional string chrome_version = 5;
+
+ // Last time when pre-sync data on the device was saved. The device can be
+ // restored to state back to this time. In millisecond since UNIX epoch.
+ optional int64 backup_timestamp = 6;
}
diff --git a/sync/protocol/proto_value_conversions.cc b/sync/protocol/proto_value_conversions.cc
index 8e58af4..2716210 100644
--- a/sync/protocol/proto_value_conversions.cc
+++ b/sync/protocol/proto_value_conversions.cc
@@ -10,8 +10,10 @@
#include "base/base64.h"
#include "base/basictypes.h"
+#include "base/i18n/time_formatting.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
#include "base/values.h"
#include "sync/internal_api/public/base/unique_position.h"
#include "sync/protocol/app_list_specifics.pb.h"
@@ -41,6 +43,7 @@
#include "sync/protocol/theme_specifics.pb.h"
#include "sync/protocol/typed_url_specifics.pb.h"
#include "sync/protocol/unique_position.pb.h"
+#include "sync/util/time.h"
namespace syncer {
@@ -82,6 +85,11 @@ base::ListValue* MakeRepeatedValue(const F& fields, V* (*converter_fn)(T)) {
return list;
}
+base::StringValue* MakeTimestampValue(int64 tm) {
+ return new base::StringValue(
+ base::TimeFormatShortDateAndTime(syncer::ProtoTimeToTime(tm)));
+}
+
} // namespace
// Helper macros to reduce the amount of boilerplate.
@@ -102,6 +110,7 @@ base::ListValue* MakeRepeatedValue(const F& fields, V* (*converter_fn)(T)) {
#define SET_INT64(field) SET(field, MakeInt64Value)
#define SET_INT64_REP(field) SET_REP(field, MakeInt64Value)
#define SET_STR(field) SET(field, new base::StringValue)
+#define SET_TIME_STR(field) SET(field, MakeTimestampValue)
#define SET_STR_REP(field) \
value->Set(#field, \
MakeRepeatedValue<const std::string&, \
@@ -489,6 +498,7 @@ base::DictionaryValue* DeviceInfoSpecificsToValue(
SET_ENUM(device_type, GetDeviceTypeString);
SET_STR(sync_user_agent);
SET_STR(chrome_version);
+ SET_TIME_STR(backup_timestamp);
return value;
}
diff --git a/sync/sync_internal_api.gypi b/sync/sync_internal_api.gypi
index 1ff913f..7d92f68 100644
--- a/sync/sync_internal_api.gypi
+++ b/sync/sync_internal_api.gypi
@@ -135,6 +135,7 @@
'internal_api/public/util/report_unrecoverable_error_function.h',
'internal_api/public/util/sync_string_conversions.cc',
'internal_api/public/util/sync_string_conversions.h',
+ 'internal_api/public/util/sync_db_util.h',
'internal_api/public/util/syncer_error.cc',
'internal_api/public/util/syncer_error.h',
'internal_api/public/util/unrecoverable_error_handler.h',
@@ -152,6 +153,7 @@
'internal_api/sync_context_proxy.cc',
'internal_api/sync_context_proxy_impl.cc',
'internal_api/sync_context_proxy_impl.h',
+ 'internal_api/sync_db_util.cc',
'internal_api/sync_encryption_handler_impl.cc',
'internal_api/sync_encryption_handler_impl.h',
'internal_api/sync_manager_factory.cc',