blob: 71c475846585eb507cb94bde74cb6c39ba90b0a0 [file] [log] [blame]
// Copyright 2020 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 "chrome/browser/sharing/webrtc/sharing_service_host.h"
#include "base/strings/strcat.h"
#include "base/test/bind_test_util.h"
#include "chrome/browser/sharing/mock_sharing_device_source.h"
#include "chrome/browser/sharing/sharing_sync_preference.h"
#include "chrome/browser/sharing/webrtc/sharing_webrtc_connection_host.h"
#include "chrome/services/sharing/public/mojom/webrtc.mojom.h"
#include "components/sync_device_info/fake_device_info_sync_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "google_apis/google_api_keys.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class FakeSharingMojoService : public sharing::mojom::Sharing,
public sharing::mojom::SignallingReceiver {
public:
FakeSharingMojoService() = default;
~FakeSharingMojoService() override = default;
// sharing::mojom::Sharing:
void CreateSharingWebRtcConnection(
mojo::PendingRemote<sharing::mojom::SignallingSender> signalling_sender,
mojo::PendingReceiver<sharing::mojom::SignallingReceiver>
signalling_receiver,
mojo::PendingRemote<sharing::mojom::SharingWebRtcConnectionDelegate>
delegate,
mojo::PendingReceiver<sharing::mojom::SharingWebRtcConnection> connection,
mojo::PendingRemote<network::mojom::P2PSocketManager> socket_manager,
mojo::PendingRemote<network::mojom::MdnsResponder> mdns_responder,
std::vector<sharing::mojom::IceServerPtr> ice_servers) override {
signaling_set.Add(this, std::move(signalling_receiver));
}
void OnOfferReceived(const std::string& offer,
OnOfferReceivedCallback callback) override {
std::move(callback).Run(answer);
}
void OnIceCandidatesReceived(
std::vector<sharing::mojom::IceCandidatePtr> ice_candidates) override {}
mojo::Receiver<sharing::mojom::Sharing> receiver{this};
mojo::ReceiverSet<sharing::mojom::SignallingReceiver> signaling_set;
std::string answer;
};
} // namespace
class SharingServiceHostTest : public testing::Test {
public:
SharingServiceHostTest() {
SharingSyncPreference::RegisterProfilePrefs(prefs_.registry());
host_ = std::make_unique<SharingServiceHost>(
/*message_sender=*/nullptr,
/*gcm_driver=*/nullptr, &sync_prefs_, &device_source_,
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_));
host_->BindSharingServiceForTesting(
fake_mojo_service_.receiver.BindNewPipeAndPassRemote());
}
std::string GetApiUrl() const {
return base::StrCat(
{"https://networktraversal.googleapis.com/v1alpha/iceconfig?key=",
google_apis::GetSharingAPIKey()});
}
std::string OnOfferReceivedSync(const std::string& guid) {
std::string result;
base::RunLoop run_loop;
host_->OnOfferReceived(
guid, /*fcm_configuration=*/{}, "offer",
base::BindLambdaForTesting([&](const std::string& answer) {
result = answer;
run_loop.Quit();
}));
run_loop.Run();
return result;
}
protected:
content::BrowserTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME,
content::BrowserTaskEnvironment::MainThreadType::IO};
MockSharingDeviceSource device_source_;
sync_preferences::TestingPrefServiceSyncable prefs_;
syncer::FakeDeviceInfoSyncService fake_device_info_sync_service_;
SharingSyncPreference sync_prefs_{&prefs_, &fake_device_info_sync_service_};
network::TestURLLoaderFactory test_url_loader_factory_;
FakeSharingMojoService fake_mojo_service_;
std::unique_ptr<SharingServiceHost> host_;
};
TEST_F(SharingServiceHostTest, OnIceCandidatesReceived_BeforeConnection) {
host_->OnIceCandidatesReceived("unknown_guid", {}, {});
// Receiving an IceCandidate should not open new connections.
EXPECT_TRUE(host_->GetConnectionsForTesting().empty());
}
TEST_F(SharingServiceHostTest, OnOfferReceived_BeforeConnection) {
std::string guid = "unknown_guid";
std::string answer = "answer";
fake_mojo_service_.answer = answer;
EXPECT_CALL(device_source_, GetDeviceByGuid(guid))
.WillOnce(testing::Return(testing::ByMove(nullptr)));
test_url_loader_factory_.AddResponse(GetApiUrl(), /*response=*/std::string(),
net::HTTP_OK);
EXPECT_EQ(answer, OnOfferReceivedSync(guid));
// Receiving an offer should initialize a WebRTC connection.
EXPECT_EQ(1u, host_->GetConnectionsForTesting().size());
}
TEST_F(SharingServiceHostTest, OnOfferReceived_ExistingConnection) {
std::string guid = "existing_guid";
fake_mojo_service_.answer = "answer";
// Simulate existing connection for |guid|
host_->GetConnectionsForTesting()[guid] = nullptr;
EXPECT_EQ("", OnOfferReceivedSync(guid));
// We should still have only one connection
auto& connections = host_->GetConnectionsForTesting();
EXPECT_EQ(1u, connections.size());
EXPECT_TRUE(connections.find(guid) != connections.end());
}