Index: base/ios/weak_nsobject.mm |
diff --git a/base/ios/weak_nsobject.mm b/base/ios/weak_nsobject.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..36f9d3ea7cdd700da53d77a34245c3bad68a86c1 |
--- /dev/null |
+++ b/base/ios/weak_nsobject.mm |
@@ -0,0 +1,61 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/ios/weak_nsobject.h" |
+ |
+#include "base/mac/scoped_nsautorelease_pool.h" |
+#include "base/mac/scoped_nsobject.h" |
+ |
+namespace { |
+// The key needed by objc_setAssociatedObject. |
+char sentinelObserverKey_; |
+} |
+ |
+@interface CRBWeakNSProtocolSentinel () |
+// Container to notify on dealloc. |
+@property(readonly, assign) scoped_refptr<base::WeakContainer> container; |
+// Designed initializer. |
+- (id)initWithContainer:(scoped_refptr<base::WeakContainer>)container; |
+@end |
+ |
+@implementation CRBWeakNSProtocolSentinel |
+ |
+@synthesize container = container_; |
+ |
++ (scoped_refptr<base::WeakContainer>)containerForObject:(id)object { |
+ if (object == nil) |
+ return nullptr; |
+ // The autoreleasePool is needed here as the call to objc_getAssociatedObject |
+ // returns an autoreleased object which is better released sooner than later. |
+ base::mac::ScopedNSAutoreleasePool pool; |
+ CRBWeakNSProtocolSentinel* sentinel = |
+ objc_getAssociatedObject(object, &sentinelObserverKey_); |
+ if (!sentinel) { |
+ base::scoped_nsobject<CRBWeakNSProtocolSentinel> newSentinel( |
+ [[CRBWeakNSProtocolSentinel alloc] |
+ initWithContainer:new base::WeakContainer(object)]); |
+ sentinel = newSentinel; |
+ objc_setAssociatedObject(object, &sentinelObserverKey_, sentinel, |
+ OBJC_ASSOCIATION_RETAIN); |
+ // The retain count is 2. One retain is due to the alloc, the other to the |
+ // association with the weak object. |
+ DCHECK_EQ(2u, [sentinel retainCount]); |
+ } |
+ return [sentinel container]; |
+} |
+ |
+- (id)initWithContainer:(scoped_refptr<base::WeakContainer>)container { |
+ DCHECK(container.get()); |
+ self = [super init]; |
+ if (self) |
+ container_ = container; |
+ return self; |
+} |
+ |
+- (void)dealloc { |
+ self.container->nullify(); |
+ [super dealloc]; |
+} |
+ |
+@end |