summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-01 21:21:46 +0000
committerjiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-01 21:21:46 +0000
commitd322066dba0d6bfb0e591b651c47f5e27efcb98a (patch)
tree39714d7f6a3539ef29b41d282b5705e75bb5b976
parent142c27f34f9e70290ee032d92cec7bd2b78c4b90 (diff)
downloadchromium_src-d322066dba0d6bfb0e591b651c47f5e27efcb98a.zip
chromium_src-d322066dba0d6bfb0e591b651c47f5e27efcb98a.tar.gz
chromium_src-d322066dba0d6bfb0e591b651c47f5e27efcb98a.tar.bz2
Generates the DTLS identity in browser process and returns it to the renderer process.
This is the first part of implementing a persistent identity store for WebRTC in Chrome. It implements the IPC messages to request and return the DTLS identity and the identity generation in browser process. A persistent store based on SQLite DB will be implemented later. DTLSIdentityService: used in the renderer process to request a DTLS identity. It sends an IPC to the browser process and receives the reply containing the identity in a callback. DTLSIdentityServiceHost: listens for the IPC message from DTLSIdentityService and passes the request to DTLSIdentityStore. DTLSIdentityStore: created per RenerProcessHost. For now it always generates a new identity on a worker thread for each request, without any caching or persistent storage. BUG=https://code.google.com/p/webrtc/issues/detail?id=1864 Review URL: https://chromiumcodereview.appspot.com/15969025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@209499 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/media/webrtc_identity_store.cc180
-rw-r--r--content/browser/media/webrtc_identity_store.h74
-rw-r--r--content/browser/media/webrtc_identity_store_unittest.cc104
-rw-r--r--content/browser/renderer_host/media/webrtc_identity_service_host.cc80
-rw-r--r--content/browser/renderer_host/media/webrtc_identity_service_host.h66
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc8
-rw-r--r--content/browser/storage_partition_impl.cc17
-rw-r--r--content/browser/storage_partition_impl.h7
-rw-r--r--content/browser/storage_partition_impl_unittest.cc12
-rw-r--r--content/common/content_message_generator.h1
-rw-r--r--content/common/media/webrtc_identity_messages.h32
-rw-r--r--content/content_browser.gypi4
-rw-r--r--content/content_common.gypi1
-rw-r--r--content/content_renderer.gypi2
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/renderer/media/webrtc_identity_service.cc82
-rw-r--r--content/renderer/media/webrtc_identity_service.h51
-rw-r--r--ipc/ipc_message_start.h3
-rw-r--r--net/base/net_error_list.h3
19 files changed, 718 insertions, 10 deletions
diff --git a/content/browser/media/webrtc_identity_store.cc b/content/browser/media/webrtc_identity_store.cc
new file mode 100644
index 0000000..17827cb
--- /dev/null
+++ b/content/browser/media/webrtc_identity_store.cc
@@ -0,0 +1,180 @@
+// 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/browser/media/webrtc_identity_store.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/logging.h"
+#include "base/rand_util.h"
+#include "base/threading/worker_pool.h"
+#include "content/public/browser/browser_thread.h"
+#include "crypto/rsa_private_key.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_errors.h"
+#include "net/cert/x509_util.h"
+
+namespace content {
+
+struct WebRTCIdentityRequestResult {
+ int error;
+ std::string certificate;
+ std::string private_key;
+};
+
+static void GenerateIdentityWorker(const std::string& common_name,
+ WebRTCIdentityRequestResult* result) {
+ result->error = net::OK;
+ int serial_number = base::RandInt(0, std::numeric_limits<int>::max());
+
+ scoped_ptr<crypto::RSAPrivateKey> key(crypto::RSAPrivateKey::Create(1024));
+ if (!key.get()) {
+ DLOG(ERROR) << "Unable to create key pair for client";
+ result->error = net::ERR_KEY_GENERATION_FAILED;
+ return;
+ }
+
+ base::Time now = base::Time::Now();
+ bool success =
+ net::x509_util::CreateSelfSignedCert(key.get(),
+ "CN=" + common_name,
+ serial_number,
+ now,
+ now + base::TimeDelta::FromDays(30),
+ &result->certificate);
+ if (!success) {
+ DLOG(ERROR) << "Unable to create x509 cert for client";
+ result->error = net::ERR_SELF_SIGNED_CERT_GENERATION_FAILED;
+ return;
+ }
+
+ std::vector<uint8> private_key_info;
+ if (!key->ExportPrivateKey(&private_key_info)) {
+ DLOG(ERROR) << "Unable to export private key";
+ result->error = net::ERR_PRIVATE_KEY_EXPORT_FAILED;
+ return;
+ }
+
+ result->private_key =
+ std::string(private_key_info.begin(), private_key_info.end());
+}
+
+// The class represents an identity request internal to WebRTCIdentityStore.
+// It has a one-to-one mapping to the external version of the request
+// WebRTCIdentityRequestHandle, which is the target of the
+// WebRTCIdentityRequest's completion callback.
+// It's deleted automatically when the request is completed.
+class WebRTCIdentityRequest {
+ public:
+ WebRTCIdentityRequest(const WebRTCIdentityStore::CompletionCallback& callback)
+ : callback_(callback) {}
+
+ void Cancel() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ callback_.Reset();
+ }
+
+ private:
+ friend class WebRTCIdentityStore;
+
+ void Post(WebRTCIdentityRequestResult* result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (callback_.is_null())
+ return;
+ callback_.Run(result->error, result->certificate, result->private_key);
+ // "this" will be deleted after this point.
+ }
+
+ WebRTCIdentityStore::CompletionCallback callback_;
+};
+
+// The class represents an identity request which calls back to the external
+// client when the request completes.
+// Its lifetime is tied with the Callback held by the corresponding
+// WebRTCIdentityRequest.
+class WebRTCIdentityRequestHandle {
+ public:
+ WebRTCIdentityRequestHandle(
+ WebRTCIdentityStore* store,
+ const WebRTCIdentityStore::CompletionCallback& callback)
+ : store_(store), request_(NULL), callback_(callback) {}
+
+ private:
+ friend class WebRTCIdentityStore;
+
+ // Cancel the request. Does nothing if the request finished or was already
+ // cancelled.
+ void Cancel() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!request_)
+ return;
+
+ callback_.Reset();
+ WebRTCIdentityRequest* request = request_;
+ request_ = NULL;
+ // "this" will be deleted after the following call, because "this" is
+ // owned by the Callback held by |request|.
+ request->Cancel();
+ }
+
+ void OnRequestStarted(WebRTCIdentityRequest* request) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(request);
+ request_ = request;
+ }
+
+ void OnRequestComplete(int error,
+ const std::string& certificate,
+ const std::string& private_key) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(request_);
+ request_ = NULL;
+ base::ResetAndReturn(&callback_).Run(error, certificate, private_key);
+ }
+
+ WebRTCIdentityStore* store_;
+ WebRTCIdentityRequest* request_;
+ WebRTCIdentityStore::CompletionCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityRequestHandle);
+};
+
+WebRTCIdentityStore::WebRTCIdentityStore()
+ : task_runner_(base::WorkerPool::GetTaskRunner(true)) {}
+
+WebRTCIdentityStore::~WebRTCIdentityStore() {}
+
+base::Closure WebRTCIdentityStore::RequestIdentity(
+ const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name,
+ const CompletionCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ WebRTCIdentityRequestHandle* handle =
+ new WebRTCIdentityRequestHandle(this, callback);
+
+ WebRTCIdentityRequest* request = new WebRTCIdentityRequest(base::Bind(
+ &WebRTCIdentityRequestHandle::OnRequestComplete, base::Owned(handle)));
+ handle->OnRequestStarted(request);
+
+ WebRTCIdentityRequestResult* result = new WebRTCIdentityRequestResult();
+ if (!task_runner_->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&GenerateIdentityWorker, common_name, result),
+ base::Bind(&WebRTCIdentityRequest::Post,
+ base::Owned(request),
+ base::Owned(result))))
+ return base::Closure();
+
+ return base::Bind(&WebRTCIdentityRequestHandle::Cancel,
+ base::Unretained(handle));
+}
+
+void WebRTCIdentityStore::SetTaskRunnerForTesting(
+ const scoped_refptr<base::TaskRunner>& task_runner) {
+ task_runner_ = task_runner;
+}
+
+} // namespace content
diff --git a/content/browser/media/webrtc_identity_store.h b/content/browser/media/webrtc_identity_store.h
new file mode 100644
index 0000000..9b3b444
--- /dev/null
+++ b/content/browser/media/webrtc_identity_store.h
@@ -0,0 +1,74 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_H_
+#define CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+
+class GURL;
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+namespace content {
+
+class WebRTCIdentityStoreTest;
+
+// A class for creating and fetching DTLS identities, i.e. the private key and
+// the self-signed certificate.
+class CONTENT_EXPORT WebRTCIdentityStore {
+ public:
+ typedef base::Callback<void(int error,
+ const std::string& certificate,
+ const std::string& private_key)>
+ CompletionCallback;
+
+ WebRTCIdentityStore();
+ ~WebRTCIdentityStore();
+
+ // Retrieve the cached DTLS private key and certificate, i.e. identity, for
+ // the |origin| and |identity_name| pair, or generate a new identity using
+ // |common_name| if such an identity does not exist.
+ // If the given |common_name| is different from the common name in the cached
+ // identity that has the same origin and identity_name, a new private key and
+ // a new certificate will be generated, overwriting the old one.
+ // TODO(jiayl): implement identity caching through a persistent storage.
+ //
+ // |origin| is the origin of the DTLS connection;
+ // |identity_name| is used to identify an identity within an origin; it is
+ // opaque to WebRTCIdentityStore and remains private to the caller, i.e. not
+ // present in the certificate;
+ // |common_name| is the common name used to generate the certificate and will
+ // be shared with the peer of the DTLS connection. Identities created for
+ // different origins or different identity names may have the same common
+ // name.
+ // |callback| is the callback to return the result.
+ //
+ // Returns the Closure used to cancel the request if the request is accepted.
+ // The Closure can only be called before the request completes.
+ base::Closure RequestIdentity(const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name,
+ const CompletionCallback& callback);
+
+ private:
+ friend class WebRTCIdentityStoreTest;
+
+ void SetTaskRunnerForTesting(
+ const scoped_refptr<base::TaskRunner>& task_runner);
+
+ // The TaskRunner for doing work on a worker thread.
+ scoped_refptr<base::TaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityStore);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_H_
diff --git a/content/browser/media/webrtc_identity_store_unittest.cc b/content/browser/media/webrtc_identity_store_unittest.cc
new file mode 100644
index 0000000..d68528e
--- /dev/null
+++ b/content/browser/media/webrtc_identity_store_unittest.cc
@@ -0,0 +1,104 @@
+// 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 "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "content/browser/media/webrtc_identity_store.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_errors.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+// TODO(jiayl): the tests fail on Android since the openssl version of
+// CreateSelfSignedCert is not implemented. We should mock out this dependency
+// and remove the if-defined.
+
+#if !defined(OS_ANDROID)
+class WebRTCIdentityStoreTest : public testing::Test {
+ public:
+ WebRTCIdentityStoreTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ sequenced_worker_pool_(
+ new base::SequencedWorkerPool(3, "WebRTCIdentityStoreTest")),
+ webrtc_identity_store_(new WebRTCIdentityStore()) {
+ webrtc_identity_store_->SetTaskRunnerForTesting(sequenced_worker_pool_);
+ }
+
+ virtual ~WebRTCIdentityStoreTest() { sequenced_worker_pool_->Shutdown(); }
+
+ protected:
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_refptr<base::SequencedWorkerPool> sequenced_worker_pool_;
+ scoped_ptr<WebRTCIdentityStore> webrtc_identity_store_;
+};
+
+static void OnRequestCompleted(bool* completed,
+ int error,
+ const std::string& certificate,
+ const std::string& private_key) {
+ ASSERT_EQ(net::OK, error);
+ ASSERT_NE("", certificate);
+ ASSERT_NE("", private_key);
+ *completed = true;
+}
+
+TEST_F(WebRTCIdentityStoreTest, RequestIdentity) {
+ bool completed = false;
+ base::Closure cancel_callback =
+ webrtc_identity_store_->RequestIdentity(
+ GURL("http://google.com"),
+ "a",
+ "b",
+ base::Bind(&OnRequestCompleted, &completed));
+ ASSERT_FALSE(cancel_callback.is_null());
+ sequenced_worker_pool_->FlushForTesting();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(completed);
+}
+
+TEST_F(WebRTCIdentityStoreTest, CancelRequest) {
+ bool completed = false;
+ base::Closure cancel_callback =
+ webrtc_identity_store_->RequestIdentity(
+ GURL("http://google.com"),
+ "a",
+ "b",
+ base::Bind(&OnRequestCompleted, &completed));
+ ASSERT_FALSE(cancel_callback.is_null());
+ cancel_callback.Run();
+ sequenced_worker_pool_->FlushForTesting();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(completed);
+}
+
+TEST_F(WebRTCIdentityStoreTest, MultipleRequests) {
+ bool completed_1 = false;
+ bool completed_2 = false;
+ base::Closure cancel_callback_1 =
+ webrtc_identity_store_->RequestIdentity(
+ GURL("http://foo.com"),
+ "a",
+ "b",
+ base::Bind(&OnRequestCompleted, &completed_1));
+ ASSERT_FALSE(cancel_callback_1.is_null());
+
+ base::Closure cancel_callback_2 =
+ webrtc_identity_store_->RequestIdentity(
+ GURL("http://bar.com"),
+ "a",
+ "b",
+ base::Bind(&OnRequestCompleted, &completed_2));
+ ASSERT_FALSE(cancel_callback_2.is_null());
+
+ sequenced_worker_pool_->FlushForTesting();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(completed_1);
+ EXPECT_TRUE(completed_2);
+}
+#endif
+} // namespace content
diff --git a/content/browser/renderer_host/media/webrtc_identity_service_host.cc b/content/browser/renderer_host/media/webrtc_identity_service_host.cc
new file mode 100644
index 0000000..9956b86
--- /dev/null
+++ b/content/browser/renderer_host/media/webrtc_identity_service_host.cc
@@ -0,0 +1,80 @@
+// 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/browser/renderer_host/media/webrtc_identity_service_host.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "content/browser/media/webrtc_identity_store.h"
+#include "content/common/media/webrtc_identity_messages.h"
+#include "net/base/net_errors.h"
+
+namespace content {
+
+WebRTCIdentityServiceHost::WebRTCIdentityServiceHost(
+ WebRTCIdentityStore* identity_store)
+ : identity_store_(identity_store) {}
+
+WebRTCIdentityServiceHost::~WebRTCIdentityServiceHost() {
+ if (cancel_callback_.is_null())
+ return;
+ cancel_callback_.Run();
+}
+
+bool WebRTCIdentityServiceHost::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(WebRTCIdentityServiceHost, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(WebRTCIdentityMsg_RequestIdentity, OnRequestIdentity)
+ IPC_MESSAGE_HANDLER(WebRTCIdentityMsg_CancelRequest, OnCancelRequest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+ return handled;
+}
+
+void WebRTCIdentityServiceHost::OnRequestIdentity(
+ int request_id,
+ const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name) {
+ if (!cancel_callback_.is_null()) {
+ DLOG(WARNING)
+ << "The request is rejected because there is already a pending request";
+ SendErrorMessage(request_id, net::ERR_INSUFFICIENT_RESOURCES);
+ return;
+ }
+ cancel_callback_ = identity_store_->RequestIdentity(
+ origin,
+ identity_name,
+ common_name,
+ base::Bind(&WebRTCIdentityServiceHost::OnComplete,
+ base::Unretained(this),
+ request_id));
+ if (cancel_callback_.is_null()) {
+ SendErrorMessage(request_id, net::ERR_UNEXPECTED);
+ }
+}
+
+void WebRTCIdentityServiceHost::OnCancelRequest(int request_id) {
+ base::ResetAndReturn(&cancel_callback_);
+}
+
+void WebRTCIdentityServiceHost::OnComplete(int request_id,
+ int error,
+ const std::string& certificate,
+ const std::string& private_key) {
+ cancel_callback_.Reset();
+ if (error == net::OK) {
+ Send(new WebRTCIdentityHostMsg_IdentityReady(
+ request_id, certificate, private_key));
+ } else {
+ SendErrorMessage(request_id, error);
+ }
+}
+
+void WebRTCIdentityServiceHost::SendErrorMessage(int request_id, int error) {
+ Send(new WebRTCIdentityHostMsg_RequestFailed(request_id, error));
+}
+
+} // namespace content
diff --git a/content/browser/renderer_host/media/webrtc_identity_service_host.h b/content/browser/renderer_host/media/webrtc_identity_service_host.h
new file mode 100644
index 0000000..9d903cd
--- /dev/null
+++ b/content/browser/renderer_host/media/webrtc_identity_service_host.h
@@ -0,0 +1,66 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_WEBRTC_IDENTITY_SERVICE_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_WEBRTC_IDENTITY_SERVICE_HOST_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "content/public/browser/browser_message_filter.h"
+
+class GURL;
+
+namespace content {
+
+class WebRTCIdentityStore;
+
+// This class is the host for WebRTCIdentityService in the browser process.
+// It converts the IPC messages for requesting a WebRTC DTLS identity and
+// cancelling a pending request into calls of WebRTCIdentityStore. It also sends
+// the request result back to the renderer through IPC.
+// Only one outstanding request is allowed per renderer at a time. If a second
+// request is made before the first one completes, an IPC with error
+// ERR_INSUFFICIENT_RESOURCES will be sent back to the renderer.
+class WebRTCIdentityServiceHost : public BrowserMessageFilter {
+ public:
+ explicit WebRTCIdentityServiceHost(WebRTCIdentityStore* identity_store);
+
+ private:
+ virtual ~WebRTCIdentityServiceHost();
+
+ // content::BrowserMessageFilter override.
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) OVERRIDE;
+
+ void OnComplete(int request_id,
+ int error,
+ const std::string& certificate,
+ const std::string& private_key);
+
+ // Requests a DTLS identity from the DTLS identity store for the given
+ // |origin| and |identity_name|. If no such identity exists, a new one will be
+ // generated using the given |common_name|.
+ // |request_id| is a unique id chosen by the client and used to cancel a
+ // pending request.
+ void OnRequestIdentity(int request_id,
+ const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name);
+
+ // Cancels a pending request by its id. If there is no pending request having
+ // the same id, the call is ignored.
+ void OnCancelRequest(int request_id);
+
+ void SendErrorMessage(int request_id, int error);
+
+ base::Closure cancel_callback_;
+ WebRTCIdentityStore* identity_store_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityServiceHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_WEBRTC_IDENTITY_SERVICE_HOST_H_
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 6a80195..fe0e947 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -74,7 +74,6 @@
#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
#include "content/browser/renderer_host/media/midi_host.h"
-#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
#include "content/browser/renderer_host/media/video_capture_host.h"
#include "content/browser/renderer_host/memory_benchmark_message_filter.h"
#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
@@ -137,6 +136,11 @@
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#endif
+#if defined(ENABLE_WEBRTC)
+#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
+#include "content/browser/renderer_host/media/webrtc_identity_service_host.h"
+#endif
+
#include "third_party/skia/include/core/SkBitmap.h"
extern bool g_exited_main_message_loop;
@@ -632,6 +636,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get());
channel_->AddFilter(gpu_message_filter_);
#if defined(ENABLE_WEBRTC)
+ channel_->AddFilter(new WebRTCIdentityServiceHost(
+ storage_partition_impl_->GetWebRTCIdentityStore()));
peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
channel_->AddFilter(peer_connection_tracker_host_.get());
channel_->AddFilter(new MediaStreamDispatcherHost(
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 8b3000e..691a40f 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -159,15 +159,16 @@ StoragePartitionImpl::StoragePartitionImpl(
fileapi::FileSystemContext* filesystem_context,
webkit_database::DatabaseTracker* database_tracker,
DOMStorageContextImpl* dom_storage_context,
- IndexedDBContextImpl* indexed_db_context)
+ IndexedDBContextImpl* indexed_db_context,
+ scoped_ptr<WebRTCIdentityStore> webrtc_identity_store)
: partition_path_(partition_path),
quota_manager_(quota_manager),
appcache_service_(appcache_service),
filesystem_context_(filesystem_context),
database_tracker_(database_tracker),
dom_storage_context_(dom_storage_context),
- indexed_db_context_(indexed_db_context) {
-}
+ indexed_db_context_(indexed_db_context),
+ webrtc_identity_store_(webrtc_identity_store.Pass()) {}
StoragePartitionImpl::~StoragePartitionImpl() {
// These message loop checks are just to avoid leaks in unittests.
@@ -243,13 +244,17 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
scoped_refptr<ChromeAppCacheService> appcache_service =
new ChromeAppCacheService(quota_manager->proxy());
+ scoped_ptr<WebRTCIdentityStore> webrtc_identity_store(
+ new WebRTCIdentityStore());
+
return new StoragePartitionImpl(partition_path,
quota_manager.get(),
appcache_service.get(),
filesystem_context.get(),
database_tracker.get(),
dom_storage_context.get(),
- indexed_db_context.get());
+ indexed_db_context.get(),
+ webrtc_identity_store.Pass());
}
base::FilePath StoragePartitionImpl::GetPath() {
@@ -344,6 +349,10 @@ void StoragePartitionImpl::AsyncClearDataBetween(uint32 storage_mask,
}
}
+WebRTCIdentityStore* StoragePartitionImpl::GetWebRTCIdentityStore() {
+ return webrtc_identity_store_.get();
+}
+
void StoragePartitionImpl::SetURLRequestContext(
net::URLRequestContextGetter* url_request_context) {
url_request_context_ = url_request_context;
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index af206f5..9dcdfec 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -11,6 +11,7 @@
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/dom_storage/dom_storage_context_impl.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/media/webrtc_identity_store.h"
#include "content/common/content_export.h"
#include "content/public/browser/storage_partition.h"
@@ -41,6 +42,8 @@ class StoragePartitionImpl : public StoragePartition {
const base::Time& end,
const base::Closure& callback) OVERRIDE;
+ WebRTCIdentityStore* GetWebRTCIdentityStore();
+
private:
friend class StoragePartitionImplMap;
FRIEND_TEST_ALL_PREFIXES(StoragePartitionShaderClearTest, ClearShaderCache);
@@ -62,7 +65,8 @@ class StoragePartitionImpl : public StoragePartition {
fileapi::FileSystemContext* filesystem_context,
webkit_database::DatabaseTracker* database_tracker,
DOMStorageContextImpl* dom_storage_context,
- IndexedDBContextImpl* indexed_db_context);
+ IndexedDBContextImpl* indexed_db_context,
+ scoped_ptr<WebRTCIdentityStore> webrtc_identity_store);
// Used by StoragePartitionImplMap.
//
@@ -89,6 +93,7 @@ class StoragePartitionImpl : public StoragePartition {
scoped_refptr<webkit_database::DatabaseTracker> database_tracker_;
scoped_refptr<DOMStorageContextImpl> dom_storage_context_;
scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
+ scoped_ptr<WebRTCIdentityStore> webrtc_identity_store_;
DISALLOW_COPY_AND_ASSIGN(StoragePartitionImpl);
};
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index 0298513..36af638 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -107,10 +107,16 @@ TEST_F(StoragePartitionShaderClearTest, ClearShaderCache) {
EXPECT_EQ(1u, Size());
TestClosureCallback clear_cb;
- StoragePartitionImpl sp(cache_path(), NULL, NULL, NULL, NULL, NULL, NULL);
+ StoragePartitionImpl sp(cache_path(),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ scoped_ptr<WebRTCIdentityStore>());
base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&ClearData, &sp, clear_cb.callback()));
+ FROM_HERE, base::Bind(&ClearData, &sp, clear_cb.callback()));
clear_cb.WaitForResult();
EXPECT_EQ(0u, Size());
}
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index 35927dd..174a63b 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -38,6 +38,7 @@
#include "content/common/media/media_stream_messages.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/common/media/video_capture_messages.h"
+#include "content/common/media/webrtc_identity_messages.h"
#include "content/common/memory_benchmark_messages.h"
#include "content/common/mime_registry_messages.h"
#include "content/common/p2p_messages.h"
diff --git a/content/common/media/webrtc_identity_messages.h b/content/common/media/webrtc_identity_messages.h
new file mode 100644
index 0000000..4f115bcb
--- /dev/null
+++ b/content/common/media/webrtc_identity_messages.h
@@ -0,0 +1,32 @@
+// 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.
+
+// IPC messages for requesting WebRTC identity.
+// Multiply-included message file, hence no include guard.
+
+#include "googleurl/src/gurl.h"
+#include "ipc/ipc_message_macros.h"
+
+#define IPC_MESSAGE_START WebRTCIdentityMsgStart
+
+// Messages sent from the renderer to the browser.
+// Request a WebRTC identity.
+IPC_MESSAGE_CONTROL4(WebRTCIdentityMsg_RequestIdentity,
+ int /* request_id */,
+ GURL /* origin */,
+ std::string /* identity_name */,
+ std::string /* common_name */)
+// Cancel a WebRTC identity request.
+IPC_MESSAGE_CONTROL1(WebRTCIdentityMsg_CancelRequest, int /* request_id */)
+
+// Messages sent from the browser to the renderer.
+// Return a WebRTC identity.
+IPC_MESSAGE_CONTROL3(WebRTCIdentityHostMsg_IdentityReady,
+ int /* request_id */,
+ std::string /* certificate */,
+ std::string /* private_key */)
+// Notifies an error from the identity request.
+IPC_MESSAGE_CONTROL2(WebRTCIdentityHostMsg_RequestFailed,
+ int /* request_id */,
+ int /* error */)
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index cc9284e..735e951 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -658,6 +658,8 @@
'browser/media/media_internals_proxy.h',
'browser/media/media_internals_ui.cc',
'browser/media/media_internals_ui.h',
+ 'browser/media/webrtc_identity_store.cc',
+ 'browser/media/webrtc_identity_store.h',
'browser/media/webrtc_internals.cc',
'browser/media/webrtc_internals.h',
'browser/media/webrtc_internals_message_handler.cc',
@@ -1195,6 +1197,8 @@
'sources': [
'browser/renderer_host/media/peer_connection_tracker_host.cc',
'browser/renderer_host/media/peer_connection_tracker_host.h',
+ 'browser/renderer_host/media/webrtc_identity_service_host.cc',
+ 'browser/renderer_host/media/webrtc_identity_service_host.h',
'browser/renderer_host/p2p/socket_host.cc',
'browser/renderer_host/p2p/socket_host.h',
'browser/renderer_host/p2p/socket_host_tcp.cc',
diff --git a/content/content_common.gypi b/content/content_common.gypi
index ff57dc7..85762d1 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -268,6 +268,7 @@
'common/media/midi_messages.h',
'common/media/video_capture.h',
'common/media/video_capture_messages.h',
+ 'common/media/webrtc_identity_messages.h',
'common/memory_benchmark_messages.h',
'common/message_router.cc',
'common/message_router.h',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index f14f4a6..0c70df5 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -471,6 +471,8 @@
'renderer/media/webrtc_audio_device_not_impl.h',
'renderer/media/webrtc_audio_renderer.cc',
'renderer/media/webrtc_audio_renderer.h',
+ 'renderer/media/webrtc_identity_service.cc',
+ 'renderer/media/webrtc_identity_service.h',
'renderer/media/webrtc_local_audio_renderer.cc',
'renderer/media/webrtc_local_audio_renderer.h',
'renderer/media/webrtc_local_audio_track.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 33ca270..edf06a8 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -321,6 +321,7 @@
'browser/loader/upload_data_stream_builder_unittest.cc',
'browser/mach_broker_mac_unittest.cc',
'browser/media/media_internals_unittest.cc',
+ 'browser/media/webrtc_identity_store_unittest.cc',
'browser/net/sqlite_persistent_cookie_store_unittest.cc',
'browser/notification_service_impl_unittest.cc',
'browser/plugin_loader_posix_unittest.cc',
diff --git a/content/renderer/media/webrtc_identity_service.cc b/content/renderer/media/webrtc_identity_service.cc
new file mode 100644
index 0000000..7042c93
--- /dev/null
+++ b/content/renderer/media/webrtc_identity_service.cc
@@ -0,0 +1,82 @@
+// 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 "base/atomic_sequence_num.h"
+#include "content/common/media/webrtc_identity_messages.h"
+#include "content/public/renderer/render_thread.h"
+
+namespace content {
+
+WebRTCIdentityService::WebRTCIdentityService(const GURL& origin)
+ : origin_(origin), pending_observer_(NULL), pending_request_id_(0) {
+ RenderThread::Get()->AddObserver(this);
+}
+
+WebRTCIdentityService::~WebRTCIdentityService() {
+ RenderThread::Get()->RemoveObserver(this);
+ if (pending_observer_) {
+ RenderThread::Get()->Send(
+ new WebRTCIdentityMsg_CancelRequest(pending_request_id_));
+ }
+}
+
+bool WebRTCIdentityService::RequestIdentity(
+ const std::string& identity_name,
+ const std::string& common_name,
+ webrtc::DTLSIdentityRequestObserver* observer) {
+ // Static because the request id needs to be unique per renderer process
+ // across WebRTCIdentityService instances.
+ static base::AtomicSequenceNumber s_next_request_id;
+
+ DCHECK(observer);
+ if (pending_observer_)
+ return false;
+
+ pending_observer_ = observer;
+ pending_request_id_ = s_next_request_id.GetNext();
+ RenderThread::Get()->Send(new WebRTCIdentityMsg_RequestIdentity(
+ pending_request_id_, origin_, identity_name, common_name));
+ return true;
+}
+
+bool WebRTCIdentityService::OnControlMessageReceived(
+ const IPC::Message& message) {
+ if (!pending_observer_)
+ return false;
+
+ int old_pending_request_id = pending_request_id_;
+ 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()
+
+ if (pending_request_id_ == old_pending_request_id)
+ handled = false;
+
+ return handled;
+}
+
+void WebRTCIdentityService::OnIdentityReady(int request_id,
+ const std::string& certificate,
+ const std::string& private_key) {
+ if (request_id != pending_request_id_)
+ return;
+ pending_observer_->OnSuccess(certificate, private_key);
+ pending_observer_ = NULL;
+ pending_request_id_ = 0;
+}
+
+void WebRTCIdentityService::OnRequestFailed(int request_id, int error) {
+ if (request_id != pending_request_id_)
+ return;
+ pending_observer_->OnFailure(error);
+ pending_observer_ = NULL;
+ pending_request_id_ = 0;
+}
+
+} // namespace content
diff --git a/content/renderer/media/webrtc_identity_service.h b/content/renderer/media/webrtc_identity_service.h
new file mode 100644
index 0000000..6e22671
--- /dev/null
+++ b/content/renderer/media/webrtc_identity_service.h
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_IDENTITY_SERVICE_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_IDENTITY_SERVICE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "content/public/renderer/render_process_observer.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
+
+namespace content {
+
+// This class handles WebRTC DTLS identity requests by sending IPC messages to
+// the browser process.
+class WebRTCIdentityService : public webrtc::DTLSIdentityServiceInterface,
+ public RenderProcessObserver {
+ public:
+ explicit WebRTCIdentityService(const GURL& origin);
+ virtual ~WebRTCIdentityService();
+
+ // WebRTCIdentityServiceInterface implementation.
+ virtual bool RequestIdentity(const std::string& identity_name,
+ const std::string& common_name,
+ webrtc::DTLSIdentityRequestObserver* observer)
+ OVERRIDE;
+
+ private:
+ // RenderProcessObserver implementation.
+ virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ void OnIdentityReady(int request_id,
+ const std::string& certificate,
+ const std::string& private_key);
+
+ void OnRequestFailed(int request_id, int error);
+
+ // The origin of the DTLS connection.
+ GURL origin_;
+ talk_base::scoped_refptr<webrtc::DTLSIdentityRequestObserver>
+ pending_observer_;
+ int pending_request_id_;
+ DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityService);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_WEBRTC_IDENTITY_SERVICE_H_
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index 3e1e59c..bf80df0 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -85,7 +85,8 @@ enum IPCMessageStart {
MemoryBenchmarkMsgStart,
WebSocketMsgStart,
NaClHostMsgStart,
- LastIPCMsgStart // Must come last.
+ WebRTCIdentityMsgStart,
+ LastIPCMsgStart // Must come last.
};
#endif // IPC_IPC_MESSAGE_START_H_
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index 9ebb25a..234b3a9 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -660,6 +660,9 @@ NET_ERROR(ORIGIN_BOUND_CERT_GENERATION_FAILED, -711)
// Failure to export private key.
NET_ERROR(PRIVATE_KEY_EXPORT_FAILED, -712)
+// Self-signed certificate generation failed.
+NET_ERROR(SELF_SIGNED_CERT_GENERATION_FAILED, -713)
+
// DNS error codes.
// DNS resolver received a malformed response.