Commit 56f075b7 authored by Robert Sesek's avatar Robert Sesek Committed by Commit Bot

Refactor duplicate implementations of Linux blink::WebSandboxSupport.

This refactors the three implementations across //content's ppapi_plugin,
renderer, and utility into a single implementation in child. No intended
behavior change.

Change-Id: Icebe662f6d6855bd4f00f103691267e5db7e92ff
Reviewed-on: https://chromium-review.googlesource.com/c/1356026Reviewed-by: default avatarDominik Röttsches <drott@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Commit-Queue: Robert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613145}
parent dedfbe33
......@@ -5,22 +5,13 @@
#include "content/child/child_process_sandbox_support_impl_linux.h"
#include <stddef.h>
#include <sys/stat.h>
#include <limits>
#include <memory>
#include "base/pickle.h"
#include "base/posix/eintr_wrapper.h"
#include "base/posix/unix_domain_socket.h"
#include "base/sys_byteorder.h"
#include "base/trace_event/trace_event.h"
#include "base/logging.h"
#include "components/services/font/public/cpp/font_loader.h"
#include "components/services/font/public/interfaces/constants.mojom.h"
#include "components/services/font/public/interfaces/font_service.mojom.h"
#include "content/public/common/common_sandbox_support_linux.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
#include "third_party/blink/public/platform/linux/out_of_process_font.h"
#include "third_party/blink/public/platform/web_font_render_style.h"
#include "third_party/blink/public/platform/web_string.h"
......@@ -28,18 +19,32 @@
namespace content {
void GetFallbackFontForCharacter(sk_sp<font_service::FontLoader> font_loader,
int32_t character,
const char* preferred_locale,
blink::OutOfProcessFont* fallback_font) {
DCHECK(font_loader.get());
WebSandboxSupportLinux::WebSandboxSupportLinux(
sk_sp<font_service::FontLoader> font_loader)
: font_loader_(font_loader) {}
WebSandboxSupportLinux::~WebSandboxSupportLinux() = default;
void WebSandboxSupportLinux::GetFallbackFontForCharacter(
blink::WebUChar32 character,
const char* preferred_locale,
blink::OutOfProcessFont* fallback_font) {
{
base::AutoLock lock(lock_);
const auto iter = unicode_font_families_.find(character);
if (iter != unicode_font_families_.end()) {
*fallback_font = iter->second;
return;
}
}
font_service::mojom::FontIdentityPtr font_identity;
bool is_bold = false;
bool is_italic = false;
std::string family_name;
if (!font_loader->FallbackFontForCharacter(character, preferred_locale,
&font_identity, &family_name,
&is_bold, &is_italic)) {
if (!font_loader_->FallbackFontForCharacter(character, preferred_locale,
&font_identity, &family_name,
&is_bold, &is_italic)) {
LOG(ERROR) << "FontService fallback request does not receive a response.";
return;
}
......@@ -54,17 +59,36 @@ void GetFallbackFontForCharacter(sk_sp<font_service::FontLoader> font_loader,
fallback_font->ttc_index = font_identity->ttc_index;
fallback_font->is_bold = is_bold;
fallback_font->is_italic = is_italic;
return;
base::AutoLock lock(lock_);
unicode_font_families_.emplace(character, *fallback_font);
}
void WebSandboxSupportLinux::MatchFontByPostscriptNameOrFullFontName(
const char* font_unique_name,
blink::OutOfProcessFont* fallback_font) {
font_service::mojom::FontIdentityPtr font_identity;
std::string family_name;
if (!font_loader_->MatchFontByPostscriptNameOrFullFontName(font_unique_name,
&font_identity)) {
LOG(ERROR) << "FontService unique font name matching request did not "
"receive a response.";
return;
}
fallback_font->fontconfig_interface_id = font_identity->id;
fallback_font->filename.Assign(font_identity->str_representation.c_str(),
font_identity->str_representation.length());
fallback_font->ttc_index = font_identity->ttc_index;
}
void GetRenderStyleForStrike(sk_sp<font_service::FontLoader> font_loader,
const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) {
DCHECK(font_loader.get());
void WebSandboxSupportLinux::GetWebFontRenderStyleForStrike(
const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) {
font_service::mojom::FontIdentityPtr font_identity;
*out = blink::WebFontRenderStyle();
......@@ -73,9 +97,9 @@ void GetRenderStyleForStrike(sk_sp<font_service::FontLoader> font_loader,
return;
font_service::mojom::FontRenderStylePtr font_render_style;
if (!font_loader->FontRenderStyleForStrike(family, size, is_bold, is_italic,
device_scale_factor,
&font_render_style) ||
if (!font_loader_->FontRenderStyleForStrike(family, size, is_bold, is_italic,
device_scale_factor,
&font_render_style) ||
font_render_style.is_null()) {
LOG(ERROR) << "GetRenderStyleForStrike did not receive a response for "
"family and size: "
......@@ -94,23 +118,4 @@ void GetRenderStyleForStrike(sk_sp<font_service::FontLoader> font_loader,
static_cast<char>(font_render_style->use_subpixel_positioning);
}
void MatchFontByPostscriptNameOrFullFontName(
sk_sp<font_service::FontLoader> font_loader,
const char* font_unique_name,
blink::OutOfProcessFont* fallback_font) {
font_service::mojom::FontIdentityPtr font_identity;
std::string family_name;
if (!font_loader->MatchFontByPostscriptNameOrFullFontName(font_unique_name,
&font_identity)) {
LOG(ERROR) << "FontService unique font name matching request did not "
"receive a response.";
return;
}
fallback_font->fontconfig_interface_id = font_identity->id;
fallback_font->filename.Assign(font_identity->str_representation.c_str(),
font_identity->str_representation.length());
fallback_font->ttc_index = font_identity->ttc_index;
}
} // namespace content
......@@ -5,9 +5,15 @@
#ifndef CONTENT_CHILD_CHILD_PROCESS_SANDBOX_SUPPORT_IMPL_LINUX_H_
#define CONTENT_CHILD_CHILD_PROCESS_SANDBOX_SUPPORT_IMPL_LINUX_H_
#include <map>
#include <stdint.h>
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "components/services/font/public/cpp/font_loader.h"
#include "third_party/blink/public/platform/linux/web_sandbox_support.h"
#include "third_party/skia/include/core/SkRefCnt.h"
namespace blink {
......@@ -17,36 +23,54 @@ struct WebFontRenderStyle;
namespace content {
// Returns a font family which provides glyphs for the Unicode code point
// specified by |character|, a UTF-32 character. |preferred_locale| contains the
// preferred locale identifier for |character|. The instance has an empty font
// name if the request could not be satisfied.
void GetFallbackFontForCharacter(sk_sp<font_service::FontLoader> font_loader,
const int32_t character,
const char* preferred_locale,
blink::OutOfProcessFont* family);
// Returns rendering settings for a provided font family, size, and style.
// |size_and_style| stores the bold setting in its least-significant bit, the
// italic setting in its second-least-significant bit, and holds the requested
// size in pixels into its remaining bits.
void GetRenderStyleForStrike(sk_sp<font_service::FontLoader> font_loader,
const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out);
// Matches a font uniquely by postscript name or full font name. Used in Blink
// for @font-face { src: local(arg) } matching. Provide full font name or
// postscript name as argument font_unique_name in UTF-8. fallback_font contains
// a filename and fontconfig interface id if a match was found. The filename is
// empty and the interface id is zero if no match is found.
void MatchFontByPostscriptNameOrFullFontName(
sk_sp<font_service::FontLoader> font_loader,
const char* font_unique_name,
blink::OutOfProcessFont* uniquely_matched_font);
// Child-process implementation of the Blink interface that sandboxed processes
// use to obtain data from the privileged process (browser), which would
// otherwise be blocked by the sandbox.
class WebSandboxSupportLinux : public blink::WebSandboxSupport {
public:
explicit WebSandboxSupportLinux(sk_sp<font_service::FontLoader> font_loader);
~WebSandboxSupportLinux() override;
// Returns a font family which provides glyphs for the Unicode code point
// specified by |character|, a UTF-32 character. |preferred_locale| contains
// the preferred locale identifier for |character|. The instance has an empty
// font name if the request could not be satisfied.
void GetFallbackFontForCharacter(blink::WebUChar32 character,
const char* preferred_locale,
blink::OutOfProcessFont* font) override;
// Matches a font uniquely by postscript name or full font name. Used in
// Blink for @font-face { src: local(arg) } matching. Provide full font name
// or postscript name as argument font_unique_name in UTF-8. fallback_font
// contains a filename and fontconfig interface id if a match was found. The
// filename is empty and the interface id is zero if no match is found.
void MatchFontByPostscriptNameOrFullFontName(
const char* font_unique_name,
blink::OutOfProcessFont* font) override;
// Returns rendering settings for a provided font family, size, and style.
// |size_and_style| stores the bold setting in its least-significant bit, the
// italic setting in its second-least-significant bit, and holds the requested
// size in pixels into its remaining bits.
void GetWebFontRenderStyleForStrike(const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) override;
private:
// Blink calls GetFallbackFontForCharacter frequently, so the results are
// cached. The cache is protected by this lock.
base::Lock lock_;
// Maps unicode chars to their fallback fonts.
std::map<int32_t, blink::OutOfProcessFont> unicode_font_families_
GUARDED_BY(lock_);
sk_sp<font_service::FontLoader> font_loader_;
DISALLOW_COPY_AND_ASSIGN(WebSandboxSupportLinux);
};
}; // namespace content
......
......@@ -20,11 +20,8 @@
#if defined(OS_MACOSX)
#include "content/child/child_process_sandbox_support_impl_mac.h"
#elif defined(OS_POSIX) && !defined(OS_ANDROID)
#elif defined(OS_LINUX)
#include "content/child/child_process_sandbox_support_impl_linux.h"
#include "third_party/blink/public/platform/linux/out_of_process_font.h"
#include "third_party/blink/public/platform/linux/web_sandbox_support.h"
#include "third_party/icu/source/common/unicode/utf16.h"
#endif
using blink::WebSandboxSupport;
......@@ -36,94 +33,12 @@ typedef struct CGFont* CGFontRef;
namespace content {
#if defined(OS_LINUX)
class PpapiBlinkPlatformImpl::SandboxSupport : public WebSandboxSupport {
public:
explicit SandboxSupport(sk_sp<font_service::FontLoader> font_loader)
: font_loader_(std::move(font_loader)) {}
~SandboxSupport() override {}
SandboxSupport();
void GetFallbackFontForCharacter(
WebUChar32 character,
const char* preferred_locale,
blink::OutOfProcessFont* fallbackFont) override;
void MatchFontByPostscriptNameOrFullFontName(
const char* font_unique_name,
blink::OutOfProcessFont* fallback_font) override;
void GetWebFontRenderStyleForStrike(const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) override;
private:
// WebKit likes to ask us for the correct font family to use for a set of
// unicode code points. It needs this information frequently so we cache it
// here.
std::map<int32_t, blink::OutOfProcessFont> unicode_font_families_;
sk_sp<font_service::FontLoader> font_loader_;
// For debugging https://crbug.com/312965
base::SequenceCheckerImpl creation_thread_sequence_checker_;
};
PpapiBlinkPlatformImpl::SandboxSupport::SandboxSupport() {}
void PpapiBlinkPlatformImpl::SandboxSupport::GetFallbackFontForCharacter(
WebUChar32 character,
const char* preferred_locale,
blink::OutOfProcessFont* fallbackFont) {
ppapi::ProxyLock::AssertAcquired();
// For debugging crbug.com/312965
CHECK(creation_thread_sequence_checker_.CalledOnValidSequence());
const std::map<int32_t, blink::OutOfProcessFont>::const_iterator iter =
unicode_font_families_.find(character);
if (iter != unicode_font_families_.end()) {
fallbackFont->name = iter->second.name;
fallbackFont->filename = iter->second.filename;
fallbackFont->fontconfig_interface_id =
iter->second.fontconfig_interface_id;
fallbackFont->ttc_index = iter->second.ttc_index;
fallbackFont->is_bold = iter->second.is_bold;
fallbackFont->is_italic = iter->second.is_italic;
return;
}
content::GetFallbackFontForCharacter(font_loader_, character,
preferred_locale, fallbackFont);
unicode_font_families_.insert(std::make_pair(character, *fallbackFont));
}
void PpapiBlinkPlatformImpl::SandboxSupport::GetWebFontRenderStyleForStrike(
const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) {
GetRenderStyleForStrike(font_loader_, family, size, is_bold, is_italic,
device_scale_factor, out);
}
void PpapiBlinkPlatformImpl::SandboxSupport::
MatchFontByPostscriptNameOrFullFontName(
const char* font_unique_name,
blink::OutOfProcessFont* uniquely_matched_font) {
content::MatchFontByPostscriptNameOrFullFontName(
font_loader_, font_unique_name, uniquely_matched_font);
}
#endif
PpapiBlinkPlatformImpl::PpapiBlinkPlatformImpl() {
#if defined(OS_LINUX)
font_loader_ =
sk_make_sp<font_service::FontLoader>(ChildThread::Get()->GetConnector());
SkFontConfigInterface::SetGlobal(font_loader_);
sandbox_support_.reset(
new PpapiBlinkPlatformImpl::SandboxSupport(font_loader_));
sandbox_support_.reset(new WebSandboxSupportLinux(font_loader_));
#elif defined(OS_MACOSX)
sandbox_support_.reset(
new WebSandboxSupportMac(ChildThread::Get()->GetConnector()));
......
......@@ -47,7 +47,6 @@ class PpapiBlinkPlatformImpl : public BlinkPlatformImpl {
#endif
#if defined(OS_LINUX)
class SandboxSupport;
sk_sp<font_service::FontLoader> font_loader_;
#endif
......
......@@ -111,21 +111,12 @@
#if defined(OS_MACOSX)
#include "content/child/child_process_sandbox_support_impl_mac.h"
#include "content/common/mac/font_loader.h"
#elif defined(OS_LINUX)
#include "content/child/child_process_sandbox_support_impl_linux.h"
#endif
#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
#include <map>
#include <string>
#include "base/synchronization/lock.h"
#include "content/child/child_process_sandbox_support_impl_linux.h"
#include "third_party/blink/public/platform/linux/out_of_process_font.h"
#include "third_party/blink/public/platform/linux/web_sandbox_support.h"
#include "third_party/icu/source/common/unicode/utf16.h"
#endif
#endif
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
......@@ -193,40 +184,6 @@ gpu::ContextType ToGpuContextType(blink::Platform::ContextType type) {
//------------------------------------------------------------------------------
#if defined(OS_LINUX)
class RendererBlinkPlatformImpl::SandboxSupport
: public blink::WebSandboxSupport {
public:
explicit SandboxSupport(sk_sp<font_service::FontLoader> font_loader)
: font_loader_(std::move(font_loader)) {}
~SandboxSupport() override {}
void GetFallbackFontForCharacter(
blink::WebUChar32 character,
const char* preferred_locale,
blink::OutOfProcessFont* fallbackFont) override;
void MatchFontByPostscriptNameOrFullFontName(
const char* font_unique_name,
blink::OutOfProcessFont* fallback_font) override;
void GetWebFontRenderStyleForStrike(const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) override;
private:
// WebKit likes to ask us for the correct font family to use for a set of
// unicode code points. It needs this information frequently so we cache it
// here.
base::Lock unicode_font_families_mutex_;
std::map<int32_t, blink::OutOfProcessFont> unicode_font_families_;
sk_sp<font_service::FontLoader> font_loader_;
};
#endif // defined(OS_LINUX)
//------------------------------------------------------------------------------
RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
blink::scheduler::WebThreadScheduler* main_thread_scheduler)
: BlinkPlatformImpl(main_thread_scheduler->DefaultTaskRunner(),
......@@ -261,8 +218,7 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
#if defined(OS_MACOSX)
sandbox_support_.reset(new WebSandboxSupportMac(connector_.get()));
#else
sandbox_support_.reset(
new RendererBlinkPlatformImpl::SandboxSupport(font_loader_));
sandbox_support_.reset(new WebSandboxSupportLinux(font_loader_));
#endif
} else {
DVLOG(1) << "Disabling sandbox support for testing.";
......@@ -560,54 +516,6 @@ WebString RendererBlinkPlatformImpl::FileSystemCreateOriginIdentifier(
//------------------------------------------------------------------------------
#if defined(OS_LINUX)
void RendererBlinkPlatformImpl::SandboxSupport::GetFallbackFontForCharacter(
blink::WebUChar32 character,
const char* preferred_locale,
blink::OutOfProcessFont* fallbackFont) {
base::AutoLock lock(unicode_font_families_mutex_);
const std::map<int32_t, blink::OutOfProcessFont>::const_iterator iter =
unicode_font_families_.find(character);
if (iter != unicode_font_families_.end()) {
fallbackFont->name = iter->second.name;
fallbackFont->filename = iter->second.filename;
fallbackFont->fontconfig_interface_id =
iter->second.fontconfig_interface_id;
fallbackFont->ttc_index = iter->second.ttc_index;
fallbackFont->is_bold = iter->second.is_bold;
fallbackFont->is_italic = iter->second.is_italic;
return;
}
content::GetFallbackFontForCharacter(font_loader_, character,
preferred_locale, fallbackFont);
unicode_font_families_.insert(std::make_pair(character, *fallbackFont));
}
void RendererBlinkPlatformImpl::SandboxSupport::
MatchFontByPostscriptNameOrFullFontName(
const char* font_unique_name,
blink::OutOfProcessFont* fallback_font) {
content::MatchFontByPostscriptNameOrFullFontName(
font_loader_, font_unique_name, fallback_font);
}
void RendererBlinkPlatformImpl::SandboxSupport::GetWebFontRenderStyleForStrike(
const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) {
GetRenderStyleForStrike(font_loader_, family, size, is_bold, is_italic,
device_scale_factor, out);
}
#endif
//------------------------------------------------------------------------------
Platform::FileHandle RendererBlinkPlatformImpl::DatabaseOpenFile(
const WebString& vfs_file_name,
int desired_flags) {
......
......@@ -300,7 +300,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
scoped_refptr<blink::mojom::ThreadSafeCodeCacheHostPtr> code_cache_host_;
#if defined(OS_LINUX)
class SandboxSupport;
sk_sp<font_service::FontLoader> font_loader_;
#endif
......
......@@ -7,67 +7,20 @@
#include "build/build_config.h"
#if defined(OS_MACOSX)
#include "base/mac/foundation_util.h"
#include "content/child/child_process_sandbox_support_impl_mac.h"
#elif defined(OS_LINUX)
#include "base/synchronization/lock.h"
#include "content/child/child_process_sandbox_support_impl_linux.h"
#include "content/child/child_thread_impl.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/platform/linux/out_of_process_font.h"
#include "third_party/blink/public/platform/linux/web_sandbox_support.h"
#endif
namespace blink {
class WebSandboxSupport;
struct OutOfProcessFont;
struct WebFontRenderStyle;
} // namespace blink
namespace content {
#if defined(OS_LINUX)
class UtilityBlinkPlatformWithSandboxSupportImpl::SandboxSupport
: public blink::WebSandboxSupport {
public:
explicit SandboxSupport(sk_sp<font_service::FontLoader> font_loader)
: font_loader_(std::move(font_loader)) {}
~SandboxSupport() override {}
void GetFallbackFontForCharacter(
blink::WebUChar32 character,
const char* preferred_locale,
blink::OutOfProcessFont* fallbackFont) override;
void MatchFontByPostscriptNameOrFullFontName(
const char* font_unique_name,
blink::OutOfProcessFont* uniquely_matched_font) override;
void GetWebFontRenderStyleForStrike(const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) override;
private:
// WebKit likes to ask us for the correct font family to use for a set of
// unicode code points. It needs this information frequently so we cache it
// here.
base::Lock unicode_font_families_mutex_;
// Maps unicode chars to their fallback fonts.
std::map<int32_t, blink::OutOfProcessFont> unicode_font_families_;
sk_sp<font_service::FontLoader> font_loader_;
};
#endif // defined(OS_LINUX)
UtilityBlinkPlatformWithSandboxSupportImpl::
UtilityBlinkPlatformWithSandboxSupportImpl(
service_manager::Connector* connector) {
#if defined(OS_LINUX)
font_loader_ = sk_make_sp<font_service::FontLoader>(connector);
SkFontConfigInterface::SetGlobal(font_loader_);
sandbox_support_ = std::make_unique<SandboxSupport>(font_loader_);
sandbox_support_ = std::make_unique<WebSandboxSupportLinux>(font_loader_);
#elif defined(OS_MACOSX)
sandbox_support_ = std::make_unique<WebSandboxSupportMac>(connector);
#endif
......@@ -85,49 +38,4 @@ UtilityBlinkPlatformWithSandboxSupportImpl::GetSandboxSupport() {
#endif
}
#if defined(OS_LINUX)
void UtilityBlinkPlatformWithSandboxSupportImpl::SandboxSupport::
GetFallbackFontForCharacter(blink::WebUChar32 character,
const char* preferred_locale,
blink::OutOfProcessFont* fallback_font) {
base::AutoLock lock(unicode_font_families_mutex_);
const std::map<int32_t, blink::OutOfProcessFont>::const_iterator iter =
unicode_font_families_.find(character);
if (iter != unicode_font_families_.end()) {
fallback_font->name = iter->second.name;
fallback_font->filename = iter->second.filename;
fallback_font->fontconfig_interface_id =
iter->second.fontconfig_interface_id;
fallback_font->ttc_index = iter->second.ttc_index;
fallback_font->is_bold = iter->second.is_bold;
fallback_font->is_italic = iter->second.is_italic;
return;
}
content::GetFallbackFontForCharacter(font_loader_, character,
preferred_locale, fallback_font);
unicode_font_families_.emplace(character, *fallback_font);
}
void UtilityBlinkPlatformWithSandboxSupportImpl::SandboxSupport::
GetWebFontRenderStyleForStrike(const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) {
GetRenderStyleForStrike(font_loader_, family, size, is_bold, is_italic,
device_scale_factor, out);
}
void UtilityBlinkPlatformWithSandboxSupportImpl::SandboxSupport::
MatchFontByPostscriptNameOrFullFontName(
const char* font_unique_name,
blink::OutOfProcessFont* uniquely_matched_font) {
content::MatchFontByPostscriptNameOrFullFontName(
font_loader_, font_unique_name, uniquely_matched_font);
}
#endif
} // namespace content
......@@ -43,7 +43,6 @@ class UtilityBlinkPlatformWithSandboxSupportImpl : public blink::Platform {
std::unique_ptr<blink::WebSandboxSupport> sandbox_support_;
#endif
#if defined(OS_LINUX)
class SandboxSupport;
sk_sp<font_service::FontLoader> font_loader_;
#endif
......
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