Commit ce7d4eda authored by Michael van Ouwerkerk's avatar Michael van Ouwerkerk Committed by Commit Bot

Add tracing to the primary suspects of latency in sharing code.

Bug: 1035433

Change-Id: Ib04f5413245aced84f5fea526841014ce6219459
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2019022
Commit-Queue: Michael van Ouwerkerk <mvanouwerkerk@chromium.org>
Reviewed-by: default avatarRichard Knoll <knollr@chromium.org>
Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#735014}
parent bb8e99d0
......@@ -123,6 +123,7 @@
X("sequence_manager") \
X("service_manager") \
X("ServiceWorker") \
X("sharing") \
X("shell") \
X("shortcut_viewer") \
X("shutdown") \
......
......@@ -6,6 +6,7 @@
#include "base/android/jni_string.h"
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "chrome/android/chrome_jni_headers/ClickToCallMessageHandler_jni.h"
#include "chrome/browser/sharing/proto/click_to_call_message.pb.h"
#include "chrome/browser/sharing/proto/sharing_message.pb.h"
......@@ -18,6 +19,8 @@ void ClickToCallMessageHandler::OnMessage(
chrome_browser_sharing::SharingMessage message,
SharingMessageHandler::DoneCallback done_callback) {
DCHECK(message.has_click_to_call_message());
TRACE_EVENT0("sharing", "ClickToCallMessageHandler::OnMessage");
std::string phone_number = message.click_to_call_message().phone_number();
JNIEnv* env = base::android::AttachCurrentThread();
......
......@@ -8,6 +8,7 @@
#include <string>
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "chrome/browser/sharing/proto/shared_clipboard_message.pb.h"
#include "chrome/browser/sharing/proto/sharing_message.pb.h"
#include "chrome/browser/sharing/sharing_device_source.h"
......@@ -25,6 +26,7 @@ void SharedClipboardMessageHandler::OnMessage(
chrome_browser_sharing::SharingMessage message,
SharingMessageHandler::DoneCallback done_callback) {
DCHECK(message.has_shared_clipboard_message());
TRACE_EVENT0("sharing", "SharedClipboardMessageHandler::OnMessage");
ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste)
.WriteText(base::UTF8ToUTF16(message.shared_clipboard_message().text()));
......
......@@ -5,6 +5,7 @@
#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_android.h"
#include "base/android/jni_string.h"
#include "base/trace_event/trace_event.h"
#include "chrome/android/chrome_jni_headers/SharedClipboardMessageHandler_jni.h"
#include "ui/base/clipboard/clipboard_buffer.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
......@@ -18,6 +19,9 @@ SharedClipboardMessageHandlerAndroid::~SharedClipboardMessageHandlerAndroid() =
void SharedClipboardMessageHandlerAndroid::ShowNotification(
const std::string& device_name) {
TRACE_EVENT0("sharing",
"SharedClipboardMessageHandlerAndroid::ShowNotification");
JNIEnv* env = base::android::AttachCurrentThread();
Java_SharedClipboardMessageHandler_showNotification(
env, base::android::ConvertUTF8ToJavaString(env, device_name));
......
......@@ -7,6 +7,7 @@
#include "base/guid.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "chrome/browser/notifications/notification_display_service.h"
#include "chrome/browser/notifications/notification_display_service_factory.h"
#include "chrome/grit/generated_resources.h"
......@@ -26,6 +27,9 @@ SharedClipboardMessageHandlerDesktop::~SharedClipboardMessageHandlerDesktop() =
void SharedClipboardMessageHandlerDesktop::ShowNotification(
const std::string& device_name) {
TRACE_EVENT0("sharing",
"SharedClipboardMessageHandlerDesktop::ShowNotification");
std::string notification_id = base::GenerateGUID();
base::string16 notification_title =
......
......@@ -7,6 +7,7 @@
#include "base/no_destructor.h"
#include "base/strings/strcat.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "chrome/browser/sharing/features.h"
#include "chrome/browser/sharing/sharing_constants.h"
#include "chrome/browser/sharing/sharing_fcm_sender.h"
......@@ -85,6 +86,8 @@ void SharingFCMHandler::ShutdownHandler() {
void SharingFCMHandler::OnMessage(const std::string& app_id,
const gcm::IncomingMessage& message) {
TRACE_EVENT_BEGIN0("sharing", "SharingFCMHandler::OnMessage");
base::TimeTicks message_received_time = base::TimeTicks::Now();
std::string message_id = GetStrippedMessageId(message.message_id);
chrome_browser_sharing::SharingMessage sharing_message;
......@@ -92,23 +95,23 @@ void SharingFCMHandler::OnMessage(const std::string& app_id,
LOG(ERROR) << "Failed to parse incoming message with id : " << message_id;
return;
}
DCHECK(sharing_message.payload_case() !=
chrome_browser_sharing::SharingMessage::PayloadCase payload_case =
sharing_message.payload_case();
DCHECK(payload_case !=
chrome_browser_sharing::SharingMessage::PAYLOAD_NOT_SET)
<< "No payload set in SharingMessage received";
chrome_browser_sharing::MessageType message_type =
SharingPayloadCaseToMessageType(sharing_message.payload_case());
LogSharingMessageReceived(sharing_message.payload_case());
SharingPayloadCaseToMessageType(payload_case);
LogSharingMessageReceived(payload_case);
SharingMessageHandler* handler =
handler_registry_->GetSharingHandler(sharing_message.payload_case());
handler_registry_->GetSharingHandler(payload_case);
if (!handler) {
LOG(ERROR) << "No handler found for payload : "
<< sharing_message.payload_case();
LOG(ERROR) << "No handler found for payload : " << payload_case;
} else {
SharingMessageHandler::DoneCallback done_callback = base::DoNothing();
if (sharing_message.payload_case() !=
chrome_browser_sharing::SharingMessage::kAckMessage) {
if (payload_case != chrome_browser_sharing::SharingMessage::kAckMessage) {
done_callback = base::BindOnce(
&SharingFCMHandler::SendAckMessage, weak_ptr_factory_.GetWeakPtr(),
std::move(message_id), message_type, GetTargetInfo(sharing_message),
......@@ -118,6 +121,9 @@ void SharingFCMHandler::OnMessage(const std::string& app_id,
handler->OnMessage(std::move(sharing_message), std::move(done_callback));
}
TRACE_EVENT_END1("sharing", "SharingFCMHandler::OnMessage", "message_type",
SharingMessageTypeToString(message_type));
}
void SharingFCMHandler::OnSendAcknowledged(const std::string& app_id,
......@@ -164,6 +170,12 @@ void SharingFCMHandler::SendAckMessage(
return;
}
int trace_id = GenerateSharingTraceId();
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
"sharing", "Sharing.SendAckMessage", TRACE_ID_LOCAL(trace_id),
"original_message_type",
SharingMessageTypeToString(original_message_type));
chrome_browser_sharing::SharingMessage sharing_message;
chrome_browser_sharing::AckMessage* ack_message =
sharing_message.mutable_ack_message();
......@@ -178,17 +190,22 @@ void SharingFCMHandler::SendAckMessage(
base::BindOnce(&SharingFCMHandler::OnAckMessageSent,
weak_ptr_factory_.GetWeakPtr(),
std::move(original_message_id), original_message_type,
sender_device_type));
sender_device_type, trace_id));
}
void SharingFCMHandler::OnAckMessageSent(
std::string original_message_id,
chrome_browser_sharing::MessageType original_message_type,
SharingDevicePlatform sender_device_type,
int trace_id,
SharingSendMessageResult result,
base::Optional<std::string> message_id) {
LogSendSharingAckMessageResult(original_message_type, sender_device_type,
result);
if (result != SharingSendMessageResult::kSuccessful)
LOG(ERROR) << "Failed to send ack mesage for " << original_message_id;
TRACE_EVENT_NESTABLE_ASYNC_END1("sharing", "Sharing.SendAckMessage",
TRACE_ID_LOCAL(trace_id), "result",
SharingSendMessageResultToString(result));
}
......@@ -79,6 +79,7 @@ class SharingFCMHandler : public gcm::GCMAppHandler {
std::string original_message_id,
chrome_browser_sharing::MessageType original_message_type,
SharingDevicePlatform sender_device_type,
int trace_id,
SharingSendMessageResult result,
base::Optional<std::string> message_id);
......
......@@ -17,6 +17,7 @@
#include "components/sync_device_info/device_info.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 "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -129,6 +130,8 @@ class SharingFCMHandlerTest : public testing::Test {
return incoming_message;
}
content::BrowserTaskEnvironment task_environment_;
FakeSharingHandlerRegistry handler_registry_;
testing::NiceMock<MockSharingMessageHandler> mock_sharing_message_handler_;
......
......@@ -30,6 +30,8 @@ void SharingFCMSender::SendMessageToTargetInfo(
base::TimeDelta time_to_live,
SharingMessage message,
SendMessageCallback callback) {
TRACE_EVENT0("sharing", "SharingFCMSender::SendMessageToTargetInfo");
base::Optional<SharingSyncPreference::FCMRegistration> fcm_registration =
sync_preference_->GetFCMRegistration();
if (!fcm_registration) {
......@@ -64,6 +66,8 @@ void SharingFCMSender::DoSendMessageToDevice(const syncer::DeviceInfo& device,
base::TimeDelta time_to_live,
SharingMessage message,
SendMessageCallback callback) {
TRACE_EVENT0("sharing", "SharingFCMSender::DoSendMessageToDevice");
base::Optional<syncer::DeviceInfo::SharingTargetInfo> target_info =
GetTargetInfo(device);
if (!target_info) {
......@@ -118,6 +122,8 @@ bool SharingFCMSender::SetMessageSenderInfo(SharingMessage* message) {
void SharingFCMSender::OnMessageSent(SendMessageCallback callback,
gcm::SendWebPushMessageResult result,
base::Optional<std::string> message_id) {
TRACE_EVENT1("sharing", "SharingFCMSender::OnMessageSent", "result", result);
SharingSendMessageResult send_message_result;
switch (result) {
case gcm::SendWebPushMessageResult::kSuccessful:
......
......@@ -7,6 +7,7 @@
#include "base/guid.h"
#include "base/stl_util.h"
#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "chrome/browser/sharing/sharing_constants.h"
#include "chrome/browser/sharing/sharing_metrics.h"
#include "chrome/browser/sharing/sharing_sync_preference.h"
......@@ -32,6 +33,13 @@ void SharingMessageSender::SendMessageToDevice(
DCHECK(message.payload_case() !=
chrome_browser_sharing::SharingMessage::kAckMessage);
int trace_id = GenerateSharingTraceId();
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
"sharing", "Sharing.SendMessage", TRACE_ID_LOCAL(trace_id),
"message_type",
SharingMessageTypeToString(
SharingPayloadCaseToMessageType(message.payload_case())));
std::string message_guid = base::GenerateGUID();
chrome_browser_sharing::MessageType message_type =
SharingPayloadCaseToMessageType(message.payload_case());
......@@ -44,7 +52,7 @@ void SharingMessageSender::SendMessageToDevice(
message_metadata_, message_guid,
SentMessageMetadata(std::move(callback), base::TimeTicks::Now(),
message_type, receiver_device_platform,
last_updated_age));
last_updated_age, trace_id));
DCHECK(inserted.second);
auto delegate_iter = send_delegates_.find(delegate_type);
......@@ -84,6 +92,8 @@ void SharingMessageSender::SendMessageToDevice(
message.set_sender_device_name(
send_tab_to_self::GetSharingDeviceNames(local_device_info).full_name);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("sharing", "Sharing.DoSendMessage",
TRACE_ID_LOCAL(trace_id));
delegate->DoSendMessageToDevice(
device, response_timeout, std::move(message),
base::BindOnce(&SharingMessageSender::OnMessageSent,
......@@ -94,6 +104,10 @@ void SharingMessageSender::OnMessageSent(
const std::string& message_guid,
SharingSendMessageResult result,
base::Optional<std::string> message_id) {
TRACE_EVENT_NESTABLE_ASYNC_END1(
"sharing", "Sharing.DoSendMessage",
TRACE_ID_LOCAL(message_metadata_.find(message_guid)->second.trace_id),
"result", SharingSendMessageResultToString(result));
if (result != SharingSendMessageResult::kSuccessful) {
InvokeSendMessageCallback(message_guid, result,
/*response=*/nullptr);
......@@ -114,6 +128,7 @@ void SharingMessageSender::OnMessageSent(
void SharingMessageSender::OnAckReceived(
const std::string& message_id,
std::unique_ptr<chrome_browser_sharing::ResponseMessage> response) {
TRACE_EVENT0("sharing", "SharingMessageSender::OnAckReceived");
auto guid_iter = message_guids_.find(message_id);
if (guid_iter == message_guids_.end()) {
// We don't have the guid yet, store the response until we receive it.
......@@ -159,6 +174,9 @@ void SharingMessageSender::InvokeSendMessageCallback(
LogSendSharingMessageResult(metadata.type, metadata.receiver_device_platform,
result);
LogSharingDeviceLastUpdatedAgeWithResult(result, metadata.last_updated_age);
TRACE_EVENT_NESTABLE_ASYNC_END1("sharing", "SharingMessageSender.SendMessage",
TRACE_ID_LOCAL(metadata.trace_id), "result",
SharingSendMessageResultToString(result));
}
SharingMessageSender::SentMessageMetadata::SentMessageMetadata(
......@@ -166,12 +184,14 @@ SharingMessageSender::SentMessageMetadata::SentMessageMetadata(
base::TimeTicks timestamp,
chrome_browser_sharing::MessageType type,
SharingDevicePlatform receiver_device_platform,
base::TimeDelta last_updated_age)
base::TimeDelta last_updated_age,
int trace_id)
: callback(std::move(callback)),
timestamp(timestamp),
type(type),
receiver_device_platform(receiver_device_platform),
last_updated_age(last_updated_age) {}
last_updated_age(last_updated_age),
trace_id(trace_id) {}
SharingMessageSender::SentMessageMetadata::SentMessageMetadata(
SentMessageMetadata&& other) = default;
......
......@@ -84,7 +84,8 @@ class SharingMessageSender {
base::TimeTicks timestamp,
chrome_browser_sharing::MessageType type,
SharingDevicePlatform receiver_device_platform,
base::TimeDelta last_updated_age);
base::TimeDelta last_updated_age,
int trace_id);
SentMessageMetadata(SentMessageMetadata&& other);
SentMessageMetadata& operator=(SentMessageMetadata&& other);
~SentMessageMetadata();
......@@ -94,6 +95,7 @@ class SharingMessageSender {
chrome_browser_sharing::MessageType type;
SharingDevicePlatform receiver_device_platform;
base::TimeDelta last_updated_age;
int trace_id;
};
void OnMessageSent(const std::string& message_guid,
......
......@@ -9,6 +9,7 @@
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/sharing/sharing_device_registration_result.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_thread.h"
namespace {
const char* GetEnumStringValue(SharingFeatureName feature) {
......@@ -46,9 +47,20 @@ std::string DevicePlatformToString(SharingDevicePlatform device_platform) {
}
}
// Maps SharingSendMessageResult enum values to strings used as histogram
// suffixes. Keep in sync with "SharingSendMessageResult" in histograms.xml.
std::string SendMessageResultToSuffix(SharingSendMessageResult result) {
// Major Chrome version comparison with the receiver device.
// These values are logged to UMA. Entries should not be renumbered and numeric
// values should never be reused. Please keep in sync with
// "SharingMajorVersionComparison" in enums.xml.
enum class SharingMajorVersionComparison {
kUnknown = 0,
kSenderIsLower = 1,
kSame = 2,
kSenderIsHigher = 3,
kMaxValue = kSenderIsHigher,
};
} // namespace
std::string SharingSendMessageResultToString(SharingSendMessageResult result) {
switch (result) {
case SharingSendMessageResult::kSuccessful:
return "Successful";
......@@ -65,32 +77,6 @@ std::string SendMessageResultToSuffix(SharingSendMessageResult result) {
}
}
const std::string& MessageTypeToMessageSuffix(
chrome_browser_sharing::MessageType message_type) {
// For proto3 enums unrecognized enum values are kept when parsing and their
// name is an empty string. We don't want to use that as a histogram suffix.
// The returned values must match the values of the SharingMessage suffixes
// defined in histograms.xml.
if (!chrome_browser_sharing::MessageType_IsValid(message_type)) {
return chrome_browser_sharing::MessageType_Name(
chrome_browser_sharing::UNKNOWN_MESSAGE);
}
return chrome_browser_sharing::MessageType_Name(message_type);
}
// Major Chrome version comparison with the receiver device.
// These values are logged to UMA. Entries should not be renumbered and numeric
// values should never be reused. Please keep in sync with
// "SharingMajorVersionComparison" in enums.xml.
enum class SharingMajorVersionComparison {
kUnknown = 0,
kSenderIsLower = 1,
kSame = 2,
kSenderIsHigher = 3,
kMaxValue = kSenderIsHigher,
};
} // namespace
chrome_browser_sharing::MessageType SharingPayloadCaseToMessageType(
chrome_browser_sharing::SharingMessage::PayloadCase payload_case) {
switch (payload_case) {
......@@ -124,6 +110,23 @@ chrome_browser_sharing::MessageType SharingPayloadCaseToMessageType(
return chrome_browser_sharing::UNKNOWN_MESSAGE;
}
const std::string& SharingMessageTypeToString(
chrome_browser_sharing::MessageType message_type) {
// For proto3 enums unrecognized enum values are kept when parsing and their
// name is an empty string. We don't want to use that as a histogram suffix.
if (!chrome_browser_sharing::MessageType_IsValid(message_type)) {
return chrome_browser_sharing::MessageType_Name(
chrome_browser_sharing::UNKNOWN_MESSAGE);
}
return chrome_browser_sharing::MessageType_Name(message_type);
}
int GenerateSharingTraceId() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
static int next_id = 0;
return next_id++;
}
void LogSharingMessageReceived(
chrome_browser_sharing::SharingMessage::PayloadCase payload_case) {
base::UmaHistogramExactLinear("Sharing.MessageReceivedType",
......@@ -218,11 +221,11 @@ void LogSharingMessageAckTime(chrome_browser_sharing::MessageType message_type,
SharingDevicePlatform receiver_device_platform,
base::TimeDelta time) {
std::string suffixed_name = base::StrCat(
{"Sharing.MessageAckTime.", MessageTypeToMessageSuffix(message_type)});
{"Sharing.MessageAckTime.", SharingMessageTypeToString(message_type)});
std::string platform_suffixed_name =
base::StrCat({"Sharing.MessageAckTime.",
DevicePlatformToString(receiver_device_platform), ".",
MessageTypeToMessageSuffix(message_type)});
SharingMessageTypeToString(message_type)});
switch (message_type) {
case chrome_browser_sharing::MessageType::UNKNOWN_MESSAGE:
case chrome_browser_sharing::MessageType::PING_MESSAGE:
......@@ -251,7 +254,7 @@ void LogSharingMessageHandlerTime(
base::TimeDelta time_taken) {
base::UmaHistogramMediumTimes(
base::StrCat({"Sharing.MessageHandlerTime.",
MessageTypeToMessageSuffix(message_type)}),
SharingMessageTypeToString(message_type)}),
time_taken);
}
......@@ -262,7 +265,7 @@ void LogSharingDeviceLastUpdatedAge(
int hours = age.InHours();
base::UmaHistogramCounts1000(kBase, hours);
base::UmaHistogramCounts1000(
base::StrCat({kBase, ".", MessageTypeToMessageSuffix(message_type)}),
base::StrCat({kBase, ".", SharingMessageTypeToString(message_type)}),
hours);
}
......@@ -270,7 +273,7 @@ void LogSharingDeviceLastUpdatedAgeWithResult(SharingSendMessageResult result,
base::TimeDelta age) {
base::UmaHistogramCounts1000(
base::StrCat({"Sharing.DeviceLastUpdatedAgeWithResult.",
SendMessageResultToSuffix(result)}),
SharingSendMessageResultToString(result)}),
age.InHours());
}
......@@ -300,7 +303,7 @@ void LogSharingVersionComparison(
constexpr char kBase[] = "Sharing.MajorVersionComparison";
base::UmaHistogramEnumeration(kBase, result);
base::UmaHistogramEnumeration(
base::StrCat({kBase, ".", MessageTypeToMessageSuffix(message_type)}),
base::StrCat({kBase, ".", SharingMessageTypeToString(message_type)}),
result);
}
......@@ -319,7 +322,7 @@ void LogSendSharingMessageResult(
base::UmaHistogramEnumeration(metric_prefix, result);
base::UmaHistogramEnumeration(
base::StrCat(
{metric_prefix, ".", MessageTypeToMessageSuffix(message_type)}),
{metric_prefix, ".", SharingMessageTypeToString(message_type)}),
result);
base::UmaHistogramEnumeration(
......@@ -329,7 +332,7 @@ void LogSendSharingMessageResult(
base::UmaHistogramEnumeration(
base::StrCat({metric_prefix, ".",
DevicePlatformToString(receiving_device_platform), ".",
MessageTypeToMessageSuffix(message_type)}),
SharingMessageTypeToString(message_type)}),
result);
}
......@@ -342,7 +345,7 @@ void LogSendSharingAckMessageResult(
base::UmaHistogramEnumeration(metric_prefix, result);
base::UmaHistogramEnumeration(
base::StrCat(
{metric_prefix, ".", MessageTypeToMessageSuffix(message_type)}),
{metric_prefix, ".", SharingMessageTypeToString(message_type)}),
result);
base::UmaHistogramEnumeration(
......@@ -352,7 +355,7 @@ void LogSendSharingAckMessageResult(
base::UmaHistogramEnumeration(
base::StrCat({metric_prefix, ".",
DevicePlatformToString(ack_receiver_device_type), ".",
MessageTypeToMessageSuffix(message_type)}),
SharingMessageTypeToString(message_type)}),
result);
}
......@@ -365,7 +368,8 @@ void LogSharedClipboardRetries(int retries, SharingSendMessageResult result) {
constexpr char kBase[] = "Sharing.SharedClipboardRetries";
base::UmaHistogramExactLinear(kBase, retries, /*value_max=*/20);
base::UmaHistogramExactLinear(
base::StrCat({kBase, ".", SendMessageResultToSuffix(result)}), retries,
base::StrCat({kBase, ".", SharingSendMessageResultToString(result)}),
retries,
/*value_max=*/20);
}
......
......@@ -42,9 +42,22 @@ enum class SharingDialogType {
const char kSharingUiContextMenu[] = "ContextMenu";
const char kSharingUiDialog[] = "Dialog";
// Maps SharingSendMessageResult enums to strings used as histogram suffixes.
// Keep in sync with "SharingSendMessageResult" in histograms.xml.
std::string SharingSendMessageResultToString(SharingSendMessageResult result);
// Maps PayloadCase enums to MessageType enums.
chrome_browser_sharing::MessageType SharingPayloadCaseToMessageType(
chrome_browser_sharing::SharingMessage::PayloadCase payload_case);
// Maps MessageType enums to strings used as histogram suffixes. Keep in sync
// with "SharingMessage" in histograms.xml.
const std::string& SharingMessageTypeToString(
chrome_browser_sharing::MessageType message_type);
// Generates trace ids for async traces in the "sharing" category.
int GenerateSharingTraceId();
// Logs the |payload_case| to UMA. This should be called when a SharingMessage
// is received.
void LogSharingMessageReceived(
......
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