Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(647)

Side by Side Diff: chrome/browser/ui/webui/copresence_ui_handler.cc

Issue 734243003: Adding the chrome://copresence page (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@state
Patch Set: Fixing BUILD.gn Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "chrome/browser/ui/webui/copresence_ui_handler.h"
6
7 #include <map>
8 #include <string>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/i18n/time_formatting.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/time/time.h"
15 #include "base/values.h"
16 #include "chrome/browser/extensions/api/copresence/copresence_api.h"
17 #include "components/copresence/proto/chrome_only.pb.h"
18 #include "components/copresence/proto/data.pb.h"
19 #include "components/copresence/public/copresence_manager.h"
20 #include "components/copresence/public/copresence_state.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/browser/web_ui.h"
23
24 using base::ListValue;
25 using base::DictionaryValue;
26 using content::WebUI;
27 using copresence::Directive;
28 using copresence::ReceivedToken;
29 using copresence::SentToken;
30 using extensions::CopresenceService;
31
32 // TODO(ckehoe): s/Sent/Transmitted/g
33
34 namespace {
35
36 const int kMillisecondsPerMinute = 60 * 1000;
37 const int kMillisecondsPerHour = 60 * kMillisecondsPerMinute;
38
39 std::string FormatInstructionType(
40 copresence::TokenInstructionType directive_type) {
41 if (directive_type == copresence::TRANSMIT) {
42 return "Transmit";
43 } else {
44 DCHECK(directive_type == copresence::RECEIVE);
45 return "Receive";
46 }
47 }
48
49 std::string FormatMedium(copresence::TokenMedium medium) {
50 if (medium == copresence::AUDIO_ULTRASOUND_PASSBAND) {
51 return "Ultrasound";
52 } else {
53 DCHECK(medium == copresence::AUDIO_AUDIBLE_DTMF);
54 return "Audible";
55 }
56 }
57
58 std::string FormatDuration(int64 milliseconds) {
59 DCHECK_GE(milliseconds, 0);
60 if (milliseconds < 1000) {
61 return base::StringPrintf("%ld milliseconds", milliseconds);
62 } else if (milliseconds < kMillisecondsPerMinute) {
63 int seconds = milliseconds / 1000;
64 return seconds == 1 ? "1 second" :
65 base::StringPrintf("%d seconds", seconds);
66 } else if (milliseconds < kMillisecondsPerHour) {
67 int minutes = milliseconds / kMillisecondsPerMinute;
68 return minutes == 1 ? "1 minute" :
69 base::StringPrintf("%d minutes", minutes);
70 } else {
71 int hours = milliseconds / kMillisecondsPerHour;
72 return hours == 1 ? "1 hour" :
73 base::StringPrintf("%d hours", hours);
74 }
75 }
76
77 base::Time ParseTimestamp(int64 milliseconds) {
78 return base::Time::UnixEpoch() +
79 base::TimeDelta::FromMilliseconds(milliseconds);
80 }
81
82 base::string16 FormatTime(int64 milliseconds) {
83 return base::TimeFormatTimeOfDay(ParseTimestamp(milliseconds));
84 }
85
86 std::string ConvertStatus(const SentToken& token) {
87 DCHECK(token.has_stop_time_millis());
88 bool done =
89 ParseTimestamp(token.stop_time_millis()) < base::Time::Now();
90 std::string status = done ? "done" : "active";
91 if (token.broadcast_confirmed())
92 status += " confirmed";
93 return status;
94 }
95
96 std::string ConvertStatus(const ReceivedToken& token) {
97 if (token.has_valid())
98 return token.valid() ? "valid" : "invalid";
99 else
100 return std::string();
101 }
102
103 template<class T>
104 scoped_ptr<DictionaryValue> FormatToken(const T& token) {
105 scoped_ptr<DictionaryValue> js_token(new DictionaryValue);
106
107 js_token->SetString("id", token.id());
108 js_token->SetString("statuses", ConvertStatus(token));
109 js_token->SetString("medium", FormatMedium(token.medium()));
110 js_token->SetString("time", FormatTime(token.start_time_millis()));
111
112 return js_token.Pass();
113 }
114
115 // Safely retrieve the CopresenceState, if any.
116 copresence::CopresenceState* GetCopresenceState(
117 WebUI* web_ui) {
118 DCHECK(web_ui && web_ui->GetWebContents());
119 CopresenceService* service = CopresenceService::GetFactoryInstance()->Get(
120 web_ui->GetWebContents()->GetBrowserContext());
121 return service && service->manager() ? service->manager()->state() : nullptr;
122 }
123
124 } // namespace
125
126
127 // Public functions.
128
129 CopresenceUIHandler::CopresenceUIHandler(WebUI* web_ui)
130 : state_(GetCopresenceState(web_ui)) {
131 DCHECK(state_);
132 state_->AddObserver(this);
133 }
134
135 CopresenceUIHandler::~CopresenceUIHandler() {
136 // Check if the CopresenceService is still up before unregistering.
137 state_ = GetCopresenceState(web_ui());
138 if (state_)
139 state_->RemoveObserver(this);
140 }
141
142
143 // Private functions.
144
145 void CopresenceUIHandler::RegisterMessages() {
146 web_ui()->RegisterMessageCallback(
147 "populateCopresenceState",
148 base::Bind(&CopresenceUIHandler::HandlePopulateState,
149 base::Unretained(this)));
150 }
151
152 void CopresenceUIHandler::DirectivesUpdated() {
153 ListValue js_directives;
154 for (const Directive& directive : state_->active_directives()) {
155 DictionaryValue* js_directive = new DictionaryValue;
156
157 js_directive->SetString("type", FormatInstructionType(
158 directive.token_instruction().token_instruction_type()));
159 js_directive->SetString("medium", FormatMedium(
160 directive.token_instruction().medium()));
161 js_directive->SetString("duration", FormatDuration(directive.ttl_millis()));
162
163 js_directives.Append(js_directive);
164 }
165
166 web_ui()->CallJavascriptFunction("refreshDirectives", js_directives);
167 }
168
169 void CopresenceUIHandler::TokenSent(const copresence::SentToken& token) {
170 web_ui()->CallJavascriptFunction("updateSentToken",
171 *FormatToken(token));
172 }
173
174 void CopresenceUIHandler::TokenReceived(
175 const copresence::ReceivedToken& token) {
176 web_ui()->CallJavascriptFunction("updateReceivedToken",
177 *FormatToken(token));
178 }
179
180 void CopresenceUIHandler::HandlePopulateState(const ListValue* args) {
181 DCHECK(args->empty()) << "populateCopresenceState() doesn't take arguments";
182 DirectivesUpdated();
183 // TODO(ckehoe): Pass tokens to JS as a batch.
184 for (const auto& token_entry : state_->sent_tokens())
185 TokenSent(token_entry.second);
186 for (const auto& token_entry : state_->received_tokens())
187 TokenReceived(token_entry.second);
188 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698