blob: c85dce1398e833197aa6ec60a079dd481839027c [file] [log] [blame]
// 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 "content/renderer/media/webrtc_identity_service.h"
#include "content/common/media/webrtc_identity_messages.h"
#include "content/public/renderer/render_thread.h"
#include "net/base/net_errors.h"
namespace content {
WebRTCIdentityService::RequestInfo::RequestInfo(
int request_id,
const GURL& origin,
const std::string& identity_name,
const std::string& common_name,
const SuccessCallback& success_callback,
const FailureCallback& failure_callback)
: request_id(request_id),
origin(origin),
identity_name(identity_name),
common_name(common_name),
success_callback(success_callback),
failure_callback(failure_callback) {}
WebRTCIdentityService::RequestInfo::~RequestInfo() {}
WebRTCIdentityService::WebRTCIdentityService() : next_request_id_(1) {
// RenderThread::Get() could be NULL in unit tests.
if (RenderThread::Get())
RenderThread::Get()->AddObserver(this);
}
WebRTCIdentityService::~WebRTCIdentityService() {
// RenderThread::Get() could be NULL in unit tests.
if (RenderThread::Get()) {
RenderThread::Get()->RemoveObserver(this);
if (!pending_requests_.empty()) {
RenderThread::Get()->Send(new WebRTCIdentityMsg_CancelRequest());
}
}
}
int WebRTCIdentityService::RequestIdentity(
const GURL& origin,
const std::string& identity_name,
const std::string& common_name,
const SuccessCallback& success_callback,
const FailureCallback& failure_callback) {
int request_id = next_request_id_++;
RequestInfo request_info(request_id,
origin,
identity_name,
common_name,
success_callback,
failure_callback);
pending_requests_.push_back(request_info);
if (pending_requests_.size() == 1)
SendRequest(request_info);
return request_id;
}
void WebRTCIdentityService::CancelRequest(int request_id) {
std::deque<RequestInfo>::iterator it;
for (it = pending_requests_.begin(); it != pending_requests_.end(); ++it) {
if (it->request_id != request_id)
continue;
if (it != pending_requests_.begin()) {
pending_requests_.erase(it);
} else {
Send(new WebRTCIdentityMsg_CancelRequest());
OnOutstandingRequestReturned();
}
break;
}
}
bool WebRTCIdentityService::Send(IPC::Message* message) {
// Unit tests should override this method to avoid null-ptr-deref.
return RenderThread::Get()->Send(message);
}
bool WebRTCIdentityService::OnControlMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(WebRTCIdentityService, message)
IPC_MESSAGE_HANDLER(WebRTCIdentityHostMsg_IdentityReady, OnIdentityReady)
IPC_MESSAGE_HANDLER(WebRTCIdentityHostMsg_RequestFailed, OnRequestFailed)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void WebRTCIdentityService::OnIdentityReady(int request_id,
const std::string& certificate,
const std::string& private_key) {
// The browser process may have sent the response before it receives the
// message to cancel the request. So we need to check if the returned response
// matches the request on the top of the queue.
if (pending_requests_.empty() ||
pending_requests_.front().request_id != request_id)
return;
pending_requests_.front().success_callback.Run(certificate, private_key);
OnOutstandingRequestReturned();
}
void WebRTCIdentityService::OnRequestFailed(int request_id, int error) {
// The browser process may have sent the response before it receives the
// message to cancel the request. So we need to check if the returned response
// matches the request on the top of the queue.
if (pending_requests_.empty() ||
pending_requests_.front().request_id != request_id)
return;
pending_requests_.front().failure_callback.Run(error);
OnOutstandingRequestReturned();
}
void WebRTCIdentityService::SendRequest(const RequestInfo& request_info) {
if (!Send(new WebRTCIdentityMsg_RequestIdentity(request_info.request_id,
request_info.origin,
request_info.identity_name,
request_info.common_name))) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&WebRTCIdentityService::OnRequestFailed,
base::Unretained(this),
request_info.request_id,
net::ERR_UNEXPECTED));
}
}
void WebRTCIdentityService::OnOutstandingRequestReturned() {
pending_requests_.pop_front();
if (!pending_requests_.empty())
SendRequest(pending_requests_.front());
}
} // namespace content