Extension syncing: Introduce a NeedsSync pref
[chromium-blink-merge.git] / components / copresence / copresence_state_impl.cc
blob9a873d32e828df8e832ec4e9c1205b6da84af754
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.
5 #include <set>
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 {
16 namespace {
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);
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;
49 } // namespace
52 // Public functions.
54 CopresenceStateImpl::CopresenceStateImpl() {}
56 CopresenceStateImpl::~CopresenceStateImpl() {}
58 void CopresenceStateImpl::AddObserver(CopresenceObserver* observer) {
59 DCHECK(observer);
60 observers_.AddObserver(observer);
63 void CopresenceStateImpl::RemoveObserver(CopresenceObserver* observer) {
64 DCHECK(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,
94 observers_,
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,
107 observers_,
108 TokenTransmitted(transmitted_tokens_[token.id]));
109 } else {
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,
120 observers_,
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,
134 observers_,
135 TokenReceived(received_tokens_[token_id]));
136 } else {
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,
162 observers_,
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,
174 observers_,
175 TokenTransmitted(transmitted_tokens_[token]));
179 } // namespace copresence