|  | // Copyright (c) 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/webrtc/webrtc_internals.h" | 
|  |  | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <utility> | 
|  |  | 
|  | #include "base/run_loop.h" | 
|  | #include "base/values.h" | 
|  | #include "content/browser/webrtc/webrtc_internals_connections_observer.h" | 
|  | #include "content/browser/webrtc/webrtc_internals_ui_observer.h" | 
|  | #include "content/public/browser/browser_task_traits.h" | 
|  | #include "content/public/browser/browser_thread.h" | 
|  | #include "content/public/test/browser_task_environment.h" | 
|  | #include "mojo/public/cpp/bindings/pending_receiver.h" | 
|  | #include "mojo/public/cpp/bindings/receiver.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | namespace content { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | const char kContraints[] = "c"; | 
|  | const char kRtcConfiguration[] = "r"; | 
|  | const char kUrl[] = "u"; | 
|  | const char* const kWakeLockConnectingValues[] = {"checking", "connected", | 
|  | "completed"}; | 
|  | const char* const kWakeLockDisconnectingValues[] = {"disconnected", "closed", | 
|  | "failed", "new"}; | 
|  |  | 
|  | class MockWebRtcInternalsProxy : public WebRTCInternalsUIObserver { | 
|  | public: | 
|  | MockWebRtcInternalsProxy() : loop_(nullptr) {} | 
|  | explicit MockWebRtcInternalsProxy(base::RunLoop* loop) : loop_(loop) {} | 
|  |  | 
|  | const std::string& command() const { return command_; } | 
|  |  | 
|  | base::Value* value() { return value_.get(); } | 
|  |  | 
|  | private: | 
|  | void OnUpdate(const char* command, const base::Value* value) override { | 
|  | command_ = command; | 
|  | value_.reset(value ? value->DeepCopy() : nullptr); | 
|  | if (loop_) | 
|  | loop_->Quit(); | 
|  | } | 
|  |  | 
|  | std::string command_; | 
|  | std::unique_ptr<base::Value> value_; | 
|  | base::RunLoop* loop_; | 
|  | }; | 
|  |  | 
|  | class MockWakeLock : public device::mojom::WakeLock { | 
|  | public: | 
|  | explicit MockWakeLock(mojo::PendingReceiver<device::mojom::WakeLock> receiver) | 
|  | : receiver_(this, std::move(receiver)), has_wakelock_(false) {} | 
|  | ~MockWakeLock() override {} | 
|  |  | 
|  | // Implement device::mojom::WakeLock: | 
|  | void RequestWakeLock() override { has_wakelock_ = true; } | 
|  | void CancelWakeLock() override { has_wakelock_ = false; } | 
|  | void AddClient( | 
|  | mojo::PendingReceiver<device::mojom::WakeLock> receiver) override {} | 
|  | void ChangeType(device::mojom::WakeLockType type, | 
|  | ChangeTypeCallback callback) override {} | 
|  | void HasWakeLockForTests(HasWakeLockForTestsCallback callback) override {} | 
|  |  | 
|  | bool HasWakeLock() { | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | return has_wakelock_; | 
|  | } | 
|  |  | 
|  | private: | 
|  | mojo::Receiver<device::mojom::WakeLock> receiver_; | 
|  | bool has_wakelock_; | 
|  | }; | 
|  |  | 
|  | class TestWebRtcConnectionsObserver | 
|  | : public WebRtcInternalsConnectionsObserver { | 
|  | public: | 
|  | TestWebRtcConnectionsObserver() = default; | 
|  |  | 
|  | ~TestWebRtcConnectionsObserver() override = default; | 
|  |  | 
|  | uint32_t latest_connections_count() const { | 
|  | return latest_connections_count_; | 
|  | } | 
|  |  | 
|  | private: | 
|  | // content::WebRtcInternalsConnectionsObserver: | 
|  | void OnConnectionsCountChange(uint32_t count) override { | 
|  | latest_connections_count_ = count; | 
|  | } | 
|  |  | 
|  | uint32_t latest_connections_count_ = 0u; | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | // Derived class for testing only.  Allows the tests to have their own instance | 
|  | // for testing and control the period for which WebRTCInternals will bulk up | 
|  | // updates (changes down from 500ms to 1ms). | 
|  | class WebRTCInternalsForTest : public WebRTCInternals { | 
|  | public: | 
|  | WebRTCInternalsForTest() | 
|  | : WebRTCInternals(1, true), | 
|  | mock_wake_lock_(wake_lock_.BindNewPipeAndPassReceiver()) {} | 
|  |  | 
|  | ~WebRTCInternalsForTest() override {} | 
|  |  | 
|  | bool HasWakeLock() { return mock_wake_lock_.HasWakeLock(); } | 
|  |  | 
|  | private: | 
|  | MockWakeLock mock_wake_lock_; | 
|  | }; | 
|  |  | 
|  | class WebRtcInternalsTest : public testing::Test { | 
|  | protected: | 
|  | void VerifyString(const base::DictionaryValue* dict, | 
|  | const std::string& key, | 
|  | const std::string& expected) { | 
|  | std::string actual; | 
|  | EXPECT_TRUE(dict->GetString(key, &actual)); | 
|  | EXPECT_EQ(expected, actual); | 
|  | } | 
|  |  | 
|  | void VerifyInt(const base::DictionaryValue* dict, | 
|  | const std::string& key, | 
|  | int expected) { | 
|  | int actual; | 
|  | EXPECT_TRUE(dict->GetInteger(key, &actual)); | 
|  | EXPECT_EQ(expected, actual); | 
|  | } | 
|  |  | 
|  | void VerifyList(const base::Value& dict, | 
|  | base::StringPiece key, | 
|  | const base::Value& expected) { | 
|  | ASSERT_TRUE(dict.is_dict()); | 
|  | ASSERT_TRUE(expected.is_list()); | 
|  | const base::Value* actual = dict.FindListKey(key); | 
|  | ASSERT_TRUE(actual); | 
|  | EXPECT_TRUE(expected.Equals(actual)); | 
|  | } | 
|  |  | 
|  | void VerifyGetUserMediaData(base::Value* actual_data, | 
|  | int rid, | 
|  | int pid, | 
|  | const std::string& origin, | 
|  | const std::string& audio, | 
|  | const std::string& video) { | 
|  | base::DictionaryValue* dict = nullptr; | 
|  | EXPECT_TRUE(actual_data->GetAsDictionary(&dict)); | 
|  |  | 
|  | VerifyInt(dict, "rid", rid); | 
|  | VerifyInt(dict, "pid", pid); | 
|  | VerifyString(dict, "origin", origin); | 
|  | VerifyString(dict, "audio", audio); | 
|  | VerifyString(dict, "video", video); | 
|  | } | 
|  |  | 
|  | BrowserTaskEnvironment task_environment_; | 
|  | }; | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, AddRemoveObserver) { | 
|  | base::RunLoop loop; | 
|  | MockWebRtcInternalsProxy observer(&loop); | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | webrtc_internals.AddObserver(&observer); | 
|  |  | 
|  | webrtc_internals.RemoveObserver(&observer); | 
|  | // The observer should not get notified of this activity. | 
|  | webrtc_internals.OnAddPeerConnection(0, 3, 4, kUrl, kRtcConfiguration, | 
|  | kContraints); | 
|  |  | 
|  | GetUIThreadTaskRunner({})->PostTask(FROM_HERE, loop.QuitClosure()); | 
|  | loop.Run(); | 
|  |  | 
|  | EXPECT_EQ("", observer.command()); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(3, 4); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, EnsureNoLogWhenNoObserver) { | 
|  | base::RunLoop loop; | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | webrtc_internals.OnAddPeerConnection(0, 3, 4, kUrl, kRtcConfiguration, | 
|  | kContraints); | 
|  | webrtc_internals.OnUpdatePeerConnection(3, 4, "update_type", "update_value"); | 
|  | GetUIThreadTaskRunner({})->PostTask(FROM_HERE, loop.QuitClosure()); | 
|  | loop.Run(); | 
|  |  | 
|  | // Make sure we don't have a log entry since there was no observer. | 
|  | MockWebRtcInternalsProxy observer; | 
|  | webrtc_internals.UpdateObserver(&observer); | 
|  | EXPECT_EQ("updateAllPeerConnections", observer.command()); | 
|  |  | 
|  | base::ListValue* list = nullptr; | 
|  | ASSERT_TRUE(observer.value()->GetAsList(&list)); | 
|  | EXPECT_EQ(1U, list->GetSize()); | 
|  | base::DictionaryValue* dict = nullptr; | 
|  | ASSERT_TRUE((*list->begin()).GetAsDictionary(&dict)); | 
|  | base::ListValue* log = nullptr; | 
|  | ASSERT_FALSE(dict->GetList("log", &log)); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(3, 4); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, EnsureLogIsRemovedWhenObserverIsRemoved) { | 
|  | base::RunLoop loop; | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | MockWebRtcInternalsProxy observer; | 
|  | webrtc_internals.AddObserver(&observer); | 
|  | webrtc_internals.OnAddPeerConnection(0, 3, 4, kUrl, kRtcConfiguration, | 
|  | kContraints); | 
|  | webrtc_internals.OnUpdatePeerConnection(3, 4, "update_type", "update_value"); | 
|  | GetUIThreadTaskRunner({})->PostTask(FROM_HERE, loop.QuitClosure()); | 
|  | loop.Run(); | 
|  |  | 
|  | // Make sure we have a log entry since there was an observer. | 
|  | webrtc_internals.UpdateObserver(&observer); | 
|  | EXPECT_EQ("updateAllPeerConnections", observer.command()); | 
|  |  | 
|  | base::ListValue* list = nullptr; | 
|  | ASSERT_TRUE(observer.value()->GetAsList(&list)); | 
|  | EXPECT_EQ(1U, list->GetSize()); | 
|  | base::DictionaryValue* dict = nullptr; | 
|  | ASSERT_TRUE((*list->begin()).GetAsDictionary(&dict)); | 
|  | base::ListValue* log = nullptr; | 
|  | ASSERT_TRUE(dict->GetList("log", &log)); | 
|  |  | 
|  | // Make sure we the log entry was removed when the last observer was removed. | 
|  | webrtc_internals.RemoveObserver(&observer); | 
|  | webrtc_internals.UpdateObserver(&observer); | 
|  | EXPECT_EQ("updateAllPeerConnections", observer.command()); | 
|  |  | 
|  | ASSERT_TRUE(observer.value()->GetAsList(&list)); | 
|  | EXPECT_EQ(1U, list->GetSize()); | 
|  | ASSERT_TRUE((*list->begin()).GetAsDictionary(&dict)); | 
|  | ASSERT_FALSE(dict->GetList("log", &log)); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(3, 4); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, SendAddPeerConnectionUpdate) { | 
|  | base::RunLoop loop; | 
|  | MockWebRtcInternalsProxy observer(&loop); | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | webrtc_internals.AddObserver(&observer); | 
|  | webrtc_internals.OnAddPeerConnection(0, 1, 2, kUrl, kRtcConfiguration, | 
|  | kContraints); | 
|  |  | 
|  | loop.Run(); | 
|  |  | 
|  | ASSERT_EQ("addPeerConnection", observer.command()); | 
|  |  | 
|  | base::DictionaryValue* dict = nullptr; | 
|  | EXPECT_TRUE(observer.value()->GetAsDictionary(&dict)); | 
|  |  | 
|  | VerifyInt(dict, "pid", 1); | 
|  | VerifyInt(dict, "lid", 2); | 
|  | VerifyString(dict, "url", kUrl); | 
|  | VerifyString(dict, "rtcConfiguration", kRtcConfiguration); | 
|  | VerifyString(dict, "constraints", kContraints); | 
|  |  | 
|  | webrtc_internals.RemoveObserver(&observer); | 
|  | webrtc_internals.OnRemovePeerConnection(1, 2); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, SendRemovePeerConnectionUpdate) { | 
|  | base::RunLoop loop; | 
|  | MockWebRtcInternalsProxy observer(&loop); | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | webrtc_internals.AddObserver(&observer); | 
|  | webrtc_internals.OnAddPeerConnection(0, 1, 2, kUrl, kRtcConfiguration, | 
|  | kContraints); | 
|  | webrtc_internals.OnRemovePeerConnection(1, 2); | 
|  |  | 
|  | loop.Run(); | 
|  |  | 
|  | ASSERT_EQ("removePeerConnection", observer.command()); | 
|  |  | 
|  | base::DictionaryValue* dict = nullptr; | 
|  | EXPECT_TRUE(observer.value()->GetAsDictionary(&dict)); | 
|  |  | 
|  | VerifyInt(dict, "pid", 1); | 
|  | VerifyInt(dict, "lid", 2); | 
|  |  | 
|  | webrtc_internals.RemoveObserver(&observer); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, SendUpdatePeerConnectionUpdate) { | 
|  | base::RunLoop loop; | 
|  | MockWebRtcInternalsProxy observer(&loop); | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | webrtc_internals.AddObserver(&observer); | 
|  | webrtc_internals.OnAddPeerConnection(0, 1, 2, kUrl, kRtcConfiguration, | 
|  | kContraints); | 
|  |  | 
|  | const std::string update_type = "fakeType"; | 
|  | const std::string update_value = "fakeValue"; | 
|  | webrtc_internals.OnUpdatePeerConnection(1, 2, update_type, update_value); | 
|  |  | 
|  | loop.Run(); | 
|  |  | 
|  | ASSERT_EQ("updatePeerConnection", observer.command()); | 
|  |  | 
|  | base::DictionaryValue* dict = nullptr; | 
|  | EXPECT_TRUE(observer.value()->GetAsDictionary(&dict)); | 
|  |  | 
|  | VerifyInt(dict, "pid", 1); | 
|  | VerifyInt(dict, "lid", 2); | 
|  | VerifyString(dict, "type", update_type); | 
|  | VerifyString(dict, "value", update_value); | 
|  |  | 
|  | std::string time; | 
|  | EXPECT_TRUE(dict->GetString("time", &time)); | 
|  | EXPECT_FALSE(time.empty()); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(1, 2); | 
|  | webrtc_internals.RemoveObserver(&observer); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, AddGetUserMedia) { | 
|  | base::RunLoop loop; | 
|  | MockWebRtcInternalsProxy observer(&loop); | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  |  | 
|  | // Add one observer before "getUserMedia". | 
|  | webrtc_internals.AddObserver(&observer); | 
|  |  | 
|  | const int rid = 1; | 
|  | const int pid = 2; | 
|  | const std::string audio_constraint = "aaa"; | 
|  | const std::string video_constraint = "vvv"; | 
|  | webrtc_internals.OnGetUserMedia(rid, pid, kUrl, true, true, audio_constraint, | 
|  | video_constraint); | 
|  |  | 
|  | loop.Run(); | 
|  |  | 
|  | ASSERT_EQ("addGetUserMedia", observer.command()); | 
|  | VerifyGetUserMediaData(observer.value(), rid, pid, kUrl, audio_constraint, | 
|  | video_constraint); | 
|  |  | 
|  | webrtc_internals.RemoveObserver(&observer); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, SendAllUpdateWithGetUserMedia) { | 
|  | const int rid = 1; | 
|  | const int pid = 2; | 
|  | const std::string audio_constraint = "aaa"; | 
|  | const std::string video_constraint = "vvv"; | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | webrtc_internals.OnGetUserMedia(rid, pid, kUrl, true, true, audio_constraint, | 
|  | video_constraint); | 
|  |  | 
|  | MockWebRtcInternalsProxy observer; | 
|  | // Add one observer after "getUserMedia". | 
|  | webrtc_internals.AddObserver(&observer); | 
|  | webrtc_internals.UpdateObserver(&observer); | 
|  |  | 
|  | EXPECT_EQ("addGetUserMedia", observer.command()); | 
|  | VerifyGetUserMediaData(observer.value(), rid, pid, kUrl, audio_constraint, | 
|  | video_constraint); | 
|  |  | 
|  | webrtc_internals.RemoveObserver(&observer); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, SendAllUpdatesWithPeerConnectionUpdate) { | 
|  | const int rid = 0, pid = 1, lid = 2; | 
|  | const std::string update_type = "fakeType"; | 
|  | const std::string update_value = "fakeValue"; | 
|  |  | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  |  | 
|  | MockWebRtcInternalsProxy observer; | 
|  | webrtc_internals.AddObserver(&observer); | 
|  |  | 
|  | webrtc_internals.OnAddPeerConnection(rid, pid, lid, kUrl, kRtcConfiguration, | 
|  | kContraints); | 
|  | webrtc_internals.OnUpdatePeerConnection(pid, lid, update_type, update_value); | 
|  |  | 
|  | webrtc_internals.UpdateObserver(&observer); | 
|  |  | 
|  | EXPECT_EQ("updateAllPeerConnections", observer.command()); | 
|  | ASSERT_TRUE(observer.value()); | 
|  |  | 
|  | base::ListValue* list = nullptr; | 
|  | EXPECT_TRUE(observer.value()->GetAsList(&list)); | 
|  | EXPECT_EQ(1U, list->GetSize()); | 
|  |  | 
|  | base::DictionaryValue* dict = nullptr; | 
|  | EXPECT_TRUE((*list->begin()).GetAsDictionary(&dict)); | 
|  |  | 
|  | VerifyInt(dict, "rid", rid); | 
|  | VerifyInt(dict, "pid", pid); | 
|  | VerifyInt(dict, "lid", lid); | 
|  | VerifyString(dict, "url", kUrl); | 
|  | VerifyString(dict, "rtcConfiguration", kRtcConfiguration); | 
|  | VerifyString(dict, "constraints", kContraints); | 
|  |  | 
|  | base::ListValue* log = nullptr; | 
|  | ASSERT_TRUE(dict->GetList("log", &log)); | 
|  | EXPECT_EQ(1U, log->GetSize()); | 
|  |  | 
|  | EXPECT_TRUE((*log->begin()).GetAsDictionary(&dict)); | 
|  | VerifyString(dict, "type", update_type); | 
|  | VerifyString(dict, "value", update_value); | 
|  | std::string time; | 
|  | EXPECT_TRUE(dict->GetString("time", &time)); | 
|  | EXPECT_FALSE(time.empty()); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, OnAddStandardStats) { | 
|  | const int rid = 0; | 
|  | const int pid = 1; | 
|  | const int lid = 2; | 
|  | base::RunLoop loop; | 
|  | MockWebRtcInternalsProxy observer(&loop); | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | webrtc_internals.AddObserver(&observer); | 
|  | webrtc_internals.OnAddPeerConnection(rid, pid, lid, kUrl, kRtcConfiguration, | 
|  | kContraints); | 
|  |  | 
|  | base::Value list(base::Value::Type::LIST); | 
|  | list.Append("xxx"); | 
|  | list.Append("yyy"); | 
|  | webrtc_internals.OnAddStandardStats(pid, lid, list.Clone()); | 
|  |  | 
|  | loop.Run(); | 
|  |  | 
|  | EXPECT_EQ("addStandardStats", observer.command()); | 
|  | ASSERT_TRUE(observer.value()); | 
|  |  | 
|  | base::DictionaryValue* dict = nullptr; | 
|  | EXPECT_TRUE(observer.value()->GetAsDictionary(&dict)); | 
|  |  | 
|  | VerifyInt(dict, "pid", pid); | 
|  | VerifyInt(dict, "lid", lid); | 
|  | VerifyList(*dict, "reports", list); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, OnAddLegacyStats) { | 
|  | const int rid = 0; | 
|  | const int pid = 1; | 
|  | const int lid = 2; | 
|  | base::RunLoop loop; | 
|  | MockWebRtcInternalsProxy observer(&loop); | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | webrtc_internals.AddObserver(&observer); | 
|  | webrtc_internals.OnAddPeerConnection(rid, pid, lid, kUrl, kRtcConfiguration, | 
|  | kContraints); | 
|  |  | 
|  | base::Value list(base::Value::Type::LIST); | 
|  | list.Append("xxx"); | 
|  | list.Append("yyy"); | 
|  | webrtc_internals.OnAddLegacyStats(pid, lid, list.Clone()); | 
|  |  | 
|  | loop.Run(); | 
|  |  | 
|  | EXPECT_EQ("addLegacyStats", observer.command()); | 
|  | ASSERT_TRUE(observer.value()); | 
|  |  | 
|  | base::DictionaryValue* dict = nullptr; | 
|  | EXPECT_TRUE(observer.value()->GetAsDictionary(&dict)); | 
|  |  | 
|  | VerifyInt(dict, "pid", pid); | 
|  | VerifyInt(dict, "lid", lid); | 
|  | VerifyList(*dict, "reports", list); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, AudioDebugRecordingsFileSelectionCanceled) { | 
|  | base::RunLoop loop; | 
|  |  | 
|  | MockWebRtcInternalsProxy observer(&loop); | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  |  | 
|  | webrtc_internals.AddObserver(&observer); | 
|  | webrtc_internals.FileSelectionCanceled(nullptr); | 
|  |  | 
|  | loop.Run(); | 
|  |  | 
|  | EXPECT_EQ("audioDebugRecordingsFileSelectionCancelled", observer.command()); | 
|  | EXPECT_EQ(nullptr, observer.value()); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, WakeLockCreateRemove) { | 
|  | const int kRenderProcessId = 1; | 
|  | const int kPid = 1; | 
|  | const int kLid = 1; | 
|  |  | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnAddPeerConnection(kRenderProcessId, kPid, kLid, kUrl, | 
|  | kRtcConfiguration, kContraints); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(kPid, kLid); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, WakeLockConnecting) { | 
|  | const int kRenderProcessId = 1; | 
|  | const int kPid = 1; | 
|  | const int kLid = 1; | 
|  |  | 
|  | for (const char* value : kWakeLockConnectingValues) { | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnAddPeerConnection(kRenderProcessId, kPid, kLid, kUrl, | 
|  | kRtcConfiguration, kContraints); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection(kPid, kLid, | 
|  | "iceConnectionStateChange", value); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(kPid, kLid); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  | } | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, WakeLockConnectingSequence) { | 
|  | const int kRenderProcessId = 1; | 
|  | const int kPid = 1; | 
|  | const int kLid = 1; | 
|  |  | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnAddPeerConnection(kRenderProcessId, kPid, kLid, kUrl, | 
|  | kRtcConfiguration, kContraints); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | // A sequence of connecting messages should not increase the number of | 
|  | // connected connections beyond 1. | 
|  | for (const char* value : kWakeLockConnectingValues) { | 
|  | webrtc_internals.OnUpdatePeerConnection(kPid, kLid, | 
|  | "iceConnectionStateChange", value); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  | } | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(kPid, kLid); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, WakeLockDisconnecting) { | 
|  | const int kRenderProcessId = 1; | 
|  | const int kPid = 1; | 
|  | const int kLid = 1; | 
|  |  | 
|  | for (const char* value : kWakeLockDisconnectingValues) { | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnAddPeerConnection(kRenderProcessId, kPid, kLid, kUrl, | 
|  | kRtcConfiguration, kContraints); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLid, "iceConnectionStateChange", "connected"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection(kPid, kLid, | 
|  | "iceConnectionStateChange", value); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(kPid, kLid); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  | } | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, WakeLockDisconnectingSequence) { | 
|  | const int kRenderProcessId = 1; | 
|  | const int kPid = 1; | 
|  | const int kLid = 1; | 
|  |  | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnAddPeerConnection(kRenderProcessId, kPid, kLid, kUrl, | 
|  | kRtcConfiguration, kContraints); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLid, "iceConnectionStateChange", "connected"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | // A sequence of disconnecting messages should not decrease the number of | 
|  | // connected connections below zero. | 
|  | for (const char* value : kWakeLockDisconnectingValues) { | 
|  | webrtc_internals.OnUpdatePeerConnection(kPid, kLid, | 
|  | "iceConnectionStateChange", value); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  | } | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(kPid, kLid); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, WakeLockReconnect) { | 
|  | const int kRenderProcessId = 1; | 
|  | const int kPid = 1; | 
|  | const int kLid = 1; | 
|  |  | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnAddPeerConnection(kRenderProcessId, kPid, kLid, kUrl, | 
|  | kRtcConfiguration, kContraints); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLid, "iceConnectionStateChange", "connected"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLid, "iceConnectionStateChange", "disconnected"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLid, "iceConnectionStateChange", "connected"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(kPid, kLid); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, WakeLockMultplePeerConnections) { | 
|  | const int kRenderProcessId = 1; | 
|  | const int kPid = 1; | 
|  | const int kLids[] = {1, 2, 3}; | 
|  |  | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | for (const int lid : kLids) { | 
|  | webrtc_internals.OnAddPeerConnection(kRenderProcessId, kPid, lid, kUrl, | 
|  | kRtcConfiguration, kContraints); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  | } | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLids[0], "iceConnectionStateChange", "connected"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLids[1], "iceConnectionStateChange", "completed"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 2); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLids[2], "iceConnectionStateChange", "checking"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 3); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | // A duplicate message should not alter the number of connected connections. | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLids[2], "iceConnectionStateChange", "checking"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 3); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection(kPid, kLids[0], | 
|  | "iceConnectionStateChange", "closed"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 2); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection(kPid, kLids[1], "stop", | 
|  | std::string()); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(kPid, kLids[0]); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(kPid, kLids[1]); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_TRUE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | // Remove the remaining open peer connection. | 
|  | webrtc_internals.OnRemovePeerConnection(kPid, kLids[2]); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_FALSE(webrtc_internals.HasWakeLock()); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(WebRtcInternalsTest, TestWebRtcConnectionsObserver) { | 
|  | const int kRenderProcessId = 1; | 
|  | const int kPid = 1; | 
|  | const int kLid = 1; | 
|  |  | 
|  | TestWebRtcConnectionsObserver observer; | 
|  |  | 
|  | WebRTCInternalsForTest webrtc_internals; | 
|  | webrtc_internals.AddConnectionsObserver(&observer); | 
|  | EXPECT_EQ(0u, observer.latest_connections_count()); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  |  | 
|  | webrtc_internals.OnAddPeerConnection(kRenderProcessId, kPid, kLid, kUrl, | 
|  | kRtcConfiguration, kContraints); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_EQ(0u, observer.latest_connections_count()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLid, "iceConnectionStateChange", "connected"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_EQ(1u, observer.latest_connections_count()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLid, "iceConnectionStateChange", "disconnected"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_EQ(0u, observer.latest_connections_count()); | 
|  |  | 
|  | webrtc_internals.OnUpdatePeerConnection( | 
|  | kPid, kLid, "iceConnectionStateChange", "connected"); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 1); | 
|  | EXPECT_EQ(1u, observer.latest_connections_count()); | 
|  |  | 
|  | webrtc_internals.OnRemovePeerConnection(kPid, kLid); | 
|  | EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); | 
|  | EXPECT_EQ(0u, observer.latest_connections_count()); | 
|  |  | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | // TODO(eladalon): Add tests that WebRtcEventLogger::Enable/Disable is | 
|  | // correctly called. https://crbug.com/775415 | 
|  |  | 
|  | }  // namespace content |