summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormcasas@chromium.org <mcasas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-07 17:24:15 +0000
committermcasas@chromium.org <mcasas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-07 17:24:15 +0000
commitb242a522833e4465005c8efc13189f574a85691e (patch)
tree08a4962258e99811b8bfcc845f53d1723786d429
parentcbed02ae31011f741d1341472abc0108cf42b148 (diff)
downloadchromium_src-b242a522833e4465005c8efc13189f574a85691e.zip
chromium_src-b242a522833e4465005c8efc13189f574a85691e.tar.gz
chromium_src-b242a522833e4465005c8efc13189f574a85691e.tar.bz2
Mac AVFoundation device monitor: clean removal of device observers
This CL fixes a crash happening when Chrome shuts down or a capture device is removed from the system while there are observers observing the "suspended" property of the AVCaptureDevice going out of scope -- basically leaving the observer observing a zombie. For that, the CrAVFoundationSuspendObserver registers to observe both "suspended" and "connected". In the case of "connected" received, it can only mean disconnected, so both observers are removed. The |device| pointer is passed to -addObserver:forKeyPath:options:context: as the |context|, and is received then in the -observeValueForKeyPath:... . CrAVFoundationSuspendObserver renamed to CrAVFoundationDeviceObserver. BUG=288562, 348917 Review URL: https://codereview.chromium.org/188383004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@255648 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/device_monitor_mac.mm22
1 files changed, 15 insertions, 7 deletions
diff --git a/content/browser/device_monitor_mac.mm b/content/browser/device_monitor_mac.mm
index 34d1916..0e53674 100644
--- a/content/browser/device_monitor_mac.mm
+++ b/content/browser/device_monitor_mac.mm
@@ -204,14 +204,14 @@ void QTKitMonitorImpl::OnDeviceChanged() {
ConsolidateDevicesListAndNotify(snapshot_devices);
}
-// Forward declaration for use by CrAVFoundationSuspendObserver.
+// Forward declaration for use by CrAVFoundationDeviceObserver.
class AVFoundationMonitorImpl;
} // namespace
// This class is a Key-Value Observer (KVO) shim. It is needed because C++
// classes cannot observe Key-Values directly.
-@interface CrAVFoundationSuspendObserver : NSObject {
+@interface CrAVFoundationDeviceObserver : NSObject {
@private
AVFoundationMonitorImpl* receiver_;
}
@@ -232,7 +232,7 @@ class AVFoundationMonitorImpl : public DeviceMonitorMacImpl {
virtual void OnDeviceChanged() OVERRIDE;
private:
- base::scoped_nsobject<CrAVFoundationSuspendObserver> suspend_observer_;
+ base::scoped_nsobject<CrAVFoundationDeviceObserver> suspend_observer_;
DISALLOW_COPY_AND_ASSIGN(AVFoundationMonitorImpl);
};
@@ -255,7 +255,7 @@ AVFoundationMonitorImpl::AVFoundationMonitorImpl(
usingBlock:^(NSNotification* notification) {
OnDeviceChanged();}];
suspend_observer_.reset(
- [[CrAVFoundationSuspendObserver alloc] initWithChangeReceiver:this]);
+ [[CrAVFoundationDeviceObserver alloc] initWithChangeReceiver:this]);
for (CrAVCaptureDevice* device in [AVCaptureDeviceGlue devices])
[suspend_observer_ startObserving:device];
}
@@ -292,7 +292,7 @@ void AVFoundationMonitorImpl::OnDeviceChanged() {
} // namespace
-@implementation CrAVFoundationSuspendObserver
+@implementation CrAVFoundationDeviceObserver
- (id)initWithChangeReceiver:(AVFoundationMonitorImpl*)receiver {
if ((self = [super init])) {
@@ -307,13 +307,19 @@ void AVFoundationMonitorImpl::OnDeviceChanged() {
[device addObserver:self
forKeyPath:@"suspended"
options:0
- context:nil];
+ context:device];
+ [device addObserver:self
+ forKeyPath:@"connected"
+ options:0
+ context:device];
}
- (void)stopObserving:(CrAVCaptureDevice*)device {
DCHECK(device != nil);
[device removeObserver:self
forKeyPath:@"suspended"];
+ [device removeObserver:self
+ forKeyPath:@"connected"];
}
- (void)observeValueForKeyPath:(NSString*)keyPath
@@ -322,9 +328,11 @@ void AVFoundationMonitorImpl::OnDeviceChanged() {
context:(void*)context {
if ([keyPath isEqual:@"suspended"])
receiver_->OnDeviceChanged();
+ if ([keyPath isEqual:@"connected"])
+ [self stopObserving:static_cast<CrAVCaptureDevice*>(context)];
}
-@end // @implementation CrAVFoundationSuspendObserver
+@end // @implementation CrAVFoundationDeviceObserver
namespace content {