// 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/extensions/api/gcd_private/gcd_private_api.h" #include "base/lazy_instance.h" #include "base/location.h" #include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/thread_task_runner_handle.h" #include "chrome/browser/local_discovery/cloud_device_list.h" #include "chrome/browser/local_discovery/cloud_print_printer_list.h" #include "chrome/browser/local_discovery/gcd_api_flow.h" #include "chrome/browser/local_discovery/gcd_constants.h" #include "chrome/browser/local_discovery/privet_device_lister_impl.h" #include "chrome/browser/local_discovery/privet_http_asynchronous_factory.h" #include "chrome/browser/local_discovery/privet_http_impl.h" #include "chrome/browser/local_discovery/privetv3_session.h" #include "chrome/browser/local_discovery/service_discovery_shared_client.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/browser/signin_manager_base.h" #include "extensions/browser/event_router.h" #include "net/base/net_util.h" #if defined(ENABLE_WIFI_BOOTSTRAPPING) #include "chrome/browser/local_discovery/wifi/wifi_manager.h" #endif namespace extensions { namespace gcd_private = api::gcd_private; namespace { const int kNumRequestsNeeded = 2; const char kIDPrefixCloudPrinter[] = "cloudprint:"; const char kIDPrefixGcd[] = "gcd:"; const char kIDPrefixMdns[] = "mdns:"; const char kPrivatAPISetup[] = "/privet/v3/setup/start"; const char kPrivetKeyWifi[] = "wifi"; const char kPrivetKeyPassphrase[] = "passphrase"; const char kPrivetKeySSID[] = "ssid"; const char kPrivetKeyPassphraseDotted[] = "wifi.passphrase"; scoped_ptr MakeDeviceStateChangedEvent( const gcd_private::GCDDevice& device) { scoped_ptr params = gcd_private::OnDeviceStateChanged::Create(device); scoped_ptr event( new Event(events::UNKNOWN, gcd_private::OnDeviceStateChanged::kEventName, params.Pass())); return event.Pass(); } scoped_ptr MakeDeviceRemovedEvent(const std::string& device) { scoped_ptr params = gcd_private::OnDeviceRemoved::Create(device); scoped_ptr event(new Event(events::UNKNOWN, gcd_private::OnDeviceRemoved::kEventName, params.Pass())); return event.Pass(); } GcdPrivateAPI::GCDApiFlowFactoryForTests* g_gcd_api_flow_factory = NULL; base::LazyInstance > g_factory = LAZY_INSTANCE_INITIALIZER; scoped_ptr MakeGCDApiFlow(Profile* profile) { if (g_gcd_api_flow_factory) { return g_gcd_api_flow_factory->CreateGCDApiFlow(); } ProfileOAuth2TokenService* token_service = ProfileOAuth2TokenServiceFactory::GetForProfile(profile); if (!token_service) return scoped_ptr(); SigninManagerBase* signin_manager = SigninManagerFactory::GetInstance()->GetForProfile(profile); if (!signin_manager) return scoped_ptr(); return local_discovery::GCDApiFlow::Create( profile->GetRequestContext(), token_service, signin_manager->GetAuthenticatedAccountId()); } } // namespace class GcdPrivateSessionHolder; class GcdPrivateAPIImpl : public EventRouter::Observer, public local_discovery::PrivetDeviceLister::Delegate { public: typedef base::Callback SuccessCallback; typedef base::Callback CreateSessionCallback; typedef base::Callback SessionCallback; typedef base::Callback MessageResponseCallback; explicit GcdPrivateAPIImpl(content::BrowserContext* context); virtual ~GcdPrivateAPIImpl(); static GcdPrivateAPIImpl* Get(content::BrowserContext* context); bool QueryForDevices(); void CreateSession(const std::string& service_name, const CreateSessionCallback& callback); void StartPairing(int session_id, api::gcd_private::PairingType pairing_type, const SessionCallback& callback); void ConfirmCode(int session_id, const std::string& code, const SessionCallback& callback); void SendMessage(int session_id, const std::string& api, const base::DictionaryValue& input, const MessageResponseCallback& callback); void RequestWifiPassword(const std::string& ssid, const SuccessCallback& callback); void RemoveSession(int session_id); void RemoveSessionDelayed(int session_id); scoped_ptr GetPrefetchedSSIDList(); private: typedef std::map > GCDDeviceMap; typedef std::map PasswordMap; // EventRouter::Observer implementation. void OnListenerAdded(const EventListenerInfo& details) override; void OnListenerRemoved(const EventListenerInfo& details) override; // local_discovery::PrivetDeviceLister implementation. void DeviceChanged( bool added, const std::string& name, const local_discovery::DeviceDescription& description) override; void DeviceRemoved(const std::string& name) override; void DeviceCacheFlushed() override; void SendMessageInternal(int session_id, const std::string& api, const base::DictionaryValue& input, const MessageResponseCallback& callback); void OnServiceResolved(int session_id, const CreateSessionCallback& callback, scoped_ptr client); #if defined(ENABLE_WIFI_BOOTSTRAPPING) void OnWifiPassword(const SuccessCallback& callback, bool success, const std::string& ssid, const std::string& password); void StartWifiIfNotStarted(); #endif int num_device_listeners_; scoped_refptr service_discovery_client_; scoped_ptr privet_device_lister_; GCDDeviceMap known_devices_; struct SessionInfo { linked_ptr session; linked_ptr http_resolution; }; std::map sessions_; int last_session_id_; content::BrowserContext* const browser_context_; #if defined(ENABLE_WIFI_BOOTSTRAPPING) scoped_ptr wifi_manager_; #endif PasswordMap wifi_passwords_; base::WeakPtrFactory weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(GcdPrivateAPIImpl); }; GcdPrivateAPIImpl::GcdPrivateAPIImpl(content::BrowserContext* context) : num_device_listeners_(0), last_session_id_(0), browser_context_(context) { DCHECK(browser_context_); if (EventRouter::Get(context)) { EventRouter::Get(context) ->RegisterObserver(this, gcd_private::OnDeviceStateChanged::kEventName); EventRouter::Get(context) ->RegisterObserver(this, gcd_private::OnDeviceRemoved::kEventName); } } GcdPrivateAPIImpl::~GcdPrivateAPIImpl() { if (EventRouter::Get(browser_context_)) { EventRouter::Get(browser_context_)->UnregisterObserver(this); } } void GcdPrivateAPIImpl::OnListenerAdded(const EventListenerInfo& details) { if (details.event_name == gcd_private::OnDeviceStateChanged::kEventName || details.event_name == gcd_private::OnDeviceRemoved::kEventName) { num_device_listeners_++; if (num_device_listeners_ == 1) { service_discovery_client_ = local_discovery::ServiceDiscoverySharedClient::GetInstance(); privet_device_lister_.reset(new local_discovery::PrivetDeviceListerImpl( service_discovery_client_.get(), this)); privet_device_lister_->Start(); } for (GCDDeviceMap::iterator i = known_devices_.begin(); i != known_devices_.end(); i++) { EventRouter::Get(browser_context_)->DispatchEventToExtension( details.extension_id, MakeDeviceStateChangedEvent(*i->second)); } } } void GcdPrivateAPIImpl::OnListenerRemoved(const EventListenerInfo& details) { if (details.event_name == gcd_private::OnDeviceStateChanged::kEventName || details.event_name == gcd_private::OnDeviceRemoved::kEventName) { num_device_listeners_--; if (num_device_listeners_ == 0) { privet_device_lister_.reset(); service_discovery_client_ = NULL; } } } void GcdPrivateAPIImpl::DeviceChanged( bool added, const std::string& name, const local_discovery::DeviceDescription& description) { linked_ptr device(new gcd_private::GCDDevice); device->setup_type = gcd_private::SETUP_TYPE_MDNS; device->device_id = kIDPrefixMdns + name; device->device_type = description.type; device->device_name = description.name; device->device_description = description.description; if (!description.id.empty()) device->cloud_id.reset(new std::string(description.id)); known_devices_[device->device_id] = device; EventRouter::Get(browser_context_) ->BroadcastEvent(MakeDeviceStateChangedEvent(*device)); } void GcdPrivateAPIImpl::DeviceRemoved(const std::string& name) { GCDDeviceMap::iterator found = known_devices_.find(kIDPrefixMdns + name); linked_ptr device = found->second; known_devices_.erase(found); EventRouter::Get(browser_context_) ->BroadcastEvent(MakeDeviceRemovedEvent(device->device_id)); } void GcdPrivateAPIImpl::DeviceCacheFlushed() { for (GCDDeviceMap::iterator i = known_devices_.begin(); i != known_devices_.end(); i++) { EventRouter::Get(browser_context_) ->BroadcastEvent(MakeDeviceRemovedEvent(i->second->device_id)); } known_devices_.clear(); } // static GcdPrivateAPIImpl* GcdPrivateAPIImpl::Get(content::BrowserContext* context) { GcdPrivateAPI* gcd_api = BrowserContextKeyedAPIFactory::Get(context); return gcd_api ? gcd_api->impl_.get() : NULL; } bool GcdPrivateAPIImpl::QueryForDevices() { if (!privet_device_lister_) return false; privet_device_lister_->DiscoverNewDevices(true); return true; } void GcdPrivateAPIImpl::CreateSession(const std::string& service_name, const CreateSessionCallback& callback) { int session_id = last_session_id_++; scoped_ptr factory( local_discovery::PrivetHTTPAsynchronousFactory::CreateInstance( browser_context_->GetRequestContext())); auto& session_data = sessions_[session_id]; session_data.http_resolution.reset( factory->CreatePrivetHTTP(service_name).release()); session_data.http_resolution->Start( base::Bind(&GcdPrivateAPIImpl::OnServiceResolved, base::Unretained(this), session_id, callback)); } void GcdPrivateAPIImpl::OnServiceResolved( int session_id, const CreateSessionCallback& callback, scoped_ptr client) { if (!client) { return callback.Run(session_id, gcd_private::STATUS_SERVICERESOLUTIONERROR, base::DictionaryValue()); } auto& session_data = sessions_[session_id]; session_data.session.reset( new local_discovery::PrivetV3Session(client.Pass())); session_data.session->Init(base::Bind(callback, session_id)); } void GcdPrivateAPIImpl::StartPairing(int session_id, api::gcd_private::PairingType pairing_type, const SessionCallback& callback) { auto found = sessions_.find(session_id); if (found == sessions_.end()) return callback.Run(gcd_private::STATUS_UNKNOWNSESSIONERROR); found->second.session->StartPairing(pairing_type, callback); } void GcdPrivateAPIImpl::ConfirmCode(int session_id, const std::string& code, const SessionCallback& callback) { auto found = sessions_.find(session_id); if (found == sessions_.end()) return callback.Run(gcd_private::STATUS_UNKNOWNSESSIONERROR); found->second.session->ConfirmCode(code, callback); } void GcdPrivateAPIImpl::SendMessage(int session_id, const std::string& api, const base::DictionaryValue& input, const MessageResponseCallback& callback) { const base::DictionaryValue* input_actual = &input; scoped_ptr input_cloned; if (api == kPrivatAPISetup) { const base::DictionaryValue* wifi = NULL; if (input.GetDictionary(kPrivetKeyWifi, &wifi)) { std::string ssid; if (!wifi->GetString(kPrivetKeySSID, &ssid)) { LOG(ERROR) << "Missing " << kPrivetKeySSID; return callback.Run(gcd_private::STATUS_SETUPPARSEERROR, base::DictionaryValue()); } if (!wifi->HasKey(kPrivetKeyPassphrase)) { // If the message is a setup message, has a wifi section, try sending // the passphrase. PasswordMap::iterator found = wifi_passwords_.find(ssid); if (found == wifi_passwords_.end()) { LOG(ERROR) << "Password is unknown"; return callback.Run(gcd_private::STATUS_WIFIPASSWORDERROR, base::DictionaryValue()); } input_cloned.reset(input.DeepCopy()); input_cloned->SetString(kPrivetKeyPassphraseDotted, found->second); input_actual = input_cloned.get(); } } } auto found = sessions_.find(session_id); if (found == sessions_.end()) { return callback.Run(gcd_private::STATUS_UNKNOWNSESSIONERROR, base::DictionaryValue()); } found->second.session->SendMessage(api, *input_actual, callback); } void GcdPrivateAPIImpl::RequestWifiPassword(const std::string& ssid, const SuccessCallback& callback) { #if defined(ENABLE_WIFI_BOOTSTRAPPING) StartWifiIfNotStarted(); wifi_manager_->RequestNetworkCredentials( ssid, base::Bind(&GcdPrivateAPIImpl::OnWifiPassword, base::Unretained(this), callback)); #else callback.Run(false); #endif } #if defined(ENABLE_WIFI_BOOTSTRAPPING) void GcdPrivateAPIImpl::OnWifiPassword(const SuccessCallback& callback, bool success, const std::string& ssid, const std::string& password) { if (success) { wifi_passwords_[ssid] = password; } callback.Run(success); } void GcdPrivateAPIImpl::StartWifiIfNotStarted() { if (!wifi_manager_) { wifi_manager_ = local_discovery::wifi::WifiManager::Create(); wifi_manager_->Start(); } } #endif void GcdPrivateAPIImpl::RemoveSession(int session_id) { sessions_.erase(session_id); } void GcdPrivateAPIImpl::RemoveSessionDelayed(int session_id) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&GcdPrivateAPIImpl::RemoveSession, weak_ptr_factory_.GetWeakPtr(), session_id)); } scoped_ptr GcdPrivateAPIImpl::GetPrefetchedSSIDList() { scoped_ptr retval(new base::ListValue); #if defined(ENABLE_WIFI_BOOTSTRAPPING) for (PasswordMap::iterator i = wifi_passwords_.begin(); i != wifi_passwords_.end(); i++) { retval->AppendString(i->first); } #endif return retval.Pass(); } GcdPrivateAPI::GcdPrivateAPI(content::BrowserContext* context) : impl_(new GcdPrivateAPIImpl(context)) { } GcdPrivateAPI::~GcdPrivateAPI() { } // static BrowserContextKeyedAPIFactory* GcdPrivateAPI::GetFactoryInstance() { return g_factory.Pointer(); } // static void GcdPrivateAPI::SetGCDApiFlowFactoryForTests( GCDApiFlowFactoryForTests* factory) { g_gcd_api_flow_factory = factory; } GcdPrivateGetCloudDeviceListFunction::GcdPrivateGetCloudDeviceListFunction() { } GcdPrivateGetCloudDeviceListFunction::~GcdPrivateGetCloudDeviceListFunction() { } bool GcdPrivateGetCloudDeviceListFunction::RunAsync() { requests_succeeded_ = 0; requests_failed_ = 0; printer_list_ = MakeGCDApiFlow(GetProfile()); device_list_ = MakeGCDApiFlow(GetProfile()); if (!printer_list_ || !device_list_) return false; // Balanced in CheckListingDone() AddRef(); printer_list_->Start(make_scoped_ptr( new local_discovery::CloudPrintPrinterList(this))); device_list_->Start(make_scoped_ptr( new local_discovery::CloudDeviceList(this))); return true; } void GcdPrivateGetCloudDeviceListFunction::OnDeviceListReady( const DeviceList& devices) { requests_succeeded_++; devices_.insert(devices_.end(), devices.begin(), devices.end()); CheckListingDone(); } void GcdPrivateGetCloudDeviceListFunction::OnDeviceListUnavailable() { requests_failed_++; CheckListingDone(); } void GcdPrivateGetCloudDeviceListFunction::CheckListingDone() { if (requests_failed_ + requests_succeeded_ != kNumRequestsNeeded) return; if (requests_succeeded_ == 0) { SendResponse(false); return; } std::vector > devices; for (DeviceList::iterator i = devices_.begin(); i != devices_.end(); i++) { linked_ptr device(new gcd_private::GCDDevice); device->setup_type = gcd_private::SETUP_TYPE_CLOUD; if (i->type == local_discovery::kGCDTypePrinter) { device->device_id = kIDPrefixCloudPrinter + i->id; } else { device->device_id = kIDPrefixGcd + i->id; } device->cloud_id.reset(new std::string(i->id)); device->device_type = i->type; device->device_name = i->display_name; device->device_description = i->description; devices.push_back(device); } results_ = gcd_private::GetCloudDeviceList::Results::Create(devices); SendResponse(true); Release(); } GcdPrivateQueryForNewLocalDevicesFunction:: GcdPrivateQueryForNewLocalDevicesFunction() { } GcdPrivateQueryForNewLocalDevicesFunction:: ~GcdPrivateQueryForNewLocalDevicesFunction() { } bool GcdPrivateQueryForNewLocalDevicesFunction::RunSync() { GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); if (!gcd_api->QueryForDevices()) { error_ = "You must first subscribe to onDeviceStateChanged or onDeviceRemoved " "notifications"; return false; } return true; } GcdPrivatePrefetchWifiPasswordFunction:: GcdPrivatePrefetchWifiPasswordFunction() { } GcdPrivatePrefetchWifiPasswordFunction:: ~GcdPrivatePrefetchWifiPasswordFunction() { } bool GcdPrivatePrefetchWifiPasswordFunction::RunAsync() { scoped_ptr params = gcd_private::PrefetchWifiPassword::Params::Create(*args_); if (!params) return false; GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); gcd_api->RequestWifiPassword( params->ssid, base::Bind(&GcdPrivatePrefetchWifiPasswordFunction::OnResponse, this)); return true; } void GcdPrivatePrefetchWifiPasswordFunction::OnResponse(bool response) { scoped_ptr response_value( new base::FundamentalValue(response)); SetResult(response_value.release()); SendResponse(true); } GcdPrivateGetDeviceInfoFunction::GcdPrivateGetDeviceInfoFunction() { } GcdPrivateGetDeviceInfoFunction::~GcdPrivateGetDeviceInfoFunction() { } bool GcdPrivateGetDeviceInfoFunction::RunAsync() { scoped_ptr params = gcd_private::CreateSession::Params::Create(*args_); if (!params) return false; GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); GcdPrivateAPIImpl::CreateSessionCallback callback = base::Bind(&GcdPrivateGetDeviceInfoFunction::OnSessionInitialized, this); gcd_api->CreateSession(params->service_name, callback); return true; } void GcdPrivateGetDeviceInfoFunction::OnSessionInitialized( int session_id, api::gcd_private::Status status, const base::DictionaryValue& info) { gcd_private::GetDeviceInfo::Results::DeviceInfo device_info; device_info.additional_properties.MergeDictionary(&info); results_ = gcd_private::GetDeviceInfo::Results::Create(status, device_info); SendResponse(true); GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); gcd_api->RemoveSessionDelayed(session_id); } GcdPrivateCreateSessionFunction::GcdPrivateCreateSessionFunction() { } GcdPrivateCreateSessionFunction::~GcdPrivateCreateSessionFunction() { } bool GcdPrivateCreateSessionFunction::RunAsync() { scoped_ptr params = gcd_private::CreateSession::Params::Create(*args_); if (!params) return false; GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); GcdPrivateAPIImpl::CreateSessionCallback callback = base::Bind(&GcdPrivateCreateSessionFunction::OnSessionInitialized, this); gcd_api->CreateSession(params->service_name, callback); return true; } void GcdPrivateCreateSessionFunction::OnSessionInitialized( int session_id, api::gcd_private::Status status, const base::DictionaryValue& info) { std::vector pairing_types; // TODO(vitalybuka): Remove this parsing and |pairing_types| from callback. if (status == gcd_private::STATUS_SUCCESS) { const base::ListValue* pairing = nullptr; if (info.GetList("authentication.pairing", &pairing)) { for (const base::Value* value : *pairing) { std::string pairing_string; if (value->GetAsString(&pairing_string)) { api::gcd_private::PairingType pairing_type = api::gcd_private::ParsePairingType(pairing_string); if (pairing_type != api::gcd_private::PAIRING_TYPE_NONE) pairing_types.push_back(pairing_type); } } } else { status = gcd_private::STATUS_SESSIONERROR; } } results_ = gcd_private::CreateSession::Results::Create(session_id, status, pairing_types); SendResponse(true); } GcdPrivateStartPairingFunction::GcdPrivateStartPairingFunction() { } GcdPrivateStartPairingFunction::~GcdPrivateStartPairingFunction() { } bool GcdPrivateStartPairingFunction::RunAsync() { scoped_ptr params = gcd_private::StartPairing::Params::Create(*args_); if (!params) return false; GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); gcd_api->StartPairing( params->session_id, params->pairing_type, base::Bind(&GcdPrivateStartPairingFunction::OnPairingStarted, this)); return true; } void GcdPrivateStartPairingFunction::OnPairingStarted( api::gcd_private::Status status) { results_ = gcd_private::StartPairing::Results::Create(status); SendResponse(true); } GcdPrivateConfirmCodeFunction::GcdPrivateConfirmCodeFunction() { } GcdPrivateConfirmCodeFunction::~GcdPrivateConfirmCodeFunction() { } bool GcdPrivateConfirmCodeFunction::RunAsync() { scoped_ptr params = gcd_private::ConfirmCode::Params::Create(*args_); if (!params) return false; GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); gcd_api->ConfirmCode( params->session_id, params->code, base::Bind(&GcdPrivateConfirmCodeFunction::OnCodeConfirmed, this)); return true; } void GcdPrivateConfirmCodeFunction::OnCodeConfirmed( api::gcd_private::Status status) { results_ = gcd_private::ConfirmCode::Results::Create(status); SendResponse(true); } GcdPrivateSendMessageFunction::GcdPrivateSendMessageFunction() { } GcdPrivateSendMessageFunction::~GcdPrivateSendMessageFunction() { } bool GcdPrivateSendMessageFunction::RunAsync() { scoped_ptr params = gcd_private::PassMessage::Params::Create(*args_); if (!params) return false; GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); gcd_api->SendMessage( params->session_id, params->api, params->input.additional_properties, base::Bind(&GcdPrivateSendMessageFunction::OnMessageSentCallback, this)); return true; } void GcdPrivateSendMessageFunction::OnMessageSentCallback( api::gcd_private::Status status, const base::DictionaryValue& value) { gcd_private::PassMessage::Results::Response response; response.additional_properties.MergeDictionary(&value); results_ = gcd_private::PassMessage::Results::Create(status, response); SendResponse(true); } GcdPrivateTerminateSessionFunction::GcdPrivateTerminateSessionFunction() { } GcdPrivateTerminateSessionFunction::~GcdPrivateTerminateSessionFunction() { } bool GcdPrivateTerminateSessionFunction::RunAsync() { scoped_ptr params = gcd_private::TerminateSession::Params::Create(*args_); if (!params) return false; GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); gcd_api->RemoveSession(params->session_id); SendResponse(true); return true; } GcdPrivateGetCommandDefinitionsFunction:: GcdPrivateGetCommandDefinitionsFunction() { } GcdPrivateGetCommandDefinitionsFunction:: ~GcdPrivateGetCommandDefinitionsFunction() { } GcdPrivateGetPrefetchedWifiNameListFunction:: GcdPrivateGetPrefetchedWifiNameListFunction() { } GcdPrivateGetPrefetchedWifiNameListFunction:: ~GcdPrivateGetPrefetchedWifiNameListFunction() { } bool GcdPrivateGetPrefetchedWifiNameListFunction::RunSync() { GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); scoped_ptr ssid_list = gcd_api->GetPrefetchedSSIDList(); SetResult(ssid_list.release()); return true; } bool GcdPrivateGetCommandDefinitionsFunction::RunAsync() { return false; } GcdPrivateInsertCommandFunction::GcdPrivateInsertCommandFunction() { } GcdPrivateInsertCommandFunction::~GcdPrivateInsertCommandFunction() { } bool GcdPrivateInsertCommandFunction::RunAsync() { return false; } GcdPrivateGetCommandFunction::GcdPrivateGetCommandFunction() { } GcdPrivateGetCommandFunction::~GcdPrivateGetCommandFunction() { } bool GcdPrivateGetCommandFunction::RunAsync() { return false; } GcdPrivateCancelCommandFunction::GcdPrivateCancelCommandFunction() { } GcdPrivateCancelCommandFunction::~GcdPrivateCancelCommandFunction() { } bool GcdPrivateCancelCommandFunction::RunAsync() { return false; } GcdPrivateGetCommandsListFunction::GcdPrivateGetCommandsListFunction() { } GcdPrivateGetCommandsListFunction::~GcdPrivateGetCommandsListFunction() { } bool GcdPrivateGetCommandsListFunction::RunAsync() { return false; } } // namespace extensions