mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-09 00:28:59 +01:00
Fix assertion when loading the PDF extension with begin-frame-scheduling and OSR (issue #1686)
This commit is contained in:
parent
a63d646e3b
commit
4b491c3a77
@ -371,6 +371,9 @@ class UploadFolderHelper :
|
|||||||
DISALLOW_COPY_AND_ASSIGN(UploadFolderHelper);
|
DISALLOW_COPY_AND_ASSIGN(UploadFolderHelper);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns the primary OSR host view for the specified |web_contents|. If a
|
||||||
|
// full-screen host view currently exists then it will be returned. Otherwise,
|
||||||
|
// the main host view will be returned.
|
||||||
CefRenderWidgetHostViewOSR* GetOSRHostView(content::WebContents* web_contents) {
|
CefRenderWidgetHostViewOSR* GetOSRHostView(content::WebContents* web_contents) {
|
||||||
CefRenderWidgetHostViewOSR* fs_view =
|
CefRenderWidgetHostViewOSR* fs_view =
|
||||||
static_cast<CefRenderWidgetHostViewOSR*>(
|
static_cast<CefRenderWidgetHostViewOSR*>(
|
||||||
@ -2375,7 +2378,7 @@ bool CefBrowserHostImpl::HandleContextMenu(
|
|||||||
content::WebContents* CefBrowserHostImpl::GetActionableWebContents() {
|
content::WebContents* CefBrowserHostImpl::GetActionableWebContents() {
|
||||||
if (web_contents() && extensions::ExtensionsEnabled()) {
|
if (web_contents() && extensions::ExtensionsEnabled()) {
|
||||||
content::WebContents* guest_contents =
|
content::WebContents* guest_contents =
|
||||||
extensions::GetGuestForOwnerContents(web_contents());
|
extensions::GetFullPageGuestForOwnerContents(web_contents());
|
||||||
if (guest_contents)
|
if (guest_contents)
|
||||||
return guest_contents;
|
return guest_contents;
|
||||||
}
|
}
|
||||||
|
@ -7,28 +7,51 @@
|
|||||||
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
|
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
|
||||||
#include "content/browser/browser_plugin/browser_plugin_guest.h"
|
#include "content/browser/browser_plugin/browser_plugin_guest.h"
|
||||||
#include "content/browser/web_contents/web_contents_impl.h"
|
#include "content/browser/web_contents/web_contents_impl.h"
|
||||||
|
#include "content/public/browser/browser_context.h"
|
||||||
|
#include "content/public/browser/browser_plugin_guest_manager.h"
|
||||||
|
|
||||||
namespace extensions {
|
namespace extensions {
|
||||||
|
|
||||||
content::WebContents* GetGuestForOwnerContents(content::WebContents* guest) {
|
namespace {
|
||||||
content::WebContentsImpl* guest_impl =
|
|
||||||
static_cast<content::WebContentsImpl*>(guest);
|
bool InsertWebContents(std::vector<content::WebContents*>* vector,
|
||||||
content::BrowserPluginEmbedder* embedder =
|
content::WebContents* web_contents) {
|
||||||
guest_impl->GetBrowserPluginEmbedder();
|
vector->push_back(web_contents);
|
||||||
if (embedder) {
|
return false; // Continue iterating.
|
||||||
content::BrowserPluginGuest* guest = embedder->GetFullPageGuest();
|
}
|
||||||
if (guest)
|
|
||||||
return guest->web_contents();
|
} // namespace
|
||||||
|
|
||||||
|
content::WebContents* GetFullPageGuestForOwnerContents(
|
||||||
|
content::WebContents* owner) {
|
||||||
|
content::WebContentsImpl* owner_impl =
|
||||||
|
static_cast<content::WebContentsImpl*>(owner);
|
||||||
|
content::BrowserPluginEmbedder* plugin_embedder =
|
||||||
|
owner_impl->GetBrowserPluginEmbedder();
|
||||||
|
if (plugin_embedder) {
|
||||||
|
content::BrowserPluginGuest* plugin_guest =
|
||||||
|
plugin_embedder->GetFullPageGuest();
|
||||||
|
if (plugin_guest)
|
||||||
|
return plugin_guest->web_contents();
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
content::WebContents* GetOwnerForGuestContents(content::WebContents* owner) {
|
void GetAllGuestsForOwnerContents(content::WebContents* owner,
|
||||||
content::WebContentsImpl* owner_impl =
|
std::vector<content::WebContents*>* guests) {
|
||||||
static_cast<content::WebContentsImpl*>(owner);
|
content::BrowserPluginGuestManager* plugin_guest_manager =
|
||||||
content::BrowserPluginGuest* guest = owner_impl->GetBrowserPluginGuest();
|
owner->GetBrowserContext()->GetGuestManager();
|
||||||
if (guest)
|
plugin_guest_manager->ForEachGuest(owner,
|
||||||
return guest->embedder_web_contents();
|
base::Bind(InsertWebContents, guests));
|
||||||
|
}
|
||||||
|
|
||||||
|
content::WebContents* GetOwnerForGuestContents(content::WebContents* guest) {
|
||||||
|
content::WebContentsImpl* guest_impl =
|
||||||
|
static_cast<content::WebContentsImpl*>(guest);
|
||||||
|
content::BrowserPluginGuest* plugin_guest =
|
||||||
|
guest_impl->GetBrowserPluginGuest();
|
||||||
|
if (plugin_guest)
|
||||||
|
return plugin_guest->embedder_web_contents();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,17 +5,24 @@
|
|||||||
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_
|
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_
|
||||||
#define CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_
|
#define CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace content {
|
namespace content {
|
||||||
class WebContents;
|
class WebContents;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace extensions {
|
namespace extensions {
|
||||||
|
|
||||||
// Returns the WebContents that owns the specified |guest|, if any.
|
// Returns the full-page guest WebContents for the specified |owner|, if any.
|
||||||
content::WebContents* GetGuestForOwnerContents(content::WebContents* guest);
|
content::WebContents* GetFullPageGuestForOwnerContents(
|
||||||
|
content::WebContents* owner);
|
||||||
|
|
||||||
// Returns the guest WebContents for the specified |owner|, if any.
|
// Populates |guests| with all guest WebContents with the specified |owner|.
|
||||||
content::WebContents* GetOwnerForGuestContents(content::WebContents* owner);
|
void GetAllGuestsForOwnerContents(content::WebContents* owner,
|
||||||
|
std::vector<content::WebContents*>* guests);
|
||||||
|
|
||||||
|
// Returns the WebContents that owns the specified |guest|, if any.
|
||||||
|
content::WebContents* GetOwnerForGuestContents(content::WebContents* guest);
|
||||||
|
|
||||||
} // namespace extensions
|
} // namespace extensions
|
||||||
|
|
||||||
|
@ -498,6 +498,11 @@ CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() {
|
|||||||
delegated_frame_host_.reset(NULL);
|
delegated_frame_host_.reset(NULL);
|
||||||
compositor_.reset(NULL);
|
compositor_.reset(NULL);
|
||||||
root_layer_.reset(NULL);
|
root_layer_.reset(NULL);
|
||||||
|
|
||||||
|
DCHECK(parent_host_view_ == NULL);
|
||||||
|
DCHECK(popup_host_view_ == NULL);
|
||||||
|
DCHECK(child_host_view_ == NULL);
|
||||||
|
DCHECK(guest_host_views_.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called for full-screen widgets.
|
// Called for full-screen widgets.
|
||||||
@ -508,7 +513,7 @@ void CefRenderWidgetHostViewOSR::InitAsChild(gfx::NativeView parent_view) {
|
|||||||
|
|
||||||
if (parent_host_view_->child_host_view_) {
|
if (parent_host_view_->child_host_view_) {
|
||||||
// Cancel the previous popup widget.
|
// Cancel the previous popup widget.
|
||||||
parent_host_view_->child_host_view_->CancelChildWidget();
|
parent_host_view_->child_host_view_->CancelWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
parent_host_view_->set_child_host_view(this);
|
parent_host_view_->set_child_host_view(this);
|
||||||
@ -690,7 +695,7 @@ void CefRenderWidgetHostViewOSR::InitAsPopup(
|
|||||||
|
|
||||||
if (parent_host_view_->popup_host_view_) {
|
if (parent_host_view_->popup_host_view_) {
|
||||||
// Cancel the previous popup widget.
|
// Cancel the previous popup widget.
|
||||||
parent_host_view_->popup_host_view_->CancelPopupWidget();
|
parent_host_view_->popup_host_view_->CancelWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
parent_host_view_->set_popup_host_view(this);
|
parent_host_view_->set_popup_host_view(this);
|
||||||
@ -792,6 +797,7 @@ void CefRenderWidgetHostViewOSR::RenderProcessGone(
|
|||||||
parent_host_view_ = NULL;
|
parent_host_view_ = NULL;
|
||||||
popup_host_view_ = NULL;
|
popup_host_view_ = NULL;
|
||||||
child_host_view_ = NULL;
|
child_host_view_ = NULL;
|
||||||
|
guest_host_views_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::Destroy() {
|
void CefRenderWidgetHostViewOSR::Destroy() {
|
||||||
@ -799,15 +805,14 @@ void CefRenderWidgetHostViewOSR::Destroy() {
|
|||||||
is_destroyed_ = true;
|
is_destroyed_ = true;
|
||||||
|
|
||||||
if (has_parent_) {
|
if (has_parent_) {
|
||||||
if (IsPopupWidget())
|
CancelWidget();
|
||||||
CancelPopupWidget();
|
|
||||||
else
|
|
||||||
CancelChildWidget();
|
|
||||||
} else {
|
} else {
|
||||||
if (popup_host_view_)
|
if (popup_host_view_)
|
||||||
popup_host_view_->CancelPopupWidget();
|
popup_host_view_->CancelWidget();
|
||||||
if (child_host_view_)
|
if (child_host_view_)
|
||||||
child_host_view_->CancelChildWidget();
|
child_host_view_->CancelWidget();
|
||||||
|
for (auto guest_host_view : guest_host_views_)
|
||||||
|
guest_host_view->CancelWidget();
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -978,6 +983,8 @@ bool CefRenderWidgetHostViewOSR::OnMessageReceived(const IPC::Message& msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::OnSetNeedsBeginFrames(bool enabled) {
|
void CefRenderWidgetHostViewOSR::OnSetNeedsBeginFrames(bool enabled) {
|
||||||
|
SetFrameRate();
|
||||||
|
|
||||||
// Start/stop the timer that sends BeginFrame requests.
|
// Start/stop the timer that sends BeginFrame requests.
|
||||||
begin_frame_timer_->SetActive(enabled);
|
begin_frame_timer_->SetActive(enabled);
|
||||||
if (software_output_device_) {
|
if (software_output_device_) {
|
||||||
@ -1094,6 +1101,10 @@ void CefRenderWidgetHostViewOSR::OnScreenInfoChanged() {
|
|||||||
// We might want to change the cursor scale factor here as well - see the
|
// We might want to change the cursor scale factor here as well - see the
|
||||||
// cache for the current_cursor_, as passed by UpdateCursor from the renderer
|
// cache for the current_cursor_, as passed by UpdateCursor from the renderer
|
||||||
// in the rwhv_aura (current_cursor_.SetScaleFactor)
|
// in the rwhv_aura (current_cursor_.SetScaleFactor)
|
||||||
|
|
||||||
|
// Notify the guest hosts if any.
|
||||||
|
for (auto guest_host_view : guest_host_views_)
|
||||||
|
guest_host_view->OnScreenInfoChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::Invalidate(
|
void CefRenderWidgetHostViewOSR::Invalidate(
|
||||||
@ -1174,7 +1185,7 @@ void CefRenderWidgetHostViewOSR::SendMouseWheelEvent(
|
|||||||
// Execute asynchronously to avoid deleting the widget from inside some
|
// Execute asynchronously to avoid deleting the widget from inside some
|
||||||
// other callback.
|
// other callback.
|
||||||
CEF_POST_TASK(CEF_UIT,
|
CEF_POST_TASK(CEF_UIT,
|
||||||
base::Bind(&CefRenderWidgetHostViewOSR::CancelPopupWidget,
|
base::Bind(&CefRenderWidgetHostViewOSR::CancelWidget,
|
||||||
popup_host_view_->weak_ptr_factory_.GetWeakPtr()));
|
popup_host_view_->weak_ptr_factory_.GetWeakPtr()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1205,6 +1216,10 @@ void CefRenderWidgetHostViewOSR::SendFocusEvent(bool focus) {
|
|||||||
void CefRenderWidgetHostViewOSR::UpdateFrameRate() {
|
void CefRenderWidgetHostViewOSR::UpdateFrameRate() {
|
||||||
frame_rate_threshold_ms_ = 0;
|
frame_rate_threshold_ms_ = 0;
|
||||||
SetFrameRate();
|
SetFrameRate();
|
||||||
|
|
||||||
|
// Notify the guest hosts if any.
|
||||||
|
for (auto guest_host_view : guest_host_views_)
|
||||||
|
guest_host_view->UpdateFrameRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::HoldResize() {
|
void CefRenderWidgetHostViewOSR::HoldResize() {
|
||||||
@ -1258,6 +1273,16 @@ void CefRenderWidgetHostViewOSR::OnPaint(
|
|||||||
ReleaseResize();
|
ReleaseResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefRenderWidgetHostViewOSR::AddGuestHostView(
|
||||||
|
CefRenderWidgetHostViewOSR* guest_host) {
|
||||||
|
guest_host_views_.insert(guest_host);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefRenderWidgetHostViewOSR::RemoveGuestHostView(
|
||||||
|
CefRenderWidgetHostViewOSR* guest_host) {
|
||||||
|
guest_host_views_.erase(guest_host);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
int CefRenderWidgetHostViewOSR::ClampFrameRate(int frame_rate) {
|
int CefRenderWidgetHostViewOSR::ClampFrameRate(int frame_rate) {
|
||||||
if (frame_rate < 1)
|
if (frame_rate < 1)
|
||||||
@ -1268,16 +1293,21 @@ int CefRenderWidgetHostViewOSR::ClampFrameRate(int frame_rate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::SetFrameRate() {
|
void CefRenderWidgetHostViewOSR::SetFrameRate() {
|
||||||
DCHECK(browser_impl_.get());
|
CefRefPtr<CefBrowserHostImpl> browser;
|
||||||
if (!browser_impl_.get())
|
if (parent_host_view_) {
|
||||||
return;
|
// Use the same frame rate as the embedding browser.
|
||||||
|
browser = parent_host_view_->browser_impl_;
|
||||||
|
} else {
|
||||||
|
browser = browser_impl_;
|
||||||
|
}
|
||||||
|
CHECK(browser);
|
||||||
|
|
||||||
// Only set the frame rate one time.
|
// Only set the frame rate one time.
|
||||||
if (frame_rate_threshold_ms_ != 0)
|
if (frame_rate_threshold_ms_ != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int frame_rate =
|
const int frame_rate =
|
||||||
ClampFrameRate(browser_impl_->settings().windowless_frame_rate);
|
ClampFrameRate(browser->settings().windowless_frame_rate);
|
||||||
frame_rate_threshold_ms_ = 1000 / frame_rate;
|
frame_rate_threshold_ms_ = 1000 / frame_rate;
|
||||||
|
|
||||||
// Configure the VSync interval for the browser process.
|
// Configure the VSync interval for the browser process.
|
||||||
@ -1377,15 +1407,13 @@ void CefRenderWidgetHostViewOSR::SendBeginFrame(base::TimeTicks frame_time,
|
|||||||
vsync_period, cc::BeginFrameArgs::NORMAL)));
|
vsync_period, cc::BeginFrameArgs::NORMAL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::CancelPopupWidget() {
|
void CefRenderWidgetHostViewOSR::CancelWidget() {
|
||||||
DCHECK(IsPopupWidget());
|
|
||||||
|
|
||||||
if (render_widget_host_)
|
if (render_widget_host_)
|
||||||
render_widget_host_->LostCapture();
|
render_widget_host_->LostCapture();
|
||||||
|
|
||||||
Hide();
|
Hide();
|
||||||
|
|
||||||
if (browser_impl_.get()) {
|
if (IsPopupWidget() && browser_impl_.get()) {
|
||||||
CefRefPtr<CefRenderHandler> handler =
|
CefRefPtr<CefRenderHandler> handler =
|
||||||
browser_impl_->client()->GetRenderHandler();
|
browser_impl_->client()->GetRenderHandler();
|
||||||
if (handler.get())
|
if (handler.get())
|
||||||
@ -1394,25 +1422,12 @@ void CefRenderWidgetHostViewOSR::CancelPopupWidget() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (parent_host_view_) {
|
if (parent_host_view_) {
|
||||||
parent_host_view_->set_popup_host_view(NULL);
|
if (parent_host_view_->popup_host_view_ == this)
|
||||||
parent_host_view_ = NULL;
|
parent_host_view_->set_popup_host_view(NULL);
|
||||||
}
|
else if (parent_host_view_->child_host_view_ == this)
|
||||||
|
parent_host_view_->set_child_host_view(NULL);
|
||||||
if (render_widget_host_ && !is_destroyed_) {
|
else
|
||||||
is_destroyed_ = true;
|
parent_host_view_->RemoveGuestHostView(this);
|
||||||
// Results in a call to Destroy().
|
|
||||||
render_widget_host_->Shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
parent_host_view_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#define CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
#define CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "include/cef_base.h"
|
#include "include/cef_base.h"
|
||||||
@ -255,6 +256,9 @@ class CefRenderWidgetHostViewOSR
|
|||||||
gfx::Range* actual_range) const;
|
gfx::Range* actual_range) const;
|
||||||
#endif // defined(OS_MACOSX)
|
#endif // defined(OS_MACOSX)
|
||||||
|
|
||||||
|
void AddGuestHostView(CefRenderWidgetHostViewOSR* guest_host);
|
||||||
|
void RemoveGuestHostView(CefRenderWidgetHostViewOSR* guest_host);
|
||||||
|
|
||||||
CefRefPtr<CefBrowserHostImpl> browser_impl() const { return browser_impl_; }
|
CefRefPtr<CefBrowserHostImpl> browser_impl() const { return browser_impl_; }
|
||||||
void set_browser_impl(CefRefPtr<CefBrowserHostImpl> browser) {
|
void set_browser_impl(CefRefPtr<CefBrowserHostImpl> browser) {
|
||||||
browser_impl_ = browser;
|
browser_impl_ = browser;
|
||||||
@ -286,8 +290,7 @@ class CefRenderWidgetHostViewOSR
|
|||||||
void SendBeginFrame(base::TimeTicks frame_time,
|
void SendBeginFrame(base::TimeTicks frame_time,
|
||||||
base::TimeDelta vsync_period);
|
base::TimeDelta vsync_period);
|
||||||
|
|
||||||
void CancelPopupWidget();
|
void CancelWidget();
|
||||||
void CancelChildWidget();
|
|
||||||
|
|
||||||
void OnScrollOffsetChanged();
|
void OnScrollOffsetChanged();
|
||||||
|
|
||||||
@ -357,6 +360,7 @@ class CefRenderWidgetHostViewOSR
|
|||||||
CefRenderWidgetHostViewOSR* parent_host_view_;
|
CefRenderWidgetHostViewOSR* parent_host_view_;
|
||||||
CefRenderWidgetHostViewOSR* popup_host_view_;
|
CefRenderWidgetHostViewOSR* popup_host_view_;
|
||||||
CefRenderWidgetHostViewOSR* child_host_view_;
|
CefRenderWidgetHostViewOSR* child_host_view_;
|
||||||
|
std::set<CefRenderWidgetHostViewOSR*> guest_host_views_;
|
||||||
|
|
||||||
CefRefPtr<CefBrowserHostImpl> browser_impl_;
|
CefRefPtr<CefBrowserHostImpl> browser_impl_;
|
||||||
|
|
||||||
|
@ -119,8 +119,16 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
|
|||||||
|
|
||||||
if (guest_) {
|
if (guest_) {
|
||||||
// Based on WebContentsViewGuest::CreateViewForWidget.
|
// Based on WebContentsViewGuest::CreateViewForWidget.
|
||||||
|
content::WebContents* embedder_web_contents =
|
||||||
|
guest_->embedder_web_contents();
|
||||||
|
CefRenderWidgetHostViewOSR* embedder_host_view =
|
||||||
|
static_cast<CefRenderWidgetHostViewOSR*>(
|
||||||
|
embedder_web_contents->GetRenderViewHost()->GetView());
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR* platform_widget =
|
CefRenderWidgetHostViewOSR* platform_widget =
|
||||||
new CefRenderWidgetHostViewOSR(render_widget_host, NULL);
|
new CefRenderWidgetHostViewOSR(render_widget_host, embedder_host_view);
|
||||||
|
embedder_host_view->AddGuestHostView(platform_widget);
|
||||||
|
|
||||||
return new content::RenderWidgetHostViewGuest(
|
return new content::RenderWidgetHostViewGuest(
|
||||||
render_widget_host,
|
render_widget_host,
|
||||||
guest_,
|
guest_,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user