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 <deque> 6 7 #include "content/browser/child_process_security_policy_impl.h" 8 #include "content/browser/media/webrtc_identity_store.h" 9 #include "content/browser/renderer_host/media/webrtc_identity_service_host.h" 10 #include "content/common/media/webrtc_identity_messages.h" 11 #include "content/public/test/test_browser_thread_bundle.h" 12 #include "ipc/ipc_message.h" 13 #include "net/base/net_errors.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace content { 17 18 namespace { 19 20 const char FAKE_ORIGIN[] = "http://fake.com"; 21 const char FAKE_IDENTITY_NAME[] = "fake identity"; 22 const char FAKE_COMMON_NAME[] = "fake common name"; 23 const char FAKE_CERTIFICATE[] = "fake cert"; 24 const char FAKE_PRIVATE_KEY[] = "fake private key"; 25 const int FAKE_RENDERER_ID = 10; 26 const int FAKE_SEQUENCE_NUMBER = 1; 27 28 class MockWebRTCIdentityStore : public WebRTCIdentityStore { 29 public: 30 MockWebRTCIdentityStore() : WebRTCIdentityStore(base::FilePath(), NULL) {} 31 32 virtual base::Closure RequestIdentity( 33 const GURL& origin, 34 const std::string& identity_name, 35 const std::string& common_name, 36 const CompletionCallback& callback) OVERRIDE { 37 EXPECT_TRUE(callback_.is_null()); 38 39 callback_ = callback; 40 return base::Bind(&MockWebRTCIdentityStore::OnCancel, 41 base::Unretained(this)); 42 } 43 44 bool HasPendingRequest() const { return !callback_.is_null(); } 45 46 void RunCompletionCallback(int error, 47 const std::string& cert, 48 const std::string& key) { 49 callback_.Run(error, cert, key); 50 callback_.Reset(); 51 } 52 53 private: 54 virtual ~MockWebRTCIdentityStore() {} 55 56 void OnCancel() { callback_.Reset(); } 57 58 CompletionCallback callback_; 59 }; 60 61 class WebRTCIdentityServiceHostForTest : public WebRTCIdentityServiceHost { 62 public: 63 explicit WebRTCIdentityServiceHostForTest(WebRTCIdentityStore* identity_store) 64 : WebRTCIdentityServiceHost(FAKE_RENDERER_ID, identity_store) { 65 ChildProcessSecurityPolicyImpl* policy = 66 ChildProcessSecurityPolicyImpl::GetInstance(); 67 policy->Add(FAKE_RENDERER_ID); 68 } 69 70 virtual bool Send(IPC::Message* message) OVERRIDE { 71 messages_.push_back(*message); 72 delete message; 73 return true; 74 } 75 76 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 77 return WebRTCIdentityServiceHost::OnMessageReceived(message); 78 } 79 80 IPC::Message GetLastMessage() { return messages_.back(); } 81 82 int GetNumberOfMessages() { return messages_.size(); } 83 84 void ClearMessages() { messages_.clear(); } 85 86 private: 87 virtual ~WebRTCIdentityServiceHostForTest() { 88 ChildProcessSecurityPolicyImpl* policy = 89 ChildProcessSecurityPolicyImpl::GetInstance(); 90 policy->Remove(FAKE_RENDERER_ID); 91 } 92 93 std::deque<IPC::Message> messages_; 94 }; 95 96 class WebRTCIdentityServiceHostTest : public ::testing::Test { 97 public: 98 WebRTCIdentityServiceHostTest() 99 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), 100 store_(new MockWebRTCIdentityStore()), 101 host_(new WebRTCIdentityServiceHostForTest(store_.get())) {} 102 103 void SendRequestToHost() { 104 host_->OnMessageReceived( 105 WebRTCIdentityMsg_RequestIdentity(FAKE_SEQUENCE_NUMBER, 106 GURL(FAKE_ORIGIN), 107 FAKE_IDENTITY_NAME, 108 FAKE_COMMON_NAME)); 109 } 110 111 void SendCancelRequestToHost() { 112 host_->OnMessageReceived(WebRTCIdentityMsg_CancelRequest()); 113 } 114 115 void VerifyRequestFailedMessage(int error) { 116 EXPECT_EQ(1, host_->GetNumberOfMessages()); 117 IPC::Message ipc = host_->GetLastMessage(); 118 EXPECT_EQ(ipc.type(), WebRTCIdentityHostMsg_RequestFailed::ID); 119 120 Tuple2<int, int> error_in_message; 121 WebRTCIdentityHostMsg_RequestFailed::Read(&ipc, &error_in_message); 122 EXPECT_EQ(FAKE_SEQUENCE_NUMBER, error_in_message.a); 123 EXPECT_EQ(error, error_in_message.b); 124 } 125 126 void VerifyIdentityReadyMessage(const std::string& cert, 127 const std::string& key) { 128 EXPECT_EQ(1, host_->GetNumberOfMessages()); 129 IPC::Message ipc = host_->GetLastMessage(); 130 EXPECT_EQ(ipc.type(), WebRTCIdentityHostMsg_IdentityReady::ID); 131 132 Tuple3<int, std::string, std::string> identity_in_message; 133 WebRTCIdentityHostMsg_IdentityReady::Read(&ipc, &identity_in_message); 134 EXPECT_EQ(FAKE_SEQUENCE_NUMBER, identity_in_message.a); 135 EXPECT_EQ(cert, identity_in_message.b); 136 EXPECT_EQ(key, identity_in_message.c); 137 } 138 139 protected: 140 TestBrowserThreadBundle browser_thread_bundle_; 141 scoped_refptr<MockWebRTCIdentityStore> store_; 142 scoped_refptr<WebRTCIdentityServiceHostForTest> host_; 143 }; 144 145 } // namespace 146 147 TEST_F(WebRTCIdentityServiceHostTest, TestSendAndCancelRequest) { 148 SendRequestToHost(); 149 EXPECT_TRUE(store_->HasPendingRequest()); 150 SendCancelRequestToHost(); 151 EXPECT_FALSE(store_->HasPendingRequest()); 152 } 153 154 TEST_F(WebRTCIdentityServiceHostTest, TestOnlyOneRequestAllowed) { 155 SendRequestToHost(); 156 EXPECT_TRUE(store_->HasPendingRequest()); 157 EXPECT_EQ(0, host_->GetNumberOfMessages()); 158 SendRequestToHost(); 159 160 VerifyRequestFailedMessage(net::ERR_INSUFFICIENT_RESOURCES); 161 } 162 163 TEST_F(WebRTCIdentityServiceHostTest, TestOnIdentityReady) { 164 SendRequestToHost(); 165 store_->RunCompletionCallback(net::OK, FAKE_CERTIFICATE, FAKE_PRIVATE_KEY); 166 VerifyIdentityReadyMessage(FAKE_CERTIFICATE, FAKE_PRIVATE_KEY); 167 } 168 169 TEST_F(WebRTCIdentityServiceHostTest, TestOnRequestFailed) { 170 SendRequestToHost(); 171 store_->RunCompletionCallback(net::ERR_KEY_GENERATION_FAILED, "", ""); 172 VerifyRequestFailedMessage(net::ERR_KEY_GENERATION_FAILED); 173 } 174 175 TEST_F(WebRTCIdentityServiceHostTest, TestOriginAccessDenied) { 176 ChildProcessSecurityPolicyImpl* policy = 177 ChildProcessSecurityPolicyImpl::GetInstance(); 178 policy->Remove(FAKE_RENDERER_ID); 179 180 SendRequestToHost(); 181 VerifyRequestFailedMessage(net::ERR_ACCESS_DENIED); 182 } 183 184 // Verifies that we do not crash if we try to cancel a completed request. 185 TEST_F(WebRTCIdentityServiceHostTest, TestCancelAfterRequestCompleted) { 186 SendRequestToHost(); 187 store_->RunCompletionCallback(net::OK, FAKE_CERTIFICATE, FAKE_PRIVATE_KEY); 188 SendCancelRequestToHost(); 189 } 190 191 } // namespace content 192