[Extensions Toolbar Mac] Fix actions bar min size, spacing
[chromium-blink-merge.git] / chrome / browser / ui / webui / copresence_ui_handler.cc
blob72da86bbae3a90461db32c7027025c1b8ebd6049
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 "chrome/browser/ui/webui/copresence_ui_handler.h"
7 #include <map>
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/i18n/time_formatting.h"
13 #include "base/time/time.h"
14 #include "base/values.h"
15 #include "chrome/browser/extensions/api/copresence/copresence_api.h"
16 #include "components/copresence/proto/data.pb.h"
17 #include "components/copresence/public/copresence_manager.h"
18 #include "components/copresence/public/copresence_state.h"
19 #include "components/copresence/tokens.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/browser/web_ui.h"
22 #include "ui/base/l10n/time_format.h"
24 using base::ListValue;
25 using base::DictionaryValue;
26 using content::WebUI;
27 using copresence::Directive;
28 using copresence::ReceivedToken;
29 using copresence::TransmittedToken;
30 using extensions::CopresenceService;
32 // TODO(ckehoe): Make debug strings translatable?
34 namespace {
36 std::string FormatInstructionType(
37 copresence::TokenInstructionType directive_type) {
38 switch (directive_type) {
39 case copresence::TRANSMIT:
40 return "Transmit";
42 case copresence::RECEIVE:
43 return "Receive";
45 default:
46 NOTREACHED();
47 return "Unknown";
51 std::string FormatMedium(copresence::TokenMedium medium) {
52 switch (medium) {
53 case copresence::AUDIO_ULTRASOUND_PASSBAND:
54 return "Ultrasound";
56 case copresence::AUDIO_AUDIBLE_DTMF:
57 return "Audible";
59 default:
60 NOTREACHED();
61 return "Unknown";
65 std::string ConvertStatus(const TransmittedToken& token) {
66 bool done = token.stop_time < base::Time::Now();
67 std::string status = done ? "done" : "active";
68 if (token.broadcast_confirmed)
69 status += " confirmed";
70 return status;
73 std::string ConvertStatus(const ReceivedToken& token) {
74 switch (token.valid) {
75 case ReceivedToken::VALID:
76 return "valid";
78 case ReceivedToken::INVALID:
79 return "invalid";
81 case ReceivedToken::UNKNOWN:
82 return std::string();
84 default:
85 NOTREACHED();
86 return std::string();
90 template<class T>
91 scoped_ptr<DictionaryValue> FormatToken(const T& token) {
92 scoped_ptr<DictionaryValue> js_token(new DictionaryValue);
94 js_token->SetString("id", token.id);
95 js_token->SetString("statuses", ConvertStatus(token));
96 js_token->SetString("medium", FormatMedium(token.medium));
97 DCHECK(!token.start_time.is_null());
98 js_token->SetString("time",
99 base::TimeFormatTimeOfDay(token.start_time));
101 return js_token.Pass();
104 // Retrieve the CopresenceService, if any.
105 CopresenceService* GetCopresenceService(WebUI* web_ui) {
106 DCHECK(web_ui);
107 return CopresenceService::GetFactoryInstance()->Get(
108 web_ui->GetWebContents()->GetBrowserContext());
111 // Safely retrieve the CopresenceState, if any.
112 copresence::CopresenceState* GetCopresenceState(CopresenceService* service) {
113 // During shutdown, there may be no CopresenceService.
114 return service && service->manager() ? service->manager()->state() : nullptr;
117 // Safely retrieve the CopresenceState, if any. It would be cleaner if we could
118 // put this into CopresenceUIHandler and call WebUIMessageHandler::web_ui()
119 // instead of taking an argument. However, it turns out that web_ui() returns
120 // null when called in the constructor. So we pass in the web_ui explicitly.
121 copresence::CopresenceState* GetCopresenceState(WebUI* web_ui) {
122 return GetCopresenceState(GetCopresenceService(web_ui));
125 } // namespace
128 // Public functions.
130 CopresenceUIHandler::CopresenceUIHandler(WebUI* web_ui)
131 : state_(GetCopresenceState(web_ui)) {
132 DCHECK(state_);
133 state_->AddObserver(this);
136 CopresenceUIHandler::~CopresenceUIHandler() {
137 // Check if the CopresenceService is still up before unregistering.
138 state_ = GetCopresenceState(web_ui());
139 if (state_)
140 state_->RemoveObserver(this);
144 // Private functions.
146 void CopresenceUIHandler::RegisterMessages() {
147 web_ui()->RegisterMessageCallback(
148 "populateCopresenceState",
149 base::Bind(&CopresenceUIHandler::HandlePopulateState,
150 base::Unretained(this)));
151 web_ui()->RegisterMessageCallback(
152 "clearCopresenceState",
153 base::Bind(&CopresenceUIHandler::HandleClearState,
154 base::Unretained(this)));
157 void CopresenceUIHandler::DirectivesUpdated() {
158 ListValue js_directives;
159 for (const Directive& directive : state_->active_directives()) {
160 scoped_ptr<DictionaryValue> js_directive(new DictionaryValue);
162 js_directive->SetString("type", FormatInstructionType(
163 directive.token_instruction().token_instruction_type()));
164 js_directive->SetString("medium", FormatMedium(
165 directive.token_instruction().medium()));
166 js_directive->SetString("duration", ui::TimeFormat::Simple(
167 ui::TimeFormat::FORMAT_DURATION,
168 ui::TimeFormat::LENGTH_LONG,
169 base::TimeDelta::FromMilliseconds(directive.ttl_millis())));
171 js_directives.Append(js_directive.release());
174 web_ui()->CallJavascriptFunction("refreshDirectives", js_directives);
177 void CopresenceUIHandler::TokenTransmitted(const TransmittedToken& token) {
178 web_ui()->CallJavascriptFunction("updateTransmittedToken",
179 *FormatToken(token));
182 void CopresenceUIHandler::TokenReceived(const ReceivedToken& token) {
183 web_ui()->CallJavascriptFunction("updateReceivedToken",
184 *FormatToken(token));
187 void CopresenceUIHandler::HandlePopulateState(const ListValue* args) {
188 DCHECK(args->empty());
189 DirectivesUpdated();
190 // TODO(ckehoe): Pass tokens to JS as a batch.
191 for (const auto& token_entry : state_->transmitted_tokens())
192 TokenTransmitted(token_entry.second);
193 for (const auto& token_entry : state_->received_tokens())
194 TokenReceived(token_entry.second);
197 void CopresenceUIHandler::HandleClearState(const ListValue* args) {
198 DCHECK(args->empty());
200 CopresenceService* service = GetCopresenceService(web_ui());
201 DCHECK(service);
202 service->ResetState();
204 // CopresenceService::ResetState() deletes the CopresenceState object
205 // we were using. We have to get the new one and reconnect to it.
206 state_ = GetCopresenceState(service);
207 DCHECK(state_);
208 state_->AddObserver(this);
210 web_ui()->CallJavascriptFunction("clearTokens");
211 DirectivesUpdated();