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.
5 #include "sync/engine/traffic_recorder.h"
7 #include "base/json/json_writer.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/values.h"
11 #include "sync/protocol/proto_value_conversions.h"
12 #include "sync/protocol/sync.pb.h"
13 #include "sync/sessions/sync_session.h"
17 TrafficRecorder::TrafficRecord::TrafficRecord(const std::string
& message
,
18 TrafficMessageType message_type
,
21 message_type(message_type
),
22 truncated(truncated
) {
25 TrafficRecorder::TrafficRecord::TrafficRecord()
26 : message_type(UNKNOWN_MESSAGE_TYPE
),
30 TrafficRecorder::TrafficRecord::~TrafficRecord() {
33 TrafficRecorder::TrafficRecorder(unsigned int max_messages
,
34 unsigned int max_message_size
)
35 : max_messages_(max_messages
),
36 max_message_size_(max_message_size
) {
39 TrafficRecorder::~TrafficRecorder() {
43 const char* GetMessageTypeString(TrafficRecorder::TrafficMessageType type
) {
45 case TrafficRecorder::CLIENT_TO_SERVER_MESSAGE
:
47 case TrafficRecorder::CLIENT_TO_SERVER_RESPONSE
:
56 DictionaryValue
* TrafficRecorder::TrafficRecord::ToValue() const {
57 scoped_ptr
<DictionaryValue
> value
;
59 value
.reset(new DictionaryValue());
60 value
->SetString("message_type",
61 GetMessageTypeString(message_type
));
62 value
->SetBoolean("truncated", true);
63 } else if (message_type
== TrafficRecorder::CLIENT_TO_SERVER_MESSAGE
) {
64 sync_pb::ClientToServerMessage message_proto
;
65 if (message_proto
.ParseFromString(message
))
67 ClientToServerMessageToValue(message_proto
,
68 false /* include_specifics */));
69 } else if (message_type
== TrafficRecorder::CLIENT_TO_SERVER_RESPONSE
) {
70 sync_pb::ClientToServerResponse message_proto
;
71 if (message_proto
.ParseFromString(message
))
73 ClientToServerResponseToValue(message_proto
,
74 false /* include_specifics */));
79 return value
.release();
83 ListValue
* TrafficRecorder::ToValue() const {
84 scoped_ptr
<ListValue
> value(new ListValue());
85 std::deque
<TrafficRecord
>::const_iterator it
;
86 for (it
= records_
.begin(); it
!= records_
.end(); ++it
) {
87 const TrafficRecord
& record
= *it
;
88 value
->Append(record
.ToValue());
91 return value
.release();
95 void TrafficRecorder::AddTrafficToQueue(TrafficRecord
* record
) {
96 records_
.resize(records_
.size() + 1);
97 std::swap(records_
.back(), *record
);
99 // We might have more records than our limit.
100 // Maintain the size invariant by deleting items.
101 while (records_
.size() > max_messages_
) {
102 records_
.pop_front();
106 void TrafficRecorder::StoreProtoInQueue(
107 const ::google::protobuf::MessageLite
& msg
,
108 TrafficMessageType type
) {
109 bool truncated
= false;
111 if (static_cast<unsigned int>(msg
.ByteSize()) >= max_message_size_
) {
112 // TODO(lipalani): Trim the specifics to fit in size.
115 msg
.SerializeToString(&message
);
118 TrafficRecord
record(message
, type
, truncated
);
119 AddTrafficToQueue(&record
);
122 void TrafficRecorder::RecordClientToServerMessage(
123 const sync_pb::ClientToServerMessage
& msg
) {
124 StoreProtoInQueue(msg
, CLIENT_TO_SERVER_MESSAGE
);
127 void TrafficRecorder::RecordClientToServerResponse(
128 const sync_pb::ClientToServerResponse
& response
) {
129 StoreProtoInQueue(response
, CLIENT_TO_SERVER_RESPONSE
);
132 } // namespace syncer