| OLD | NEW | 
| (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/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" | 
 |   23  | 
 |   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; | 
 |   31  | 
 |   32 // TODO(ckehoe): Make debug strings translatable? | 
 |   33  | 
 |   34 namespace { | 
 |   35  | 
 |   36 std::string FormatInstructionType( | 
 |   37     copresence::TokenInstructionType directive_type) { | 
 |   38   switch (directive_type) { | 
 |   39     case copresence::TRANSMIT: | 
 |   40       return "Transmit"; | 
 |   41  | 
 |   42     case copresence::RECEIVE: | 
 |   43       return "Receive"; | 
 |   44  | 
 |   45     default: | 
 |   46       NOTREACHED(); | 
 |   47       return "Unknown"; | 
 |   48   } | 
 |   49 } | 
 |   50  | 
 |   51 std::string FormatMedium(copresence::TokenMedium medium) { | 
 |   52   switch (medium) { | 
 |   53     case copresence::AUDIO_ULTRASOUND_PASSBAND: | 
 |   54       return "Ultrasound"; | 
 |   55  | 
 |   56     case copresence::AUDIO_AUDIBLE_DTMF: | 
 |   57       return "Audible"; | 
 |   58  | 
 |   59     default: | 
 |   60       NOTREACHED(); | 
 |   61       return "Unknown"; | 
 |   62   } | 
 |   63 } | 
 |   64  | 
 |   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; | 
 |   71 } | 
 |   72  | 
 |   73 std::string ConvertStatus(const ReceivedToken& token) { | 
 |   74   switch (token.valid) { | 
 |   75     case ReceivedToken::VALID: | 
 |   76       return "valid"; | 
 |   77  | 
 |   78     case ReceivedToken::INVALID: | 
 |   79       return "invalid"; | 
 |   80  | 
 |   81     case ReceivedToken::UNKNOWN: | 
 |   82       return std::string(); | 
 |   83  | 
 |   84     default: | 
 |   85       NOTREACHED(); | 
 |   86       return std::string(); | 
 |   87   } | 
 |   88 } | 
 |   89  | 
 |   90 template<class T> | 
 |   91 scoped_ptr<DictionaryValue> FormatToken(const T& token) { | 
 |   92   scoped_ptr<DictionaryValue> js_token(new DictionaryValue); | 
 |   93  | 
 |   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)); | 
 |  100  | 
 |  101   return js_token.Pass(); | 
 |  102 } | 
 |  103  | 
 |  104 // Safely retrieve the CopresenceState, if any. | 
 |  105 copresence::CopresenceState* GetCopresenceState(WebUI* web_ui) { | 
 |  106   // This function must be called with a valid web_ui. | 
 |  107   DCHECK(web_ui); | 
 |  108   DCHECK(web_ui->GetWebContents()); | 
 |  109  | 
 |  110   // During shutdown, however, there may be no CopresenceService. | 
 |  111   CopresenceService* service = CopresenceService::GetFactoryInstance()->Get( | 
 |  112       web_ui->GetWebContents()->GetBrowserContext()); | 
 |  113   return service && service->manager() ? service->manager()->state() : nullptr; | 
 |  114 } | 
 |  115  | 
 |  116 }  // namespace | 
 |  117  | 
 |  118  | 
 |  119 // Public functions. | 
 |  120  | 
 |  121 CopresenceUIHandler::CopresenceUIHandler(WebUI* web_ui) | 
 |  122     : state_(GetCopresenceState(web_ui)) { | 
 |  123   DCHECK(state_); | 
 |  124   state_->AddObserver(this); | 
 |  125 } | 
 |  126  | 
 |  127 CopresenceUIHandler::~CopresenceUIHandler() { | 
 |  128   // Check if the CopresenceService is still up before unregistering. | 
 |  129   state_ = GetCopresenceState(web_ui()); | 
 |  130   if (state_) | 
 |  131     state_->RemoveObserver(this); | 
 |  132 } | 
 |  133  | 
 |  134  | 
 |  135 // Private functions. | 
 |  136  | 
 |  137 void CopresenceUIHandler::RegisterMessages() { | 
 |  138   web_ui()->RegisterMessageCallback( | 
 |  139       "populateCopresenceState", | 
 |  140       base::Bind(&CopresenceUIHandler::HandlePopulateState, | 
 |  141                  base::Unretained(this))); | 
 |  142 } | 
 |  143  | 
 |  144 void CopresenceUIHandler::DirectivesUpdated() { | 
 |  145   ListValue js_directives; | 
 |  146   for (const Directive& directive : state_->active_directives()) { | 
 |  147     scoped_ptr<DictionaryValue> js_directive(new DictionaryValue); | 
 |  148  | 
 |  149     js_directive->SetString("type", FormatInstructionType( | 
 |  150         directive.token_instruction().token_instruction_type())); | 
 |  151     js_directive->SetString("medium", FormatMedium( | 
 |  152         directive.token_instruction().medium())); | 
 |  153     js_directive->SetString("duration", ui::TimeFormat::Simple( | 
 |  154         ui::TimeFormat::FORMAT_DURATION, | 
 |  155         ui::TimeFormat::LENGTH_LONG, | 
 |  156         base::TimeDelta::FromMilliseconds(directive.ttl_millis()))); | 
 |  157  | 
 |  158     js_directives.Append(js_directive.release()); | 
 |  159   } | 
 |  160  | 
 |  161   web_ui()->CallJavascriptFunction("refreshDirectives", js_directives); | 
 |  162 } | 
 |  163  | 
 |  164 void CopresenceUIHandler::TokenTransmitted(const TransmittedToken& token) { | 
 |  165   web_ui()->CallJavascriptFunction("updateTransmittedToken", | 
 |  166                                    *FormatToken(token)); | 
 |  167 } | 
 |  168  | 
 |  169 void CopresenceUIHandler::TokenReceived(const ReceivedToken& token) { | 
 |  170   web_ui()->CallJavascriptFunction("updateReceivedToken", | 
 |  171                                    *FormatToken(token)); | 
 |  172 } | 
 |  173  | 
 |  174 void CopresenceUIHandler::HandlePopulateState(const ListValue* args) { | 
 |  175   DCHECK(args->empty()); | 
 |  176   DirectivesUpdated(); | 
 |  177   // TODO(ckehoe): Pass tokens to JS as a batch. | 
 |  178   for (const auto& token_entry : state_->transmitted_tokens()) | 
 |  179     TokenTransmitted(token_entry.second); | 
 |  180   for (const auto& token_entry : state_->received_tokens()) | 
 |  181     TokenReceived(token_entry.second); | 
 |  182 } | 
| OLD | NEW |