// 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::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