local_discovery_ui_handler.cc revision 3551c9c881056c480085172ff9840cab31610854
1// Copyright 2013 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/local_discovery/local_discovery_ui_handler.h" 6 7#include "base/bind.h" 8#include "base/strings/stringprintf.h" 9#include "base/values.h" 10#include "chrome/browser/local_discovery/privet_device_lister_impl.h" 11#include "chrome/browser/local_discovery/privet_http_impl.h" 12#include "chrome/browser/profiles/profile.h" 13#include "chrome/browser/signin/profile_oauth2_token_service.h" 14#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 15#include "chrome/browser/signin/signin_manager.h" 16#include "chrome/browser/signin/signin_manager_base.h" 17#include "chrome/browser/signin/signin_manager_factory.h" 18#include "content/public/browser/web_ui.h" 19#include "net/base/host_port_pair.h" 20#include "net/base/net_util.h" 21#include "net/http/http_status_code.h" 22 23namespace local_discovery { 24 25namespace { 26// TODO(noamsml): This is a temporary shim until automated_url is in the 27// response. 28const char kPrivetAutomatedClaimURLFormat[] = "%s/confirm?token=%s"; 29 30LocalDiscoveryUIHandler::Factory* g_factory = NULL; 31} // namespace 32 33LocalDiscoveryUIHandler::LocalDiscoveryUIHandler() { 34} 35 36LocalDiscoveryUIHandler::LocalDiscoveryUIHandler( 37 scoped_ptr<PrivetDeviceLister> privet_lister) { 38 privet_lister.swap(privet_lister_); 39} 40 41LocalDiscoveryUIHandler::~LocalDiscoveryUIHandler() { 42 if (service_discovery_client_.get()) { 43 service_discovery_client_ = NULL; 44 ServiceDiscoveryHostClientFactory::ReleaseClient(); 45 } 46} 47 48// static 49LocalDiscoveryUIHandler* LocalDiscoveryUIHandler::Create() { 50 if (g_factory) return g_factory->CreateLocalDiscoveryUIHandler(); 51 return new LocalDiscoveryUIHandler(); 52} 53 54// static 55void LocalDiscoveryUIHandler::SetFactory(Factory* factory) { 56 g_factory = factory; 57} 58 59void LocalDiscoveryUIHandler::RegisterMessages() { 60 web_ui()->RegisterMessageCallback("start", base::Bind( 61 &LocalDiscoveryUIHandler::HandleStart, 62 base::Unretained(this))); 63 web_ui()->RegisterMessageCallback("registerDevice", base::Bind( 64 &LocalDiscoveryUIHandler::HandleRegisterDevice, 65 base::Unretained(this))); 66 web_ui()->RegisterMessageCallback("info", base::Bind( 67 &LocalDiscoveryUIHandler::HandleInfoRequested, 68 base::Unretained(this))); 69} 70 71void LocalDiscoveryUIHandler::HandleStart(const base::ListValue* args) { 72 // If privet_lister_ is already set, it is a mock used for tests or the result 73 // of a reload. 74 if (!privet_lister_) { 75 service_discovery_client_ = ServiceDiscoveryHostClientFactory::GetClient(); 76 privet_lister_.reset(new PrivetDeviceListerImpl( 77 service_discovery_client_.get(), this)); 78 privet_http_factory_.reset(new PrivetHTTPAsynchronousFactoryImpl( 79 service_discovery_client_.get(), 80 Profile::FromWebUI(web_ui())->GetRequestContext())); 81 } 82 83 privet_lister_->Start(); 84 privet_lister_->DiscoverNewDevices(false); 85} 86 87void LocalDiscoveryUIHandler::HandleRegisterDevice( 88 const base::ListValue* args) { 89 std::string device_name; 90 91 bool rv = args->GetString(0, &device_name); 92 DCHECK(rv); 93 94 privet_resolution_ = privet_http_factory_->CreatePrivetHTTP( 95 device_name, 96 device_descriptions_[device_name].address, 97 base::Bind(&LocalDiscoveryUIHandler::StartRegisterHTTP, 98 base::Unretained(this))); 99 privet_resolution_->Start(); 100} 101 102void LocalDiscoveryUIHandler::HandleInfoRequested(const base::ListValue* args) { 103 std::string device_name; 104 args->GetString(0, &device_name); 105 106 privet_resolution_ = privet_http_factory_->CreatePrivetHTTP( 107 device_name, 108 device_descriptions_[device_name].address, 109 base::Bind(&LocalDiscoveryUIHandler::StartInfoHTTP, 110 base::Unretained(this))); 111 privet_resolution_->Start(); 112} 113 114void LocalDiscoveryUIHandler::StartRegisterHTTP( 115 scoped_ptr<PrivetHTTPClient> http_client) { 116 current_http_client_.swap(http_client); 117 118 if (!current_http_client_) { 119 LogRegisterErrorToWeb("Resolution failed"); 120 return; 121 } 122 123 Profile* profile = Profile::FromWebUI(web_ui()); 124 SigninManagerBase* signin_manager = 125 SigninManagerFactory::GetForProfileIfExists(profile); 126 127 if (!signin_manager) { 128 LogRegisterErrorToWeb("You must be signed in"); 129 return; 130 } 131 132 std::string username = signin_manager->GetAuthenticatedUsername(); 133 134 current_register_operation_ = 135 current_http_client_->CreateRegisterOperation(username, this); 136 current_register_operation_->Start(); 137} 138 139void LocalDiscoveryUIHandler::StartInfoHTTP( 140 scoped_ptr<PrivetHTTPClient> http_client) { 141 current_http_client_.swap(http_client); 142 if (!current_http_client_) { 143 LogRegisterErrorToWeb("Resolution failed"); 144 return; 145 } 146 147 current_info_operation_ = current_http_client_->CreateInfoOperation(this); 148 current_info_operation_->Start(); 149} 150 151void LocalDiscoveryUIHandler::OnPrivetRegisterClaimToken( 152 PrivetRegisterOperation* operation, 153 const std::string& token, 154 const GURL& url) { 155 if (device_descriptions_.count(current_http_client_->GetName()) == 0) { 156 LogRegisterErrorToWeb("Device no longer exists"); 157 return; 158 } 159 160 GURL automated_claim_url(base::StringPrintf( 161 kPrivetAutomatedClaimURLFormat, 162 device_descriptions_[current_http_client_->GetName()].url.c_str(), 163 token.c_str())); 164 165 Profile* profile = Profile::FromWebUI(web_ui()); 166 167 OAuth2TokenService* token_service = 168 ProfileOAuth2TokenServiceFactory::GetForProfile(profile); 169 170 if (!token_service) { 171 LogRegisterErrorToWeb("Could not get token service"); 172 return; 173 } 174 175 confirm_api_call_flow_.reset(new PrivetConfirmApiCallFlow( 176 profile->GetRequestContext(), 177 token_service, 178 automated_claim_url, 179 base::Bind(&LocalDiscoveryUIHandler::OnConfirmDone, 180 base::Unretained(this)))); 181 182 confirm_api_call_flow_->Start(); 183} 184 185void LocalDiscoveryUIHandler::OnPrivetRegisterError( 186 PrivetRegisterOperation* operation, 187 const std::string& action, 188 PrivetRegisterOperation::FailureReason reason, 189 int printer_http_code, 190 const DictionaryValue* json) { 191 // TODO(noamsml): Add detailed error message. 192 LogRegisterErrorToWeb("Registration error"); 193} 194 195void LocalDiscoveryUIHandler::OnPrivetRegisterDone( 196 PrivetRegisterOperation* operation, 197 const std::string& device_id) { 198 current_register_operation_.reset(); 199 current_http_client_.reset(); 200 201 LogRegisterDoneToWeb(device_id); 202} 203 204void LocalDiscoveryUIHandler::OnConfirmDone( 205 PrivetConfirmApiCallFlow::Status status) { 206 if (status == PrivetConfirmApiCallFlow::SUCCESS) { 207 DLOG(INFO) << "Confirm success."; 208 confirm_api_call_flow_.reset(); 209 current_register_operation_->CompleteRegistration(); 210 } else { 211 // TODO(noamsml): Add detailed error message. 212 LogRegisterErrorToWeb("Confirm error"); 213 } 214} 215 216void LocalDiscoveryUIHandler::DeviceChanged( 217 bool added, 218 const std::string& name, 219 const DeviceDescription& description) { 220 device_descriptions_[name] = description; 221 222 base::StringValue service_name(name); 223 base::DictionaryValue info; 224 info.SetString("domain", description.address.host()); 225 info.SetInteger("port", description.address.port()); 226 std::string ip_addr_string; 227 if (!description.ip_address.empty()) 228 ip_addr_string = net::IPAddressToString(description.ip_address); 229 230 info.SetString("ip", ip_addr_string); 231 info.SetString("lastSeen", "unknown"); 232 info.SetBoolean("registered", !description.id.empty()); 233 234 web_ui()->CallJavascriptFunction("local_discovery.onServiceUpdate", 235 service_name, info); 236} 237 238void LocalDiscoveryUIHandler::DeviceRemoved(const std::string& name) { 239 device_descriptions_.erase(name); 240 scoped_ptr<base::Value> null_value(base::Value::CreateNullValue()); 241 base::StringValue name_value(name); 242 243 web_ui()->CallJavascriptFunction("local_discovery.onServiceUpdate", 244 name_value, *null_value); 245} 246 247void LocalDiscoveryUIHandler::LogRegisterErrorToWeb(const std::string& error) { 248 base::StringValue error_value(error); 249 web_ui()->CallJavascriptFunction("local_discovery.registrationFailed", 250 error_value); 251 DLOG(ERROR) << error; 252} 253 254void LocalDiscoveryUIHandler::LogRegisterDoneToWeb(const std::string& id) { 255 base::StringValue id_value(id); 256 web_ui()->CallJavascriptFunction("local_discovery.registrationSuccess", 257 id_value); 258 DLOG(INFO) << "Registered " << id; 259} 260 261void LocalDiscoveryUIHandler::LogInfoErrorToWeb(const std::string& error) { 262 base::StringValue error_value(error); 263 web_ui()->CallJavascriptFunction("local_discovery.infoFailed", error_value); 264 LOG(ERROR) << error; 265} 266 267void LocalDiscoveryUIHandler::OnPrivetInfoDone( 268 PrivetInfoOperation* operation, 269 int http_code, 270 const base::DictionaryValue* json_value) { 271 if (http_code != net::HTTP_OK || !json_value) { 272 LogInfoErrorToWeb(base::StringPrintf("HTTP error %d", http_code)); 273 return; 274 } 275 276 web_ui()->CallJavascriptFunction("local_discovery.renderInfo", *json_value); 277} 278 279} // namespace local_discovery 280