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

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 // TODO(ckehoe): s/Sent/Transmitted/g\
Dan Beam 2014/12/09 05:33:38 nit: did you mean to end this with .?
Charlie 2014/12/17 23:39:55 Just went ahead and did the TODO.
33 // TODO(ckehoe): Make debug strings translatable?
34
35 namespace {
36
37 const int kMillisecondsPerMinute = 60 * 1000;
38 const int kMillisecondsPerHour = 60 * kMillisecondsPerMinute;
39
40 std::string FormatInstructionType(
41 copresence::TokenInstructionType directive_type) {
42 if (directive_type == copresence::TRANSMIT) {
Dan Beam 2014/12/09 05:33:38 should this be a switch so you get notified when n
Charlie 2014/12/17 23:39:56 That isn't supposed to happen. But sure.
43 return "Transmit";
44 } else {
Dan Beam 2014/12/09 05:33:38 no else after return (everywhere in this file)
Charlie 2014/12/17 23:39:55 Done.
45 DCHECK(directive_type == copresence::RECEIVE);
Dan Beam 2014/12/09 05:33:38 nit: DCHECK_EQ(copresence::RECEIVE, directive_type
Charlie 2014/12/17 23:39:55 Deleted.
46 return "Receive";
47 }
48 }
49
50 std::string FormatMedium(copresence::TokenMedium medium) {
51 if (medium == copresence::AUDIO_ULTRASOUND_PASSBAND) {
52 return "Ultrasound";
53 } else {
54 DCHECK(medium == copresence::AUDIO_AUDIBLE_DTMF);
Dan Beam 2014/12/09 05:33:38 same nits
Charlie 2014/12/17 23:39:56 Fixed.
55 return "Audible";
56 }
57 }
58
59 std::string FormatDuration(int64 milliseconds) {
60 DCHECK_GE(milliseconds, 0);
61 if (milliseconds < 1000) {
62 return base::StringPrintf("%ld milliseconds", milliseconds);
Dan Beam 2014/12/09 05:33:38 can you use this instead? https://code.google.com/
Charlie 2014/12/17 23:39:55 Yes, much better. Thanks!
63 } else if (milliseconds < kMillisecondsPerMinute) {
64 int seconds = milliseconds / 1000;
65 return seconds == 1 ? "1 second" :
66 base::StringPrintf("%d seconds", seconds);
67 } else if (milliseconds < kMillisecondsPerHour) {
68 int minutes = milliseconds / kMillisecondsPerMinute;
69 return minutes == 1 ? "1 minute" :
70 base::StringPrintf("%d minutes", minutes);
71 } else {
72 int hours = milliseconds / kMillisecondsPerHour;
73 return hours == 1 ? "1 hour" :
74 base::StringPrintf("%d hours", hours);
75 }
76 }
77
78 base::Time ParseTimestamp(int64 milliseconds) {
79 return base::Time::UnixEpoch() +
80 base::TimeDelta::FromMilliseconds(milliseconds);
81 }
82
83 base::string16 FormatTime(int64 milliseconds) {
84 return base::TimeFormatTimeOfDay(ParseTimestamp(milliseconds));
85 }
86
87 std::string ConvertStatus(const SentToken& token) {
88 DCHECK(token.has_stop_time_millis());
89 bool done =
90 ParseTimestamp(token.stop_time_millis()) < base::Time::Now();
91 std::string status = done ? "done" : "active";
92 if (token.broadcast_confirmed())
93 status += " confirmed";
94 return status;
95 }
96
97 std::string ConvertStatus(const ReceivedToken& token) {
98 if (token.has_valid())
99 return token.valid() ? "valid" : "invalid";
100 else
101 return std::string();
102 }
103
104 template<class T>
105 scoped_ptr<DictionaryValue> FormatToken(const T& token) {
106 scoped_ptr<DictionaryValue> js_token(new DictionaryValue);
107
108 js_token->SetString("id", token.id());
109 js_token->SetString("statuses", ConvertStatus(token));
110 js_token->SetString("medium", FormatMedium(token.medium()));
111 js_token->SetString("time", FormatTime(token.start_time_millis()));
112
113 return js_token.Pass();
114 }
115
116 // Safely retrieve the CopresenceState, if any.
117 copresence::CopresenceState* GetCopresenceState(
118 WebUI* web_ui) {
119 DCHECK(web_ui && web_ui->GetWebContents());
Dan Beam 2014/12/09 05:33:38 this gives less information than: DCHECK(web_ui
Charlie 2014/12/17 23:39:56 Done with a clarifying comment.
120 CopresenceService* service = CopresenceService::GetFactoryInstance()->Get(
121 web_ui->GetWebContents()->GetBrowserContext());
122 return service && service->manager() ? service->manager()->state() : nullptr;
123 }
124
125 } // namespace
126
127
Dan Beam 2014/12/09 05:33:38 \n\n -> \n
Charlie 2014/12/17 23:39:55 I separate file sections, like the public and priv
128 // Public functions.
129
130 CopresenceUIHandler::CopresenceUIHandler(WebUI* web_ui)
131 : state_(GetCopresenceState(web_ui)) {
132 DCHECK(state_);
133 state_->AddObserver(this);
134 }
135
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);
141 }
142
143
Dan Beam 2014/12/09 05:33:38 \n\n -> \n
Charlie 2014/12/17 23:39:55 Acknowledged.
144 // Private functions.
145
146 void CopresenceUIHandler::RegisterMessages() {
147 web_ui()->RegisterMessageCallback(
148 "populateCopresenceState",
149 base::Bind(&CopresenceUIHandler::HandlePopulateState,
150 base::Unretained(this)));
151 }
152
153 void CopresenceUIHandler::DirectivesUpdated() {
154 ListValue js_directives;
155 for (const Directive& directive : state_->active_directives()) {
156 DictionaryValue* js_directive = new DictionaryValue;
Dan Beam 2014/12/09 05:33:38 nit: scoped_ptr<> + release()
Charlie 2014/12/17 23:39:55 Done.
157
158 js_directive->SetString("type", FormatInstructionType(
159 directive.token_instruction().token_instruction_type()));
160 js_directive->SetString("medium", FormatMedium(
161 directive.token_instruction().medium()));
162 js_directive->SetString("duration", FormatDuration(directive.ttl_millis()));
163
164 js_directives.Append(js_directive);
165 }
166
167 web_ui()->CallJavascriptFunction("refreshDirectives", js_directives);
168 }
169
170 void CopresenceUIHandler::TokenSent(const copresence::SentToken& token) {
171 web_ui()->CallJavascriptFunction("updateSentToken",
172 *FormatToken(token));
173 }
174
175 void CopresenceUIHandler::TokenReceived(
176 const copresence::ReceivedToken& token) {
177 web_ui()->CallJavascriptFunction("updateReceivedToken",
178 *FormatToken(token));
179 }
180
181 void CopresenceUIHandler::HandlePopulateState(const ListValue* args) {
182 DCHECK(args->empty()) << "populateCopresenceState() doesn't take arguments";
Dan Beam 2014/12/09 05:33:38 remove message
Charlie 2014/12/17 23:39:56 Done.
183 DirectivesUpdated();
184 // TODO(ckehoe): Pass tokens to JS as a batch.
185 for (const auto& token_entry : state_->sent_tokens())
186 TokenSent(token_entry.second);
187 for (const auto& token_entry : state_->received_tokens())
188 TokenReceived(token_entry.second);
189 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698