Commit 640009eb authored by Maxim Kolosovskiy's avatar Maxim Kolosovskiy Committed by Chromium LUCI CQ

Revert "Support multiple receivers for Cros APIs."

This reverts commit 8aca3b4d.

Reason for revert: I suspect the CL caused WindowOpenApiTest.PopupBlockingExtension failure
https://ci.chromium.org/ui/p/chromium/builders/ci/linux-chromeos-dbg/22177/overview

[ RUN      ] WindowOpenApiTest.PopupBlockingExtension
2021-01-13T05:48:40.927570Z INFO browser_tests[28993:28993]: [content_main_runner_impl.cc(1055)] Chrome is running in full browser mode.
2021-01-13T05:48:41.111260Z WARNING browser_tests[28993:28993]: [audio_manager_linux.cc(69)] Falling back to ALSA for audio output. PulseAudio is not available or could not be initialized.
2021-01-13T05:48:41.147293Z ERROR browser_tests[28993:28993]: [cras_audio_handler.cc(1627)] Failed to retrieve WBS mic deprioritized flag
2021-01-13T05:48:41.148942Z WARNING browser_tests[28993:29172]: [statistics_provider.cc(321)] Finished loading statistics.
2021-01-13T05:48:41.786294Z WARNING browser_tests[28993:28993]: [user_policy_manager_builder_chromeos.cc(123)] No policy loaded for known non-enterprise user
2021-01-13T05:48:42.161192Z WARNING browser_tests[28993:28993]: [merge_session_throttling_utils.cc(143)] Loading content for a profile without session restore?
2021-01-13T05:48:42.192143Z WARNING browser_tests[28993:28993]: [browser_util.cc(167)] Lacros-chrome is not supported
2021-01-13T05:48:42.205962Z ERROR browser_tests[28993:28993]: [proximity_auth_profile_pref_manager.cc(192)] Failed to find local state prefs for current user.
2021-01-13T05:48:42.726389Z WARNING browser_tests[28993:28993]: [merge_session_throttling_utils.cc(143)] Loading content for a profile without session restore?
2021-01-13T05:48:43.054799Z WARNING browser_tests[28993:28993]: [wallpaper_controller_client.cc(377)] Cannot get wallpaper files id in RemovePolicyWallpaper. This should never happen under normal circumstances.
2021-01-13T05:48:43.218141Z WARNING browser_tests[28993:28993]: [browser_util.cc(167)] Lacros-chrome is not supported
2021-01-13T05:48:43.726830Z WARNING browser_tests[29202:29284]: [http_cache_transaction.cc(1192)] Unable to open or create cache entry
2021-01-13T05:48:44.322210Z WARNING browser_tests[28993:28993]: [browser_util.cc(167)] Lacros-chrome is not supported
2021-01-13T05:48:44.376219Z ERROR browser_tests[28993:28993]: [plugin_vm_manager_impl.cc(141)] New session has dispatcher unexpected already running. Perhaps Chrome crashed?
2021-01-13T05:48:44.859368Z INFO browser_tests[28993:28993]: [key_permissions_manager_impl.cc(495)] One-time key permissions migration started for token: 0.
2021-01-13T05:48:44.863796Z INFO browser_tests[28993:28993]: [android_sms_pairing_state_tracker_impl.cc(72)] No Pairing cookie found
2021-01-13T05:48:45.010359Z ERROR browser_tests[28993:29140]: [object_proxy.cc(621)] Failed to call method: org.chromium.U2F.IsUvpaa: object_path= /org/chromium/U2F: org.freedesktop.DBus.Error.ServiceUnknown: The name org.chromium.U2F was not provided by any .service files
2021-01-13T05:48:45.018258Z ERROR browser_tests[28993:29172]: [als_reader.cc(47)] Missing num of als
2021-01-13T05:48:45.681453Z WARNING browser_tests[28993:28993]: [browser_util.cc(167)] Lacros-chrome is not supported
2021-01-13T05:48:45.682492Z WARNING browser_tests[28993:28993]: [browser_util.cc(167)] Lacros-chrome is not supported
2021-01-13T05:48:45.685002Z INFO browser_tests[28993:28993]: [key_permissions_manager_impl.cc(520)] One-time key permissions migration succeeded for token: 0.
2021-01-13T05:48:45.768048Z WARNING browser_tests[28993:28993]: [browser_util.cc(167)] Lacros-chrome is not supported
2021-01-13T05:48:45.769933Z WARNING browser_tests[28993:28993]: [browser_util.cc(167)] Lacros-chrome is not supported
2021-01-13T05:48:46.230042Z WARNING browser_tests[28993:28993]: [browser_util.cc(167)] Lacros-chrome is not supported
2021-01-13T05:48:50.078030Z ERROR browser_tests[28993:29172]: [object_proxy.cc(621)] Failed to call method: org.chromium.debugd.GetPerfOutputFd: object_path= /org/chromium/debugd: org.freedesktop.DBus.Error.ServiceUnknown: The name org.chromium.debugd was not provided by any .service files
2021-01-13T05:49:10.763123Z WARNING browser_tests[28993:29410]: [embedded_test_server.cc(668)] Request not handled. Returning 404: /favicon.ico
2021-01-13T05:49:10.833186Z WARNING browser_tests[28993:29410]: [embedded_test_server.cc(668)] Request not handled. Returning 404: /favicon.ico
../../chrome/browser/extensions/window_open_apitest.cc:91: Failure
Expected equality of these values:
  num_browsers
    Which is: 4
  chrome::GetBrowserCount(browser->profile())
    Which is: 2
