OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include <set> | |
6 | |
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" | |
13 | |
14 namespace copresence { | |
15 | |
16 namespace { | |
17 | |
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; | |
24 } else { | |
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); | |
29 } | |
30 } | |
31 | |
32 void UpdateToken(const TransmittedToken& new_token, | |
33 TransmittedToken* current_token) { | |
34 HandleCommonFields(new_token, current_token); | |
35 | |
36 current_token->stop_time = new_token.stop_time; | |
37 current_token->broadcast_confirmed = new_token.broadcast_confirmed; | |
38 } | |
39 | |
40 void UpdateToken(const ReceivedToken& new_token, | |
41 ReceivedToken* current_token) { | |
42 HandleCommonFields(new_token, current_token); | |
43 | |
44 current_token->last_time = new_token.last_time; | |
45 if (new_token.valid != ReceivedToken::UNKNOWN) | |
46 current_token->valid = new_token.valid; | |
47 } | |
48 | |
49 } // namespace | |
50 | |
51 | |
52 // Public functions. | |
53 | |
54 CopresenceStateImpl::CopresenceStateImpl() {} | |
55 | |
56 CopresenceStateImpl::~CopresenceStateImpl() {} | |
57 | |
58 void CopresenceStateImpl::AddObserver(CopresenceObserver* observer) { | |
59 DCHECK(observer); | |
60 observers_.AddObserver(observer); | |
61 } | |
62 | |
63 void CopresenceStateImpl::RemoveObserver(CopresenceObserver* observer) { | |
64 DCHECK(observer); | |
65 observers_.RemoveObserver(observer); | |
66 } | |
67 | |
68 const std::vector<Directive>& CopresenceStateImpl::active_directives() const { | |
69 return active_directives_; | |
70 } | |
71 | |
72 const std::map<std::string, TransmittedToken>& | |
73 CopresenceStateImpl::transmitted_tokens() const { | |
74 return transmitted_tokens_; | |
75 } | |
76 | |
77 const std::map<std::string, ReceivedToken>& | |
78 CopresenceStateImpl::received_tokens() const { | |
79 return received_tokens_; | |
80 } | |
81 | |
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()); | |
88 } | |
89 | |
90 void CopresenceStateImpl::UpdateTransmittedToken( | |
91 const TransmittedToken& token) { | |
92 UpdateToken(token, &transmitted_tokens_[token.id]); | |
93 FOR_EACH_OBSERVER(CopresenceObserver, | |
94 observers_, | |
95 TokenTransmitted(transmitted_tokens_[token.id])); | |
96 } | |
97 | |
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()); | |
101 | |
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, | |
107 observers_, | |
108 TokenTransmitted(transmitted_tokens_[token.id])); | |
109 } else { | |
110 ReceivedToken& stored_token = received_tokens_[token.id]; | |
111 UpdateToken(token, &stored_token); | |
112 | |
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; | |
118 | |
119 FOR_EACH_OBSERVER(CopresenceObserver, | |
120 observers_, | |
121 TokenReceived(stored_token)); | |
122 } | |
123 } | |
124 | |
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, | |
134 observers_, | |
135 TokenReceived(received_tokens_[token_id])); | |
136 } else { | |
137 LOG(ERROR) << "Got status update for unrecognized token " << token_id; | |
138 } | |
139 } | |
140 | |
141 | |
142 // Private functions. | |
143 | |
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); | |
148 | |
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()); | |
153 | |
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()); | |
160 | |
161 FOR_EACH_OBSERVER(CopresenceObserver, | |
162 observers_, | |
163 TokenTransmitted(token)); | |
164 } | |
165 } | |
166 | |
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; | |
172 | |
173 FOR_EACH_OBSERVER(CopresenceObserver, | |
174 observers_, | |
175 TokenTransmitted(transmitted_tokens_[token])); | |
176 } | |
177 } | |
178 | |
179 } // namespace copresence | |
OLD | NEW |