Browse Source

fix: offscreen rendering crash on input select (#34093)

Co-authored-by: Shelley Vohr <[email protected]>
trop[bot] 3 years ago
parent
commit
de09ba2c51

+ 8 - 21
shell/browser/osr/osr_render_widget_host_view.cc

@@ -397,7 +397,7 @@ void OffScreenRenderWidgetHostView::ResetFallbackToFirstNavigationSurface() {
 
 void OffScreenRenderWidgetHostView::InitAsPopup(
     content::RenderWidgetHostView* parent_host_view,
-    const gfx::Rect& pos,
+    const gfx::Rect& bounds,
     const gfx::Rect& anchor_rect) {
   DCHECK_EQ(parent_host_view_, parent_host_view);
   DCHECK_EQ(widget_type_, content::WidgetType::kPopup);
@@ -411,13 +411,10 @@ void OffScreenRenderWidgetHostView::InitAsPopup(
       base::BindRepeating(&OffScreenRenderWidgetHostView::OnPopupPaint,
                           parent_host_view_->weak_ptr_factory_.GetWeakPtr());
 
-  popup_position_ = pos;
+  popup_position_ = bounds;
 
-  ResizeRootLayer(false);
+  ResizeRootLayer(true);
   SetPainting(parent_host_view_->IsPainting());
-  if (video_consumer_) {
-    video_consumer_->SizeChanged();
-  }
   Show();
 }
 
@@ -688,13 +685,8 @@ void OffScreenRenderWidgetHostView::OnPaint(const gfx::Rect& damage_rect,
 
 gfx::Size OffScreenRenderWidgetHostView::SizeInPixels() {
   float sf = GetDeviceScaleFactor();
-  if (IsPopupWidget()) {
-    return gfx::ToFlooredSize(
-        gfx::ConvertSizeToPixels(popup_position_.size(), sf));
-  } else {
-    return gfx::ToFlooredSize(
-        gfx::ConvertSizeToPixels(GetViewBounds().size(), sf));
-  }
+  return gfx::ToFlooredSize(
+      gfx::ConvertSizeToPixels(GetViewBounds().size(), sf));
 }
 
 void OffScreenRenderWidgetHostView::CompositeFrame(
@@ -995,7 +987,7 @@ void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) {
       display::Screen::GetScreen()->GetDisplayNearestView(GetNativeView());
   const float scaleFactor = display.device_scale_factor();
   float sf = GetDeviceScaleFactor();
-  const bool scaleFactorDidChange = scaleFactor != sf;
+  const bool sf_did_change = scaleFactor != sf;
 
   // Initialize a screen_infos_ struct as needed, to cache the scale factor.
   if (screen_infos_.screen_infos.empty()) {
@@ -1003,14 +995,9 @@ void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) {
   }
   screen_infos_.mutable_current().device_scale_factor = scaleFactor;
 
-  gfx::Size size;
-  if (!IsPopupWidget())
-    size = GetViewBounds().size();
-  else
-    size = popup_position_.size();
+  gfx::Size size = GetViewBounds().size();
 
-  if (!force && !scaleFactorDidChange &&
-      size == GetRootLayer()->bounds().size())
+  if (!force && !sf_did_change && size == GetRootLayer()->bounds().size())
     return;
 
   GetRootLayer()->SetBounds(gfx::Rect(size));

+ 1 - 1
shell/browser/osr/osr_render_widget_host_view.h

@@ -121,7 +121,7 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
 
   void ResetFallbackToFirstNavigationSurface() override;
   void InitAsPopup(content::RenderWidgetHostView* parent_host_view,
-                   const gfx::Rect& pos,
+                   const gfx::Rect& bounds,
                    const gfx::Rect& anchor_rect) override;
   void UpdateCursor(const content::WebCursor&) override;
   void SetIsLoading(bool is_loading) override;

+ 23 - 8
shell/browser/osr/osr_video_consumer.cc

@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "media/base/limits.h"
 #include "media/base/video_frame_metadata.h"
 #include "media/capture/mojom/video_capture_buffer.mojom.h"
 #include "media/capture/mojom/video_capture_types.mojom.h"
@@ -13,6 +14,21 @@
 #include "shell/browser/osr/osr_render_widget_host_view.h"
 #include "ui/gfx/skbitmap_operations.h"
 
+namespace {
+
+bool IsValidMinAndMaxFrameSize(gfx::Size min_frame_size,
+                               gfx::Size max_frame_size) {
+  // Returns true if
+  // 0 < |min_frame_size| <= |max_frame_size| <= media::limits::kMaxDimension.
+  return 0 < min_frame_size.width() && 0 < min_frame_size.height() &&
+         min_frame_size.width() <= max_frame_size.width() &&
+         min_frame_size.height() <= max_frame_size.height() &&
+         max_frame_size.width() <= media::limits::kMaxDimension &&
+         max_frame_size.height() <= media::limits::kMaxDimension;
+}
+
+}  // namespace
+
 namespace electron {
 
 OffScreenVideoConsumer::OffScreenVideoConsumer(
@@ -21,11 +37,11 @@ OffScreenVideoConsumer::OffScreenVideoConsumer(
     : callback_(callback),
       view_(view),
       video_capturer_(view->CreateVideoCapturer()) {
-  video_capturer_->SetResolutionConstraints(view_->SizeInPixels(),
-                                            view_->SizeInPixels(), true);
   video_capturer_->SetAutoThrottlingEnabled(false);
   video_capturer_->SetMinSizeChangePeriod(base::TimeDelta());
   video_capturer_->SetFormat(media::PIXEL_FORMAT_ARGB);
+
+  SizeChanged(view_->SizeInPixels());
   SetFrameRate(view_->GetFrameRate());
 }
 
@@ -43,9 +59,10 @@ void OffScreenVideoConsumer::SetFrameRate(int frame_rate) {
   video_capturer_->SetMinCapturePeriod(base::Seconds(1) / frame_rate);
 }
 
-void OffScreenVideoConsumer::SizeChanged() {
-  video_capturer_->SetResolutionConstraints(view_->SizeInPixels(),
-                                            view_->SizeInPixels(), true);
+void OffScreenVideoConsumer::SizeChanged(const gfx::Size& size_in_pixels) {
+  DCHECK(IsValidMinAndMaxFrameSize(size_in_pixels, size_in_pixels));
+  video_capturer_->SetResolutionConstraints(size_in_pixels, size_in_pixels,
+                                            true);
   video_capturer_->RequestRefreshFrame();
 }
 
@@ -58,9 +75,7 @@ void OffScreenVideoConsumer::OnFrameCaptured(
   auto& data_region = data->get_read_only_shmem_region();
 
   if (!CheckContentRect(content_rect)) {
-    gfx::Size view_size = view_->SizeInPixels();
-    video_capturer_->SetResolutionConstraints(view_size, view_size, true);
-    video_capturer_->RequestRefreshFrame();
+    SizeChanged(view_->SizeInPixels());
     return;
   }
 

+ 1 - 1
shell/browser/osr/osr_video_consumer.h

@@ -33,7 +33,7 @@ class OffScreenVideoConsumer : public viz::mojom::FrameSinkVideoConsumer {
 
   void SetActive(bool active);
   void SetFrameRate(int frame_rate);
-  void SizeChanged();
+  void SizeChanged(const gfx::Size& size_in_pixels);
 
  private:
   // viz::mojom::FrameSinkVideoConsumer implementation.