Index: content/browser/renderer_host/media/web_contents_video_capture_device.cc |
diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device.cc b/content/browser/renderer_host/media/web_contents_video_capture_device.cc |
index e5e4af7b8ae975b18e7bc8fcf894526cb08c1d73..d15c3592bd67fbcabf690162d4b51efdf61d03d4 100644 |
--- a/content/browser/renderer_host/media/web_contents_video_capture_device.cc |
+++ b/content/browser/renderer_host/media/web_contents_video_capture_device.cc |
@@ -151,6 +151,8 @@ class BackingStoreCopier : public WebContentsObserver { |
BackingStoreCopier(int render_process_id, int render_view_id); |
+ virtual ~BackingStoreCopier(); |
+ |
// If non-NULL, use the given |override| to access the backing store. |
// This is used for unit testing. |
void SetRenderWidgetHostForTesting(RenderWidgetHost* override); |
@@ -162,6 +164,11 @@ class BackingStoreCopier : public WebContentsObserver { |
void StartCopy(int frame_number, int desired_width, int desired_height, |
const DoneCB& done_cb); |
+ // Stops observing an existing WebContents instance, if any. This must be |
+ // called before BackingStoreCopier is destroyed. Must be run on the UI |
+ // BrowserThread. |
+ void StopObservingWebContents(); |
+ |
virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
fullscreen_widget_id_ = routing_id; |
@@ -174,6 +181,8 @@ class BackingStoreCopier : public WebContentsObserver { |
} |
private: |
+ virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE; |
+ |
void LookUpAndObserveWebContents(); |
void CopyFromBackingStoreComplete(int frame_number, |
@@ -290,6 +299,25 @@ BackingStoreCopier::BackingStoreCopier(int render_process_id, |
: render_process_id_(render_process_id), render_view_id_(render_view_id), |
fullscreen_widget_id_(MSG_ROUTING_NONE), rwh_for_testing_(NULL) {} |
+BackingStoreCopier::~BackingStoreCopier() { |
+ DCHECK(!web_contents()); |
+} |
+ |
+void BackingStoreCopier::StopObservingWebContents() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ if (web_contents()) { |
+ web_contents()->DecrementCapturerCount(); |
+ Observe(NULL); |
+ } |
+} |
+ |
+void BackingStoreCopier::WebContentsDestroyed(WebContents* web_contents) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ web_contents->DecrementCapturerCount(); |
+} |
+ |
void BackingStoreCopier::LookUpAndObserveWebContents() { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
@@ -309,8 +337,10 @@ void BackingStoreCopier::LookUpAndObserveWebContents() { |
<< render_process_id_ << ", " << render_view_id_ |
<< ") returned NULL."; |
Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL); |
- DVLOG_IF(1, !web_contents()) |
- << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; |
+ if (web_contents()) |
+ web_contents()->IncrementCapturerCount(); |
+ else |
+ DVLOG(1) << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; |
if (fullscreen_widget_id_ == MSG_ROUTING_NONE && web_contents()) { |
fullscreen_widget_id_ = static_cast<WebContentsImpl*>(web_contents())-> |
@@ -714,6 +744,8 @@ class CaptureMachine |
const SkBitmap* frame_buffer); |
void DeliverComplete(const SkBitmap* frame_buffer); |
+ void DoShutdownTasksOnUIThread(); |
+ |
// Specialized RefCounted traits for CaptureMachine, so that operator delete |
// is called from an "outside" thread. See comments for "traits" in |
// base/memory/ref_counted.h. |
@@ -840,6 +872,10 @@ void CaptureMachine::DeAllocate() { |
Stop(); |
} |
if (state_ == kAllocated) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&CaptureMachine::DoShutdownTasksOnUIThread, this)); |
+ |
TransitionStateTo(kIdle); |
} |
} |
@@ -1019,6 +1055,10 @@ void CaptureMachine::DeliverComplete(const SkBitmap* frame_buffer) { |
renderer_.Release(frame_buffer); |
} |
+void CaptureMachine::DoShutdownTasksOnUIThread() { |
+ copier_.StopObservingWebContents(); |
+} |
+ |
WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( |
const media::VideoCaptureDevice::Name& name, |
int render_process_id, int render_view_id) |