Google Test trace:
../../chrome/browser/extensions/window_open_apitest.cc:76: WaitForTabsPopupsApps tabs:5, popups:2, app_popups:1
Stack trace:
#0 0x56363e71a458 extensions::WaitForTabsPopupsApps()
#1 0x56363e71c5aa extensions::WindowOpenApiTest_PopupBlockingExtension_Test::RunTestOnMainThread()
#2 0x563646f1d248 content::BrowserTestBase::ProxyRunTestOnMainThreadLoop()
#3 0x563646f207ca base::internal::FunctorTraits<>::Invoke<>()
#4 0x563646f20741 base::internal::InvokeHelper<>::MakeItSo<>()
#5 0x563646f206e7 _ZN4base8internal7InvokerINS0_9BindStateIMN7content15BrowserTestBaseEFvvEJNS0_17UnretainedWrapperIS4_EEEEEFvvEE7RunImplIS6_NSt4__Cr5tupleIJS8_EEEJLm0EEEEvOT_OT0_NSD_16integer_sequenceImJXspT1_EEEE
#6 0x563646f2068c base::internal::Invoker<>::RunOnce()
#7 0x56363c76ba61 _ZNO4base12OnceCallbackIFvvEE3RunEv
#8 0x563645c03021 ChromeBrowserMainParts::PreMainMessageLoopRunImpl()
#9 0x563645c01fc2 ChromeBrowserMainParts::PreMainMessageLoopRun()
#10 0x563640599fc6 chromeos::ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun()
#11 0x7fb5dc82e9e5 content::BrowserMainLoop::PreMainMessageLoopRun()
#12 0x7fb5dc8383ca base::internal::FunctorTraits<>::Invoke<>()
#13 0x7fb5dc8382e1 base::internal::InvokeHelper<>::MakeItSo<>()
#14 0x7fb5dc838267 _ZN4base8internal7InvokerINS0_9BindStateIMN7content15BrowserMainLoopEFivEJNS0_17UnretainedWrapperIS4_EEEEEFivEE7RunImplIS6_NSt4__Cr5tupleIJS8_EEEJLm0EEEEiOT_OT0_NSD_16integer_sequenceImJXspT1_EEEE
#15 0x7fb5dc83820c base::internal::Invoker<>::RunOnce()
#16 0x7fb5dcc03581 _ZNO4base12OnceCallbackIFivEE3RunEv
#17 0x7fb5dda03df6 content::StartupTaskRunner::RunAllTasksNow()
#18 0x7fb5dc82d3ad content::BrowserMainLoop::CreateStartupTasks()
#19 0x7fb5dc83bfd3 content::BrowserMainRunnerImpl::Initialize()
#20 0x7fb5dc82a804 content::BrowserMain()
#21 0x7fb5de9aae56 content::RunBrowserProcessMain()
#22 0x7fb5de9ac3c9 content::ContentMainRunnerImpl::RunBrowser()
#23 0x7fb5de9abd27 content::ContentMainRunnerImpl::Run()
#24 0x7fb5de9a9106 content::RunContentProcess()
#25 0x7fb5de9a9a3d content::ContentMain()
#26 0x563646f1cb13 content::BrowserTestBase::SetUp()
#27 0x563645acb283 InProcessBrowserTest::SetUp()
#28 0x563645ab3802 extensions::ExtensionBrowserTest::SetUp()
#29 0x56364163b48b testing::internal::HandleSehExceptionsInMethodIfSupported<>()
#30 0x56364162ee67 testing::internal::HandleExceptionsInMethodIfSupported<>()



