
Split from: https://chromium-review.googlesource.com/c/chromium/src/+/6004959 Generated patch --------------- - Tool: ./tool/clang/spanify/rewrite-multiple-platform.sh - Platform: Linux. - Filter: This includes 2400/4222 patches. I included the std::array ones and excluded build errors. Google announcement: -------------------- https://groups.google.com/a/google.com/g/chrome-memory-safety/c/RMiO4gaVLQA/m/Yz-3NCObAgAJ Benchmarks: ---------- See design doc and https://chromium-review.googlesource.com/c/chromium/src/+/6004959/21 Description ----------- The consensus during the memory safety summit was to begin rewriting relevant C-style arrays to C++11 std::array. It can be done immediately, offers better developer ergonomics, and fix large chunks of the -Wunsafe-buffer-usage errors in Chrome. To clarify, this effort is complementary to the longer plan work with enabling -fsanitize=array-bounds, and we plan to leverage both, especially for protecting 3p code. [Attached] is a document detailing the rationale, benefits, and considerations for potential compile-time and performance impacts. [Attached]:https://docs.google.com/document/d/1z5aBDg26lHmNDjXRCysElWKx7E4PAJXqykI_k7ondJI/edit?tab=t.0#heading=h.cqgo7wvp0kzt NO_IFTTT=No need to update base/debug/stack_trace.h Bug: 378069401 Change-Id: I6d36543c267f12c672cce00d75cf833fff238ebf R: dcheng@chromium.org AX-Relnotes: n/a. Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6039265 Reviewed-by: Daniel Cheng <dcheng@chromium.org> Auto-Submit: Arthur Sonzogni <arthursonzogni@chromium.org> Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org> Owners-Override: Daniel Cheng <dcheng@chromium.org> Cr-Commit-Position: refs/heads/main@{#1395908}
922 lines
33 KiB
C++
922 lines
33 KiB
C++
// Copyright 2013 The Chromium Authors
|
|
// 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 <array>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <utility>
|
|
|
|
#include "base/memory/raw_ptr.h"
|
|
#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 GlobalRenderFrameHostId kFrameId = {20, 30};
|
|
const int kLid = 40;
|
|
const int kPid = 123;
|
|
const int kRequestId = 1;
|
|
const char kRtcConfiguration[] = "r";
|
|
const char kUrl[] = "u";
|
|
const char* const kWakeLockConnectingValues[] = {"checking", "connected",
|
|
"completed"};
|
|
const char* const kWakeLockDisconnectingValues[] = {"disconnected", "closed",
|
|
"failed", "new"};
|
|
const char kAudioConstraint[] = "aaa";
|
|
const char kVideoConstraint[] = "vvv";
|
|
|
|
const char kStreamId[] = "streamid";
|
|
const char kAudioTrackInfo[] = "id:audio label:fancy device";
|
|
const char kVideoTrackInfo[] = "id:audio label:fancy device";
|
|
const char kGetUserMediaError[] = "SomeError";
|
|
const char kGetUserMediaErrorMessage[] = "Something bad happened.";
|
|
|
|
class MockWebRtcInternalsProxy : public WebRTCInternalsUIObserver {
|
|
public:
|
|
MockWebRtcInternalsProxy() = default;
|
|
explicit MockWebRtcInternalsProxy(base::RunLoop* loop) : loop_(loop) {}
|
|
|
|
const std::string& event_name() const { return event_name_; }
|
|
|
|
base::Value* event_data() { return &event_data_; }
|
|
|
|
private:
|
|
void OnUpdate(const std::string& event_name,
|
|
const base::Value* event_data) override {
|
|
event_name_ = event_name;
|
|
event_data_ = event_data ? event_data->Clone() : base::Value();
|
|
if (loop_)
|
|
loop_->Quit();
|
|
}
|
|
|
|
std::string event_name_;
|
|
base::Value event_data_;
|
|
raw_ptr<base::RunLoop> loop_{nullptr};
|
|
};
|
|
|
|
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::Value::Dict& dict,
|
|
const std::string& key,
|
|
const std::string& expected) {
|
|
const std::string* actual = dict.FindString(key);
|
|
ASSERT_TRUE(actual);
|
|
EXPECT_EQ(expected, *actual);
|
|
}
|
|
|
|
void VerifyInt(const base::Value::Dict& dict,
|
|
const std::string& key,
|
|
int expected) {
|
|
std::optional<int> actual = dict.FindInt(key);
|
|
ASSERT_TRUE(actual.has_value());
|
|
EXPECT_EQ(expected, actual.value());
|
|
}
|
|
|
|
void VerifyList(const base::Value::Dict& dict,
|
|
std::string_view key,
|
|
const base::Value::List& expected) {
|
|
const base::Value::List* actual = dict.FindList(key);
|
|
ASSERT_TRUE(actual);
|
|
EXPECT_EQ(expected, *actual);
|
|
}
|
|
|
|
void VerifyGetUserMediaData(const std::string& request_type,
|
|
base::Value* actual_data,
|
|
GlobalRenderFrameHostId frame_id,
|
|
int pid,
|
|
int request_id,
|
|
const std::string& audio,
|
|
const std::string& video) {
|
|
ASSERT_TRUE(actual_data->is_dict());
|
|
const base::Value::Dict& dict = actual_data->GetDict();
|
|
|
|
VerifyInt(dict, "rid", frame_id.child_id);
|
|
VerifyInt(dict, "pid", pid);
|
|
// origin is the empty string in tests.
|
|
VerifyString(dict, "origin", "");
|
|
VerifyInt(dict, "request_id", request_id);
|
|
VerifyString(dict, "request_type", request_type);
|
|
VerifyString(dict, "audio", audio);
|
|
VerifyString(dict, "video", video);
|
|
}
|
|
|
|
void VerifyGetUserMediaSuccessData(base::Value* actual_data,
|
|
GlobalRenderFrameHostId frame_id,
|
|
int pid,
|
|
int request_id,
|
|
const std::string& stream_id,
|
|
const std::string& audio_track_info,
|
|
const std::string& video_track_info) {
|
|
ASSERT_TRUE(actual_data->is_dict());
|
|
const base::Value::Dict& dict = actual_data->GetDict();
|
|
|
|
VerifyInt(dict, "rid", frame_id.child_id);
|
|
VerifyInt(dict, "pid", pid);
|
|
VerifyInt(dict, "request_id", request_id);
|
|
VerifyString(dict, "stream_id", stream_id);
|
|
VerifyString(dict, "audio_track_info", audio_track_info);
|
|
VerifyString(dict, "video_track_info", video_track_info);
|
|
}
|
|
|
|
void VerifyGetUserMediaFailureData(base::Value* actual_data,
|
|
GlobalRenderFrameHostId frame_id,
|
|
int pid,
|
|
int request_id,
|
|
const std::string& error,
|
|
const std::string& error_message) {
|
|
ASSERT_TRUE(actual_data->is_dict());
|
|
const base::Value::Dict& dict = actual_data->GetDict();
|
|
|
|
VerifyInt(dict, "rid", frame_id.child_id);
|
|
VerifyInt(dict, "pid", pid);
|
|
VerifyInt(dict, "request_id", request_id);
|
|
VerifyString(dict, "error", error);
|
|
VerifyString(dict, "error_message", error_message);
|
|
}
|
|
|
|
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.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
|
|
GetUIThreadTaskRunner({})->PostTask(FROM_HERE, loop.QuitClosure());
|
|
loop.Run();
|
|
|
|
EXPECT_EQ("", observer.event_name());
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, EnsureNoLogWhenNoObserver) {
|
|
base::RunLoop loop;
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
webrtc_internals.OnPeerConnectionUpdated(kFrameId, kLid, "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("update-all-peer-connections", observer.event_name());
|
|
|
|
ASSERT_TRUE(observer.event_data()->is_list());
|
|
EXPECT_EQ(1U, observer.event_data()->GetList().size());
|
|
const base::Value::Dict* dict =
|
|
observer.event_data()->GetList()[0].GetIfDict();
|
|
ASSERT_TRUE(dict);
|
|
ASSERT_FALSE(dict->Find("log"));
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, EnsureLogIsRemovedWhenObserverIsRemoved) {
|
|
base::RunLoop loop;
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
MockWebRtcInternalsProxy observer;
|
|
webrtc_internals.AddObserver(&observer);
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
webrtc_internals.OnPeerConnectionUpdated(kFrameId, kLid, "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("update-all-peer-connections", observer.event_name());
|
|
|
|
ASSERT_TRUE(observer.event_data()->is_list());
|
|
EXPECT_EQ(1U, observer.event_data()->GetList().size());
|
|
const base::Value::Dict* dict =
|
|
observer.event_data()->GetList()[0].GetIfDict();
|
|
ASSERT_TRUE(dict);
|
|
ASSERT_TRUE(dict->FindList("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("update-all-peer-connections", observer.event_name());
|
|
|
|
ASSERT_TRUE(observer.event_data()->is_list());
|
|
EXPECT_EQ(1U, observer.event_data()->GetList().size());
|
|
const base::Value::Dict* updated_dict =
|
|
observer.event_data()->GetList()[0].GetIfDict();
|
|
ASSERT_FALSE(updated_dict->Find("log"));
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, SendAddPeerConnectionUpdate) {
|
|
base::RunLoop loop;
|
|
MockWebRtcInternalsProxy observer(&loop);
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
webrtc_internals.AddObserver(&observer);
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
|
|
loop.Run();
|
|
|
|
ASSERT_EQ("add-peer-connection", observer.event_name());
|
|
|
|
ASSERT_TRUE(observer.event_data()->is_dict());
|
|
const base::Value::Dict& dict = observer.event_data()->GetDict();
|
|
|
|
VerifyInt(dict, "rid", kFrameId.child_id);
|
|
VerifyInt(dict, "lid", kLid);
|
|
VerifyInt(dict, "pid", kPid);
|
|
VerifyString(dict, "url", kUrl);
|
|
VerifyString(dict, "rtcConfiguration", kRtcConfiguration);
|
|
|
|
webrtc_internals.RemoveObserver(&observer);
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, SendRemovePeerConnectionUpdate) {
|
|
base::RunLoop loop;
|
|
MockWebRtcInternalsProxy observer(&loop);
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
webrtc_internals.AddObserver(&observer);
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
|
|
loop.Run();
|
|
|
|
ASSERT_EQ("remove-peer-connection", observer.event_name());
|
|
|
|
ASSERT_TRUE(observer.event_data()->is_dict());
|
|
const base::Value::Dict& dict = observer.event_data()->GetDict();
|
|
|
|
VerifyInt(dict, "rid", kFrameId.child_id);
|
|
VerifyInt(dict, "lid", kLid);
|
|
|
|
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.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
|
|
const std::string update_type = "fakeType";
|
|
const std::string update_value = "fakeValue";
|
|
webrtc_internals.OnPeerConnectionUpdated(kFrameId, kLid, update_type,
|
|
update_value);
|
|
|
|
loop.Run();
|
|
|
|
ASSERT_EQ("update-peer-connection", observer.event_name());
|
|
|
|
ASSERT_TRUE(observer.event_data()->is_dict());
|
|
const base::Value::Dict& dict = observer.event_data()->GetDict();
|
|
|
|
VerifyInt(dict, "rid", kFrameId.child_id);
|
|
VerifyInt(dict, "lid", kLid);
|
|
VerifyString(dict, "type", update_type);
|
|
VerifyString(dict, "value", update_value);
|
|
|
|
const std::string* time = dict.FindString("time");
|
|
ASSERT_TRUE(time);
|
|
EXPECT_FALSE(time->empty());
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
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);
|
|
|
|
webrtc_internals.OnGetUserMedia(kFrameId, kPid, kRequestId, /*audio=*/true,
|
|
/*video=*/true, kAudioConstraint,
|
|
kVideoConstraint);
|
|
|
|
loop.Run();
|
|
|
|
ASSERT_EQ("add-media", observer.event_name());
|
|
VerifyGetUserMediaData("getUserMedia", observer.event_data(), kFrameId, kPid,
|
|
kRequestId, kAudioConstraint, kVideoConstraint);
|
|
webrtc_internals.RemoveObserver(&observer);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, UpdateGetUserMediaSuccess) {
|
|
base::RunLoop loop;
|
|
MockWebRtcInternalsProxy observer(&loop);
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
|
|
// Add one observer before "getUserMediaSuccess".
|
|
webrtc_internals.AddObserver(&observer);
|
|
|
|
webrtc_internals.OnGetUserMediaSuccess(kFrameId, kPid, kRequestId, kStreamId,
|
|
kAudioTrackInfo, kVideoTrackInfo);
|
|
|
|
loop.Run();
|
|
|
|
ASSERT_EQ("update-media", observer.event_name());
|
|
VerifyGetUserMediaSuccessData(observer.event_data(), kFrameId, kPid,
|
|
kRequestId, kStreamId, kAudioTrackInfo,
|
|
kVideoTrackInfo);
|
|
|
|
webrtc_internals.RemoveObserver(&observer);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, UpdateGetUserMediaError) {
|
|
base::RunLoop loop;
|
|
MockWebRtcInternalsProxy observer(&loop);
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
|
|
// Add one observer before "getUserMediaFailure".
|
|
webrtc_internals.AddObserver(&observer);
|
|
|
|
webrtc_internals.OnGetUserMediaFailure(kFrameId, kPid, kRequestId,
|
|
kGetUserMediaError,
|
|
kGetUserMediaErrorMessage);
|
|
|
|
loop.Run();
|
|
|
|
ASSERT_EQ("update-media", observer.event_name());
|
|
VerifyGetUserMediaFailureData(observer.event_data(), kFrameId, kPid,
|
|
kRequestId, kGetUserMediaError,
|
|
kGetUserMediaErrorMessage);
|
|
|
|
webrtc_internals.RemoveObserver(&observer);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, AddGetDisplayMedia) {
|
|
base::RunLoop loop;
|
|
MockWebRtcInternalsProxy observer(&loop);
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
|
|
// Add one observer before "getDisplayMedia".
|
|
webrtc_internals.AddObserver(&observer);
|
|
|
|
webrtc_internals.OnGetDisplayMedia(kFrameId, kPid, kRequestId, /*audio=*/true,
|
|
/*video=*/true, kAudioConstraint,
|
|
kVideoConstraint);
|
|
|
|
loop.Run();
|
|
|
|
ASSERT_EQ("add-media", observer.event_name());
|
|
VerifyGetUserMediaData("getDisplayMedia", observer.event_data(), kFrameId,
|
|
kPid, kRequestId, kAudioConstraint, kVideoConstraint);
|
|
webrtc_internals.RemoveObserver(&observer);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, UpdateGetDisplayMediaSuccess) {
|
|
base::RunLoop loop;
|
|
MockWebRtcInternalsProxy observer(&loop);
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
|
|
// Add one observer before "getDisplayMediaSuccess".
|
|
webrtc_internals.AddObserver(&observer);
|
|
|
|
webrtc_internals.OnGetDisplayMediaSuccess(
|
|
kFrameId, kPid, kRequestId, kStreamId, kAudioTrackInfo, kVideoTrackInfo);
|
|
|
|
loop.Run();
|
|
|
|
ASSERT_EQ("update-media", observer.event_name());
|
|
VerifyGetUserMediaSuccessData(observer.event_data(), kFrameId, kPid,
|
|
kRequestId, kStreamId, kAudioTrackInfo,
|
|
kVideoTrackInfo);
|
|
|
|
webrtc_internals.RemoveObserver(&observer);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, UpdateGetDisplayMediaError) {
|
|
base::RunLoop loop;
|
|
MockWebRtcInternalsProxy observer(&loop);
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
|
|
// Add one observer before "getDisplayMediaFailure".
|
|
webrtc_internals.AddObserver(&observer);
|
|
|
|
webrtc_internals.OnGetDisplayMediaFailure(kFrameId, kPid, kRequestId,
|
|
kGetUserMediaError,
|
|
kGetUserMediaErrorMessage);
|
|
|
|
loop.Run();
|
|
|
|
ASSERT_EQ("update-media", observer.event_name());
|
|
VerifyGetUserMediaFailureData(observer.event_data(), kFrameId, kPid,
|
|
kRequestId, kGetUserMediaError,
|
|
kGetUserMediaErrorMessage);
|
|
|
|
webrtc_internals.RemoveObserver(&observer);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, SendAllUpdateWithGetUserMedia) {
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
webrtc_internals.OnGetUserMedia(kFrameId, kPid, kRequestId, /*audio=*/true,
|
|
/*video=*/true, kAudioConstraint,
|
|
kVideoConstraint);
|
|
|
|
MockWebRtcInternalsProxy observer;
|
|
// Add one observer after "getUserMedia".
|
|
webrtc_internals.AddObserver(&observer);
|
|
webrtc_internals.UpdateObserver(&observer);
|
|
|
|
EXPECT_EQ("add-media", observer.event_name());
|
|
VerifyGetUserMediaData("getUserMedia", observer.event_data(), kFrameId, kPid,
|
|
kRequestId, kAudioConstraint, kVideoConstraint);
|
|
|
|
webrtc_internals.RemoveObserver(&observer);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, SendAllUpdateWithGetDisplayMedia) {
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
webrtc_internals.OnGetDisplayMedia(kFrameId, kPid, kRequestId, /*audio=*/true,
|
|
/*video=*/true, kAudioConstraint,
|
|
kVideoConstraint);
|
|
|
|
MockWebRtcInternalsProxy observer;
|
|
// Add one observer after "getDisplayMedia".
|
|
webrtc_internals.AddObserver(&observer);
|
|
webrtc_internals.UpdateObserver(&observer);
|
|
|
|
EXPECT_EQ("add-media", observer.event_name());
|
|
VerifyGetUserMediaData("getDisplayMedia", observer.event_data(), kFrameId,
|
|
kPid, kRequestId, kAudioConstraint, kVideoConstraint);
|
|
|
|
webrtc_internals.RemoveObserver(&observer);
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, SendAllUpdatesWithPeerConnectionUpdate) {
|
|
const std::string update_type = "fakeType";
|
|
const std::string update_value = "fakeValue";
|
|
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
|
|
MockWebRtcInternalsProxy observer;
|
|
webrtc_internals.AddObserver(&observer);
|
|
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
webrtc_internals.OnPeerConnectionUpdated(kFrameId, kLid, update_type,
|
|
update_value);
|
|
|
|
webrtc_internals.UpdateObserver(&observer);
|
|
|
|
EXPECT_EQ("update-all-peer-connections", observer.event_name());
|
|
ASSERT_TRUE(observer.event_data());
|
|
|
|
ASSERT_TRUE(observer.event_data()->is_list());
|
|
const base::Value::List& list = observer.event_data()->GetList();
|
|
EXPECT_EQ(1U, list.size());
|
|
|
|
ASSERT_TRUE(list.begin()->is_dict());
|
|
const base::Value::Dict& dict = list.begin()->GetDict();
|
|
|
|
VerifyInt(dict, "rid", kFrameId.child_id);
|
|
VerifyInt(dict, "lid", kLid);
|
|
VerifyInt(dict, "pid", kPid);
|
|
VerifyString(dict, "url", kUrl);
|
|
VerifyString(dict, "rtcConfiguration", kRtcConfiguration);
|
|
|
|
const base::Value::List* log_value = dict.FindList("log");
|
|
ASSERT_TRUE(log_value);
|
|
EXPECT_EQ(1U, log_value->size());
|
|
|
|
ASSERT_TRUE(log_value->begin()->is_dict());
|
|
const base::Value::Dict& inner_dict = log_value->begin()->GetDict();
|
|
VerifyString(inner_dict, "type", update_type);
|
|
VerifyString(inner_dict, "value", update_value);
|
|
|
|
const std::string* time = inner_dict.FindString("time");
|
|
ASSERT_TRUE(time);
|
|
EXPECT_FALSE(time->empty());
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, OnAddStandardStats) {
|
|
base::RunLoop loop;
|
|
MockWebRtcInternalsProxy observer(&loop);
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
webrtc_internals.AddObserver(&observer);
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
|
|
base::Value::List list;
|
|
list.Append("xxx");
|
|
list.Append("yyy");
|
|
webrtc_internals.OnAddStandardStats(kFrameId, kLid, list.Clone());
|
|
|
|
loop.Run();
|
|
|
|
EXPECT_EQ("add-standard-stats", observer.event_name());
|
|
ASSERT_TRUE(observer.event_data());
|
|
|
|
ASSERT_TRUE(observer.event_data()->is_dict());
|
|
const base::Value::Dict& dict = observer.event_data()->GetDict();
|
|
|
|
VerifyInt(dict, "rid", kFrameId.child_id);
|
|
VerifyInt(dict, "lid", kLid);
|
|
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();
|
|
|
|
loop.Run();
|
|
|
|
EXPECT_EQ("audio-debug-recordings-file-selection-cancelled",
|
|
observer.event_name());
|
|
EXPECT_TRUE(observer.event_data()->is_none());
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, WakeLockCreateRemove) {
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, WakeLockConnecting) {
|
|
for (const char* value : kWakeLockConnectingValues) {
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(kFrameId, kLid,
|
|
"iceconnectionstatechange", value);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
}
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, WakeLockConnectingSequence) {
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
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.OnPeerConnectionUpdated(kFrameId, kLid,
|
|
"iceconnectionstatechange", value);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
}
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, WakeLockDisconnecting) {
|
|
for (const char* value : kWakeLockDisconnectingValues) {
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, kLid, "iceconnectionstatechange", "connected");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(kFrameId, kLid,
|
|
"iceconnectionstatechange", value);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
}
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, WakeLockDisconnectingSequence) {
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, 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.OnPeerConnectionUpdated(kFrameId, kLid,
|
|
"iceconnectionstatechange", value);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
}
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, WakeLockReconnect) {
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, kLid, "iceconnectionstatechange", "connected");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, kLid, "iceconnectionstatechange", "disconnected");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, kLid, "iceconnectionstatechange", "connected");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, WakeLockMultplePeerConnections) {
|
|
const auto kLids = std::to_array<int>({71, 72, 73});
|
|
|
|
WebRTCInternalsForTest webrtc_internals;
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
for (const int lid : kLids) {
|
|
webrtc_internals.OnPeerConnectionAdded(kFrameId, lid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
}
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, kLids[0], "iceconnectionstatechange", "connected");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, kLids[1], "iceconnectionstatechange", "completed");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 2);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, 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.OnPeerConnectionUpdated(
|
|
kFrameId, kLids[2], "iceconnectionstatechange", "checking");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 3);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, kLids[0], "iceconnectionstatechange", "closed");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 2);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(kFrameId, kLids[1], "close",
|
|
std::string());
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLids[0]);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLids[1]);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_TRUE(webrtc_internals.HasWakeLock());
|
|
|
|
// Remove the remaining open peer connection.
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLids[2]);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_FALSE(webrtc_internals.HasWakeLock());
|
|
|
|
base::RunLoop().RunUntilIdle();
|
|
}
|
|
|
|
TEST_F(WebRtcInternalsTest, TestWebRtcConnectionsObserver) {
|
|
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.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl,
|
|
kRtcConfiguration);
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_EQ(0u, observer.latest_connections_count());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, kLid, "iceconnectionstatechange", "connected");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_EQ(1u, observer.latest_connections_count());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, kLid, "iceconnectionstatechange", "disconnected");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 0);
|
|
EXPECT_EQ(0u, observer.latest_connections_count());
|
|
|
|
webrtc_internals.OnPeerConnectionUpdated(
|
|
kFrameId, kLid, "iceconnectionstatechange", "connected");
|
|
EXPECT_EQ(webrtc_internals.num_connected_connections(), 1);
|
|
EXPECT_EQ(1u, observer.latest_connections_count());
|
|
|
|
webrtc_internals.OnPeerConnectionRemoved(kFrameId, 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
|