Commit 2ba387a3 authored by Daniel Bratell's avatar Daniel Bratell Committed by Commit Bot

Remove using namespace from components/signin code

The using namespace construct is disallowed in the code style guide.
It also causes issues (compilation warnings turned into errors)
in jumbo builds since they will be in a "header context" there
which is explicitly blocked by our compiler settings.

This patch also has a bit of a feature creep to remove a number
of unnecessary static_casts that made the code hard to read,
especially with the namespaces.

Change-Id: Icaa4968695a6f033868aac681a9ebe08eee75c3e
Reviewed-on: https://chromium-review.googlesource.com/c/1320131
Commit-Queue: Daniel Bratell <bratell@opera.com>
Reviewed-by: default avatarMihai Sardarescu <msarda@chromium.org>
Cr-Commit-Position: refs/heads/master@{#606113}
parent da790f92
...@@ -30,9 +30,6 @@ ...@@ -30,9 +30,6 @@
#include "google_apis/gaia/oauth2_token_service_delegate.h" #include "google_apis/gaia/oauth2_token_service_delegate.h"
#include "net/base/backoff_entry.h" #include "net/base/backoff_entry.h"
using base::Time;
using namespace signin_internals_util;
namespace { namespace {
// The maximum number of the refresh token events. Only the last // The maximum number of the refresh token events. Only the last
...@@ -76,15 +73,16 @@ void AddCookieEntry(base::ListValue* accounts_list, ...@@ -76,15 +73,16 @@ void AddCookieEntry(base::ListValue* accounts_list,
accounts_list->Append(std::move(entry)); accounts_list->Append(std::move(entry));
} }
std::string SigninStatusFieldToLabel(UntimedSigninStatusField field) { std::string SigninStatusFieldToLabel(
signin_internals_util::UntimedSigninStatusField field) {
switch (field) { switch (field) {
case ACCOUNT_ID: case signin_internals_util::ACCOUNT_ID:
return "Account Id"; return "Account Id";
case GAIA_ID: case signin_internals_util::GAIA_ID:
return "Gaia Id"; return "Gaia Id";
case USERNAME: case signin_internals_util::USERNAME:
return "Username"; return "Username";
case UNTIMED_FIELDS_END: case signin_internals_util::UNTIMED_FIELDS_END:
NOTREACHED(); NOTREACHED();
return std::string(); return std::string();
} }
...@@ -119,17 +117,18 @@ std::string TokenServiceLoadCredentialsStateToLabel( ...@@ -119,17 +117,18 @@ std::string TokenServiceLoadCredentialsStateToLabel(
} }
#if !defined (OS_CHROMEOS) #if !defined (OS_CHROMEOS)
std::string SigninStatusFieldToLabel(TimedSigninStatusField field) { std::string SigninStatusFieldToLabel(
signin_internals_util::TimedSigninStatusField field) {
switch (field) { switch (field) {
case AUTHENTICATION_RESULT_RECEIVED: case signin_internals_util::AUTHENTICATION_RESULT_RECEIVED:
return "Gaia Authentication Result"; return "Gaia Authentication Result";
case REFRESH_TOKEN_RECEIVED: case signin_internals_util::REFRESH_TOKEN_RECEIVED:
return "RefreshToken Received"; return "RefreshToken Received";
case SIGNIN_STARTED: case signin_internals_util::SIGNIN_STARTED:
return "SigninManager Started"; return "SigninManager Started";
case SIGNIN_COMPLETED: case signin_internals_util::SIGNIN_COMPLETED:
return "SigninManager Completed"; return "SigninManager Completed";
case TIMED_FIELDS_END: case signin_internals_util::TIMED_FIELDS_END:
NOTREACHED(); NOTREACHED();
return "Error"; return "Error";
} }
...@@ -139,7 +138,7 @@ std::string SigninStatusFieldToLabel(TimedSigninStatusField field) { ...@@ -139,7 +138,7 @@ std::string SigninStatusFieldToLabel(TimedSigninStatusField field) {
#endif // !defined (OS_CHROMEOS) #endif // !defined (OS_CHROMEOS)
void SetPref(PrefService* prefs, void SetPref(PrefService* prefs,
TimedSigninStatusField field, signin_internals_util::TimedSigninStatusField field,
const std::string& time, const std::string& time,
const std::string& value) { const std::string& value) {
std::string value_pref = SigninStatusFieldToString(field) + ".value"; std::string value_pref = SigninStatusFieldToString(field) + ".value";
...@@ -149,7 +148,7 @@ void SetPref(PrefService* prefs, ...@@ -149,7 +148,7 @@ void SetPref(PrefService* prefs,
} }
void GetPref(PrefService* prefs, void GetPref(PrefService* prefs,
TimedSigninStatusField field, signin_internals_util::TimedSigninStatusField field,
std::string* time, std::string* time,
std::string* value) { std::string* value) {
std::string value_pref = SigninStatusFieldToString(field) + ".value"; std::string value_pref = SigninStatusFieldToString(field) + ".value";
...@@ -158,7 +157,8 @@ void GetPref(PrefService* prefs, ...@@ -158,7 +157,8 @@ void GetPref(PrefService* prefs,
*time = prefs->GetString(time_pref); *time = prefs->GetString(time_pref);
} }
void ClearPref(PrefService* prefs, TimedSigninStatusField field) { void ClearPref(PrefService* prefs,
signin_internals_util::TimedSigninStatusField field) {
std::string value_pref = SigninStatusFieldToString(field) + ".value"; std::string value_pref = SigninStatusFieldToString(field) + ".value";
std::string time_pref = SigninStatusFieldToString(field) + ".time"; std::string time_pref = SigninStatusFieldToString(field) + ".time";
prefs->ClearPref(value_pref); prefs->ClearPref(value_pref);
...@@ -202,6 +202,19 @@ AboutSigninInternals::AboutSigninInternals( ...@@ -202,6 +202,19 @@ AboutSigninInternals::AboutSigninInternals(
AboutSigninInternals::~AboutSigninInternals() {} AboutSigninInternals::~AboutSigninInternals() {}
signin_internals_util::UntimedSigninStatusField& operator++(
signin_internals_util::UntimedSigninStatusField& field) {
field =
static_cast<signin_internals_util::UntimedSigninStatusField>(field + 1);
return field;
}
signin_internals_util::TimedSigninStatusField& operator++(
signin_internals_util::TimedSigninStatusField& field) {
field = static_cast<signin_internals_util::TimedSigninStatusField>(field + 1);
return field;
}
// static // static
void AboutSigninInternals::RegisterPrefs(PrefRegistrySimple* user_prefs) { void AboutSigninInternals::RegisterPrefs(PrefRegistrySimple* user_prefs) {
// SigninManager information for about:signin-internals. // SigninManager information for about:signin-internals.
...@@ -209,19 +222,18 @@ void AboutSigninInternals::RegisterPrefs(PrefRegistrySimple* user_prefs) { ...@@ -209,19 +222,18 @@ void AboutSigninInternals::RegisterPrefs(PrefRegistrySimple* user_prefs) {
// TODO(rogerta): leaving untimed fields here for now because legacy // TODO(rogerta): leaving untimed fields here for now because legacy
// profiles still have these prefs. In three or four version from M43 // profiles still have these prefs. In three or four version from M43
// we can probably remove them. // we can probably remove them.
for (int i = UNTIMED_FIELDS_BEGIN; i < UNTIMED_FIELDS_END; ++i) { for (signin_internals_util::UntimedSigninStatusField i =
const std::string pref_path = signin_internals_util::UNTIMED_FIELDS_BEGIN;
SigninStatusFieldToString(static_cast<UntimedSigninStatusField>(i)); i < signin_internals_util::UNTIMED_FIELDS_END; ++i) {
const std::string pref_path = SigninStatusFieldToString(i);
user_prefs->RegisterStringPref(pref_path, std::string()); user_prefs->RegisterStringPref(pref_path, std::string());
} }
for (int i = TIMED_FIELDS_BEGIN; i < TIMED_FIELDS_END; ++i) { for (signin_internals_util::TimedSigninStatusField i =
const std::string value = signin_internals_util::TIMED_FIELDS_BEGIN;
SigninStatusFieldToString(static_cast<TimedSigninStatusField>(i)) + i < signin_internals_util::TIMED_FIELDS_END; ++i) {
".value"; const std::string value = SigninStatusFieldToString(i) + ".value";
const std::string time = const std::string time = SigninStatusFieldToString(i) + ".time";
SigninStatusFieldToString(static_cast<TimedSigninStatusField>(i)) +
".time";
user_prefs->RegisterStringPref(value, std::string()); user_prefs->RegisterStringPref(value, std::string());
user_prefs->RegisterStringPref(time, std::string()); user_prefs->RegisterStringPref(time, std::string());
} }
...@@ -238,13 +250,13 @@ void AboutSigninInternals::RemoveSigninObserver( ...@@ -238,13 +250,13 @@ void AboutSigninInternals::RemoveSigninObserver(
} }
void AboutSigninInternals::NotifySigninValueChanged( void AboutSigninInternals::NotifySigninValueChanged(
const TimedSigninStatusField& field, const signin_internals_util::TimedSigninStatusField& field,
const std::string& value) { const std::string& value) {
unsigned int field_index = field - TIMED_FIELDS_BEGIN; unsigned int field_index = field - signin_internals_util::TIMED_FIELDS_BEGIN;
DCHECK(field_index >= 0 && DCHECK(field_index >= 0 &&
field_index < signin_status_.timed_signin_fields.size()); field_index < signin_status_.timed_signin_fields.size());
Time now = Time::NowFromSystemTime(); base::Time now = base::Time::NowFromSystemTime();
std::string time_as_str = std::string time_as_str =
base::UTF16ToUTF8(base::TimeFormatShortDateAndTime(now)); base::UTF16ToUTF8(base::TimeFormatShortDateAndTime(now));
TimedSigninStatusValue timed_value(value, time_as_str); TimedSigninStatusValue timed_value(value, time_as_str);
...@@ -256,10 +268,11 @@ void AboutSigninInternals::NotifySigninValueChanged( ...@@ -256,10 +268,11 @@ void AboutSigninInternals::NotifySigninValueChanged(
// If the user is restarting a sign in process, clear the fields that are // If the user is restarting a sign in process, clear the fields that are
// to come. // to come.
if (field == AUTHENTICATION_RESULT_RECEIVED) { if (field == signin_internals_util::AUTHENTICATION_RESULT_RECEIVED) {
ClearPref(client_->GetPrefs(), REFRESH_TOKEN_RECEIVED); ClearPref(client_->GetPrefs(),
ClearPref(client_->GetPrefs(), SIGNIN_STARTED); signin_internals_util::REFRESH_TOKEN_RECEIVED);
ClearPref(client_->GetPrefs(), SIGNIN_COMPLETED); ClearPref(client_->GetPrefs(), signin_internals_util::SIGNIN_STARTED);
ClearPref(client_->GetPrefs(), signin_internals_util::SIGNIN_COMPLETED);
} }
NotifyObservers(); NotifyObservers();
...@@ -271,13 +284,16 @@ void AboutSigninInternals::RefreshSigninPrefs() { ...@@ -271,13 +284,16 @@ void AboutSigninInternals::RefreshSigninPrefs() {
return; return;
PrefService* pref_service = client_->GetPrefs(); PrefService* pref_service = client_->GetPrefs();
for (int i = TIMED_FIELDS_BEGIN; i < TIMED_FIELDS_END; ++i) { for (signin_internals_util::TimedSigninStatusField i =
signin_internals_util::TIMED_FIELDS_BEGIN;
i < signin_internals_util::TIMED_FIELDS_END; ++i) {
std::string time_str; std::string time_str;
std::string value_str; std::string value_str;
GetPref(pref_service, static_cast<TimedSigninStatusField>(i), GetPref(pref_service, i, &time_str, &value_str);
&time_str, &value_str);
TimedSigninStatusValue value(value_str, time_str); TimedSigninStatusValue value(value_str, time_str);
signin_status_.timed_signin_fields[i - TIMED_FIELDS_BEGIN] = value; signin_status_
.timed_signin_fields[i - signin_internals_util::TIMED_FIELDS_BEGIN] =
value;
} }
// TODO(rogerta): Get status and timestamps for oauth2 tokens. // TODO(rogerta): Get status and timestamps for oauth2 tokens.
...@@ -408,12 +424,14 @@ void AboutSigninInternals::OnAccessTokenRemoved( ...@@ -408,12 +424,14 @@ void AboutSigninInternals::OnAccessTokenRemoved(
} }
void AboutSigninInternals::OnRefreshTokenReceived(const std::string& status) { void AboutSigninInternals::OnRefreshTokenReceived(const std::string& status) {
NotifySigninValueChanged(REFRESH_TOKEN_RECEIVED, status); NotifySigninValueChanged(signin_internals_util::REFRESH_TOKEN_RECEIVED,
status);
} }
void AboutSigninInternals::OnAuthenticationResultReceived( void AboutSigninInternals::OnAuthenticationResultReceived(
const std::string& status) { const std::string& status) {
NotifySigninValueChanged(AUTHENTICATION_RESULT_RECEIVED, status); NotifySigninValueChanged(
signin_internals_util::AUTHENTICATION_RESULT_RECEIVED, status);
} }
void AboutSigninInternals::OnErrorChanged() { void AboutSigninInternals::OnErrorChanged() {
...@@ -527,7 +545,7 @@ AboutSigninInternals::TokenInfo::ToValue() const { ...@@ -527,7 +545,7 @@ AboutSigninInternals::TokenInfo::ToValue() const {
} }
AboutSigninInternals::RefreshTokenEvent::RefreshTokenEvent() AboutSigninInternals::RefreshTokenEvent::RefreshTokenEvent()
: timestamp(Time::Now()){}; : timestamp(base::Time::Now()){};
std::string AboutSigninInternals::RefreshTokenEvent::GetTypeAsString() const { std::string AboutSigninInternals::RefreshTokenEvent::GetTypeAsString() const {
switch (type) { switch (type) {
...@@ -543,7 +561,7 @@ std::string AboutSigninInternals::RefreshTokenEvent::GetTypeAsString() const { ...@@ -543,7 +561,7 @@ std::string AboutSigninInternals::RefreshTokenEvent::GetTypeAsString() const {
} }
AboutSigninInternals::SigninStatus::SigninStatus() AboutSigninInternals::SigninStatus::SigninStatus()
: timed_signin_fields(TIMED_FIELDS_COUNT) {} : timed_signin_fields(signin_internals_util::TIMED_FIELDS_COUNT) {}
AboutSigninInternals::SigninStatus::~SigninStatus() {} AboutSigninInternals::SigninStatus::~SigninStatus() {}
...@@ -595,16 +613,13 @@ AboutSigninInternals::SigninStatus::ToValue( ...@@ -595,16 +613,13 @@ AboutSigninInternals::SigninStatus::ToValue(
if (signin_manager->IsAuthenticated()) { if (signin_manager->IsAuthenticated()) {
std::string account_id = signin_manager->GetAuthenticatedAccountId(); std::string account_id = signin_manager->GetAuthenticatedAccountId();
AddSectionEntry(basic_info, AddSectionEntry(basic_info,
SigninStatusFieldToLabel( SigninStatusFieldToLabel(signin_internals_util::ACCOUNT_ID),
static_cast<UntimedSigninStatusField>(ACCOUNT_ID)),
account_id); account_id);
AddSectionEntry(basic_info, AddSectionEntry(basic_info,
SigninStatusFieldToLabel( SigninStatusFieldToLabel(signin_internals_util::GAIA_ID),
static_cast<UntimedSigninStatusField>(GAIA_ID)),
account_tracker->GetAccountInfo(account_id).gaia); account_tracker->GetAccountInfo(account_id).gaia);
AddSectionEntry(basic_info, AddSectionEntry(basic_info,
SigninStatusFieldToLabel( SigninStatusFieldToLabel(signin_internals_util::USERNAME),
static_cast<UntimedSigninStatusField>(USERNAME)),
signin_manager->GetAuthenticatedAccountInfo().email); signin_manager->GetAuthenticatedAccountInfo().email);
if (signin_error_controller->HasError()) { if (signin_error_controller->HasError()) {
const std::string error_account_id = const std::string error_account_id =
...@@ -625,21 +640,25 @@ AboutSigninInternals::SigninStatus::ToValue( ...@@ -625,21 +640,25 @@ AboutSigninInternals::SigninStatus::ToValue(
base::ListValue* detailed_info = base::ListValue* detailed_info =
AddSection(signin_info.get(), "Last Signin Details"); AddSection(signin_info.get(), "Last Signin Details");
signin_status->Set("signin_info", std::move(signin_info)); signin_status->Set("signin_info", std::move(signin_info));
for (int i = TIMED_FIELDS_BEGIN; i < TIMED_FIELDS_END; ++i) { for (signin_internals_util::TimedSigninStatusField i =
const std::string status_field_label = signin_internals_util::TIMED_FIELDS_BEGIN;
SigninStatusFieldToLabel(static_cast<TimedSigninStatusField>(i)); i < signin_internals_util::TIMED_FIELDS_END; ++i) {
const std::string status_field_label = SigninStatusFieldToLabel(i);
AddSectionEntry(detailed_info,
status_field_label, AddSectionEntry(
timed_signin_fields[i - TIMED_FIELDS_BEGIN].first, detailed_info, status_field_label,
timed_signin_fields[i - TIMED_FIELDS_BEGIN].second); timed_signin_fields[i - signin_internals_util::TIMED_FIELDS_BEGIN]
.first,
timed_signin_fields[i - signin_internals_util::TIMED_FIELDS_BEGIN]
.second);
} }
const net::BackoffEntry* cookie_manager_backoff_entry = const net::BackoffEntry* cookie_manager_backoff_entry =
cookie_manager_service->GetBackoffEntry(); cookie_manager_service->GetBackoffEntry();
if (cookie_manager_backoff_entry->ShouldRejectRequest()) { if (cookie_manager_backoff_entry->ShouldRejectRequest()) {
Time next_retry_time = Time::NowFromSystemTime() + base::Time next_retry_time =
base::Time::NowFromSystemTime() +
cookie_manager_backoff_entry->GetTimeUntilRelease(); cookie_manager_backoff_entry->GetTimeUntilRelease();
std::string next_retry_time_as_str = std::string next_retry_time_as_str =
...@@ -657,7 +676,8 @@ AboutSigninInternals::SigninStatus::ToValue( ...@@ -657,7 +676,8 @@ AboutSigninInternals::SigninStatus::ToValue(
if (token_service_backoff_entry && if (token_service_backoff_entry &&
token_service_backoff_entry->ShouldRejectRequest()) { token_service_backoff_entry->ShouldRejectRequest()) {
Time next_retry_time = Time::NowFromSystemTime() + base::Time next_retry_time =
base::Time::NowFromSystemTime() +
token_service_backoff_entry->GetTimeUntilRelease(); token_service_backoff_entry->GetTimeUntilRelease();
std::string next_retry_time_as_str = std::string next_retry_time_as_str =
......
...@@ -25,10 +25,11 @@ const size_t kTruncateTokenStringLength = 6; ...@@ -25,10 +25,11 @@ const size_t kTruncateTokenStringLength = 6;
// Helper enums to access fields from SigninStatus (declared below). // Helper enums to access fields from SigninStatus (declared below).
enum { enum {
SIGNIN_FIELDS_BEGIN = 0, SIGNIN_FIELDS_BEGIN = 0,
UNTIMED_FIELDS_BEGIN = SIGNIN_FIELDS_BEGIN UNTIMED_FIELDS_BEGIN_UNTYPED = SIGNIN_FIELDS_BEGIN
}; };
enum UntimedSigninStatusField { enum UntimedSigninStatusField {
UNTIMED_FIELDS_BEGIN = UNTIMED_FIELDS_BEGIN_UNTYPED,
ACCOUNT_ID = UNTIMED_FIELDS_BEGIN, ACCOUNT_ID = UNTIMED_FIELDS_BEGIN,
GAIA_ID, GAIA_ID,
USERNAME, USERNAME,
...@@ -37,10 +38,11 @@ enum UntimedSigninStatusField { ...@@ -37,10 +38,11 @@ enum UntimedSigninStatusField {
enum { enum {
UNTIMED_FIELDS_COUNT = UNTIMED_FIELDS_END - UNTIMED_FIELDS_BEGIN, UNTIMED_FIELDS_COUNT = UNTIMED_FIELDS_END - UNTIMED_FIELDS_BEGIN,
TIMED_FIELDS_BEGIN = UNTIMED_FIELDS_END TIMED_FIELDS_BEGIN_UNTYPED = UNTIMED_FIELDS_END
}; };
enum TimedSigninStatusField { enum TimedSigninStatusField {
TIMED_FIELDS_BEGIN = TIMED_FIELDS_BEGIN_UNTYPED,
AUTHENTICATION_RESULT_RECEIVED = TIMED_FIELDS_BEGIN, AUTHENTICATION_RESULT_RECEIVED = TIMED_FIELDS_BEGIN,
REFRESH_TOKEN_RECEIVED, REFRESH_TOKEN_RECEIVED,
SIGNIN_STARTED, SIGNIN_STARTED,
......
...@@ -24,8 +24,6 @@ ...@@ -24,8 +24,6 @@
#include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/google_service_auth_error.h"
#include "third_party/icu/source/i18n/unicode/regex.h" #include "third_party/icu/source/i18n/unicode/regex.h"
using namespace signin_internals_util;
SigninManager::SigninManager( SigninManager::SigninManager(
SigninClient* client, SigninClient* client,
ProfileOAuth2TokenService* token_service, ProfileOAuth2TokenService* token_service,
...@@ -91,7 +89,8 @@ bool SigninManager::PrepareForSignin(SigninType type, ...@@ -91,7 +89,8 @@ bool SigninManager::PrepareForSignin(SigninType type,
password_.assign(password); password_.assign(password);
signin_manager_signed_in_ = false; signin_manager_signed_in_ = false;
user_info_fetched_by_account_tracker_ = false; user_info_fetched_by_account_tracker_ = false;
NotifyDiagnosticsObservers(SIGNIN_STARTED, SigninTypeToString(type)); NotifyDiagnosticsObservers(signin_internals_util::SIGNIN_STARTED,
SigninTypeToString(type));
return true; return true;
} }
...@@ -404,7 +403,8 @@ void SigninManager::MergeSigninCredentialIntoCookieJar() { ...@@ -404,7 +403,8 @@ void SigninManager::MergeSigninCredentialIntoCookieJar() {
} }
void SigninManager::CompletePendingSignin() { void SigninManager::CompletePendingSignin() {
NotifyDiagnosticsObservers(SIGNIN_COMPLETED, "Successful"); NotifyDiagnosticsObservers(signin_internals_util::SIGNIN_COMPLETED,
"Successful");
DCHECK(!possibly_invalid_account_id_.empty()); DCHECK(!possibly_invalid_account_id_.empty());
OnSignedIn(); OnSignedIn();
......
...@@ -24,8 +24,6 @@ ...@@ -24,8 +24,6 @@
#include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h" #include "google_apis/gaia/gaia_urls.h"
using namespace signin_internals_util;
SigninManagerBase::SigninManagerBase( SigninManagerBase::SigninManagerBase(
SigninClient* client, SigninClient* client,
AccountTrackerService* account_tracker_service, AccountTrackerService* account_tracker_service,
...@@ -249,17 +247,17 @@ void SigninManagerBase::RemoveObserver(Observer* observer) { ...@@ -249,17 +247,17 @@ void SigninManagerBase::RemoveObserver(Observer* observer) {
} }
void SigninManagerBase::AddSigninDiagnosticsObserver( void SigninManagerBase::AddSigninDiagnosticsObserver(
SigninDiagnosticsObserver* observer) { signin_internals_util::SigninDiagnosticsObserver* observer) {
signin_diagnostics_observers_.AddObserver(observer); signin_diagnostics_observers_.AddObserver(observer);
} }
void SigninManagerBase::RemoveSigninDiagnosticsObserver( void SigninManagerBase::RemoveSigninDiagnosticsObserver(
SigninDiagnosticsObserver* observer) { signin_internals_util::SigninDiagnosticsObserver* observer) {
signin_diagnostics_observers_.RemoveObserver(observer); signin_diagnostics_observers_.RemoveObserver(observer);
} }
void SigninManagerBase::NotifyDiagnosticsObservers( void SigninManagerBase::NotifyDiagnosticsObservers(
const TimedSigninStatusField& field, const signin_internals_util::TimedSigninStatusField& field,
const std::string& value) { const std::string& value) {
for (auto& observer : signin_diagnostics_observers_) for (auto& observer : signin_diagnostics_observers_)
observer.NotifySigninValueChanged(field, value); observer.NotifySigninValueChanged(field, value);
......
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