Original change's description:
> Support multiple receivers for Cros APIs.
>
> With this CL, most of Cros API starts to support multiple receivers.
> AshChromeService and LacrosChromeService are exceptions.
>
> Bug: 1148448
> Test: Build and run Lacros on a DUT.
> Change-Id: I1d1a0be111108ae15657d81ea747750a760bd2f8
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2624323
> Reviewed-by: James Cook <jamescook@chromium.org>
> Commit-Queue: Hidehiko Abe <hidehiko@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#842869}

TBR=jamescook@chromium.org,hidehiko@chromium.org,chromium-scoped@luci-project-accounts.iam.gserviceaccount.com

Change-Id: Id097eab1934d9a2afca29f249a007de57ef18d90
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1148448
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2626229Reviewed-by: default avatarMaxim Kolosovskiy  <kolos@chromium.org>
Commit-Queue: Maxim Kolosovskiy  <kolos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842943}
parent 85753b0f
......@@ -44,17 +44,12 @@ namespace crosapi {
AshChromeServiceImpl::AshChromeServiceImpl(
mojo::PendingReceiver<mojom::AshChromeService> pending_receiver)
: receiver_(this, std::move(pending_receiver)),
file_manager_ash_(std::make_unique<FileManagerAsh>()),
keystore_service_ash_(std::make_unique<KeystoreServiceAsh>()),
message_center_ash_(std::make_unique<MessageCenterAsh>()),
metrics_reporting_ash_(std::make_unique<MetricsReportingAsh>(
g_browser_process->local_state())),
prefs_ash_(std::make_unique<PrefsAsh>(
g_browser_process->local_state(),
ProfileManager::GetPrimaryUserProfile()->GetPrefs())),
screen_manager_ash_(std::make_unique<ScreenManagerAsh>()),
select_file_ash_(std::make_unique<SelectFileAsh>()),
feedback_ash_(std::make_unique<FeedbackAsh>()),
cert_database_ash_(std::make_unique<CertDatabaseAsh>()),
test_controller_ash_(std::make_unique<TestControllerAsh>()),
clipboard_ash_(std::make_unique<ClipboardAsh>()) {
......@@ -103,17 +98,25 @@ void AshChromeServiceImpl::BindAccountManager(
void AshChromeServiceImpl::BindFileManager(
mojo::PendingReceiver<crosapi::mojom::FileManager> receiver) {
file_manager_ash_->BindReceiver(std::move(receiver));
// TODO(https://crbug.com/1148448): Convert this to allow multiple,
// simultaneous crosapi clients. See BindScreenManager for an example.
file_manager_ash_ =
std::make_unique<crosapi::FileManagerAsh>(std::move(receiver));
}
void AshChromeServiceImpl::BindKeystoreService(
mojo::PendingReceiver<crosapi::mojom::KeystoreService> receiver) {
keystore_service_ash_->BindReceiver(std::move(receiver));
// TODO(https://crbug.com/1148448): Convert this to allow multiple,
// simultaneous crosapi clients. See BindScreenManager for an example.
keystore_service_ash_ =
std::make_unique<crosapi::KeystoreServiceAsh>(std::move(receiver));
}
void AshChromeServiceImpl::BindMessageCenter(
mojo::PendingReceiver<mojom::MessageCenter> receiver) {
message_center_ash_->BindReceiver(std::move(receiver));
// TODO(https://crbug.com/1148448): Convert this to allow multiple,
// simultaneous crosapi clients. See BindScreenManager for an example.
message_center_ash_ = std::make_unique<MessageCenterAsh>(std::move(receiver));
}
void AshChromeServiceImpl::BindMetricsReporting(
......@@ -123,7 +126,9 @@ void AshChromeServiceImpl::BindMetricsReporting(
void AshChromeServiceImpl::BindSelectFile(
mojo::PendingReceiver<mojom::SelectFile> receiver) {
select_file_ash_->BindReceiver(std::move(receiver));
// TODO(https://crbug.com/1148448): Convert this to allow multiple,
// simultaneous crosapi clients. See BindScreenManager for an example.
select_file_ash_ = std::make_unique<SelectFileAsh>(std::move(receiver));
}
void AshChromeServiceImpl::BindScreenManager(
......@@ -138,7 +143,9 @@ void AshChromeServiceImpl::BindHidManager(
void AshChromeServiceImpl::BindFeedback(
mojo::PendingReceiver<mojom::Feedback> receiver) {
feedback_ash_->BindReceiver(std::move(receiver));
// TODO(https://crbug.com/1148448): Convert this to allow multiple,
// simultaneous crosapi clients. See BindScreenManager for an example.
feedback_ash_ = std::make_unique<FeedbackAsh>(std::move(receiver));
}
void AshChromeServiceImpl::BindMediaSessionController(
......
......@@ -23,15 +23,11 @@ chrome::FeedbackSource FromMojo(mojom::LacrosFeedbackSource source) {
} // namespace
FeedbackAsh::FeedbackAsh() = default;
FeedbackAsh::FeedbackAsh(mojo::PendingReceiver<mojom::Feedback> receiver)
: receiver_(this, std::move(receiver)) {}
FeedbackAsh::~FeedbackAsh() = default;
void FeedbackAsh::BindReceiver(
mojo::PendingReceiver<mojom::Feedback> receiver) {
receivers_.Add(this, std::move(receiver));
}
void FeedbackAsh::ShowFeedbackPage(mojom::FeedbackInfoPtr feedback_info) {
const user_manager::User* user =
user_manager::UserManager::Get()->GetPrimaryUser();
......
......@@ -7,7 +7,7 @@
#include "chromeos/crosapi/mojom/feedback.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/receiver.h"
namespace crosapi {
......@@ -15,18 +15,16 @@ namespace crosapi {
// UI thread. Shows feedback page in response to mojo IPCs from lacros-chrome.
class FeedbackAsh : public mojom::Feedback {
public:
FeedbackAsh();
explicit FeedbackAsh(mojo::PendingReceiver<mojom::Feedback> receiver);
FeedbackAsh(const FeedbackAsh&) = delete;
FeedbackAsh& operator=(const FeedbackAsh&) = delete;
~FeedbackAsh() override;
void BindReceiver(mojo::PendingReceiver<mojom::Feedback> receiver);
// crosapi::mojom::Feedback:
void ShowFeedbackPage(mojom::FeedbackInfoPtr feedback_info) override;
private:
mojo::ReceiverSet<mojom::Feedback> receivers_;
mojo::Receiver<mojom::Feedback> receiver_;
};
} // namespace crosapi
......
......@@ -67,15 +67,12 @@ void OpenItem(const base::FilePath& path,
} // namespace
FileManagerAsh::FileManagerAsh() = default;
FileManagerAsh::FileManagerAsh(
mojo::PendingReceiver<mojom::FileManager> receiver)
: receiver_(this, std::move(receiver)) {}
FileManagerAsh::~FileManagerAsh() = default;
void FileManagerAsh::BindReceiver(
mojo::PendingReceiver<mojom::FileManager> receiver) {
receivers_.Add(this, std::move(receiver));
}
void FileManagerAsh::DeprecatedShowItemInFolder(const base::FilePath& path) {
Profile* primary_profile = ProfileManager::GetPrimaryUserProfile();
base::FilePath final_path = ExpandPath(primary_profile, path);
......
......@@ -7,7 +7,7 @@
#include "chromeos/crosapi/mojom/file_manager.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/receiver.h"
namespace crosapi {
......@@ -16,13 +16,11 @@ namespace crosapi {
// manager, for example to open a folder or highlight a file.
class FileManagerAsh : public mojom::FileManager {
public:
FileManagerAsh();
explicit FileManagerAsh(mojo::PendingReceiver<mojom::FileManager> receiver);
FileManagerAsh(const FileManagerAsh&) = delete;
FileManagerAsh& operator=(const FileManagerAsh&) = delete;
~FileManagerAsh() override;
void BindReceiver(mojo::PendingReceiver<mojom::FileManager> receiver);
// crosapi::mojom::FileManager:
void DeprecatedShowItemInFolder(const base::FilePath& path) override;
void ShowItemInFolder(const base::FilePath& path,
......@@ -32,7 +30,7 @@ class FileManagerAsh : public mojom::FileManager {
void OpenFile(const base::FilePath& path, OpenFileCallback callback) override;
private:
mojo::ReceiverSet<mojom::FileManager> receivers_;
mojo::Receiver<mojom::FileManager> receiver_;
};
} // namespace crosapi
......
......@@ -62,7 +62,9 @@ base::Optional<TokenId> KeystoreToToken(mojom::KeystoreType type) {
} // namespace
KeystoreServiceAsh::KeystoreServiceAsh() {
KeystoreServiceAsh::KeystoreServiceAsh(
mojo::PendingReceiver<mojom::KeystoreService> receiver)
: receiver_(this, std::move(receiver)) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
......@@ -70,11 +72,6 @@ KeystoreServiceAsh::~KeystoreServiceAsh() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
void KeystoreServiceAsh::BindReceiver(
mojo::PendingReceiver<mojom::KeystoreService> receiver) {
receivers_.Add(this, std::move(receiver));
}
void KeystoreServiceAsh::ChallengeAttestationOnlyKeystore(
const std::string& challenge,
mojom::KeystoreType type,
......
......@@ -12,7 +12,7 @@
#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
#include "chromeos/crosapi/mojom/keystore_service.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/receiver.h"
namespace chromeos {
namespace attestation {
......@@ -28,13 +28,12 @@ namespace crosapi {
// system keystores. This class is affine to the UI thread.
class KeystoreServiceAsh : public mojom::KeystoreService {
public:
KeystoreServiceAsh();
explicit KeystoreServiceAsh(
mojo::PendingReceiver<mojom::KeystoreService> receiver);
KeystoreServiceAsh(const KeystoreServiceAsh&) = delete;
KeystoreServiceAsh& operator=(const KeystoreServiceAsh&) = delete;
~KeystoreServiceAsh() override;
void BindReceiver(mojo::PendingReceiver<mojom::KeystoreService> receiver);
// mojom::KeystoreService:
using KeystoreType = mojom::KeystoreType;
void ChallengeAttestationOnlyKeystore(
......@@ -82,7 +81,7 @@ class KeystoreServiceAsh : public mojom::KeystoreService {
// Container to keep outstanding challenges alive.
std::vector<std::unique_ptr<chromeos::attestation::TpmChallengeKey>>
outstanding_challenges_;
mojo::ReceiverSet<mojom::KeystoreService> receivers_;
mojo::Receiver<mojom::KeystoreService> receiver_;
base::WeakPtrFactory<KeystoreServiceAsh> weak_factory_{this};
};
......
......@@ -156,15 +156,12 @@ class ForwardingDelegate : public message_center::NotificationDelegate {
} // namespace
MessageCenterAsh::MessageCenterAsh() = default;
MessageCenterAsh::MessageCenterAsh(
mojo::PendingReceiver<mojom::MessageCenter> receiver)
: receiver_(this, std::move(receiver)) {}
MessageCenterAsh::~MessageCenterAsh() = default;
void MessageCenterAsh::BindReceiver(
mojo::PendingReceiver<mojom::MessageCenter> receiver) {
receivers_.Add(this, std::move(receiver));
}
void MessageCenterAsh::DisplayNotification(
mojom::NotificationPtr notification,
mojo::PendingRemote<mojom::NotificationDelegate> delegate) {
......
......@@ -7,7 +7,7 @@
#include "chromeos/crosapi/mojom/message_center.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/receiver.h"
namespace crosapi {
......@@ -16,13 +16,12 @@ namespace crosapi {
// Sends reply IPCs when the user interacts with the notifications.
class MessageCenterAsh : public mojom::MessageCenter {
public:
MessageCenterAsh();
explicit MessageCenterAsh(
mojo::PendingReceiver<mojom::MessageCenter> receiver);
MessageCenterAsh(const MessageCenterAsh&) = delete;
MessageCenterAsh& operator=(const MessageCenterAsh&) = delete;
~MessageCenterAsh() override;
void BindReceiver(mojo::PendingReceiver<mojom::MessageCenter> receiver);
// crosapi::mojom::MessageCenter:
void DisplayNotification(
mojom::NotificationPtr notification,
......@@ -32,7 +31,7 @@ class MessageCenterAsh : public mojom::MessageCenter {
GetDisplayedNotificationsCallback callback) override;
private:
mojo::ReceiverSet<mojom::MessageCenter> receivers_;
mojo::Receiver<mojom::MessageCenter> receiver_;
};
} // namespace crosapi
......
......@@ -84,8 +84,7 @@ class MessageCenterAshTest : public testing::Test {
// testing::Test:
void SetUp() override {
message_center::MessageCenter::Initialize();
message_center_ash_ = std::make_unique<MessageCenterAsh>();
message_center_ash_->BindReceiver(
message_center_ash_ = std::make_unique<MessageCenterAsh>(
message_center_remote_.BindNewPipeAndPassReceiver());
}
......
......@@ -167,15 +167,12 @@ class SelectFileDialogHolder : public ui::SelectFileDialog::Listener {
} // namespace
SelectFileAsh::SelectFileAsh() = default;
// TODO(https://crbug.com/1090587): Connection error handling.
SelectFileAsh::SelectFileAsh(mojo::PendingReceiver<mojom::SelectFile> receiver)
: receiver_(this, std::move(receiver)) {}
SelectFileAsh::~SelectFileAsh() = default;
void SelectFileAsh::BindReceiver(
mojo::PendingReceiver<mojom::SelectFile> receiver) {
receivers_.Add(this, std::move(receiver));
}
void SelectFileAsh::Select(mojom::SelectFileOptionsPtr options,
SelectCallback callback) {
aura::Window* owner_window = nullptr;
......
......@@ -7,7 +7,7 @@
#include "chromeos/crosapi/mojom/select_file.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/receiver.h"
namespace crosapi {
......@@ -16,19 +16,17 @@ namespace crosapi {
// file manager to provide the dialogs. Lives on the UI thread.
class SelectFileAsh : public mojom::SelectFile {
public:
SelectFileAsh();
explicit SelectFileAsh(mojo::PendingReceiver<mojom::SelectFile> receiver);
SelectFileAsh(const SelectFileAsh&) = delete;
SelectFileAsh& operator=(const SelectFileAsh&) = delete;
~SelectFileAsh() override;
void BindReceiver(mojo::PendingReceiver<mojom::SelectFile> receiver);
// crosapi::mojom::SelectFile:
void Select(mojom::SelectFileOptionsPtr options,
SelectCallback callback) override;
private:
mojo::ReceiverSet<mojom::SelectFile> receivers_;
mojo::Receiver<mojom::SelectFile> receiver_;
};
} // namespace crosapi
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment