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