mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Support full-screen Flash with off-screen rendering (issue #1648)
This commit is contained in:
@@ -312,6 +312,20 @@ class UploadFolderHelper :
|
|||||||
DISALLOW_COPY_AND_ASSIGN(UploadFolderHelper);
|
DISALLOW_COPY_AND_ASSIGN(UploadFolderHelper);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CefRenderWidgetHostViewOSR* GetOSRHostView(content::WebContents* web_contents) {
|
||||||
|
CefRenderWidgetHostViewOSR* fs_view =
|
||||||
|
static_cast<CefRenderWidgetHostViewOSR*>(
|
||||||
|
web_contents->GetFullscreenRenderWidgetHostView());
|
||||||
|
if (fs_view)
|
||||||
|
return fs_view;
|
||||||
|
|
||||||
|
content::RenderViewHost* host = web_contents->GetRenderViewHost();
|
||||||
|
if (host)
|
||||||
|
return static_cast<CefRenderWidgetHostViewOSR*>(host->GetView());
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
@@ -1020,15 +1034,12 @@ void CefBrowserHostImpl::WasResized() {
|
|||||||
if (!web_contents())
|
if (!web_contents())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
|
||||||
if (!host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!IsWindowless()) {
|
if (!IsWindowless()) {
|
||||||
|
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
||||||
|
if (host)
|
||||||
host->WasResized();
|
host->WasResized();
|
||||||
} else {
|
} else {
|
||||||
CefRenderWidgetHostViewOSR* view =
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView(web_contents());
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(host->GetView());
|
|
||||||
if (view)
|
if (view)
|
||||||
view->WasResized();
|
view->WasResized();
|
||||||
}
|
}
|
||||||
@@ -1049,12 +1060,7 @@ void CefBrowserHostImpl::WasHidden(bool hidden) {
|
|||||||
if (!web_contents())
|
if (!web_contents())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView(web_contents());
|
||||||
if (!host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR* view =
|
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(host->GetView());
|
|
||||||
if (view) {
|
if (view) {
|
||||||
if (hidden)
|
if (hidden)
|
||||||
view->Hide();
|
view->Hide();
|
||||||
@@ -1078,12 +1084,7 @@ void CefBrowserHostImpl::NotifyScreenInfoChanged() {
|
|||||||
if (!web_contents())
|
if (!web_contents())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView(web_contents());
|
||||||
if (!host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR* view =
|
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(host->GetView());
|
|
||||||
if (view)
|
if (view)
|
||||||
view->OnScreenInfoChanged();
|
view->OnScreenInfoChanged();
|
||||||
}
|
}
|
||||||
@@ -1103,12 +1104,7 @@ void CefBrowserHostImpl::Invalidate(PaintElementType type) {
|
|||||||
if (!web_contents())
|
if (!web_contents())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView(web_contents());
|
||||||
if (!host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR* view =
|
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(host->GetView());
|
|
||||||
if (view)
|
if (view)
|
||||||
view->Invalidate(type);
|
view->Invalidate(type);
|
||||||
}
|
}
|
||||||
@@ -1123,18 +1119,15 @@ void CefBrowserHostImpl::SendKeyEvent(const CefKeyEvent& event) {
|
|||||||
if (!web_contents())
|
if (!web_contents())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
|
||||||
if (!host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
content::NativeWebKeyboardEvent web_event;
|
content::NativeWebKeyboardEvent web_event;
|
||||||
PlatformTranslateKeyEvent(web_event, event);
|
PlatformTranslateKeyEvent(web_event, event);
|
||||||
|
|
||||||
if (!IsWindowless()) {
|
if (!IsWindowless()) {
|
||||||
|
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
||||||
|
if (host)
|
||||||
host->ForwardKeyboardEvent(web_event);
|
host->ForwardKeyboardEvent(web_event);
|
||||||
} else {
|
} else {
|
||||||
CefRenderWidgetHostViewOSR* view =
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView(web_contents());
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(host->GetView());
|
|
||||||
if (view)
|
if (view)
|
||||||
view->SendKeyEvent(web_event);
|
view->SendKeyEvent(web_event);
|
||||||
}
|
}
|
||||||
@@ -1182,18 +1175,15 @@ void CefBrowserHostImpl::SendMouseWheelEvent(const CefMouseEvent& event,
|
|||||||
if (!web_contents())
|
if (!web_contents())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
|
||||||
if (!host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
blink::WebMouseWheelEvent web_event;
|
blink::WebMouseWheelEvent web_event;
|
||||||
PlatformTranslateWheelEvent(web_event, event, deltaX, deltaY);
|
PlatformTranslateWheelEvent(web_event, event, deltaX, deltaY);
|
||||||
|
|
||||||
if (!IsWindowless()) {
|
if (!IsWindowless()) {
|
||||||
|
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
||||||
|
if (host)
|
||||||
host->ForwardWheelEvent(web_event);
|
host->ForwardWheelEvent(web_event);
|
||||||
} else {
|
} else {
|
||||||
CefRenderWidgetHostViewOSR* view =
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView(web_contents());
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(host->GetView());
|
|
||||||
if (view)
|
if (view)
|
||||||
view->SendMouseWheelEvent(web_event);
|
view->SendMouseWheelEvent(web_event);
|
||||||
}
|
}
|
||||||
@@ -1233,15 +1223,12 @@ void CefBrowserHostImpl::SendMouseEvent(const blink::WebMouseEvent& event) {
|
|||||||
if (!web_contents())
|
if (!web_contents())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
|
||||||
if (!host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!IsWindowless()) {
|
if (!IsWindowless()) {
|
||||||
|
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
||||||
|
if (host)
|
||||||
host->ForwardMouseEvent(event);
|
host->ForwardMouseEvent(event);
|
||||||
} else {
|
} else {
|
||||||
CefRenderWidgetHostViewOSR* view =
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView(web_contents());
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(host->GetView());
|
|
||||||
if (view)
|
if (view)
|
||||||
view->SendMouseEvent(event);
|
view->SendMouseEvent(event);
|
||||||
}
|
}
|
||||||
@@ -1260,12 +1247,7 @@ void CefBrowserHostImpl::SendFocusEvent(bool setFocus) {
|
|||||||
if (!web_contents())
|
if (!web_contents())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView(web_contents());
|
||||||
if (!host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR* view =
|
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(host->GetView());
|
|
||||||
if (view)
|
if (view)
|
||||||
view->SendFocusEvent(setFocus);
|
view->SendFocusEvent(setFocus);
|
||||||
}
|
}
|
||||||
@@ -1332,12 +1314,7 @@ void CefBrowserHostImpl::SetWindowlessFrameRate(int frame_rate) {
|
|||||||
if (!web_contents())
|
if (!web_contents())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView(web_contents());
|
||||||
if (!host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR* view =
|
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(host->GetView());
|
|
||||||
if (view)
|
if (view)
|
||||||
view->UpdateFrameRate();
|
view->UpdateFrameRate();
|
||||||
}
|
}
|
||||||
@@ -1891,6 +1868,12 @@ void CefBrowserHostImpl::RunFileChooser(
|
|||||||
callback));
|
callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CefBrowserHostImpl::EmbedsFullscreenWidget() const {
|
||||||
|
// When using windowless rendering do not allow Flash to create its own full-
|
||||||
|
// screen widget.
|
||||||
|
return IsWindowless();
|
||||||
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::EnterFullscreenModeForTab(
|
void CefBrowserHostImpl::EnterFullscreenModeForTab(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
const GURL& origin) {
|
const GURL& origin) {
|
||||||
@@ -2954,9 +2937,7 @@ CefBrowserHostImpl::CefBrowserHostImpl(
|
|||||||
RenderViewCreated(web_contents->GetRenderViewHost());
|
RenderViewCreated(web_contents->GetRenderViewHost());
|
||||||
|
|
||||||
if (IsWindowless()) {
|
if (IsWindowless()) {
|
||||||
CefRenderWidgetHostViewOSR* view =
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView(web_contents);
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(
|
|
||||||
web_contents->GetRenderViewHost()->GetView());
|
|
||||||
if (view)
|
if (view)
|
||||||
view->set_browser_impl(this);
|
view->set_browser_impl(this);
|
||||||
}
|
}
|
||||||
|
@@ -405,6 +405,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
void RunFileChooser(
|
void RunFileChooser(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
const content::FileChooserParams& params) override;
|
const content::FileChooserParams& params) override;
|
||||||
|
bool EmbedsFullscreenWidget() const override;
|
||||||
void EnterFullscreenModeForTab(content::WebContents* web_contents,
|
void EnterFullscreenModeForTab(content::WebContents* web_contents,
|
||||||
const GURL& origin) override;
|
const GURL& origin) override;
|
||||||
void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
|
void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
|
||||||
|
@@ -436,7 +436,8 @@ class CefBeginFrameTimer : public cc::TimeSourceClient {
|
|||||||
|
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
||||||
content::RenderWidgetHost* widget)
|
content::RenderWidgetHost* widget,
|
||||||
|
CefRenderWidgetHostViewOSR* parent_host_view)
|
||||||
: scale_factor_(kDefaultScaleFactor),
|
: scale_factor_(kDefaultScaleFactor),
|
||||||
frame_rate_threshold_ms_(0),
|
frame_rate_threshold_ms_(0),
|
||||||
delegated_frame_host_(new content::DelegatedFrameHost(this)),
|
delegated_frame_host_(new content::DelegatedFrameHost(this)),
|
||||||
@@ -445,8 +446,10 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
|||||||
hold_resize_(false),
|
hold_resize_(false),
|
||||||
pending_resize_(false),
|
pending_resize_(false),
|
||||||
render_widget_host_(content::RenderWidgetHostImpl::From(widget)),
|
render_widget_host_(content::RenderWidgetHostImpl::From(widget)),
|
||||||
parent_host_view_(NULL),
|
has_parent_(parent_host_view != NULL),
|
||||||
|
parent_host_view_(parent_host_view),
|
||||||
popup_host_view_(NULL),
|
popup_host_view_(NULL),
|
||||||
|
child_host_view_(NULL),
|
||||||
is_showing_(true),
|
is_showing_(true),
|
||||||
is_destroyed_(false),
|
is_destroyed_(false),
|
||||||
is_scroll_offset_changed_pending_(false),
|
is_scroll_offset_changed_pending_(false),
|
||||||
@@ -497,7 +500,21 @@ CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() {
|
|||||||
root_layer_.reset(NULL);
|
root_layer_.reset(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called for full-screen widgets.
|
||||||
void CefRenderWidgetHostViewOSR::InitAsChild(gfx::NativeView parent_view) {
|
void CefRenderWidgetHostViewOSR::InitAsChild(gfx::NativeView parent_view) {
|
||||||
|
DCHECK(parent_host_view_);
|
||||||
|
browser_impl_ = parent_host_view_->browser_impl();
|
||||||
|
DCHECK(browser_impl_.get());
|
||||||
|
|
||||||
|
if (parent_host_view_->child_host_view_) {
|
||||||
|
// Cancel the previous popup widget.
|
||||||
|
parent_host_view_->child_host_view_->CancelChildWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_host_view_->set_child_host_view(this);
|
||||||
|
|
||||||
|
ResizeRootLayer();
|
||||||
|
Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
content::RenderWidgetHost*
|
content::RenderWidgetHost*
|
||||||
@@ -675,8 +692,7 @@ void CefRenderWidgetHostViewOSR::OnSwapCompositorFrame(
|
|||||||
void CefRenderWidgetHostViewOSR::InitAsPopup(
|
void CefRenderWidgetHostViewOSR::InitAsPopup(
|
||||||
content::RenderWidgetHostView* parent_host_view,
|
content::RenderWidgetHostView* parent_host_view,
|
||||||
const gfx::Rect& pos) {
|
const gfx::Rect& pos) {
|
||||||
parent_host_view_ = static_cast<CefRenderWidgetHostViewOSR*>(
|
DCHECK_EQ(parent_host_view_, parent_host_view);
|
||||||
parent_host_view);
|
|
||||||
browser_impl_ = parent_host_view_->browser_impl();
|
browser_impl_ = parent_host_view_->browser_impl();
|
||||||
DCHECK(browser_impl_.get());
|
DCHECK(browser_impl_.get());
|
||||||
|
|
||||||
@@ -785,17 +801,23 @@ void CefRenderWidgetHostViewOSR::RenderProcessGone(
|
|||||||
render_widget_host_ = NULL;
|
render_widget_host_ = NULL;
|
||||||
parent_host_view_ = NULL;
|
parent_host_view_ = NULL;
|
||||||
popup_host_view_ = NULL;
|
popup_host_view_ = NULL;
|
||||||
|
child_host_view_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::Destroy() {
|
void CefRenderWidgetHostViewOSR::Destroy() {
|
||||||
if (!is_destroyed_) {
|
if (!is_destroyed_) {
|
||||||
is_destroyed_ = true;
|
is_destroyed_ = true;
|
||||||
|
|
||||||
if (IsPopupWidget()) {
|
if (has_parent_) {
|
||||||
|
if (IsPopupWidget())
|
||||||
CancelPopupWidget();
|
CancelPopupWidget();
|
||||||
|
else
|
||||||
|
CancelChildWidget();
|
||||||
} else {
|
} else {
|
||||||
if (popup_host_view_)
|
if (popup_host_view_)
|
||||||
popup_host_view_->CancelPopupWidget();
|
popup_host_view_->CancelPopupWidget();
|
||||||
|
if (child_host_view_)
|
||||||
|
child_host_view_->CancelChildWidget();
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1393,6 +1415,24 @@ void CefRenderWidgetHostViewOSR::CancelPopupWidget() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefRenderWidgetHostViewOSR::CancelChildWidget() {
|
||||||
|
if (render_widget_host_)
|
||||||
|
render_widget_host_->LostCapture();
|
||||||
|
|
||||||
|
Hide();
|
||||||
|
|
||||||
|
if (parent_host_view_) {
|
||||||
|
parent_host_view_->set_child_host_view(NULL);
|
||||||
|
parent_host_view_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (render_widget_host_ && !is_destroyed_) {
|
||||||
|
is_destroyed_ = true;
|
||||||
|
// Results in a call to Destroy().
|
||||||
|
render_widget_host_->Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::OnScrollOffsetChanged() {
|
void CefRenderWidgetHostViewOSR::OnScrollOffsetChanged() {
|
||||||
if (browser_impl_.get()) {
|
if (browser_impl_.get()) {
|
||||||
CefRefPtr<CefRenderHandler> handler =
|
CefRefPtr<CefRenderHandler> handler =
|
||||||
|
@@ -78,7 +78,8 @@ class CefRenderWidgetHostViewOSR
|
|||||||
public ui::CompositorDelegate,
|
public ui::CompositorDelegate,
|
||||||
public content::DelegatedFrameHostClient {
|
public content::DelegatedFrameHostClient {
|
||||||
public:
|
public:
|
||||||
explicit CefRenderWidgetHostViewOSR(content::RenderWidgetHost* widget);
|
CefRenderWidgetHostViewOSR(content::RenderWidgetHost* widget,
|
||||||
|
CefRenderWidgetHostViewOSR* parent_host_view);
|
||||||
~CefRenderWidgetHostViewOSR() override;
|
~CefRenderWidgetHostViewOSR() override;
|
||||||
|
|
||||||
// RenderWidgetHostView implementation.
|
// RenderWidgetHostView implementation.
|
||||||
@@ -264,6 +265,9 @@ class CefRenderWidgetHostViewOSR
|
|||||||
void set_popup_host_view(CefRenderWidgetHostViewOSR* popup_view) {
|
void set_popup_host_view(CefRenderWidgetHostViewOSR* popup_view) {
|
||||||
popup_host_view_ = popup_view;
|
popup_host_view_ = popup_view;
|
||||||
}
|
}
|
||||||
|
void set_child_host_view(CefRenderWidgetHostViewOSR* popup_view) {
|
||||||
|
child_host_view_ = popup_view;
|
||||||
|
}
|
||||||
|
|
||||||
ui::Compositor* compositor() const { return compositor_.get(); }
|
ui::Compositor* compositor() const { return compositor_.get(); }
|
||||||
content::RenderWidgetHostImpl* render_widget_host() const
|
content::RenderWidgetHostImpl* render_widget_host() const
|
||||||
@@ -285,6 +289,7 @@ class CefRenderWidgetHostViewOSR
|
|||||||
base::TimeDelta vsync_period);
|
base::TimeDelta vsync_period);
|
||||||
|
|
||||||
void CancelPopupWidget();
|
void CancelPopupWidget();
|
||||||
|
void CancelChildWidget();
|
||||||
|
|
||||||
void OnScrollOffsetChanged();
|
void OnScrollOffsetChanged();
|
||||||
|
|
||||||
@@ -349,8 +354,11 @@ class CefRenderWidgetHostViewOSR
|
|||||||
// |render_widget_host_| is NULL and the message loop is run one last time
|
// |render_widget_host_| is NULL and the message loop is run one last time
|
||||||
// Message handlers must check for a NULL |render_widget_host_|.
|
// Message handlers must check for a NULL |render_widget_host_|.
|
||||||
content::RenderWidgetHostImpl* render_widget_host_;
|
content::RenderWidgetHostImpl* render_widget_host_;
|
||||||
|
|
||||||
|
bool has_parent_;
|
||||||
CefRenderWidgetHostViewOSR* parent_host_view_;
|
CefRenderWidgetHostViewOSR* parent_host_view_;
|
||||||
CefRenderWidgetHostViewOSR* popup_host_view_;
|
CefRenderWidgetHostViewOSR* popup_host_view_;
|
||||||
|
CefRenderWidgetHostViewOSR* child_host_view_;
|
||||||
|
|
||||||
CefRefPtr<CefBrowserHostImpl> browser_impl_;
|
CefRefPtr<CefBrowserHostImpl> browser_impl_;
|
||||||
|
|
||||||
|
@@ -75,14 +75,15 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
|
|||||||
render_widget_host->GetView());
|
render_widget_host->GetView());
|
||||||
}
|
}
|
||||||
|
|
||||||
view_ = new CefRenderWidgetHostViewOSR(render_widget_host);
|
view_ = new CefRenderWidgetHostViewOSR(render_widget_host, NULL);
|
||||||
return view_;
|
return view_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called for popup and fullscreen widgets.
|
||||||
content::RenderWidgetHostViewBase*
|
content::RenderWidgetHostViewBase*
|
||||||
CefWebContentsViewOSR::CreateViewForPopupWidget(
|
CefWebContentsViewOSR::CreateViewForPopupWidget(
|
||||||
content::RenderWidgetHost* render_widget_host) {
|
content::RenderWidgetHost* render_widget_host) {
|
||||||
return new CefRenderWidgetHostViewOSR(render_widget_host);
|
return new CefRenderWidgetHostViewOSR(render_widget_host, view_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefWebContentsViewOSR::SetPageTitle(const base::string16& title) {
|
void CefWebContentsViewOSR::SetPageTitle(const base::string16& title) {
|
||||||
|
Reference in New Issue
Block a user