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.
7 #include "base/logging.h"
8 #include "base/time/time.h"
9 #include "components/copresence/copresence_state_impl.h"
10 #include "components/copresence/proto/data.pb.h"
11 #include "components/copresence/public/copresence_constants.h"
12 #include "components/copresence/public/copresence_observer.h"
14 namespace copresence
{
18 template<typename TokenType
>
19 void HandleCommonFields(const TokenType
& new_token
, TokenType
* current_token
) {
20 if (current_token
->id
.empty()) {
21 current_token
->id
= new_token
.id
;
22 current_token
->medium
= new_token
.medium
;
23 current_token
->start_time
= new_token
.start_time
;
25 DCHECK_EQ(new_token
.id
, current_token
->id
);
26 DCHECK_EQ(new_token
.medium
, current_token
->medium
);
27 DCHECK(new_token
.start_time
.is_null() ||
28 new_token
.start_time
== current_token
->start_time
);
32 void UpdateToken(const TransmittedToken
& new_token
,
33 TransmittedToken
* current_token
) {
34 HandleCommonFields(new_token
, current_token
);
36 current_token
->stop_time
= new_token
.stop_time
;
37 current_token
->broadcast_confirmed
= new_token
.broadcast_confirmed
;
40 void UpdateToken(const ReceivedToken
& new_token
,
41 ReceivedToken
* current_token
) {
42 HandleCommonFields(new_token
, current_token
);
44 current_token
->last_time
= new_token
.last_time
;
45 if (new_token
.valid
!= ReceivedToken::UNKNOWN
)
46 current_token
->valid
= new_token
.valid
;
54 CopresenceStateImpl::CopresenceStateImpl() {}
56 CopresenceStateImpl::~CopresenceStateImpl() {}
58 void CopresenceStateImpl::AddObserver(CopresenceObserver
* observer
) {
60 observers_
.AddObserver(observer
);
63 void CopresenceStateImpl::RemoveObserver(CopresenceObserver
* observer
) {
65 observers_
.RemoveObserver(observer
);
68 const std::vector
<Directive
>& CopresenceStateImpl::active_directives() const {
69 return active_directives_
;
72 const std::map
<std::string
, TransmittedToken
>&
73 CopresenceStateImpl::transmitted_tokens() const {
74 return transmitted_tokens_
;
77 const std::map
<std::string
, ReceivedToken
>&
78 CopresenceStateImpl::received_tokens() const {
79 return received_tokens_
;
82 // TODO(ckehoe): Only send updates if the directives have really changed.
83 void CopresenceStateImpl::UpdateDirectives(
84 const std::vector
<Directive
>& directives
) {
85 active_directives_
= directives
;
86 UpdateTransmittingTokens();
87 FOR_EACH_OBSERVER(CopresenceObserver
, observers_
, DirectivesUpdated());
90 void CopresenceStateImpl::UpdateTransmittedToken(
91 const TransmittedToken
& token
) {
92 UpdateToken(token
, &transmitted_tokens_
[token
.id
]);
93 FOR_EACH_OBSERVER(CopresenceObserver
,
95 TokenTransmitted(transmitted_tokens_
[token
.id
]));
98 // TODO(ckehoe): Check which tokens are no longer heard and report them lost.
99 void CopresenceStateImpl::UpdateReceivedToken(const ReceivedToken
& token
) {
100 DCHECK(!token
.id
.empty());
102 // TODO(ckehoe): Have CopresenceManagerImpl::AudioCheck() use this to check
103 // if we can hear our token, and delete the logic from the AudioManager.
104 if (transmitted_tokens_
.count(token
.id
) > 0) {
105 transmitted_tokens_
[token
.id
].broadcast_confirmed
= true;
106 FOR_EACH_OBSERVER(CopresenceObserver
,
108 TokenTransmitted(transmitted_tokens_
[token
.id
]));
110 ReceivedToken
& stored_token
= received_tokens_
[token
.id
];
111 UpdateToken(token
, &stored_token
);
113 // The decoder doesn't track when this token was heard before,
114 // so it should just fill in the last_time.
115 // If we've never seen this token, we populate the start time too.
116 if (stored_token
.start_time
.is_null())
117 stored_token
.start_time
= token
.last_time
;
119 FOR_EACH_OBSERVER(CopresenceObserver
,
121 TokenReceived(stored_token
));
125 void CopresenceStateImpl::UpdateTokenStatus(const std::string
& token_id
,
126 TokenStatus status
) {
127 if (transmitted_tokens_
.count(token_id
) > 0) {
128 LOG_IF(ERROR
, status
!= VALID
)
129 << "Broadcast token " << token_id
<< " is invalid";
130 } else if (received_tokens_
.count(token_id
) > 0) {
131 received_tokens_
[token_id
].valid
= status
== VALID
?
132 ReceivedToken::VALID
: ReceivedToken::INVALID
;
133 FOR_EACH_OBSERVER(CopresenceObserver
,
135 TokenReceived(received_tokens_
[token_id
]));
137 LOG(ERROR
) << "Got status update for unrecognized token " << token_id
;
142 // Private functions.
144 void CopresenceStateImpl::UpdateTransmittingTokens() {
145 std::set
<std::string
> tokens_to_update
;
146 for (const auto& token_entry
: transmitted_tokens_
)
147 tokens_to_update
.insert(token_entry
.first
);
149 for (const Directive
& directive
: active_directives_
) {
150 const TokenInstruction
& instruction
= directive
.token_instruction();
151 if (instruction
.token_instruction_type() == TRANSMIT
) {
152 tokens_to_update
.erase(instruction
.token_id());
154 TransmittedToken
& token
= transmitted_tokens_
[instruction
.token_id()];
155 token
.id
= instruction
.token_id();
156 token
.medium
= instruction
.medium();
157 token
.start_time
= base::Time::Now();
158 token
.stop_time
= base::Time::Now() +
159 base::TimeDelta::FromMilliseconds(directive
.ttl_millis());
161 FOR_EACH_OBSERVER(CopresenceObserver
,
163 TokenTransmitted(token
));
167 // Tokens not updated above are no longer transmitting.
168 base::Time now
= base::Time::Now();
169 for (const std::string
& token
: tokens_to_update
) {
170 if (transmitted_tokens_
[token
].stop_time
> now
)
171 transmitted_tokens_
[token
].stop_time
= now
;
173 FOR_EACH_OBSERVER(CopresenceObserver
,
175 TokenTransmitted(transmitted_tokens_
[token
]));
179 } // namespace copresence