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