|  | // 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 |