| Index: content/browser/media/capture/web_contents_video_capture_device.cc
|
| diff --git a/content/browser/media/capture/web_contents_video_capture_device.cc b/content/browser/media/capture/web_contents_video_capture_device.cc
|
| index d258238ef7e97762740a5c88a48ce5dbab96c9b2..aae4ed1de690b7d6c0d94d6dca7dbe580873eec1 100644
|
| --- a/content/browser/media/capture/web_contents_video_capture_device.cc
|
| +++ b/content/browser/media/capture/web_contents_video_capture_device.cc
|
| @@ -155,7 +155,7 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
|
| base::WeakPtrFactory<FrameSubscriber> weak_ptr_factory_;
|
| };
|
|
|
| -// ContentCaptureSubscription is the relationship between a RenderWidgetHost
|
| +// ContentCaptureSubscription is the relationship between a RenderWidgetHostView
|
| // whose content is updating, a subscriber that is deciding which of these
|
| // updates to capture (and where to deliver them to), and a callback that
|
| // knows how to do the capture and prepare the result for delivery.
|
| @@ -180,7 +180,7 @@ class ContentCaptureSubscription {
|
| // subscription will invoke |capture_callback| on the UI thread to do the
|
| // work.
|
| ContentCaptureSubscription(
|
| - const RenderWidgetHost& source,
|
| + base::WeakPtr<RenderWidgetHostViewBase> source_view,
|
| const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
|
| const CaptureCallback& capture_callback);
|
| ~ContentCaptureSubscription();
|
| @@ -191,11 +191,7 @@ class ContentCaptureSubscription {
|
| // Called for active frame refresh requests, or mouse activity events.
|
| void OnEvent(FrameSubscriber* subscriber);
|
|
|
| - // Maintain a weak reference to the RenderWidgetHost (via its routing ID),
|
| - // since the instance could be destroyed externally during the lifetime of
|
| - // |this|.
|
| - const int render_process_id_;
|
| - const int render_widget_id_;
|
| + const base::WeakPtr<RenderWidgetHostViewBase> source_view_;
|
|
|
| std::unique_ptr<FrameSubscriber> refresh_subscriber_;
|
| std::unique_ptr<FrameSubscriber> mouse_activity_subscriber_;
|
| @@ -288,9 +284,10 @@ class WebContentsCaptureMachine : public media::VideoCaptureMachine {
|
| const gfx::Rect& region_in_frame,
|
| bool success);
|
|
|
| - // Remove the old subscription, and attempt to start a new one if |had_target|
|
| - // is true.
|
| - void RenewFrameSubscription(bool had_target);
|
| + // Remove the old subscription, and attempt to start a new one. If
|
| + // |is_still_tracking| is false, emit an error rather than attempt to start a
|
| + // new subscription.
|
| + void RenewFrameSubscription(bool is_still_tracking);
|
|
|
| // Called whenever the render widget is resized.
|
| void UpdateCaptureSize();
|
| @@ -300,7 +297,7 @@ class WebContentsCaptureMachine : public media::VideoCaptureMachine {
|
| const int initial_main_render_frame_id_;
|
|
|
| // Tracks events and calls back to RenewFrameSubscription() to maintain
|
| - // capture on the correct RenderWidgetHost.
|
| + // capture on the correct RenderWidgetHostView.
|
| const scoped_refptr<WebContentsTracker> tracker_;
|
|
|
| // Set to false to prevent the capture size from automatically adjusting in
|
| @@ -404,21 +401,17 @@ bool FrameSubscriber::IsUserInteractingWithContent() {
|
| }
|
|
|
| ContentCaptureSubscription::ContentCaptureSubscription(
|
| - const RenderWidgetHost& source,
|
| + base::WeakPtr<RenderWidgetHostViewBase> source_view,
|
| const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
|
| const CaptureCallback& capture_callback)
|
| - : render_process_id_(source.GetProcess()->GetID()),
|
| - render_widget_id_(source.GetRoutingID()),
|
| - capture_callback_(capture_callback) {
|
| + : source_view_(source_view), capture_callback_(capture_callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + DCHECK(source_view_);
|
|
|
| - RenderWidgetHostView* const view = source.GetView();
|
| #if defined(USE_AURA) || defined(OS_MACOSX)
|
| - if (view) {
|
| - cursor_renderer_ = CursorRenderer::Create(view->GetNativeView());
|
| - window_activity_tracker_ =
|
| - WindowActivityTracker::Create(view->GetNativeView());
|
| - }
|
| + cursor_renderer_ = CursorRenderer::Create(source_view_->GetNativeView());
|
| + window_activity_tracker_ =
|
| + WindowActivityTracker::Create(source_view_->GetNativeView());
|
| #endif
|
| refresh_subscriber_.reset(new FrameSubscriber(
|
| media::VideoCaptureOracle::kActiveRefreshRequest, oracle_proxy,
|
| @@ -435,16 +428,14 @@ ContentCaptureSubscription::ContentCaptureSubscription(
|
|
|
| // Subscribe to compositor updates. These will be serviced directly by the
|
| // oracle.
|
| - if (view) {
|
| - std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
|
| - new FrameSubscriber(
|
| - media::VideoCaptureOracle::kCompositorUpdate, oracle_proxy,
|
| - cursor_renderer_ ? cursor_renderer_->GetWeakPtr()
|
| - : base::WeakPtr<CursorRenderer>(),
|
| - window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr()
|
| - : base::WeakPtr<WindowActivityTracker>()));
|
| - view->BeginFrameSubscription(std::move(subscriber));
|
| - }
|
| + std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
|
| + new FrameSubscriber(
|
| + media::VideoCaptureOracle::kCompositorUpdate, oracle_proxy,
|
| + cursor_renderer_ ? cursor_renderer_->GetWeakPtr()
|
| + : base::WeakPtr<CursorRenderer>(),
|
| + window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr()
|
| + : base::WeakPtr<WindowActivityTracker>()));
|
| + source_view_->BeginFrameSubscription(std::move(subscriber));
|
|
|
| // Subscribe to mouse movement and mouse cursor update events.
|
| if (window_activity_tracker_) {
|
| @@ -462,11 +453,13 @@ ContentCaptureSubscription::~ContentCaptureSubscription() {
|
| return;
|
|
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| - RenderWidgetHost* const source =
|
| - RenderWidgetHost::FromID(render_process_id_, render_widget_id_);
|
| - RenderWidgetHostView* const view = source ? source->GetView() : NULL;
|
| - if (view)
|
| - view->EndFrameSubscription();
|
| + // If the RWHV weak pointer is still valid, make sure the view is still
|
| + // associated with a RWH before attempting to end the frame subscription. This
|
| + // is because a null RWH indicates the RWHV has had its Destroy() method
|
| + // called, which makes it invalid to call any of its methods that assume the
|
| + // compositor is present.
|
| + if (source_view_ && source_view_->GetRenderWidgetHost())
|
| + source_view_->EndFrameSubscription();
|
| }
|
|
|
| void ContentCaptureSubscription::MaybeCaptureForRefresh() {
|
| @@ -641,7 +634,7 @@ void WebContentsCaptureMachine::InternalSuspend() {
|
| return;
|
| frame_capture_active_ = false;
|
| if (IsStarted())
|
| - RenewFrameSubscription(true);
|
| + RenewFrameSubscription(tracker_->is_still_tracking());
|
| }
|
|
|
| void WebContentsCaptureMachine::Resume() {
|
| @@ -656,7 +649,7 @@ void WebContentsCaptureMachine::InternalResume() {
|
| return;
|
| frame_capture_active_ = true;
|
| if (IsStarted())
|
| - RenewFrameSubscription(true);
|
| + RenewFrameSubscription(tracker_->is_still_tracking());
|
| }
|
|
|
| void WebContentsCaptureMachine::Stop(const base::Closure& callback) {
|
| @@ -714,9 +707,8 @@ void WebContentsCaptureMachine::Capture(
|
| deliver_frame_cb) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| - RenderWidgetHost* rwh = tracker_->GetTargetRenderWidgetHost();
|
| - RenderWidgetHostViewBase* view =
|
| - rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL;
|
| + auto* const view =
|
| + static_cast<RenderWidgetHostViewBase*>(tracker_->GetTargetView());
|
| if (!view) {
|
| deliver_frame_cb.Run(base::TimeTicks(), gfx::Rect(), false);
|
| return;
|
| @@ -736,13 +728,15 @@ void WebContentsCaptureMachine::Capture(
|
| ? gfx::Size()
|
| : media::ComputeLetterboxRegion(target->visible_rect(), view_size)
|
| .size();
|
| - rwh->CopyFromBackingStore(
|
| - gfx::Rect(),
|
| - fitted_size, // Size here is a request not always honored.
|
| - base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore,
|
| - weak_ptr_factory_.GetWeakPtr(), start_time, target,
|
| - deliver_frame_cb),
|
| - kN32_SkColorType);
|
| + if (auto* rwh = view->GetRenderWidgetHost()) {
|
| + rwh->CopyFromBackingStore(
|
| + gfx::Rect(),
|
| + fitted_size, // Size here is a request not always honored.
|
| + base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore,
|
| + weak_ptr_factory_.GetWeakPtr(), start_time, target,
|
| + deliver_frame_cb),
|
| + kN32_SkColorType);
|
| + }
|
| }
|
| }
|
|
|
| @@ -795,9 +789,7 @@ gfx::Size WebContentsCaptureMachine::ComputeOptimalViewSize() const {
|
| // render widget to the "preferred size," the widget will be physically
|
| // rendered at the exact capture size, thereby eliminating unnecessary scaling
|
| // operations in the graphics pipeline.
|
| - RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost();
|
| - RenderWidgetHostView* const rwhv = rwh ? rwh->GetView() : NULL;
|
| - if (rwhv) {
|
| + if (auto* rwhv = tracker_->GetTargetView()) {
|
| const gfx::NativeView view = rwhv->GetNativeView();
|
| const float scale = ui::GetScaleFactorForNativeView(view);
|
| if (scale > 1.0f) {
|
| @@ -849,20 +841,16 @@ void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
|
| deliver_frame_cb.Run(start_time, region_in_frame, success);
|
| }
|
|
|
| -void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) {
|
| +void WebContentsCaptureMachine::RenewFrameSubscription(bool is_still_tracking) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| - RenderWidgetHost* const rwh =
|
| - had_target ? tracker_->GetTargetRenderWidgetHost() : nullptr;
|
| -
|
| // Always destroy the old subscription before creating a new one.
|
| if (subscription_) {
|
| - DVLOG(1) << "Cancelling existing ContentCaptureSubscription.";
|
| + DVLOG(1) << "Cancelling existing subscription.";
|
| subscription_.reset();
|
| }
|
|
|
| - if (!rwh) {
|
| - DVLOG(1) << "Cannot renew ContentCaptureSubscription: no RWH target.";
|
| + if (!is_still_tracking) {
|
| if (IsStarted()) {
|
| // Tracking of WebContents and/or its main frame has failed before Stop()
|
| // was called, so report this as an error:
|
| @@ -872,12 +860,23 @@ void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) {
|
| return;
|
| }
|
|
|
| - if (frame_capture_active_) {
|
| - DVLOG(1) << "Renewing ContentCaptureSubscription to RWH@" << rwh;
|
| - subscription_.reset(new ContentCaptureSubscription(
|
| - *rwh, oracle_proxy_, base::Bind(&WebContentsCaptureMachine::Capture,
|
| - weak_ptr_factory_.GetWeakPtr())));
|
| + if (!frame_capture_active_) {
|
| + DVLOG(1) << "Not renewing subscription: Frame capture is suspended.";
|
| + return;
|
| + }
|
| +
|
| + auto* const view =
|
| + static_cast<RenderWidgetHostViewBase*>(tracker_->GetTargetView());
|
| + if (!view) {
|
| + DVLOG(1) << "Cannot renew subscription: No view to capture.";
|
| + return;
|
| }
|
| +
|
| + DVLOG(1) << "Renewing subscription to RenderWidgetHostView@" << view;
|
| + subscription_.reset(new ContentCaptureSubscription(
|
| + view->GetWeakPtr(), oracle_proxy_,
|
| + base::Bind(&WebContentsCaptureMachine::Capture,
|
| + weak_ptr_factory_.GetWeakPtr())));
|
| }
|
|
|
| void WebContentsCaptureMachine::UpdateCaptureSize() {
|
| @@ -885,8 +884,7 @@ void WebContentsCaptureMachine::UpdateCaptureSize() {
|
|
|
| if (!oracle_proxy_)
|
| return;
|
| - RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost();
|
| - RenderWidgetHostView* const view = rwh ? rwh->GetView() : nullptr;
|
| + RenderWidgetHostView* const view = tracker_->GetTargetView();
|
| if (!view)
|
| return;
|
|
|
|
|