Chromium Code Reviews| Index: chrome/browser/extensions/api/networking_private/networking_private_service_client.cc |
| diff --git a/chrome/browser/extensions/api/networking_private/networking_private_service_client.cc b/chrome/browser/extensions/api/networking_private/networking_private_service_client.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..04212dad99adff759ef48f2572a13b44a2dacc38 |
| --- /dev/null |
| +++ b/chrome/browser/extensions/api/networking_private/networking_private_service_client.cc |
| @@ -0,0 +1,464 @@ |
| +// Copyright 2013 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/networking_private/networking_private_service_client.h" |
| + |
| +#include "base/base64.h" |
| +#include "base/bind.h" |
| +#include "base/sequenced_task_runner.h" |
| +#include "base/strings/string_number_conversions.h" |
| +#include "base/strings/string_util.h" |
| +#include "base/threading/worker_pool.h" |
| +#include "chrome/browser/browser_process.h" |
| +#include "chrome/browser/extensions/api/networking_private/networking_private_crypto.h" |
| +#include "chrome/common/extensions/api/networking_private.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/utility_process_host.h" |
| + |
| +using content::BrowserThread; |
| +using extensions::api::networking_private::VerificationProperties; |
| + |
| +namespace extensions { |
| + |
| +namespace { |
| + |
| +const char kNetworkingPrivateServiceClient[] = "NetworkingPrivateServiceClient"; |
| +const char kNetworkingPrivateSequenceTokenName[] = "NetworkingPrivate"; |
| + |
| +// Implementation of Verify* methods using NetworkingPrivateCrypto. |
| +// TODO(mef): Move this into NetworkingPrivateCrypto class. |
| +class CryptoVerifyImpl : public NetworkingPrivateServiceClient::CryptoVerify { |
| + bool VerifyDestination(const VerificationProperties& properties) { |
| + std::vector<std::string> data_parts; |
| + data_parts.push_back(properties.device_ssid); |
| + data_parts.push_back(properties.device_serial); |
| + data_parts.push_back(properties.device_bssid); |
| + data_parts.push_back(properties.public_key); |
| + data_parts.push_back(properties.nonce); |
| + std::string unsigned_data = JoinString(data_parts, ","); |
| + std::string signed_data; |
| + if (!base::Base64Decode(properties.signed_data, &signed_data)) |
| + return false; |
| + NetworkingPrivateCrypto crypto; |
| + return crypto.VerifyCredentials(properties.certificate, |
| + signed_data, |
| + unsigned_data, |
| + properties.device_bssid); |
| + } |
| + |
| + virtual void VerifyDestination(scoped_ptr<base::ListValue> args, |
| + bool* verified, |
| + std::string* error) OVERRIDE { |
| + using extensions::api::networking_private::VerifyDestination::Params; |
| + scoped_ptr<Params> params = Params::Create(*args); |
| + *verified = VerifyDestination(params->properties); |
| + } |
| + |
| + virtual void VerifyAndEncryptData(scoped_ptr<base::ListValue> args, |
| + std::string* base64_encoded_ciphertext, |
| + std::string* error) OVERRIDE { |
| + using extensions::api::networking_private::VerifyAndEncryptData::Params; |
| + scoped_ptr<Params> params = Params::Create(*args); |
| + |
| + if (!VerifyDestination(params->properties)) { |
| + *error = "VerifyError"; |
| + return; |
| + } |
| + |
| + std::string public_key; |
| + if (!base::Base64Decode(params->properties.public_key, &public_key)) { |
| + *error = "DecodeError"; |
| + return; |
| + } |
| + |
| + NetworkingPrivateCrypto crypto; |
| + std::string ciphertext; |
| + if (!crypto.EncryptByteString(public_key, params->data, &ciphertext)) { |
| + *error = "EncryptError"; |
| + return; |
| + } |
| + |
| + if (!base::Base64Encode(ciphertext, base64_encoded_ciphertext)) { |
| + *error = "EncodeError"; |
| + return; |
| + } |
| + } |
| +}; |
| + |
| +// Deletes WiFiService and CryptoVerify objects on worker thread. |
| +void ShutdownServicesOnWorkerThread( |
| + scoped_ptr<wifi::WiFiService> wifi_service, |
| + scoped_ptr<NetworkingPrivateServiceClient::CryptoVerify> crypto_verify) { |
| + DCHECK(wifi_service.get()); |
| + DCHECK(crypto_verify.get()); |
| +} |
| + |
| +} // namespace |
| + |
| +NetworkingPrivateServiceClient::NetworkingPrivateServiceClient( |
| + wifi::WiFiService* wifi_service, |
| + CryptoVerify* crypto_verify) |
| + : crypto_verify_(crypto_verify), |
| + wifi_service_(wifi_service), |
| + weak_factory_(this) { |
| + sequence_token_ = BrowserThread::GetBlockingPool()-> |
| + GetNamedSequenceToken(kNetworkingPrivateSequenceTokenName); |
| + task_runner_ = BrowserThread::GetBlockingPool()-> |
| + GetSequencedTaskRunnerWithShutdownBehavior( |
| + sequence_token_, |
| + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
| + task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind( |
| + &WiFiService::SetEventObservers, |
| + base::Unretained(wifi_service_.get()), |
|
stevenjb
2013/11/20 18:55:39
Is this safe? task_runner_ is a RefPtr, so couldn'
mef
2013/11/20 20:33:26
Yes, it could still be running, however |wifi_serv
stevenjb
2013/11/20 22:01:12
I see. Can we ensure that Shutdown() was called (m
mef
2013/11/21 21:15:50
Done.
|
| + base::MessageLoopProxy::current(), |
| + base::Bind( |
| + &NetworkingPrivateServiceClient::OnNetworksChangedEventOnUIThread, |
| + weak_factory_.GetWeakPtr()), |
| + base::Bind( |
| + &NetworkingPrivateServiceClient:: |
| + OnNetworkListChangedEventOnUIThread, |
| + weak_factory_.GetWeakPtr()))); |
| +} |
| + |
| +NetworkingPrivateServiceClient::~NetworkingPrivateServiceClient() { } |
|
stevenjb
2013/11/20 18:55:39
{}
mef
2013/11/20 20:33:26
Done.
|
| + |
| +NetworkingPrivateServiceClient::CryptoVerify* |
| + NetworkingPrivateServiceClient::CryptoVerify::Create() { |
| + return new CryptoVerifyImpl(); |
| +} |
| + |
| +NetworkingPrivateServiceClient::ServiceCallbacks::ServiceCallbacks() {} |
| + |
| +NetworkingPrivateServiceClient::ServiceCallbacks::~ServiceCallbacks() {} |
| + |
| +void NetworkingPrivateServiceClient::Shutdown() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + // Clear callbacks map to release callbacks from UI thread. |
| + callbacks_map_.Clear(); |
| + |
| + task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&ShutdownServicesOnWorkerThread, |
| + base::Passed(&wifi_service_), |
| + base::Passed(&crypto_verify_))); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::AddObserver(Observer* observer) { |
| + network_events_observers_.AddObserver(observer); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::RemoveObserver(Observer* observer) { |
| + network_events_observers_.RemoveObserver(observer); |
| +} |
| + |
| +NetworkingPrivateServiceClient::ServiceCallbacks* |
| +NetworkingPrivateServiceClient::AddServiceCallbacks() { |
| + ServiceCallbacks* service_callbacks = new ServiceCallbacks(); |
| + service_callbacks->id = callbacks_map_.Add(service_callbacks); |
| + return service_callbacks; |
| +} |
| + |
| +void NetworkingPrivateServiceClient::RemoveServiceCallbacks( |
| + ServiceCallbacksID callback_id) { |
| + callbacks_map_.Remove(callback_id); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::GetProperties( |
| + const std::string& network_guid, |
| + const DictionaryResultCallback& callback, |
| + const ErrorCallback& error_callback) { |
| + ServiceCallbacks* service_callbacks = AddServiceCallbacks(); |
| + service_callbacks->error_callback = error_callback; |
| + service_callbacks->get_properties_callback = callback; |
| + |
| + DictionaryValue* properties = new DictionaryValue(); |
| + std::string* error = new std::string; |
| + |
| + task_runner_->PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&WiFiService::GetProperties, |
| + base::Unretained(wifi_service_.get()), |
| + network_guid, |
| + properties, |
| + error), |
| + base::Bind(&NetworkingPrivateServiceClient::AfterGetProperties, |
| + weak_factory_.GetWeakPtr(), |
| + service_callbacks->id, |
| + network_guid, |
| + base::Owned(properties), |
| + base::Owned(error))); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::GetVisibleNetworks( |
| + const ListResultCallback& callback) { |
| + ServiceCallbacks* service_callbacks = AddServiceCallbacks(); |
| + service_callbacks->get_visible_networks_callback = callback; |
| + |
| + ListValue* networks = new ListValue(); |
| + |
| + task_runner_->PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&WiFiService::GetVisibleNetworks, |
| + base::Unretained(wifi_service_.get()), |
| + networks), |
| + base::Bind(&NetworkingPrivateServiceClient::AfterGetVisibleNetworks, |
| + weak_factory_.GetWeakPtr(), |
| + service_callbacks->id, |
| + base::Owned(networks))); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::RequestNetworkScan() { |
| + task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&WiFiService::RequestNetworkScan, |
| + base::Unretained(wifi_service_.get()))); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::SetProperties( |
| + const std::string& network_guid, |
| + const base::DictionaryValue& properties, |
| + const base::Closure& callback, |
| + const ErrorCallback& error_callback) { |
| + ServiceCallbacks* service_callbacks = AddServiceCallbacks(); |
| + service_callbacks->error_callback = error_callback; |
| + service_callbacks->set_properties_callback = callback; |
| + |
| + scoped_ptr<base::DictionaryValue> properties_ptr(properties.DeepCopy()); |
| + std::string* error = new std::string; |
| + |
| + task_runner_->PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&WiFiService::SetProperties, |
| + base::Unretained(wifi_service_.get()), |
| + network_guid, |
| + base::Passed(&properties_ptr), |
| + error), |
| + base::Bind(&NetworkingPrivateServiceClient::AfterSetProperties, |
| + weak_factory_.GetWeakPtr(), |
| + service_callbacks->id, |
| + base::Owned(error))); |
| +} |
| + |
| + |
| +void NetworkingPrivateServiceClient::StartConnect( |
| + const std::string& network_guid, |
| + const base::Closure& callback, |
| + const ErrorCallback& error_callback) { |
| + ServiceCallbacks* service_callbacks = AddServiceCallbacks(); |
| + service_callbacks->error_callback = error_callback; |
| + service_callbacks->start_connect_callback = callback; |
| + |
| + std::string* error = new std::string; |
| + |
| + task_runner_->PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&WiFiService::StartConnect, |
| + base::Unretained(wifi_service_.get()), |
| + network_guid, |
| + error), |
| + base::Bind(&NetworkingPrivateServiceClient::AfterStartConnect, |
| + weak_factory_.GetWeakPtr(), |
| + service_callbacks->id, |
| + base::Owned(error))); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::StartDisconnect( |
| + const std::string& network_guid, |
| + const base::Closure& callback, |
| + const ErrorCallback& error_callback) { |
| + ServiceCallbacks* service_callbacks = AddServiceCallbacks(); |
| + service_callbacks->error_callback = error_callback; |
| + service_callbacks->start_disconnect_callback = callback; |
| + |
| + std::string* error = new std::string; |
| + |
| + task_runner_->PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&WiFiService::StartDisconnect, |
| + base::Unretained(wifi_service_.get()), |
| + network_guid, |
| + error), |
| + base::Bind(&NetworkingPrivateServiceClient::AfterStartDisconnect, |
| + weak_factory_.GetWeakPtr(), |
| + service_callbacks->id, |
| + base::Owned(error))); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::VerifyDestination( |
| + scoped_ptr<base::ListValue> args, |
| + const BoolResultCallback& callback, |
| + const CryptoErrorCallback& error_callback) { |
| + ServiceCallbacks* service_callbacks = AddServiceCallbacks(); |
| + service_callbacks->crypto_error_callback = error_callback; |
| + service_callbacks->verify_destination_callback = callback; |
| + |
| + bool* result = new bool; |
| + std::string* error = new std::string; |
| + |
| + task_runner_->PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&CryptoVerify::VerifyDestination, |
| + base::Unretained(crypto_verify_.get()), |
| + base::Passed(&args), |
| + result, |
| + error), |
| + base::Bind(&NetworkingPrivateServiceClient::AfterVerifyDestination, |
| + weak_factory_.GetWeakPtr(), |
| + service_callbacks->id, |
| + base::Owned(result), |
| + base::Owned(error))); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::VerifyAndEncryptData( |
| + scoped_ptr<base::ListValue> args, |
| + const StringResultCallback& callback, |
| + const CryptoErrorCallback& error_callback) { |
| + ServiceCallbacks* service_callbacks = AddServiceCallbacks(); |
| + service_callbacks->crypto_error_callback = error_callback; |
| + service_callbacks->verify_and_encrypt_data_callback = callback; |
| + |
| + std::string* result = new std::string; |
| + std::string* error = new std::string; |
| + |
| + task_runner_->PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&CryptoVerify::VerifyAndEncryptData, |
| + base::Unretained(crypto_verify_.get()), |
| + base::Passed(&args), |
| + result, |
| + error), |
| + base::Bind(&NetworkingPrivateServiceClient::AfterVerifyAndEncryptData, |
| + weak_factory_.GetWeakPtr(), |
| + service_callbacks->id, |
| + base::Owned(result), |
| + base::Owned(error))); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::AfterGetProperties( |
| + ServiceCallbacksID callback_id, |
| + const std::string& network_guid, |
| + const DictionaryValue* properties, |
| + const std::string* error) { |
| + ServiceCallbacks* service_callbacks = callbacks_map_.Lookup(callback_id); |
| + DCHECK(service_callbacks); |
| + if (!error->empty()) { |
| + DCHECK(!service_callbacks->error_callback.is_null()); |
| + service_callbacks->error_callback.Run(*error, |
| + scoped_ptr<base::DictionaryValue>()); |
| + } else { |
| + DCHECK(!service_callbacks->get_properties_callback.is_null()); |
| + service_callbacks->get_properties_callback.Run(network_guid, *properties); |
| + } |
| + RemoveServiceCallbacks(callback_id); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::AfterGetVisibleNetworks( |
| + ServiceCallbacksID callback_id, |
| + const ListValue* networks) { |
| + ServiceCallbacks* service_callbacks = callbacks_map_.Lookup(callback_id); |
| + DCHECK(service_callbacks); |
| + DCHECK(!service_callbacks->get_visible_networks_callback.is_null()); |
| + service_callbacks->get_visible_networks_callback.Run(*networks); |
| + RemoveServiceCallbacks(callback_id); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::AfterSetProperties( |
| + ServiceCallbacksID callback_id, |
| + const std::string* error) { |
| + ServiceCallbacks* service_callbacks = callbacks_map_.Lookup(callback_id); |
| + DCHECK(service_callbacks); |
| + if (!error->empty()) { |
| + DCHECK(!service_callbacks->error_callback.is_null()); |
| + service_callbacks->error_callback.Run(*error, |
| + scoped_ptr<base::DictionaryValue>()); |
| + } else { |
| + DCHECK(!service_callbacks->set_properties_callback.is_null()); |
| + service_callbacks->set_properties_callback.Run(); |
| + } |
| + RemoveServiceCallbacks(callback_id); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::AfterStartConnect( |
| + ServiceCallbacksID callback_id, |
| + const std::string* error) { |
| + ServiceCallbacks* service_callbacks = callbacks_map_.Lookup(callback_id); |
| + DCHECK(service_callbacks); |
| + if (!error->empty()) { |
| + DCHECK(!service_callbacks->error_callback.is_null()); |
| + service_callbacks->error_callback.Run(*error, |
| + scoped_ptr<base::DictionaryValue>()); |
| + } else { |
| + DCHECK(!service_callbacks->start_connect_callback.is_null()); |
| + service_callbacks->start_connect_callback.Run(); |
| + } |
| + RemoveServiceCallbacks(callback_id); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::AfterStartDisconnect( |
| + ServiceCallbacksID callback_id, |
| + const std::string* error) { |
| + ServiceCallbacks* service_callbacks = callbacks_map_.Lookup(callback_id); |
| + DCHECK(service_callbacks); |
| + if (!error->empty()) { |
| + DCHECK(!service_callbacks->error_callback.is_null()); |
| + service_callbacks->error_callback.Run(*error, |
| + scoped_ptr<base::DictionaryValue>()); |
| + } else { |
| + DCHECK(!service_callbacks->start_disconnect_callback.is_null()); |
| + service_callbacks->start_disconnect_callback.Run(); |
| + } |
| + RemoveServiceCallbacks(callback_id); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::AfterVerifyDestination( |
| + ServiceCallbacksID callback_id, |
| + const bool* result, |
| + const std::string* error) { |
| + ServiceCallbacks* service_callbacks = callbacks_map_.Lookup(callback_id); |
| + DCHECK(service_callbacks); |
| + if (!error->empty()) { |
| + DCHECK(!service_callbacks->crypto_error_callback.is_null()); |
| + service_callbacks->crypto_error_callback.Run(*error, *error); |
| + } else { |
| + DCHECK(!service_callbacks->verify_destination_callback.is_null()); |
| + service_callbacks->verify_destination_callback.Run(*result); |
| + } |
| + RemoveServiceCallbacks(callback_id); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::AfterVerifyAndEncryptData( |
| + ServiceCallbacksID callback_id, |
| + const std::string* result, |
| + const std::string* error) { |
| + ServiceCallbacks* service_callbacks = callbacks_map_.Lookup(callback_id); |
| + DCHECK(service_callbacks); |
| + if (!error->empty()) { |
| + DCHECK(!service_callbacks->crypto_error_callback.is_null()); |
| + service_callbacks->crypto_error_callback.Run(*error, *error); |
| + } else { |
| + DCHECK(!service_callbacks->verify_and_encrypt_data_callback.is_null()); |
| + service_callbacks->verify_and_encrypt_data_callback.Run(*result); |
| + } |
| + RemoveServiceCallbacks(callback_id); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::OnNetworksChangedEventOnUIThread( |
| + const std::vector<std::string>& network_guids) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + FOR_EACH_OBSERVER(Observer, |
| + network_events_observers_, |
| + OnNetworksChangedEvent(network_guids)); |
| +} |
| + |
| +void NetworkingPrivateServiceClient::OnNetworkListChangedEventOnUIThread( |
| + const std::vector<std::string>& network_guids) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + FOR_EACH_OBSERVER(Observer, |
| + network_events_observers_, |
| + OnNetworkListChangedEvent(network_guids)); |
| +} |
| + |
| +} // namespace extensions |