| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright 2015 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/peer_connection_identity_store.h" |  | 
| 6 |  | 
| 7 #include <memory> |  | 
| 8 |  | 
| 9 #include "base/bind.h" |  | 
| 10 #include "base/macros.h" |  | 
| 11 #include "base/threading/thread_task_runner_handle.h" |  | 
| 12 #include "content/renderer/media/webrtc_identity_service.h" |  | 
| 13 #include "content/renderer/render_thread_impl.h" |  | 
| 14 |  | 
| 15 namespace content { |  | 
| 16 namespace { |  | 
| 17 |  | 
| 18 const char kIdentityName[] = "WebRTC"; |  | 
| 19 static unsigned int kRSAChromiumKeyLength = 1024; |  | 
| 20 static unsigned int kRSAChromiumPubExp = 0x10001; |  | 
| 21 static uint64_t kYearInSeconds = 365 * 24 * 60 * 60; |  | 
| 22 |  | 
| 23 // Bridges identity requests between the main render thread and libjingle's |  | 
| 24 // signaling thread. |  | 
| 25 class RequestHandler : public base::RefCountedThreadSafe<RequestHandler> { |  | 
| 26  public: |  | 
| 27   explicit RequestHandler( |  | 
| 28       const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, |  | 
| 29       const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread, |  | 
| 30       webrtc::DtlsIdentityRequestObserver* observer) |  | 
| 31       : main_thread_(main_thread), |  | 
| 32         signaling_thread_(signaling_thread), |  | 
| 33         observer_(observer) { |  | 
| 34     DCHECK(main_thread_); |  | 
| 35     DCHECK(signaling_thread_); |  | 
| 36     DCHECK(observer_); |  | 
| 37   } |  | 
| 38 |  | 
| 39   void RequestIdentityOnMainThread(const GURL& url, |  | 
| 40                                    const GURL& first_party_for_cookies) { |  | 
| 41     DCHECK(main_thread_->BelongsToCurrentThread()); |  | 
| 42     int request_id = |  | 
| 43         RenderThreadImpl::current() |  | 
| 44             ->get_webrtc_identity_service() |  | 
| 45             ->RequestIdentity( |  | 
| 46                 url, first_party_for_cookies, kIdentityName, kIdentityName, |  | 
| 47                 base::Bind(&RequestHandler::OnIdentityReady, this), |  | 
| 48                 base::Bind(&RequestHandler::OnRequestFailed, this)); |  | 
| 49     DCHECK_NE(request_id, 0); |  | 
| 50   } |  | 
| 51 |  | 
| 52  private: |  | 
| 53   friend class base::RefCountedThreadSafe<RequestHandler>; |  | 
| 54   ~RequestHandler() { |  | 
| 55     DCHECK(!observer_); |  | 
| 56   } |  | 
| 57 |  | 
| 58   void OnIdentityReady( |  | 
| 59       const std::string& certificate, |  | 
| 60       const std::string& private_key) { |  | 
| 61     DCHECK(main_thread_->BelongsToCurrentThread()); |  | 
| 62     signaling_thread_->PostTask(FROM_HERE, |  | 
| 63         base::Bind(static_cast<void (webrtc::DtlsIdentityRequestObserver::*)( |  | 
| 64                        const std::string&, const std::string&)>( |  | 
| 65                            &webrtc::DtlsIdentityRequestObserver::OnSuccess), |  | 
| 66                    observer_, certificate, private_key)); |  | 
| 67     signaling_thread_->PostTask(FROM_HERE, |  | 
| 68         base::Bind(&RequestHandler::EnsureReleaseObserverOnSignalingThread, |  | 
| 69             this)); |  | 
| 70   } |  | 
| 71 |  | 
| 72   void OnRequestFailed(int error) { |  | 
| 73     DCHECK(main_thread_->BelongsToCurrentThread()); |  | 
| 74     signaling_thread_->PostTask(FROM_HERE, |  | 
| 75         base::Bind(&webrtc::DtlsIdentityRequestObserver::OnFailure, observer_, |  | 
| 76                    error)); |  | 
| 77     signaling_thread_->PostTask(FROM_HERE, |  | 
| 78         base::Bind(&RequestHandler::EnsureReleaseObserverOnSignalingThread, |  | 
| 79             this)); |  | 
| 80   } |  | 
| 81 |  | 
| 82   void EnsureReleaseObserverOnSignalingThread() { |  | 
| 83     DCHECK(signaling_thread_->BelongsToCurrentThread()); |  | 
| 84     observer_ = nullptr; |  | 
| 85   } |  | 
| 86 |  | 
| 87   const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; |  | 
| 88   const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_; |  | 
| 89   scoped_refptr<webrtc::DtlsIdentityRequestObserver> observer_; |  | 
| 90 }; |  | 
| 91 |  | 
| 92 // Helper function for PeerConnectionIdentityStore::RequestIdentity. |  | 
| 93 // Used to invoke |observer|->OnSuccess in a PostTask. |  | 
| 94 void ObserverOnSuccess( |  | 
| 95     const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>& observer, |  | 
| 96     std::unique_ptr<rtc::SSLIdentity> identity) { |  | 
| 97   observer->OnSuccess(std::move(identity)); |  | 
| 98 } |  | 
| 99 |  | 
| 100 }  // namespace |  | 
| 101 |  | 
| 102 PeerConnectionIdentityStore::PeerConnectionIdentityStore( |  | 
| 103     const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, |  | 
| 104     const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread, |  | 
| 105     const GURL& url, |  | 
| 106     const GURL& first_party_for_cookies) |  | 
| 107     : main_thread_(main_thread), |  | 
| 108       signaling_thread_(signaling_thread), |  | 
| 109       url_(url), |  | 
| 110       first_party_for_cookies_(first_party_for_cookies) { |  | 
| 111   DCHECK(main_thread_); |  | 
| 112   DCHECK(signaling_thread_); |  | 
| 113 } |  | 
| 114 |  | 
| 115 PeerConnectionIdentityStore::~PeerConnectionIdentityStore() { |  | 
| 116   // Typically destructed on libjingle's signaling thread. |  | 
| 117 } |  | 
| 118 |  | 
| 119 void PeerConnectionIdentityStore::RequestIdentity( |  | 
| 120     const rtc::KeyParams& key_params, |  | 
| 121     const rtc::Optional<uint64_t>& expires_ms, |  | 
| 122     const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>& observer) { |  | 
| 123   DCHECK(signaling_thread_->BelongsToCurrentThread()); |  | 
| 124   DCHECK(observer); |  | 
| 125 |  | 
| 126   // TODO(torbjorng): crbug.com/544902. RequestIdentityOnUIThread uses Chromium |  | 
| 127   // key generation code with the assumption that it will generate with the |  | 
| 128   // following rsa_params(). This assumption should not be implicit! Either pass |  | 
| 129   // the parameters along or check against constants exported from relevant |  | 
| 130   // header file(s). |  | 
| 131   if (key_params.type() == rtc::KT_RSA && |  | 
| 132       key_params.rsa_params().mod_size == kRSAChromiumKeyLength && |  | 
| 133       key_params.rsa_params().pub_exp == kRSAChromiumPubExp && |  | 
| 134       !expires_ms) { |  | 
| 135     // Use Chromium identity generation code for its hardwired parameters (RSA, |  | 
| 136     // 1024, 0x10001). This generation code is preferred over WebRTC generation |  | 
| 137     // code due to the performance benefits of caching. |  | 
| 138     scoped_refptr<RequestHandler> handler( |  | 
| 139         new RequestHandler(main_thread_, signaling_thread_, observer)); |  | 
| 140     main_thread_->PostTask( |  | 
| 141         FROM_HERE, |  | 
| 142         base::Bind(&RequestHandler::RequestIdentityOnMainThread, handler, url_, |  | 
| 143                    first_party_for_cookies_)); |  | 
| 144   } else { |  | 
| 145     // Fall back on WebRTC identity generation code for everything else, e.g. |  | 
| 146     // RSA with any other parameters or ECDSA. These will not be cached. |  | 
| 147     std::unique_ptr<rtc::SSLIdentity> identity; |  | 
| 148     if (!expires_ms) { |  | 
| 149       identity.reset(rtc::SSLIdentity::Generate(kIdentityName, key_params)); |  | 
| 150     } else { |  | 
| 151       uint64_t expires_s = *expires_ms / 1000; |  | 
| 152       // Limit the expiration time to something reasonable (a year). This also |  | 
| 153       // ensures that the value is not too large for |time_t|. |  | 
| 154       if (expires_s > kYearInSeconds) |  | 
| 155         expires_s = kYearInSeconds; |  | 
| 156       // TODO(hbos,torbjorng): Update |SSLIdentity::GenerateWithExpiration| not |  | 
| 157       // to use |time_t| and stop using |time_t| here, its type is unspecified |  | 
| 158       // and shouldn't be used if we have a choice. bugs.webrtc.org/5720. |  | 
| 159       identity.reset(rtc::SSLIdentity::GenerateWithExpiration( |  | 
| 160           kIdentityName, key_params, static_cast<time_t>(expires_s))); |  | 
| 161     } |  | 
| 162 |  | 
| 163     // Invoke |observer| callbacks asynchronously. The callbacks of |  | 
| 164     // DtlsIdentityStoreInterface implementations have to be async. |  | 
| 165     if (identity) { |  | 
| 166       // Async call to |observer|->OnSuccess. |  | 
| 167       signaling_thread_->PostTask(FROM_HERE, |  | 
| 168           base::Bind(&ObserverOnSuccess, observer, base::Passed(&identity))); |  | 
| 169     } else { |  | 
| 170       // Async call to |observer|->OnFailure. |  | 
| 171       signaling_thread_->PostTask(FROM_HERE, |  | 
| 172           base::Bind(&webrtc::DtlsIdentityRequestObserver::OnFailure, |  | 
| 173                      observer, 0)); |  | 
| 174     } |  | 
| 175   } |  | 
| 176 } |  | 
| 177 |  | 
| 178 }  // namespace content |  | 
| OLD | NEW | 
|---|