blob: 285ccc0d263ebbde730061cc6366366b24fd9e40 [file] [log] [blame]
// Copyright 2015 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/easy_unlock_private/easy_unlock_private_connection_manager.h"
#include <utility>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h"
#include "chrome/common/extensions/api/easy_unlock_private.h"
#include "components/proximity_auth/connection.h"
#include "components/proximity_auth/wire_message.h"
#include "extensions/browser/event_router.h"
using proximity_auth::Connection;
using proximity_auth::WireMessage;
namespace extensions {
namespace {
api::easy_unlock_private::ConnectionStatus ToApiConnectionStatus(
Connection::Status status) {
switch (status) {
case Connection::DISCONNECTED:
return api::easy_unlock_private::CONNECTION_STATUS_DISCONNECTED;
case Connection::IN_PROGRESS:
return api::easy_unlock_private::CONNECTION_STATUS_IN_PROGRESS;
case Connection::CONNECTED:
return api::easy_unlock_private::CONNECTION_STATUS_CONNECTED;
}
return api::easy_unlock_private::CONNECTION_STATUS_NONE;
}
} // namespace
EasyUnlockPrivateConnectionManager::EasyUnlockPrivateConnectionManager(
content::BrowserContext* context)
: browser_context_(context) {}
EasyUnlockPrivateConnectionManager::~EasyUnlockPrivateConnectionManager() {
// Remove |this| as an observer from all connections passed to
// |AddConnection()|.
for (const auto& extension_id : extensions_) {
base::hash_set<int>* connections =
GetResourceManager()->GetResourceIds(extension_id);
for (int connection_id : *connections) {
Connection* connection = GetConnection(extension_id, connection_id);
if (connection)
connection->RemoveObserver(this);
}
}
}
int EasyUnlockPrivateConnectionManager::AddConnection(
const Extension* extension,
std::unique_ptr<Connection> connection,
bool persistent) {
DCHECK(connection);
connection->AddObserver(this);
extensions_.insert(extension->id());
EasyUnlockPrivateConnection* api_connection = new EasyUnlockPrivateConnection(
persistent, extension->id(), std::move(connection));
int connection_id = GetResourceManager()->Add(api_connection);
return connection_id;
}
api::easy_unlock_private::ConnectionStatus
EasyUnlockPrivateConnectionManager::ConnectionStatus(const Extension* extension,
int connection_id) const {
Connection* connection = GetConnection(extension->id(), connection_id);
if (connection)
return ToApiConnectionStatus(connection->status());
return api::easy_unlock_private::CONNECTION_STATUS_NONE;
}
std::string EasyUnlockPrivateConnectionManager::GetDeviceAddress(
const Extension* extension,
int connection_id) const {
Connection* connection = GetConnection(extension->id(), connection_id);
if (!connection)
return std::string();
return connection->GetDeviceAddress();
}
bool EasyUnlockPrivateConnectionManager::Disconnect(const Extension* extension,
int connection_id) {
Connection* connection = GetConnection(extension->id(), connection_id);
if (connection) {
connection->Disconnect();
return true;
}
return false;
}
bool EasyUnlockPrivateConnectionManager::SendMessage(
const Extension* extension,
int connection_id,
const std::string& payload) {
Connection* connection = GetConnection(extension->id(), connection_id);
if (connection && connection->IsConnected()) {
connection->SendMessage(base::MakeUnique<WireMessage>(payload));
return true;
}
return false;
}
void EasyUnlockPrivateConnectionManager::OnConnectionStatusChanged(
Connection* connection,
Connection::Status old_status,
Connection::Status new_status) {
std::string event_name =
api::easy_unlock_private::OnConnectionStatusChanged::kEventName;
events::HistogramValue histogram_value =
events::EASY_UNLOCK_PRIVATE_ON_CONNECTION_STATUS_CHANGED;
std::unique_ptr<base::ListValue> args =
api::easy_unlock_private::OnConnectionStatusChanged::Create(
0, ToApiConnectionStatus(old_status),
ToApiConnectionStatus(new_status));
DispatchConnectionEvent(event_name, histogram_value, connection,
std::move(args));
}
void EasyUnlockPrivateConnectionManager::OnMessageReceived(
const Connection& connection,
const WireMessage& message) {
std::string event_name = api::easy_unlock_private::OnDataReceived::kEventName;
events::HistogramValue histogram_value =
events::EASY_UNLOCK_PRIVATE_ON_DATA_RECEIVED;
std::vector<char> data(message.payload().begin(), message.payload().end());
std::unique_ptr<base::ListValue> args =
api::easy_unlock_private::OnDataReceived::Create(0, data);
DispatchConnectionEvent(event_name, histogram_value, &connection,
std::move(args));
}
void EasyUnlockPrivateConnectionManager::OnSendCompleted(
const Connection& connection,
const WireMessage& message,
bool success) {
std::string event_name =
api::easy_unlock_private::OnSendCompleted::kEventName;
events::HistogramValue histogram_value =
events::EASY_UNLOCK_PRIVATE_ON_SEND_COMPLETED;
std::vector<char> data(message.payload().begin(), message.payload().end());
std::unique_ptr<base::ListValue> args =
api::easy_unlock_private::OnSendCompleted::Create(0, data, success);
DispatchConnectionEvent(event_name, histogram_value, &connection,
std::move(args));
}
void EasyUnlockPrivateConnectionManager::DispatchConnectionEvent(
const std::string& event_name,
events::HistogramValue histogram_value,
const Connection* connection,
std::unique_ptr<base::ListValue> args) {
const EventListenerMap::ListenerList& listeners =
EventRouter::Get(browser_context_)
->listeners()
.GetEventListenersByName(event_name);
for (const auto& listener : listeners) {
std::string extension_id = listener->extension_id();
int connection_id = FindConnectionId(extension_id, connection);
std::unique_ptr<base::ListValue> args_copy(args->DeepCopy());
int connection_index = 0;
args_copy->Set(connection_index,
base::MakeUnique<base::FundamentalValue>(connection_id));
std::unique_ptr<Event> event(
new Event(histogram_value, event_name, std::move(args_copy)));
EventRouter::Get(browser_context_)
->DispatchEventToExtension(extension_id, std::move(event));
}
}
ApiResourceManager<EasyUnlockPrivateConnection>*
EasyUnlockPrivateConnectionManager::GetResourceManager() const {
return ApiResourceManager<EasyUnlockPrivateConnection>::Get(browser_context_);
}
Connection* EasyUnlockPrivateConnectionManager::GetConnection(
const std::string& extension_id,
int connection_id) const {
ApiResourceManager<EasyUnlockPrivateConnection>* manager =
GetResourceManager();
EasyUnlockPrivateConnection* easy_unlock_connection =
manager->Get(extension_id, connection_id);
if (easy_unlock_connection) {
return easy_unlock_connection->GetConnection();
}
return nullptr;
}
int EasyUnlockPrivateConnectionManager::FindConnectionId(
const std::string& extension_id,
const Connection* connection) {
base::hash_set<int>* connection_ids =
GetResourceManager()->GetResourceIds(extension_id);
for (int connection_id : *connection_ids) {
if (connection == GetConnection(extension_id, connection_id))
return connection_id;
}
return 0;
}
} // namespace extensions