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/extensions/api/gcd_private/gcd_private_api.h" 6 7#include "base/lazy_instance.h" 8#include "base/memory/linked_ptr.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/memory/scoped_vector.h" 11#include "base/strings/stringprintf.h" 12#include "chrome/browser/local_discovery/cloud_device_list.h" 13#include "chrome/browser/local_discovery/cloud_print_printer_list.h" 14#include "chrome/browser/local_discovery/gcd_api_flow.h" 15#include "chrome/browser/local_discovery/gcd_constants.h" 16#include "chrome/browser/local_discovery/privet_device_lister_impl.h" 17#include "chrome/browser/local_discovery/privet_http_impl.h" 18#include "chrome/browser/local_discovery/privetv3_session.h" 19#include "chrome/browser/local_discovery/service_discovery_shared_client.h" 20#include "chrome/browser/profiles/profile.h" 21#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 22#include "chrome/browser/signin/signin_manager_factory.h" 23#include "components/signin/core/browser/profile_oauth2_token_service.h" 24#include "components/signin/core/browser/signin_manager.h" 25#include "components/signin/core/browser/signin_manager_base.h" 26#include "extensions/browser/event_router.h" 27#include "net/base/net_util.h" 28 29#if defined(ENABLE_WIFI_BOOTSTRAPPING) 30#include "chrome/browser/local_discovery/wifi/wifi_manager.h" 31#endif 32 33namespace extensions { 34 35namespace gcd_private = api::gcd_private; 36 37namespace { 38 39const int kNumRequestsNeeded = 2; 40 41const char kIDPrefixCloudPrinter[] = "cloudprint:"; 42const char kIDPrefixGcd[] = "gcd:"; 43const char kIDPrefixMdns[] = "mdns:"; 44 45const char kPrivatAPISetup[] = "/privet/v3/setup/start"; 46const char kPrivetKeyWifi[] = "wifi"; 47const char kPrivetKeyPassphrase[] = "passphrase"; 48const char kPrivetKeySSID[] = "ssid"; 49const char kPrivetKeyPassphraseDotted[] = "wifi.passphrase"; 50 51scoped_ptr<Event> MakeDeviceStateChangedEvent( 52 const gcd_private::GCDDevice& device) { 53 scoped_ptr<base::ListValue> params = 54 gcd_private::OnDeviceStateChanged::Create(device); 55 scoped_ptr<Event> event( 56 new Event(gcd_private::OnDeviceStateChanged::kEventName, params.Pass())); 57 return event.Pass(); 58} 59 60scoped_ptr<Event> MakeDeviceRemovedEvent(const std::string& device) { 61 scoped_ptr<base::ListValue> params = 62 gcd_private::OnDeviceRemoved::Create(device); 63 scoped_ptr<Event> event( 64 new Event(gcd_private::OnDeviceRemoved::kEventName, params.Pass())); 65 return event.Pass(); 66} 67 68GcdPrivateAPI::GCDApiFlowFactoryForTests* g_gcd_api_flow_factory = NULL; 69 70base::LazyInstance<BrowserContextKeyedAPIFactory<GcdPrivateAPI> > g_factory = 71 LAZY_INSTANCE_INITIALIZER; 72 73scoped_ptr<local_discovery::GCDApiFlow> MakeGCDApiFlow(Profile* profile) { 74 if (g_gcd_api_flow_factory) { 75 return g_gcd_api_flow_factory->CreateGCDApiFlow(); 76 } 77 78 ProfileOAuth2TokenService* token_service = 79 ProfileOAuth2TokenServiceFactory::GetForProfile(profile); 80 if (!token_service) 81 return scoped_ptr<local_discovery::GCDApiFlow>(); 82 SigninManagerBase* signin_manager = 83 SigninManagerFactory::GetInstance()->GetForProfile(profile); 84 if (!signin_manager) 85 return scoped_ptr<local_discovery::GCDApiFlow>(); 86 return local_discovery::GCDApiFlow::Create( 87 profile->GetRequestContext(), 88 token_service, 89 signin_manager->GetAuthenticatedAccountId()); 90} 91 92} // namespace 93 94class GcdPrivateSessionHolder; 95 96class GcdPrivateAPIImpl : public EventRouter::Observer, 97 public local_discovery::PrivetDeviceLister::Delegate { 98 public: 99 typedef base::Callback<void(bool success)> SuccessCallback; 100 101 typedef base::Callback<void(int session_id, 102 api::gcd_private::Status status, 103 const std::string& code, 104 api::gcd_private::ConfirmationType type)> 105 ConfirmationCodeCallback; 106 107 typedef base::Callback<void(api::gcd_private::Status status)> 108 SessionEstablishedCallback; 109 110 typedef base::Callback<void(api::gcd_private::Status status, 111 const base::DictionaryValue& response)> 112 MessageResponseCallback; 113 114 explicit GcdPrivateAPIImpl(content::BrowserContext* context); 115 virtual ~GcdPrivateAPIImpl(); 116 117 static GcdPrivateAPIImpl* Get(content::BrowserContext* context); 118 119 bool QueryForDevices(); 120 121 void EstablishSession(const std::string& ip_address, 122 int port, 123 ConfirmationCodeCallback callback); 124 125 void ConfirmCode(int session_id, 126 const std::string& code, 127 SessionEstablishedCallback callback); 128 129 void SendMessage(int session_id, 130 const std::string& api, 131 const base::DictionaryValue& input, 132 MessageResponseCallback callback); 133 134 void RequestWifiPassword(const std::string& ssid, 135 const SuccessCallback& callback); 136 137 void RemoveSession(int session_id); 138 139 scoped_ptr<base::ListValue> GetPrefetchedSSIDList(); 140 141 private: 142 typedef std::map<std::string /* id_string */, 143 linked_ptr<api::gcd_private::GCDDevice> > GCDDeviceMap; 144 145 typedef std::map<int /* session id*/, linked_ptr<GcdPrivateSessionHolder> > 146 GCDSessionMap; 147 148 typedef std::map<std::string /* ssid */, std::string /* password */> 149 PasswordMap; 150 151 // EventRouter::Observer implementation. 152 virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE; 153 virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE; 154 155 // local_discovery::PrivetDeviceLister implementation. 156 virtual void DeviceChanged( 157 bool added, 158 const std::string& name, 159 const local_discovery::DeviceDescription& description) OVERRIDE; 160 virtual void DeviceRemoved(const std::string& name) OVERRIDE; 161 virtual void DeviceCacheFlushed() OVERRIDE; 162 163 void SendMessageInternal(int session_id, 164 const std::string& api, 165 const base::DictionaryValue& input, 166 const MessageResponseCallback& callback); 167 168#if defined(ENABLE_WIFI_BOOTSTRAPPING) 169 void OnWifiPassword(const SuccessCallback& callback, 170 bool success, 171 const std::string& ssid, 172 const std::string& password); 173 void StartWifiIfNotStarted(); 174#endif 175 176 int num_device_listeners_; 177 scoped_refptr<local_discovery::ServiceDiscoverySharedClient> 178 service_discovery_client_; 179 scoped_ptr<local_discovery::PrivetDeviceLister> privet_device_lister_; 180 GCDDeviceMap known_devices_; 181 182 GCDSessionMap sessions_; 183 int last_session_id_; 184 185 content::BrowserContext* const browser_context_; 186 187#if defined(ENABLE_WIFI_BOOTSTRAPPING) 188 scoped_ptr<local_discovery::wifi::WifiManager> wifi_manager_; 189#endif 190 PasswordMap wifi_passwords_; 191}; 192 193class GcdPrivateRequest : public local_discovery::PrivetV3Session::Request { 194 public: 195 GcdPrivateRequest(const std::string& api, 196 const base::DictionaryValue& input, 197 const GcdPrivateAPIImpl::MessageResponseCallback& callback, 198 GcdPrivateSessionHolder* session_holder); 199 virtual ~GcdPrivateRequest(); 200 201 // local_discovery::PrivetV3Session::Request implementation. 202 virtual std::string GetName() OVERRIDE; 203 virtual const base::DictionaryValue& GetInput() OVERRIDE; 204 virtual void OnError( 205 local_discovery::PrivetURLFetcher::ErrorType error) OVERRIDE; 206 virtual void OnParsedJson(const base::DictionaryValue& value, 207 bool has_error) OVERRIDE; 208 209 private: 210 std::string api_; 211 scoped_ptr<base::DictionaryValue> input_; 212 GcdPrivateAPIImpl::MessageResponseCallback callback_; 213 GcdPrivateSessionHolder* session_holder_; 214}; 215 216class GcdPrivateSessionHolder 217 : public local_discovery::PrivetV3Session::Delegate { 218 public: 219 typedef base::Callback<void(api::gcd_private::Status status, 220 const std::string& code, 221 api::gcd_private::ConfirmationType type)> 222 ConfirmationCodeCallback; 223 224 GcdPrivateSessionHolder(const std::string& ip_address, 225 int port, 226 net::URLRequestContextGetter* request_context); 227 virtual ~GcdPrivateSessionHolder(); 228 229 void Start(const ConfirmationCodeCallback& callback); 230 231 void ConfirmCode( 232 const std::string& code, 233 const GcdPrivateAPIImpl::SessionEstablishedCallback& callback); 234 235 void SendMessage(const std::string& api, 236 const base::DictionaryValue& input, 237 GcdPrivateAPIImpl::MessageResponseCallback callback); 238 239 void DeleteRequest(GcdPrivateRequest* request); 240 241 private: 242 // local_discovery::PrivetV3Session::Delegate implementation. 243 virtual void OnSetupConfirmationNeeded( 244 const std::string& confirmation_code, 245 api::gcd_private::ConfirmationType confirmation_type) OVERRIDE; 246 virtual void OnSessionStatus(api::gcd_private::Status status) OVERRIDE; 247 248 scoped_ptr<local_discovery::PrivetHTTPClient> http_client_; 249 scoped_ptr<local_discovery::PrivetV3Session> privet_session_; 250 typedef ScopedVector<GcdPrivateRequest> RequestVector; 251 RequestVector requests_; 252 253 ConfirmationCodeCallback confirm_callback_; 254 GcdPrivateAPIImpl::SessionEstablishedCallback session_established_callback_; 255}; 256 257GcdPrivateAPIImpl::GcdPrivateAPIImpl(content::BrowserContext* context) 258 : num_device_listeners_(0), last_session_id_(0), browser_context_(context) { 259 DCHECK(browser_context_); 260 if (EventRouter::Get(context)) { 261 EventRouter::Get(context) 262 ->RegisterObserver(this, gcd_private::OnDeviceStateChanged::kEventName); 263 EventRouter::Get(context) 264 ->RegisterObserver(this, gcd_private::OnDeviceRemoved::kEventName); 265 } 266} 267 268GcdPrivateAPIImpl::~GcdPrivateAPIImpl() { 269 if (EventRouter::Get(browser_context_)) { 270 EventRouter::Get(browser_context_)->UnregisterObserver(this); 271 } 272} 273 274void GcdPrivateAPIImpl::OnListenerAdded(const EventListenerInfo& details) { 275 if (details.event_name == gcd_private::OnDeviceStateChanged::kEventName || 276 details.event_name == gcd_private::OnDeviceRemoved::kEventName) { 277 num_device_listeners_++; 278 279 if (num_device_listeners_ == 1) { 280 service_discovery_client_ = 281 local_discovery::ServiceDiscoverySharedClient::GetInstance(); 282 privet_device_lister_.reset(new local_discovery::PrivetDeviceListerImpl( 283 service_discovery_client_.get(), this)); 284 privet_device_lister_->Start(); 285 } 286 287 for (GCDDeviceMap::iterator i = known_devices_.begin(); 288 i != known_devices_.end(); 289 i++) { 290 EventRouter::Get(browser_context_)->DispatchEventToExtension( 291 details.extension_id, MakeDeviceStateChangedEvent(*i->second)); 292 } 293 } 294} 295 296void GcdPrivateAPIImpl::OnListenerRemoved(const EventListenerInfo& details) { 297 if (details.event_name == gcd_private::OnDeviceStateChanged::kEventName || 298 details.event_name == gcd_private::OnDeviceRemoved::kEventName) { 299 num_device_listeners_--; 300 301 if (num_device_listeners_ == 0) { 302 privet_device_lister_.reset(); 303 service_discovery_client_ = NULL; 304 } 305 } 306} 307 308void GcdPrivateAPIImpl::DeviceChanged( 309 bool added, 310 const std::string& name, 311 const local_discovery::DeviceDescription& description) { 312 linked_ptr<gcd_private::GCDDevice> device(new gcd_private::GCDDevice); 313 device->setup_type = gcd_private::SETUP_TYPE_MDNS; 314 device->device_id = kIDPrefixMdns + name; 315 device->device_type = description.type; 316 device->device_name = description.name; 317 device->device_description = description.description; 318 if (!description.id.empty()) 319 device->cloud_id.reset(new std::string(description.id)); 320 321 known_devices_[device->device_id] = device; 322 323 EventRouter::Get(browser_context_) 324 ->BroadcastEvent(MakeDeviceStateChangedEvent(*device)); 325} 326 327void GcdPrivateAPIImpl::DeviceRemoved(const std::string& name) { 328 GCDDeviceMap::iterator found = known_devices_.find(kIDPrefixMdns + name); 329 linked_ptr<gcd_private::GCDDevice> device = found->second; 330 known_devices_.erase(found); 331 332 EventRouter::Get(browser_context_) 333 ->BroadcastEvent(MakeDeviceRemovedEvent(device->device_id)); 334} 335 336void GcdPrivateAPIImpl::DeviceCacheFlushed() { 337 for (GCDDeviceMap::iterator i = known_devices_.begin(); 338 i != known_devices_.end(); 339 i++) { 340 EventRouter::Get(browser_context_) 341 ->BroadcastEvent(MakeDeviceRemovedEvent(i->second->device_id)); 342 } 343 344 known_devices_.clear(); 345} 346 347// static 348GcdPrivateAPIImpl* GcdPrivateAPIImpl::Get(content::BrowserContext* context) { 349 GcdPrivateAPI* gcd_api = 350 BrowserContextKeyedAPIFactory<GcdPrivateAPI>::Get(context); 351 return gcd_api ? gcd_api->impl_.get() : NULL; 352} 353 354bool GcdPrivateAPIImpl::QueryForDevices() { 355 if (!privet_device_lister_) 356 return false; 357 358 privet_device_lister_->DiscoverNewDevices(true); 359 360 return true; 361} 362 363void GcdPrivateAPIImpl::EstablishSession(const std::string& ip_address, 364 int port, 365 ConfirmationCodeCallback callback) { 366 int session_id = last_session_id_++; 367 linked_ptr<GcdPrivateSessionHolder> session_handler( 368 new GcdPrivateSessionHolder( 369 ip_address, port, browser_context_->GetRequestContext())); 370 sessions_[session_id] = session_handler; 371 session_handler->Start(base::Bind(callback, session_id)); 372} 373 374void GcdPrivateAPIImpl::ConfirmCode(int session_id, 375 const std::string& code, 376 SessionEstablishedCallback callback) { 377 GCDSessionMap::iterator found = sessions_.find(session_id); 378 379 if (found == sessions_.end()) { 380 callback.Run(gcd_private::STATUS_UNKNOWNSESSIONERROR); 381 return; 382 } 383 384 found->second->ConfirmCode(code, callback); 385} 386 387void GcdPrivateAPIImpl::SendMessage(int session_id, 388 const std::string& api, 389 const base::DictionaryValue& input, 390 MessageResponseCallback callback) { 391 const base::DictionaryValue* input_actual = &input; 392 scoped_ptr<base::DictionaryValue> input_cloned; 393 394 if (api == kPrivatAPISetup) { 395 const base::DictionaryValue* wifi = NULL; 396 397 if (input.GetDictionary(kPrivetKeyWifi, &wifi)) { 398 std::string ssid; 399 400 if (!wifi->GetString(kPrivetKeySSID, &ssid)) { 401 callback.Run(gcd_private::STATUS_SETUPPARSEERROR, 402 base::DictionaryValue()); 403 return; 404 } 405 406 if (!wifi->HasKey(kPrivetKeyPassphrase)) { 407 // If the message is a setup message, has a wifi section, try sending 408 // the passphrase. 409 410 PasswordMap::iterator found = wifi_passwords_.find(ssid); 411 if (found == wifi_passwords_.end()) { 412 callback.Run(gcd_private::STATUS_WIFIPASSWORDERROR, 413 base::DictionaryValue()); 414 return; 415 } 416 417 input_cloned.reset(input.DeepCopy()); 418 input_cloned->SetString(kPrivetKeyPassphraseDotted, found->second); 419 input_actual = input_cloned.get(); 420 } 421 } 422 } 423 424 GCDSessionMap::iterator found = sessions_.find(session_id); 425 426 if (found == sessions_.end()) { 427 callback.Run(gcd_private::STATUS_UNKNOWNSESSIONERROR, 428 base::DictionaryValue()); 429 return; 430 } 431 432 found->second->SendMessage(api, *input_actual, callback); 433} 434 435void GcdPrivateAPIImpl::RequestWifiPassword(const std::string& ssid, 436 const SuccessCallback& callback) { 437#if defined(ENABLE_WIFI_BOOTSTRAPPING) 438 StartWifiIfNotStarted(); 439 wifi_manager_->RequestNetworkCredentials( 440 ssid, 441 base::Bind(&GcdPrivateAPIImpl::OnWifiPassword, 442 base::Unretained(this), 443 callback)); 444#else 445 callback.Run(false); 446#endif 447} 448 449#if defined(ENABLE_WIFI_BOOTSTRAPPING) 450void GcdPrivateAPIImpl::OnWifiPassword(const SuccessCallback& callback, 451 bool success, 452 const std::string& ssid, 453 const std::string& password) { 454 if (success) { 455 wifi_passwords_[ssid] = password; 456 } 457 458 callback.Run(success); 459} 460 461void GcdPrivateAPIImpl::StartWifiIfNotStarted() { 462 if (!wifi_manager_) { 463 wifi_manager_ = local_discovery::wifi::WifiManager::Create(); 464 wifi_manager_->Start(); 465 } 466} 467 468#endif 469 470void GcdPrivateAPIImpl::RemoveSession(int session_id) { 471 sessions_.erase(session_id); 472} 473 474scoped_ptr<base::ListValue> GcdPrivateAPIImpl::GetPrefetchedSSIDList() { 475 scoped_ptr<base::ListValue> retval(new base::ListValue); 476 477#if defined(ENABLE_WIFI_BOOTSTRAPPING) 478 for (PasswordMap::iterator i = wifi_passwords_.begin(); 479 i != wifi_passwords_.end(); 480 i++) { 481 retval->AppendString(i->first); 482 } 483#endif 484 485 return retval.Pass(); 486} 487 488GcdPrivateRequest::GcdPrivateRequest( 489 const std::string& api, 490 const base::DictionaryValue& input, 491 const GcdPrivateAPIImpl::MessageResponseCallback& callback, 492 GcdPrivateSessionHolder* session_holder) 493 : api_(api), 494 input_(input.DeepCopy()), 495 callback_(callback), 496 session_holder_(session_holder) { 497} 498 499GcdPrivateRequest::~GcdPrivateRequest() { 500} 501 502std::string GcdPrivateRequest::GetName() { 503 return api_; 504} 505 506const base::DictionaryValue& GcdPrivateRequest::GetInput() { 507 return *input_; 508} 509 510void GcdPrivateRequest::OnError( 511 local_discovery::PrivetURLFetcher::ErrorType error) { 512 callback_.Run(gcd_private::STATUS_CONNECTIONERROR, base::DictionaryValue()); 513 514 session_holder_->DeleteRequest(this); 515} 516 517void GcdPrivateRequest::OnParsedJson(const base::DictionaryValue& value, 518 bool has_error) { 519 callback_.Run(gcd_private::STATUS_SUCCESS, value); 520 521 session_holder_->DeleteRequest(this); 522} 523 524GcdPrivateSessionHolder::GcdPrivateSessionHolder( 525 const std::string& ip_address, 526 int port, 527 net::URLRequestContextGetter* request_context) { 528 std::string host_string; 529 net::IPAddressNumber address_number; 530 531 if (net::ParseIPLiteralToNumber(ip_address, &address_number) && 532 address_number.size() == net::kIPv6AddressSize) { 533 host_string = base::StringPrintf("[%s]", ip_address.c_str()); 534 } else { 535 host_string = ip_address; 536 } 537 538 http_client_.reset(new local_discovery::PrivetHTTPClientImpl( 539 "", net::HostPortPair(host_string, port), request_context)); 540} 541 542GcdPrivateSessionHolder::~GcdPrivateSessionHolder() { 543} 544 545void GcdPrivateSessionHolder::Start(const ConfirmationCodeCallback& callback) { 546 confirm_callback_ = callback; 547 548 privet_session_.reset( 549 new local_discovery::PrivetV3Session(http_client_.Pass(), this)); 550 privet_session_->Start(); 551} 552 553void GcdPrivateSessionHolder::ConfirmCode( 554 const std::string& code, 555 const GcdPrivateAPIImpl::SessionEstablishedCallback& callback) { 556 session_established_callback_ = callback; 557 privet_session_->ConfirmCode(code); 558} 559 560void GcdPrivateSessionHolder::SendMessage( 561 const std::string& api, 562 const base::DictionaryValue& input, 563 GcdPrivateAPIImpl::MessageResponseCallback callback) { 564 GcdPrivateRequest* request = 565 new GcdPrivateRequest(api, input, callback, this); 566 requests_.push_back(request); 567 privet_session_->StartRequest(request); 568} 569 570void GcdPrivateSessionHolder::DeleteRequest(GcdPrivateRequest* request) { 571 // TODO(noamsml): Does this need to be optimized? 572 for (RequestVector::iterator i = requests_.begin(); i != requests_.end(); 573 i++) { 574 if (*i == request) { 575 requests_.erase(i); 576 break; 577 } 578 } 579} 580 581void GcdPrivateSessionHolder::OnSetupConfirmationNeeded( 582 const std::string& confirmation_code, 583 gcd_private::ConfirmationType confirmation_type) { 584 confirm_callback_.Run( 585 gcd_private::STATUS_SUCCESS, confirmation_code, confirmation_type); 586 587 confirm_callback_.Reset(); 588} 589 590void GcdPrivateSessionHolder::OnSessionStatus(gcd_private::Status status) { 591 session_established_callback_.Run(status); 592 593 session_established_callback_.Reset(); 594} 595 596GcdPrivateAPI::GcdPrivateAPI(content::BrowserContext* context) 597 : impl_(new GcdPrivateAPIImpl(context)) { 598} 599 600GcdPrivateAPI::~GcdPrivateAPI() { 601} 602 603// static 604BrowserContextKeyedAPIFactory<GcdPrivateAPI>* 605GcdPrivateAPI::GetFactoryInstance() { 606 return g_factory.Pointer(); 607} 608 609// static 610void GcdPrivateAPI::SetGCDApiFlowFactoryForTests( 611 GCDApiFlowFactoryForTests* factory) { 612 g_gcd_api_flow_factory = factory; 613} 614 615GcdPrivateGetCloudDeviceListFunction::GcdPrivateGetCloudDeviceListFunction() { 616} 617 618GcdPrivateGetCloudDeviceListFunction::~GcdPrivateGetCloudDeviceListFunction() { 619} 620 621bool GcdPrivateGetCloudDeviceListFunction::RunAsync() { 622 requests_succeeded_ = 0; 623 requests_failed_ = 0; 624 625 printer_list_ = MakeGCDApiFlow(GetProfile()); 626 device_list_ = MakeGCDApiFlow(GetProfile()); 627 628 if (!printer_list_ || !device_list_) 629 return false; 630 631 // Balanced in CheckListingDone() 632 AddRef(); 633 634 printer_list_->Start(make_scoped_ptr<local_discovery::GCDApiFlow::Request>( 635 new local_discovery::CloudPrintPrinterList(this))); 636 device_list_->Start(make_scoped_ptr<local_discovery::GCDApiFlow::Request>( 637 new local_discovery::CloudDeviceList(this))); 638 639 return true; 640} 641 642void GcdPrivateGetCloudDeviceListFunction::OnDeviceListReady( 643 const DeviceList& devices) { 644 requests_succeeded_++; 645 646 devices_.insert(devices_.end(), devices.begin(), devices.end()); 647 648 CheckListingDone(); 649} 650 651void GcdPrivateGetCloudDeviceListFunction::OnDeviceListUnavailable() { 652 requests_failed_++; 653 654 CheckListingDone(); 655} 656 657void GcdPrivateGetCloudDeviceListFunction::CheckListingDone() { 658 if (requests_failed_ + requests_succeeded_ != kNumRequestsNeeded) 659 return; 660 661 if (requests_succeeded_ == 0) { 662 SendResponse(false); 663 return; 664 } 665 666 std::vector<linked_ptr<gcd_private::GCDDevice> > devices; 667 668 for (DeviceList::iterator i = devices_.begin(); i != devices_.end(); i++) { 669 linked_ptr<gcd_private::GCDDevice> device(new gcd_private::GCDDevice); 670 device->setup_type = gcd_private::SETUP_TYPE_CLOUD; 671 if (i->type == local_discovery::kGCDTypePrinter) { 672 device->device_id = kIDPrefixCloudPrinter + i->id; 673 } else { 674 device->device_id = kIDPrefixGcd + i->id; 675 } 676 677 device->cloud_id.reset(new std::string(i->id)); 678 device->device_type = i->type; 679 device->device_name = i->display_name; 680 device->device_description = i->description; 681 682 devices.push_back(device); 683 } 684 685 results_ = gcd_private::GetCloudDeviceList::Results::Create(devices); 686 687 SendResponse(true); 688 Release(); 689} 690 691GcdPrivateQueryForNewLocalDevicesFunction:: 692 GcdPrivateQueryForNewLocalDevicesFunction() { 693} 694 695GcdPrivateQueryForNewLocalDevicesFunction:: 696 ~GcdPrivateQueryForNewLocalDevicesFunction() { 697} 698 699bool GcdPrivateQueryForNewLocalDevicesFunction::RunSync() { 700 GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); 701 702 if (!gcd_api->QueryForDevices()) { 703 error_ = 704 "You must first subscribe to onDeviceStateChanged or onDeviceRemoved " 705 "notifications"; 706 return false; 707 } 708 709 return true; 710} 711 712GcdPrivatePrefetchWifiPasswordFunction:: 713 GcdPrivatePrefetchWifiPasswordFunction() { 714} 715 716GcdPrivatePrefetchWifiPasswordFunction:: 717 ~GcdPrivatePrefetchWifiPasswordFunction() { 718} 719 720bool GcdPrivatePrefetchWifiPasswordFunction::RunAsync() { 721 scoped_ptr<gcd_private::PrefetchWifiPassword::Params> params = 722 gcd_private::PrefetchWifiPassword::Params::Create(*args_); 723 724 if (!params) 725 return false; 726 727 GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); 728 729 gcd_api->RequestWifiPassword( 730 params->ssid, 731 base::Bind(&GcdPrivatePrefetchWifiPasswordFunction::OnResponse, this)); 732 733 return true; 734} 735 736void GcdPrivatePrefetchWifiPasswordFunction::OnResponse(bool response) { 737 scoped_ptr<base::FundamentalValue> response_value( 738 new base::FundamentalValue(response)); 739 SetResult(response_value.release()); 740 SendResponse(true); 741} 742 743GcdPrivateEstablishSessionFunction::GcdPrivateEstablishSessionFunction() { 744} 745 746GcdPrivateEstablishSessionFunction::~GcdPrivateEstablishSessionFunction() { 747} 748 749bool GcdPrivateEstablishSessionFunction::RunAsync() { 750 scoped_ptr<gcd_private::EstablishSession::Params> params = 751 gcd_private::EstablishSession::Params::Create(*args_); 752 753 if (!params) 754 return false; 755 756 GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); 757 758 gcd_api->EstablishSession( 759 params->ip_address, 760 params->port, 761 base::Bind(&GcdPrivateEstablishSessionFunction::OnConfirmCodeCallback, 762 this)); 763 764 return true; 765} 766 767void GcdPrivateEstablishSessionFunction::OnConfirmCodeCallback( 768 int session_id, 769 gcd_private::Status status, 770 const std::string& confirm_code, 771 gcd_private::ConfirmationType confirmation_type) { 772 gcd_private::ConfirmationInfo info; 773 774 info.type = confirmation_type; 775 if (!confirm_code.empty()) { 776 info.code.reset(new std::string(confirm_code)); 777 } 778 779 results_ = 780 gcd_private::EstablishSession::Results::Create(session_id, status, info); 781 SendResponse(true); 782} 783 784GcdPrivateConfirmCodeFunction::GcdPrivateConfirmCodeFunction() { 785} 786 787GcdPrivateConfirmCodeFunction::~GcdPrivateConfirmCodeFunction() { 788} 789 790bool GcdPrivateConfirmCodeFunction::RunAsync() { 791 scoped_ptr<gcd_private::ConfirmCode::Params> params = 792 gcd_private::ConfirmCode::Params::Create(*args_); 793 794 if (!params) 795 return false; 796 797 GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); 798 799 gcd_api->ConfirmCode( 800 params->session_id, 801 params->code, 802 base::Bind(&GcdPrivateConfirmCodeFunction::OnSessionEstablishedCallback, 803 this)); 804 805 return true; 806} 807 808void GcdPrivateConfirmCodeFunction::OnSessionEstablishedCallback( 809 api::gcd_private::Status status) { 810 results_ = gcd_private::ConfirmCode::Results::Create(status); 811 SendResponse(true); 812} 813 814GcdPrivateSendMessageFunction::GcdPrivateSendMessageFunction() { 815} 816 817GcdPrivateSendMessageFunction::~GcdPrivateSendMessageFunction() { 818} 819 820bool GcdPrivateSendMessageFunction::RunAsync() { 821 scoped_ptr<gcd_private::PassMessage::Params> params = 822 gcd_private::PassMessage::Params::Create(*args_); 823 824 if (!params) 825 return false; 826 827 GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); 828 829 830 gcd_api->SendMessage( 831 params->session_id, 832 params->api, 833 params->input.additional_properties, 834 base::Bind(&GcdPrivateSendMessageFunction::OnMessageSentCallback, this)); 835 836 return true; 837} 838 839void GcdPrivateSendMessageFunction::OnMessageSentCallback( 840 api::gcd_private::Status status, 841 const base::DictionaryValue& value) { 842 gcd_private::PassMessage::Results::Response response; 843 response.additional_properties.MergeDictionary(&value); 844 845 results_ = gcd_private::PassMessage::Results::Create(status, response); 846 SendResponse(true); 847} 848 849GcdPrivateTerminateSessionFunction::GcdPrivateTerminateSessionFunction() { 850} 851 852GcdPrivateTerminateSessionFunction::~GcdPrivateTerminateSessionFunction() { 853} 854 855bool GcdPrivateTerminateSessionFunction::RunAsync() { 856 scoped_ptr<gcd_private::TerminateSession::Params> params = 857 gcd_private::TerminateSession::Params::Create(*args_); 858 859 if (!params) 860 return false; 861 862 GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); 863 864 gcd_api->RemoveSession(params->session_id); 865 866 SendResponse(true); 867 return true; 868} 869 870GcdPrivateGetCommandDefinitionsFunction:: 871 GcdPrivateGetCommandDefinitionsFunction() { 872} 873 874GcdPrivateGetCommandDefinitionsFunction:: 875 ~GcdPrivateGetCommandDefinitionsFunction() { 876} 877 878GcdPrivateGetPrefetchedWifiNameListFunction:: 879 GcdPrivateGetPrefetchedWifiNameListFunction() { 880} 881 882GcdPrivateGetPrefetchedWifiNameListFunction:: 883 ~GcdPrivateGetPrefetchedWifiNameListFunction() { 884} 885 886bool GcdPrivateGetPrefetchedWifiNameListFunction::RunSync() { 887 GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); 888 889 scoped_ptr<base::ListValue> ssid_list = gcd_api->GetPrefetchedSSIDList(); 890 891 SetResult(ssid_list.release()); 892 893 return true; 894} 895 896bool GcdPrivateGetCommandDefinitionsFunction::RunAsync() { 897 return false; 898} 899 900GcdPrivateInsertCommandFunction::GcdPrivateInsertCommandFunction() { 901} 902 903GcdPrivateInsertCommandFunction::~GcdPrivateInsertCommandFunction() { 904} 905 906bool GcdPrivateInsertCommandFunction::RunAsync() { 907 return false; 908} 909 910GcdPrivateGetCommandFunction::GcdPrivateGetCommandFunction() { 911} 912 913GcdPrivateGetCommandFunction::~GcdPrivateGetCommandFunction() { 914} 915 916bool GcdPrivateGetCommandFunction::RunAsync() { 917 return false; 918} 919 920GcdPrivateCancelCommandFunction::GcdPrivateCancelCommandFunction() { 921} 922 923GcdPrivateCancelCommandFunction::~GcdPrivateCancelCommandFunction() { 924} 925 926bool GcdPrivateCancelCommandFunction::RunAsync() { 927 return false; 928} 929 930GcdPrivateGetCommandsListFunction::GcdPrivateGetCommandsListFunction() { 931} 932 933GcdPrivateGetCommandsListFunction::~GcdPrivateGetCommandsListFunction() { 934} 935 936bool GcdPrivateGetCommandsListFunction::RunAsync() { 937 return false; 938} 939 940} // namespace extensions 941