| Index: chrome/browser/extensions/api/networking_private/networking_private_process_client.cc
|
| diff --git a/chrome/browser/extensions/api/networking_private/networking_private_process_client.cc b/chrome/browser/extensions/api/networking_private/networking_private_process_client.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6afe60de14657fe2a102c76b064b9511f4cd9250
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/api/networking_private/networking_private_process_client.cc
|
| @@ -0,0 +1,458 @@
|
| +// 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_process_client.h"
|
| +
|
| +#include "base/base64.h"
|
| +#include "base/bind.h"
|
| +#include "base/strings/string_number_conversions.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/browser/profiles/profile.h"
|
| +#include "chrome/common/extensions/api/networking_private.h"
|
| +#include "chrome/common/networking_private_messages.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#include "content/public/browser/utility_process_host.h"
|
| +
|
| +using content::BrowserThread;
|
| +using content::UtilityProcessHost;
|
| +using extensions::api::networking_private::VerificationProperties;
|
| +
|
| +namespace extensions {
|
| +
|
| +namespace {
|
| +// Implementation of Verify* methods using NetworkingPrivateCrypto.
|
| +// TODO(mef): Move this into NetworkingPrivateCrypto class.
|
| +class CryptoVerifyImpl : public NetworkingPrivateProcessClient::CryptoVerify {
|
| + virtual bool VerifyDestination(
|
| + const VerificationProperties& properties) OVERRIDE {
|
| + 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 bool VerifyAndEncryptData(const VerificationProperties& properties,
|
| + const std::string& plaintext,
|
| + std::string* base64_ciphertext) OVERRIDE {
|
| + if (!VerifyDestination(properties))
|
| + return false;
|
| +
|
| + std::string public_key;
|
| + if (!base::Base64Decode(properties.public_key, &public_key))
|
| + return false;
|
| +
|
| + NetworkingPrivateCrypto crypto;
|
| + std::string ciphertext;
|
| + if (!crypto.EncryptByteString(public_key, plaintext, &ciphertext))
|
| + return false;
|
| +
|
| + return base::Base64Encode(ciphertext, base64_ciphertext);
|
| + }
|
| +};
|
| +
|
| +const char kNetworkingPrivateProcessClient[] = "NetworkingPrivateProcessClient";
|
| +
|
| +} // namespace
|
| +
|
| +scoped_refptr<NetworkingPrivateProcessClient>
|
| +NetworkingPrivateProcessClient::GetForProfile(Profile* profile) {
|
| + profile = profile->GetOriginalProfile();
|
| + if (!profile->GetUserData(kNetworkingPrivateProcessClient)) {
|
| + NetworkingPrivateProcessClient* client =
|
| + new NetworkingPrivateProcessClient(profile);
|
| + profile->SetUserData(
|
| + kNetworkingPrivateProcessClient,
|
| + new base::UserDataAdapter<NetworkingPrivateProcessClient>(client));
|
| + client->Start();
|
| + }
|
| +
|
| + return scoped_refptr<NetworkingPrivateProcessClient>(
|
| + base::UserDataAdapter<NetworkingPrivateProcessClient>::Get(
|
| + profile, kNetworkingPrivateProcessClient));
|
| +}
|
| +
|
| +NetworkingPrivateProcessClient::NetworkingPrivateProcessClient(Profile* profile)
|
| + : profile_(profile),
|
| + crypto_verify_(new CryptoVerifyImpl()) {}
|
| +
|
| +NetworkingPrivateProcessClient::~NetworkingPrivateProcessClient() {
|
| + // TODO(mef): |message_callbacks_| should be cleared on UI thread prior to
|
| + // destruction, for example from NetworkingPrivateEventRouterImpl::Shutdown().
|
| +}
|
| +
|
| +NetworkingPrivateProcessClient::MessageCallbacks::MessageCallbacks() {}
|
| +
|
| +NetworkingPrivateProcessClient::MessageCallbacks::~MessageCallbacks() {}
|
| +
|
| +void NetworkingPrivateProcessClient::Start() {
|
| + BrowserThread::ID thread_id;
|
| + CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id));
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&NetworkingPrivateProcessClient::StartProcessOnIOThread,
|
| + this,
|
| + thread_id));
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::StartProcessOnIOThread(
|
| + BrowserThread::ID thread_id) {
|
| + CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + utility_process_host_ = UtilityProcessHost::Create(
|
| + this, BrowserThread::GetMessageLoopProxyForThread(thread_id).get())
|
| + ->AsWeakPtr();
|
| + utility_process_host_->DisableSandbox();
|
| + utility_process_host_->StartBatchMode();
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::AddObserver(Observer* observer) {
|
| + network_events_observers_.AddObserver(observer);
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::RemoveObserver(Observer* observer) {
|
| + network_events_observers_.RemoveObserver(observer);
|
| + // Shutdown will occur when all remaining calls are completed.
|
| + ShutdownIfDone();
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::ShutdownIfDone() {
|
| + if (!network_events_observers_.might_have_observers() &&
|
| + callbacks_map_.IsEmpty()) {
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&NetworkingPrivateProcessClient::ShutdownProcessOnIOThread,
|
| + this));
|
| + // Remove current process client from profile, so new API calls would launch
|
| + // new process.
|
| + profile_->RemoveUserData(kNetworkingPrivateProcessClient);
|
| + }
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::ShutdownProcessOnIOThread() {
|
| + CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + // The utility_process_host_ will take care of deleting itself.
|
| + if (utility_process_host_.get()) {
|
| + utility_process_host_->EndBatchMode();
|
| + utility_process_host_.reset();
|
| + }
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::Send(IPC::Message* message) {
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &NetworkingPrivateProcessClient::SendOnIOThread, this, message));
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::SendOnIOThread(IPC::Message* message) {
|
| + CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + if (utility_process_host_.get())
|
| + utility_process_host_->Send(message);
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::OnProcessCrashed(int exit_code) {
|
| + std::string error_code("UtilityProcessCrashed");
|
| + // Report error for all pending callbacks
|
| + for (IDMap<MessageCallbacks, IDMapOwnPointer>::iterator iter(&callbacks_map_);
|
| + !iter.IsAtEnd();
|
| + iter.Advance()) {
|
| + if (!iter.GetCurrentValue()->error_callback.is_null()) {
|
| + scoped_ptr<DictionaryValue> error_data_ptr(new DictionaryValue());
|
| + iter.GetCurrentValue()->error_callback.Run(error_code,
|
| + error_data_ptr.Pass());
|
| + }
|
| + }
|
| + callbacks_map_.Clear();
|
| + if (network_events_observers_.might_have_observers()) {
|
| + // Restart the utility process.
|
| + Start();
|
| + } else {
|
| + ShutdownIfDone();
|
| + }
|
| +}
|
| +
|
| +bool NetworkingPrivateProcessClient::OnMessageReceived(
|
| + const IPC::Message& message) {
|
| + bool handled = true;
|
| + IPC_BEGIN_MESSAGE_MAP(NetworkingPrivateProcessClient, message)
|
| + // Responses from NetworkingPrivateHandler.
|
| + IPC_MESSAGE_HANDLER(NetworkingPrivateMsg_API_Error, OnApiError)
|
| + IPC_MESSAGE_HANDLER(NetworkingPrivateMsg_GetProperties_Succeeded,
|
| + OnGetPropertiesSucceeded)
|
| + IPC_MESSAGE_HANDLER(NetworkingPrivateMsg_StartConnect_Succeeded,
|
| + OnStartConnectSucceeded)
|
| + IPC_MESSAGE_HANDLER(NetworkingPrivateMsg_StartDisconnect_Succeeded,
|
| + OnStartDisconnectSucceeded)
|
| + IPC_MESSAGE_HANDLER(NetworkingPrivateMsg_SetProperties_Succeeded,
|
| + OnSetPropertiesSucceeded)
|
| + IPC_MESSAGE_HANDLER(NetworkingPrivateMsg_GetVisibleNetworksSucceeded,
|
| + OnGetVisibleNetworksSucceeded)
|
| + IPC_MESSAGE_HANDLER(NetworkingPrivateMsg_NetworksChanged_Event,
|
| + OnNetworksChangedEvent)
|
| + IPC_MESSAGE_HANDLER(NetworkingPrivateMsg_NetworkListChanged_Event,
|
| + OnNetworkListChangedEvent)
|
| + IPC_MESSAGE_UNHANDLED(handled = false)
|
| + IPC_END_MESSAGE_MAP()
|
| + return handled;
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::GetProperties(
|
| + const std::string& service_path,
|
| + const DictionaryResultCallback& callback,
|
| + const ErrorCallback& error_callback) {
|
| + MessageCallbacks* message_callbacks = AddMessageCallbacks();
|
| + message_callbacks->error_callback = error_callback;
|
| + message_callbacks->get_properties_callback = callback;
|
| +
|
| + Send(new NetworkingPrivateMsg_GetProperties(message_callbacks->id,
|
| + service_path));
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::GetVisibleNetworks(
|
| + const ListResultCallback& callback) {
|
| + MessageCallbacks* message_callbacks = AddMessageCallbacks();
|
| + message_callbacks->get_visible_networks_callback = callback;
|
| +
|
| + Send(new NetworkingPrivateMsg_GetVisibleNetworks(message_callbacks->id));
|
| +}
|
| +
|
| +// Requests network scan. Broadcasts NetworkListChangedEvent upon completion.
|
| +void NetworkingPrivateProcessClient::RequestNetworkScan() {
|
| + Send(new NetworkingPrivateMsg_RequestNetworkScan());
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::SetProperties(
|
| + const std::string& service_path,
|
| + const base::DictionaryValue& properties,
|
| + const VoidResultCallback& callback,
|
| + const ErrorCallback& error_callback) {
|
| + MessageCallbacks* message_callbacks = AddMessageCallbacks();
|
| + message_callbacks->error_callback = error_callback;
|
| + message_callbacks->set_properties_callback = callback;
|
| +
|
| + scoped_ptr<DictionaryValue> properties_ptr(properties.DeepCopy());
|
| + Send(new NetworkingPrivateMsg_SetProperties(
|
| + message_callbacks->id, service_path, *properties_ptr));
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::StartConnect(
|
| + const std::string& service_path,
|
| + const VoidResultCallback& callback,
|
| + const ErrorCallback& error_callback) {
|
| + MessageCallbacks* message_callbacks = AddMessageCallbacks();
|
| + message_callbacks->error_callback = error_callback;
|
| + message_callbacks->start_connect_callback = callback;
|
| +
|
| + Send(new NetworkingPrivateMsg_StartConnect(message_callbacks->id,
|
| + service_path));
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::StartDisconnect(
|
| + const std::string& service_path,
|
| + const VoidResultCallback& callback,
|
| + const ErrorCallback& error_callback) {
|
| + MessageCallbacks* message_callbacks = AddMessageCallbacks();
|
| + message_callbacks->error_callback = error_callback;
|
| + message_callbacks->start_disconnect_callback = callback;
|
| +
|
| + Send(new NetworkingPrivateMsg_StartDisconnect(message_callbacks->id,
|
| + service_path));
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::VerifyDestination(
|
| + scoped_ptr<base::ListValue> args,
|
| + const BoolResultCallback& callback,
|
| + const CryptoErrorCallback& error_callback) {
|
| + base::WorkerPool::PostTask(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &NetworkingPrivateProcessClient::VerifyDestinationOnWorkerThread,
|
| + this,
|
| + Passed(&args),
|
| + callback,
|
| + error_callback),
|
| + false);
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::VerifyDestinationOnWorkerThread(
|
| + scoped_ptr<base::ListValue> args,
|
| + const BoolResultCallback& callback,
|
| + const CryptoErrorCallback& error_callback) {
|
| + using extensions::api::networking_private::VerifyDestination::Params;
|
| + scoped_ptr<Params> params = Params::Create(*args);
|
| + bool result = crypto_verify_->VerifyDestination(params->properties);
|
| + BrowserThread::PostTask(BrowserThread::UI,
|
| + FROM_HERE,
|
| + base::Bind(callback, result));
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::VerifyAndEncryptData(
|
| + scoped_ptr<base::ListValue> args,
|
| + const StringResultCallback& callback,
|
| + const CryptoErrorCallback& error_callback) {
|
| + base::WorkerPool::PostTask(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &NetworkingPrivateProcessClient::VerifyAndEncryptDataOnWorkerThread,
|
| + this,
|
| + Passed(&args),
|
| + callback,
|
| + error_callback),
|
| + false);
|
| +}
|
| +
|
| +
|
| +void NetworkingPrivateProcessClient::VerifyAndEncryptDataOnWorkerThread(
|
| + scoped_ptr<base::ListValue> args,
|
| + const StringResultCallback& callback,
|
| + const CryptoErrorCallback& error_callback) {
|
| + using extensions::api::networking_private::VerifyAndEncryptData::Params;
|
| + scoped_ptr<Params> params = Params::Create(*args);
|
| + std::string encoded_data;
|
| + bool verified = crypto_verify_->VerifyAndEncryptData(
|
| + params->properties, params->data, &encoded_data);
|
| + if (verified) {
|
| + BrowserThread::PostTask(BrowserThread::UI,
|
| + FROM_HERE,
|
| + base::Bind(callback, encoded_data));
|
| + } else {
|
| + BrowserThread::PostTask(BrowserThread::UI,
|
| + FROM_HERE,
|
| + base::Bind(error_callback, "VerifyError", "Error"));
|
| + }
|
| +}
|
| +
|
| +NetworkingPrivateProcessClient::MessageCallbacks*
|
| +NetworkingPrivateProcessClient::AddMessageCallbacks() {
|
| + MessageCallbacks* message_callbacks = new MessageCallbacks();
|
| + message_callbacks->id = callbacks_map_.Add(message_callbacks);
|
| + return message_callbacks;
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::RemoveMessageCallbacks(
|
| + MessageCallbacksID message_id) {
|
| + callbacks_map_.Remove(message_id);
|
| + ShutdownIfDone();
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::SetUpForTest(
|
| + const base::DictionaryValue& parameters,
|
| + CryptoVerify* crypto_verify_mock) {
|
| + DCHECK(crypto_verify_mock);
|
| + crypto_verify_.reset(crypto_verify_mock);
|
| + // Prevent shutdown between calls.
|
| + AddMessageCallbacks();
|
| + // Pass mock parameters to utility process itself.
|
| + scoped_ptr<DictionaryValue> parameters_ptr(parameters.DeepCopy());
|
| + Send(new NetworkingPrivateMsg_SetUpForTest(*parameters_ptr));
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::TearDownForTest() {
|
| + // Remove extra callback added in SetUpForTest to prevent shutdown between
|
| + // calls.
|
| + callbacks_map_.Clear();
|
| + ShutdownIfDone();
|
| +}
|
| +
|
| +// Message handlers
|
| +void NetworkingPrivateProcessClient::OnApiError(
|
| + MessageCallbacksID message_id,
|
| + const std::string& error_code,
|
| + const base::DictionaryValue& error_data) {
|
| + MessageCallbacks* message_callbacks = callbacks_map_.Lookup(message_id);
|
| + if (message_callbacks != NULL) {
|
| + scoped_ptr<DictionaryValue> error_data_ptr(error_data.DeepCopy());
|
| + if (!message_callbacks->error_callback.is_null())
|
| + message_callbacks->error_callback.Run(error_code, error_data_ptr.Pass());
|
| + RemoveMessageCallbacks(message_id);
|
| + }
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::OnGetPropertiesSucceeded(
|
| + MessageCallbacksID message_id,
|
| + const std::string& network_guid,
|
| + const base::DictionaryValue& properties) {
|
| + MessageCallbacks* message_callbacks = callbacks_map_.Lookup(message_id);
|
| + if (message_callbacks != NULL) {
|
| + if (!message_callbacks->get_properties_callback.is_null())
|
| + message_callbacks->get_properties_callback.Run(network_guid, properties);
|
| + RemoveMessageCallbacks(message_id);
|
| + }
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::OnGetVisibleNetworksSucceeded(
|
| + MessageCallbacksID message_id,
|
| + const base::ListValue& network_list) {
|
| + MessageCallbacks* message_callbacks = callbacks_map_.Lookup(message_id);
|
| + if (message_callbacks != NULL) {
|
| + if (!message_callbacks->get_visible_networks_callback.is_null())
|
| + message_callbacks->get_visible_networks_callback.Run(network_list);
|
| + RemoveMessageCallbacks(message_id);
|
| + }
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::OnNetworksChangedEvent(
|
| + const std::vector<std::string>& network_guids) {
|
| + FOR_EACH_OBSERVER(Observer,
|
| + network_events_observers_,
|
| + OnNetworksChangedEvent(network_guids));
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::OnNetworkListChangedEvent(
|
| + const std::vector<std::string>& network_guids) {
|
| + FOR_EACH_OBSERVER(Observer,
|
| + network_events_observers_,
|
| + OnNetworkListChangedEvent(network_guids));
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::OnSetPropertiesSucceeded(
|
| + MessageCallbacksID message_id,
|
| + const std::string& network_guid) {
|
| + MessageCallbacks* message_callbacks = callbacks_map_.Lookup(message_id);
|
| + if (message_callbacks != NULL) {
|
| + if (!message_callbacks->set_properties_callback.is_null())
|
| + message_callbacks->set_properties_callback.Run();
|
| + RemoveMessageCallbacks(message_id);
|
| + }
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::OnStartConnectSucceeded(
|
| + MessageCallbacksID message_id,
|
| + const std::string& network_guid) {
|
| + MessageCallbacks* message_callbacks = callbacks_map_.Lookup(message_id);
|
| + if (message_callbacks != NULL) {
|
| + if (!message_callbacks->start_connect_callback.is_null())
|
| + message_callbacks->start_connect_callback.Run();
|
| + RemoveMessageCallbacks(message_id);
|
| + }
|
| +}
|
| +
|
| +void NetworkingPrivateProcessClient::OnStartDisconnectSucceeded(
|
| + MessageCallbacksID message_id,
|
| + const std::string& network_guid) {
|
| + MessageCallbacks* message_callbacks = callbacks_map_.Lookup(message_id);
|
| + if (message_callbacks != NULL) {
|
| + if (!message_callbacks->start_disconnect_callback.is_null())
|
| + message_callbacks->start_disconnect_callback.Run();
|
| + RemoveMessageCallbacks(message_id);
|
| + }
|
| +}
|
| +
|
| +} // namespace extensions
|
|
|