Home | History | Annotate | Download | only in media
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/renderer/media/webrtc_identity_service.h"
      6 
      7 #include "content/common/media/webrtc_identity_messages.h"
      8 #include "content/public/renderer/render_thread.h"
      9 #include "net/base/net_errors.h"
     10 
     11 namespace content {
     12 
     13 WebRTCIdentityService::RequestInfo::RequestInfo(
     14     int request_id,
     15     const GURL& origin,
     16     const std::string& identity_name,
     17     const std::string& common_name,
     18     const SuccessCallback& success_callback,
     19     const FailureCallback& failure_callback)
     20     : request_id(request_id),
     21       origin(origin),
     22       identity_name(identity_name),
     23       common_name(common_name),
     24       success_callback(success_callback),
     25       failure_callback(failure_callback) {}
     26 
     27 WebRTCIdentityService::RequestInfo::~RequestInfo() {}
     28 
     29 WebRTCIdentityService::WebRTCIdentityService() : next_request_id_(1) {
     30   // RenderThread::Get() could be NULL in unit tests.
     31   if (RenderThread::Get())
     32     RenderThread::Get()->AddObserver(this);
     33 }
     34 
     35 WebRTCIdentityService::~WebRTCIdentityService() {
     36   // RenderThread::Get() could be NULL in unit tests.
     37   if (RenderThread::Get()) {
     38     RenderThread::Get()->RemoveObserver(this);
     39 
     40     if (!pending_requests_.empty()) {
     41       RenderThread::Get()->Send(new WebRTCIdentityMsg_CancelRequest());
     42     }
     43   }
     44 }
     45 
     46 int WebRTCIdentityService::RequestIdentity(
     47     const GURL& origin,
     48     const std::string& identity_name,
     49     const std::string& common_name,
     50     const SuccessCallback& success_callback,
     51     const FailureCallback& failure_callback) {
     52   int request_id = next_request_id_++;
     53 
     54   RequestInfo request_info(request_id,
     55                            origin,
     56                            identity_name,
     57                            common_name,
     58                            success_callback,
     59                            failure_callback);
     60 
     61   pending_requests_.push_back(request_info);
     62   if (pending_requests_.size() == 1)
     63     SendRequest(request_info);
     64 
     65   return request_id;
     66 }
     67 
     68 void WebRTCIdentityService::CancelRequest(int request_id) {
     69   std::deque<RequestInfo>::iterator it;
     70   for (it = pending_requests_.begin(); it != pending_requests_.end(); ++it) {
     71     if (it->request_id != request_id)
     72       continue;
     73     if (it != pending_requests_.begin()) {
     74       pending_requests_.erase(it);
     75     } else {
     76       Send(new WebRTCIdentityMsg_CancelRequest());
     77       OnOutstandingRequestReturned();
     78     }
     79     break;
     80   }
     81 }
     82 
     83 bool WebRTCIdentityService::Send(IPC::Message* message) {
     84   // Unit tests should override this method to avoid null-ptr-deref.
     85   return RenderThread::Get()->Send(message);
     86 }
     87 
     88 bool WebRTCIdentityService::OnControlMessageReceived(
     89     const IPC::Message& message) {
     90   bool handled = true;
     91   IPC_BEGIN_MESSAGE_MAP(WebRTCIdentityService, message)
     92     IPC_MESSAGE_HANDLER(WebRTCIdentityHostMsg_IdentityReady, OnIdentityReady)
     93     IPC_MESSAGE_HANDLER(WebRTCIdentityHostMsg_RequestFailed, OnRequestFailed)
     94     IPC_MESSAGE_UNHANDLED(handled = false)
     95   IPC_END_MESSAGE_MAP()
     96 
     97   return handled;
     98 }
     99 
    100 void WebRTCIdentityService::OnIdentityReady(int request_id,
    101                                             const std::string& certificate,
    102                                             const std::string& private_key) {
    103   // The browser process may have sent the response before it receives the
    104   // message to cancel the request. So we need to check if the returned response
    105   // matches the request on the top of the queue.
    106   if (pending_requests_.empty() ||
    107       pending_requests_.front().request_id != request_id)
    108     return;
    109 
    110   pending_requests_.front().success_callback.Run(certificate, private_key);
    111   OnOutstandingRequestReturned();
    112 }
    113 
    114 void WebRTCIdentityService::OnRequestFailed(int request_id, int error) {
    115   // The browser process may have sent the response before it receives the
    116   // message to cancel the request. So we need to check if the returned response
    117   // matches the request on the top of the queue.
    118   if (pending_requests_.empty() ||
    119       pending_requests_.front().request_id != request_id)
    120     return;
    121 
    122   pending_requests_.front().failure_callback.Run(error);
    123   OnOutstandingRequestReturned();
    124 }
    125 
    126 void WebRTCIdentityService::SendRequest(const RequestInfo& request_info) {
    127   if (!Send(new WebRTCIdentityMsg_RequestIdentity(request_info.request_id,
    128                                                   request_info.origin,
    129                                                   request_info.identity_name,
    130                                                   request_info.common_name))) {
    131     base::MessageLoop::current()->PostTask(
    132         FROM_HERE,
    133         base::Bind(&WebRTCIdentityService::OnRequestFailed,
    134                    base::Unretained(this),
    135                    request_info.request_id,
    136                    net::ERR_UNEXPECTED));
    137   }
    138 }
    139 
    140 void WebRTCIdentityService::OnOutstandingRequestReturned() {
    141   pending_requests_.pop_front();
    142 
    143   if (!pending_requests_.empty())
    144     SendRequest(pending_requests_.front());
    145 }
    146 
    147 }  // namespace content
    148