diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 80e5b606ef8d..b04553e654b8 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1064,9 +1064,11 @@ void WebContents::BeginFrameSubscription( const FrameSubscriber::FrameCaptureCallback& callback) { const auto view = web_contents()->GetRenderWidgetHostView(); if (view) { - scoped_ptr frame_subscriber(new FrameSubscriber( - isolate(), view->GetVisibleViewportSize(), callback)); - view->BeginFrameSubscription(frame_subscriber.Pass()); + FrameSubscriber* frame_subscriber = new FrameSubscriber( + isolate(), view->GetVisibleViewportSize(), callback); + scoped_ptr del_frame_subscriber( + frame_subscriber->GetSubscriber()); + view->BeginFrameSubscription(del_frame_subscriber.Pass()); } } diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index 5b7241486b72..9bcf16fef857 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -13,28 +13,58 @@ namespace atom { namespace api { +using Subscriber = FrameSubscriber::Subscriber; + FrameSubscriber::FrameSubscriber(v8::Isolate* isolate, const gfx::Size& size, const FrameCaptureCallback& callback) - : isolate_(isolate), size_(size), callback_(callback) { + : isolate_(isolate), size_(size), callback_(callback), pending_frames(0) { + subscriber_ = new Subscriber(this); } -bool FrameSubscriber::ShouldCaptureFrame( +Subscriber::Subscriber( + FrameSubscriber* frame_subscriber) : frame_subscriber_(frame_subscriber) { +} + +Subscriber::~Subscriber() { + frame_subscriber_->subscriber_ = NULL; + frame_subscriber_->RequestDestruct(); +} + +bool Subscriber::ShouldCaptureFrame( const gfx::Rect& damage_rect, base::TimeTicks present_time, scoped_refptr* storage, DeliverFrameCallback* callback) { *storage = media::VideoFrame::CreateFrame( media::PIXEL_FORMAT_YV12, - size_, gfx::Rect(size_), size_, base::TimeDelta()); + frame_subscriber_->size_, gfx::Rect(frame_subscriber_->size_), + frame_subscriber_->size_, base::TimeDelta()); *callback = base::Bind(&FrameSubscriber::OnFrameDelivered, - base::Unretained(this), *storage); + base::Unretained(frame_subscriber_), *storage); + frame_subscriber_->pending_frames++; return true; } +Subscriber* FrameSubscriber::GetSubscriber() { + return subscriber_; +} + +bool FrameSubscriber::RequestDestruct() { + bool deletable = (subscriber_ == NULL && pending_frames == 0); + // Destruct FrameSubscriber if we're not waiting for frames and the + // subscription has ended + if (deletable) + delete this; + + return deletable; +} + void FrameSubscriber::OnFrameDelivered( scoped_refptr frame, base::TimeTicks, bool result) { - if (!result) + pending_frames--; + + if (!result || RequestDestruct()) return; v8::Locker locker(isolate_); diff --git a/atom/browser/api/frame_subscriber.h b/atom/browser/api/frame_subscriber.h index f7748aa5790d..6f6d66b6be80 100644 --- a/atom/browser/api/frame_subscriber.h +++ b/atom/browser/api/frame_subscriber.h @@ -14,26 +14,43 @@ namespace atom { namespace api { -class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber { +class FrameSubscriber { public: using FrameCaptureCallback = base::Callback)>; + // Inner class that is the actual subscriber sent to chromium + class Subscriber : + public content::RenderWidgetHostViewFrameSubscriber { + public: + explicit Subscriber(FrameSubscriber* frame_subscriber); + + bool ShouldCaptureFrame(const gfx::Rect& damage_rect, + base::TimeTicks present_time, + scoped_refptr* storage, + DeliverFrameCallback* callback) override; + + ~Subscriber(); + private: + FrameSubscriber* frame_subscriber_; + }; + FrameSubscriber(v8::Isolate* isolate, const gfx::Size& size, const FrameCaptureCallback& callback); - bool ShouldCaptureFrame(const gfx::Rect& damage_rect, - base::TimeTicks present_time, - scoped_refptr* storage, - DeliverFrameCallback* callback) override; + Subscriber* GetSubscriber(); private: void OnFrameDelivered( scoped_refptr frame, base::TimeTicks, bool); + bool RequestDestruct(); + v8::Isolate* isolate_; gfx::Size size_; FrameCaptureCallback callback_; + Subscriber* subscriber_; + int pending_frames; DISALLOW_COPY_AND_ASSIGN(FrameSubscriber); };