| Index: chrome/browser/ui/webui/copresence_ui_handler.cc
|
| diff --git a/chrome/browser/ui/webui/copresence_ui_handler.cc b/chrome/browser/ui/webui/copresence_ui_handler.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..47aa043c903ae4e7c3a55a16bf1512a11d3d0e91
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/webui/copresence_ui_handler.cc
|
| @@ -0,0 +1,188 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/ui/webui/copresence_ui_handler.h"
|
| +
|
| +#include <map>
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/i18n/time_formatting.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "base/time/time.h"
|
| +#include "base/values.h"
|
| +#include "chrome/browser/extensions/api/copresence/copresence_api.h"
|
| +#include "components/copresence/proto/chrome_only.pb.h"
|
| +#include "components/copresence/proto/data.pb.h"
|
| +#include "components/copresence/public/copresence_manager.h"
|
| +#include "components/copresence/public/copresence_state.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "content/public/browser/web_ui.h"
|
| +
|
| +using base::ListValue;
|
| +using base::DictionaryValue;
|
| +using content::WebUI;
|
| +using copresence::Directive;
|
| +using copresence::ReceivedToken;
|
| +using copresence::SentToken;
|
| +using extensions::CopresenceService;
|
| +
|
| +// TODO(ckehoe): s/Sent/Transmitted/g
|
| +
|
| +namespace {
|
| +
|
| +const int kMillisecondsPerMinute = 60 * 1000;
|
| +const int kMillisecondsPerHour = 60 * kMillisecondsPerMinute;
|
| +
|
| +std::string FormatInstructionType(
|
| + copresence::TokenInstructionType directive_type) {
|
| + if (directive_type == copresence::TRANSMIT) {
|
| + return "Transmit";
|
| + } else {
|
| + DCHECK(directive_type == copresence::RECEIVE);
|
| + return "Receive";
|
| + }
|
| +}
|
| +
|
| +std::string FormatMedium(copresence::TokenMedium medium) {
|
| + if (medium == copresence::AUDIO_ULTRASOUND_PASSBAND) {
|
| + return "Ultrasound";
|
| + } else {
|
| + DCHECK(medium == copresence::AUDIO_AUDIBLE_DTMF);
|
| + return "Audible";
|
| + }
|
| +}
|
| +
|
| +std::string FormatDuration(int64 milliseconds) {
|
| + DCHECK_GE(milliseconds, 0);
|
| + if (milliseconds < 1000) {
|
| + return base::StringPrintf("%ld milliseconds", milliseconds);
|
| + } else if (milliseconds < kMillisecondsPerMinute) {
|
| + int seconds = milliseconds / 1000;
|
| + return seconds == 1 ? "1 second" :
|
| + base::StringPrintf("%d seconds", seconds);
|
| + } else if (milliseconds < kMillisecondsPerHour) {
|
| + int minutes = milliseconds / kMillisecondsPerMinute;
|
| + return minutes == 1 ? "1 minute" :
|
| + base::StringPrintf("%d minutes", minutes);
|
| + } else {
|
| + int hours = milliseconds / kMillisecondsPerHour;
|
| + return hours == 1 ? "1 hour" :
|
| + base::StringPrintf("%d hours", hours);
|
| + }
|
| +}
|
| +
|
| +base::Time ParseTimestamp(int64 milliseconds) {
|
| + return base::Time::UnixEpoch() +
|
| + base::TimeDelta::FromMilliseconds(milliseconds);
|
| +}
|
| +
|
| +base::string16 FormatTime(int64 milliseconds) {
|
| + return base::TimeFormatTimeOfDay(ParseTimestamp(milliseconds));
|
| +}
|
| +
|
| +std::string ConvertStatus(const SentToken& token) {
|
| + DCHECK(token.has_stop_time_millis());
|
| + bool done =
|
| + ParseTimestamp(token.stop_time_millis()) < base::Time::Now();
|
| + std::string status = done ? "done" : "active";
|
| + if (token.broadcast_confirmed())
|
| + status += " confirmed";
|
| + return status;
|
| +}
|
| +
|
| +std::string ConvertStatus(const ReceivedToken& token) {
|
| + if (token.has_valid())
|
| + return token.valid() ? "valid" : "invalid";
|
| + else
|
| + return std::string();
|
| +}
|
| +
|
| +template<class T>
|
| +scoped_ptr<DictionaryValue> FormatToken(const T& token) {
|
| + scoped_ptr<DictionaryValue> js_token(new DictionaryValue);
|
| +
|
| + js_token->SetString("id", token.id());
|
| + js_token->SetString("statuses", ConvertStatus(token));
|
| + js_token->SetString("medium", FormatMedium(token.medium()));
|
| + js_token->SetString("time", FormatTime(token.start_time_millis()));
|
| +
|
| + return js_token.Pass();
|
| +}
|
| +
|
| +// Safely retrieve the CopresenceState, if any.
|
| +copresence::CopresenceState* GetCopresenceState(
|
| + WebUI* web_ui) {
|
| + DCHECK(web_ui && web_ui->GetWebContents());
|
| + CopresenceService* service = CopresenceService::GetFactoryInstance()->Get(
|
| + web_ui->GetWebContents()->GetBrowserContext());
|
| + return service && service->manager() ? service->manager()->state() : nullptr;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +
|
| +// Public functions.
|
| +
|
| +CopresenceUIHandler::CopresenceUIHandler(WebUI* web_ui)
|
| + : state_(GetCopresenceState(web_ui)) {
|
| + DCHECK(state_);
|
| + state_->AddObserver(this);
|
| +}
|
| +
|
| +CopresenceUIHandler::~CopresenceUIHandler() {
|
| + // Check if the CopresenceService is still up before unregistering.
|
| + state_ = GetCopresenceState(web_ui());
|
| + if (state_)
|
| + state_->RemoveObserver(this);
|
| +}
|
| +
|
| +
|
| +// Private functions.
|
| +
|
| +void CopresenceUIHandler::RegisterMessages() {
|
| + web_ui()->RegisterMessageCallback(
|
| + "populateCopresenceState",
|
| + base::Bind(&CopresenceUIHandler::HandlePopulateState,
|
| + base::Unretained(this)));
|
| +}
|
| +
|
| +void CopresenceUIHandler::DirectivesUpdated() {
|
| + ListValue js_directives;
|
| + for (const Directive& directive : state_->active_directives()) {
|
| + DictionaryValue* js_directive = new DictionaryValue;
|
| +
|
| + js_directive->SetString("type", FormatInstructionType(
|
| + directive.token_instruction().token_instruction_type()));
|
| + js_directive->SetString("medium", FormatMedium(
|
| + directive.token_instruction().medium()));
|
| + js_directive->SetString("duration", FormatDuration(directive.ttl_millis()));
|
| +
|
| + js_directives.Append(js_directive);
|
| + }
|
| +
|
| + web_ui()->CallJavascriptFunction("refreshDirectives", js_directives);
|
| +}
|
| +
|
| +void CopresenceUIHandler::TokenSent(const copresence::SentToken& token) {
|
| + web_ui()->CallJavascriptFunction("updateSentToken",
|
| + *FormatToken(token));
|
| +}
|
| +
|
| +void CopresenceUIHandler::TokenReceived(
|
| + const copresence::ReceivedToken& token) {
|
| + web_ui()->CallJavascriptFunction("updateReceivedToken",
|
| + *FormatToken(token));
|
| +}
|
| +
|
| +void CopresenceUIHandler::HandlePopulateState(const ListValue* args) {
|
| + DCHECK(args->empty()) << "populateCopresenceState() doesn't take arguments";
|
| + DirectivesUpdated();
|
| + // TODO(ckehoe): Pass tokens to JS as a batch.
|
| + for (const auto& token_entry : state_->sent_tokens())
|
| + TokenSent(token_entry.second);
|
| + for (const auto& token_entry : state_->received_tokens())
|
| + TokenReceived(token_entry.second);
|
| +}
|
|
|