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

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: 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 namespace {
33
34 const int kMillisecondsPerMinute = 60 * 1000;
35 const int kMillisecondsPerHour = 60 * kMillisecondsPerMinute;
36
37 std::string FormatInstructionType(
38 copresence::TokenInstructionType directive_type) {
39 if (directive_type == copresence::TRANSMIT) {
40 return "Broadcast";
rkc 2014/12/05 19:46:36 Any reason we aren't just sticking with "Transmit/
Charlie 2014/12/05 21:26:08 Broadcast and scan is the latest terminology used
41 } else {
42 DCHECK(directive_type == copresence::RECEIVE);
43 return "Scan";
44 }
45 }
46
47 std::string FormatMedium(copresence::TokenMedium medium) {
48 if (medium == copresence::AUDIO_ULTRASOUND_PASSBAND) {
49 return "Ultrasound";
50 } else {
51 DCHECK(medium == copresence::AUDIO_AUDIBLE_DTMF);
52 return "Audible";
53 }
54 }
55
56 std::string FormatDuration(int64 milliseconds) {
57 DCHECK_GE(milliseconds, 0);
58 if (milliseconds < 1000) {
59 return base::StringPrintf("%ld milliseconds", milliseconds);
60 } else if (milliseconds < kMillisecondsPerMinute) {
61 int seconds = milliseconds / 1000;
62 return seconds == 1 ? "1 second" :
63 base::StringPrintf("%d seconds", seconds);
64 } else if (milliseconds < kMillisecondsPerHour) {
65 int minutes = milliseconds / kMillisecondsPerMinute;
66 return minutes == 1 ? "1 minute" :
67 base::StringPrintf("%d minutes", minutes);
68 } else {
69 int hours = milliseconds / kMillisecondsPerHour;
70 return hours == 1 ? "1 hour" :
71 base::StringPrintf("%d hours", hours);
72 }
73 }
74
75 base::Time ParseTimestamp(int64 milliseconds) {
76 return base::Time::UnixEpoch() +
77 base::TimeDelta::FromMilliseconds(milliseconds);
78 }
79
80 base::string16 FormatTime(int64 milliseconds) {
81 return base::TimeFormatTimeOfDay(ParseTimestamp(milliseconds));
82 }
83
84 std::string FormatStatus(const SentToken& token) {
85 DCHECK(token.has_stop_time_millis());
86 bool playing = ParseTimestamp(token.stop_time_millis()) < base::Time::Now();
87 std::string status = playing ? "Played" : "Playing";
88 if (token.broadcast_confirmed())
89 status += " (Confirmed)";
90 return status;
91 }
92
93 std::string FormatStatus(const ReceivedToken& token) {
94 if (token.has_valid())
95 return token.valid() ? "Valid" : "Invalid";
96 else
97 return "Unknown";
98 }
99
100 template<class T>
101 scoped_ptr<DictionaryValue> FormatToken(const T& token) {
102 scoped_ptr<DictionaryValue> js_token(new DictionaryValue);
103
104 js_token->SetString("id", token.id());
105 js_token->SetString("status", FormatStatus(token));
106 js_token->SetString("medium", FormatMedium(token.medium()));
107 js_token->SetString("time", FormatTime(token.start_time_millis()));
108
109 return js_token.Pass();
110 }
111
112 // Safely retrieve the CopresenceState, if any.
113 copresence::CopresenceState* GetCopresenceState(
114 WebUI* web_ui) {
115 DCHECK(web_ui && web_ui->GetWebContents());
116 CopresenceService* service = CopresenceService::GetFactoryInstance()->Get(
117 web_ui->GetWebContents()->GetBrowserContext());
118 return service && service->manager() ? service->manager()->state() : nullptr;
119 }
120
121 } // namespace
122
123
124 // Public functions.
125
126 CopresenceUIHandler::CopresenceUIHandler(WebUI* web_ui)
127 : state_(GetCopresenceState(web_ui)) {
128 DCHECK(state_);
129 state_->AddObserver(this);
130 }
131
132 CopresenceUIHandler::~CopresenceUIHandler() {
133 // Check if the CopresenceService is still up before unregistering.
134 state_ = GetCopresenceState(web_ui());
135 if (state_)
136 state_->RemoveObserver(this);
137 }
138
139
140 // Private functions.
141
142 void CopresenceUIHandler::RegisterMessages() {
143 web_ui()->RegisterMessageCallback(
144 "populateCopresenceState",
145 base::Bind(&CopresenceUIHandler::PopulateState,
146 base::Unretained(this)));
147 }
148
149 void CopresenceUIHandler::UpdateDirectives(
150 const std::vector<Directive>& active_directives) {
rkc 2014/12/05 19:46:36 Why does this parameter exist? You always call thi
Charlie 2014/12/05 21:26:08 Seemed more natural, but it's true that it's redun
151 ListValue js_directives;
152 for (const Directive& directive : active_directives) {
153 DictionaryValue* js_directive = new DictionaryValue;
154
155 js_directive->SetString("type", FormatInstructionType(
156 directive.token_instruction().token_instruction_type()));
157 js_directive->SetString("medium", FormatMedium(
158 directive.token_instruction().medium()));
159 js_directive->SetString("duration", FormatDuration(directive.ttl_millis()));
160
161 js_directives.Append(js_directive);
162 }
163
164 web_ui()->CallJavascriptFunction("refreshDirectives", js_directives);
165 }
166
167 void CopresenceUIHandler::TokenSent(const copresence::SentToken& token) {
168 web_ui()->CallJavascriptFunction("updateSentToken",
169 *FormatToken(token));
170 }
171
172 void CopresenceUIHandler::TokenReceived(
173 const copresence::ReceivedToken& token) {
174 web_ui()->CallJavascriptFunction("updateReceivedToken",
175 *FormatToken(token));
176 }
177
178 void CopresenceUIHandler::PopulateState(const ListValue* args) {
179 DCHECK(args->empty()) << "populateCopresenceState() doesn't take arguments";
180 UpdateDirectives(state_->active_directives());
181 for (const auto& token_entry : state_->sent_tokens())
182 TokenSent(token_entry.second);
rkc 2014/12/05 19:46:36 nit: Making calls to JS is expensive. Populate an
Charlie 2014/12/05 23:02:37 Added a TODO. To make a difference, this requires
183 for (const auto& token_entry : state_->received_tokens())
184 TokenReceived(token_entry.second);
185 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698