Commit 212b7610 authored by Kurt Horimoto's avatar Kurt Horimoto Committed by Commit Bot

[iOS] Create ObjC container for fullscreen disabler observers.

This allows the proper memory management of ObserverLists used in
Objective-C blocks.

Bug: 816342
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: Ic3b232303586ec99129ab999740454a0180833bb
Reviewed-on: https://chromium-review.googlesource.com/939101Reviewed-by: default avatarJustin Cohen <justincohen@chromium.org>
Commit-Queue: Kurt Horimoto <kkhorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#539541}
parent f50def54
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
class FullscreenController; class FullscreenController;
class AnimatedScopedFullscreenDisablerObserver; class AnimatedScopedFullscreenDisablerObserver;
@class AnimatedScopedFullscreenDisablerObserverListContainer;
// A helper object that increments FullscrenController's disabled counter for // A helper object that increments FullscrenController's disabled counter for
// its entire lifetime after calling StartAnimation(). Any UI updates resulting // its entire lifetime after calling StartAnimation(). Any UI updates resulting
...@@ -29,13 +30,11 @@ class AnimatedScopedFullscreenDisabler { ...@@ -29,13 +30,11 @@ class AnimatedScopedFullscreenDisabler {
void StartAnimation(); void StartAnimation();
private: private:
// Called when the fullscreen disabling animation has finished.
void OnAnimationFinished();
// The FullscreenController being disabled by this object. // The FullscreenController being disabled by this object.
FullscreenController* controller_; FullscreenController* controller_;
// The AnimatedScopedFullscreenDisablerObservers. // A container object for the list of observers.
base::ObserverList<AnimatedScopedFullscreenDisablerObserver> observers_; __strong AnimatedScopedFullscreenDisablerObserverListContainer*
observer_list_container_;
// Whether this disabler is contributing to |controller_|'s disabled counter. // Whether this disabler is contributing to |controller_|'s disabled counter.
bool disabling_ = false; bool disabling_ = false;
...@@ -51,11 +50,16 @@ class AnimatedScopedFullscreenDisablerObserver { ...@@ -51,11 +50,16 @@ class AnimatedScopedFullscreenDisablerObserver {
// Called when the fullscreen disabling animation begins and ends. If // Called when the fullscreen disabling animation begins and ends. If
// AnimatedScopedFullscreenDisabler::StartAnimation() is called and for a // AnimatedScopedFullscreenDisabler::StartAnimation() is called and for a
// FullscreenController that is already disabled, these callbacks will not be // FullscreenController that is already disabled, these callbacks will not be
// sent. // sent. If the disabler is destroyed before the animation can finish,
// FullscreenDisablingAnimationDidFinish() will not be received.
virtual void FullscreenDisablingAnimationDidStart( virtual void FullscreenDisablingAnimationDidStart(
AnimatedScopedFullscreenDisabler* disabler){}; AnimatedScopedFullscreenDisabler* disabler) {}
virtual void FullscreenDisablingAnimationDidFinish( virtual void FullscreenDisablingAnimationDidFinish(
AnimatedScopedFullscreenDisabler* disabler){}; AnimatedScopedFullscreenDisabler* disabler) {}
// Called before the disabler is destructed.
virtual void AnimatedFullscreenDisablerDestroyed(
AnimatedScopedFullscreenDisabler* disabler) {}
}; };
#endif // IOS_CHROME_BROWSER_UI_FULLSCREEN_ANIMATED_SCOPED_FULLSCREEN_DISABLER_H_ #endif // IOS_CHROME_BROWSER_UI_FULLSCREEN_ANIMATED_SCOPED_FULLSCREEN_DISABLER_H_
...@@ -12,25 +12,103 @@ ...@@ -12,25 +12,103 @@
#error "This file requires ARC support." #error "This file requires ARC support."
#endif #endif
#pragma mark - AnimatedScopedFullscreenDisablerObserverListContainer
// An Objective-C container used to store observers. This is used to allow
// correct memory management for use in UIView animation blocks.
@interface AnimatedScopedFullscreenDisablerObserverListContainer : NSObject {
// The AnimatedScopedFullscreenDisablerObservers.
base::ObserverList<AnimatedScopedFullscreenDisablerObserver> observers_;
}
// The disabler passed on initialization.
@property(nonatomic, readonly) AnimatedScopedFullscreenDisabler* disabler;
// Designated initializer for a container containing |disabler|'s observer list.
- (instancetype)initWithDisabler:(AnimatedScopedFullscreenDisabler*)disabler
NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
// Adds and removes observers.
- (void)addObserver:(AnimatedScopedFullscreenDisablerObserver*)observer;
- (void)removeObserver:(AnimatedScopedFullscreenDisablerObserver*)observer;
// Notifies observers when the animation starts and finishes.
- (void)onAnimationStarted;
- (void)onAnimationFinished;
- (void)onDisablerDestroyed;
@end
@implementation AnimatedScopedFullscreenDisablerObserverListContainer
@synthesize disabler = _disabler;
- (instancetype)initWithDisabler:(AnimatedScopedFullscreenDisabler*)disabler {
if (self = [super init]) {
_disabler = disabler;
DCHECK(_disabler);
}
return self;
}
- (const base::ObserverList<AnimatedScopedFullscreenDisablerObserver>&)
observers {
return observers_;
}
- (void)addObserver:(AnimatedScopedFullscreenDisablerObserver*)observer {
observers_.AddObserver(observer);
}
- (void)removeObserver:(AnimatedScopedFullscreenDisablerObserver*)observer {
observers_.RemoveObserver(observer);
}
- (void)onAnimationStarted {
for (auto& observer : observers_) {
observer.FullscreenDisablingAnimationDidStart(_disabler);
}
}
- (void)onAnimationFinished {
for (auto& observer : observers_) {
observer.FullscreenDisablingAnimationDidFinish(_disabler);
}
}
- (void)onDisablerDestroyed {
for (auto& observer : observers_) {
observer.AnimatedFullscreenDisablerDestroyed(_disabler);
}
}
@end
#pragma mark - AnimatedScopedFullscreenDisabler
AnimatedScopedFullscreenDisabler::AnimatedScopedFullscreenDisabler( AnimatedScopedFullscreenDisabler::AnimatedScopedFullscreenDisabler(
FullscreenController* controller) FullscreenController* controller)
: controller_(controller) { : controller_(controller) {
DCHECK(controller_); DCHECK(controller_);
observer_list_container_ =
[[AnimatedScopedFullscreenDisablerObserverListContainer alloc]
initWithDisabler:this];
} }
AnimatedScopedFullscreenDisabler::~AnimatedScopedFullscreenDisabler() { AnimatedScopedFullscreenDisabler::~AnimatedScopedFullscreenDisabler() {
if (disabling_) if (disabling_)
controller_->DecrementDisabledCounter(); controller_->DecrementDisabledCounter();
[observer_list_container_ onDisablerDestroyed];
} }
void AnimatedScopedFullscreenDisabler::AddObserver( void AnimatedScopedFullscreenDisabler::AddObserver(
AnimatedScopedFullscreenDisablerObserver* observer) { AnimatedScopedFullscreenDisablerObserver* observer) {
observers_.AddObserver(observer); [observer_list_container_ addObserver:observer];
} }
void AnimatedScopedFullscreenDisabler::RemoveObserver( void AnimatedScopedFullscreenDisabler::RemoveObserver(
AnimatedScopedFullscreenDisablerObserver* observer) { AnimatedScopedFullscreenDisablerObserver* observer) {
observers_.RemoveObserver(observer); [observer_list_container_ removeObserver:observer];
} }
void AnimatedScopedFullscreenDisabler::StartAnimation() { void AnimatedScopedFullscreenDisabler::StartAnimation() {
...@@ -43,24 +121,18 @@ void AnimatedScopedFullscreenDisabler::StartAnimation() { ...@@ -43,24 +121,18 @@ void AnimatedScopedFullscreenDisabler::StartAnimation() {
if (controller_->IsEnabled()) { if (controller_->IsEnabled()) {
// Increment the disabled counter in an animation block if the controller is // Increment the disabled counter in an animation block if the controller is
// not already disabled. // not already disabled.
for (auto& observer : observers_) { [observer_list_container_ onAnimationStarted];
observer.FullscreenDisablingAnimationDidStart(this); __weak AnimatedScopedFullscreenDisablerObserverListContainer*
} weak_observer_list_container = observer_list_container_;
[UIView animateWithDuration:ios::material::kDuration1 [UIView animateWithDuration:ios::material::kDuration1
animations:^{ animations:^{
controller_->IncrementDisabledCounter(); controller_->IncrementDisabledCounter();
} }
completion:^(BOOL finished) { completion:^(BOOL finished) {
OnAnimationFinished(); [weak_observer_list_container onAnimationFinished];
}]; }];
} else { } else {
// If |controller_| is already disabled, no animation is necessary. // If |controller_| is already disabled, no animation is necessary.
controller_->IncrementDisabledCounter(); controller_->IncrementDisabledCounter();
} }
} }
void AnimatedScopedFullscreenDisabler::OnAnimationFinished() {
for (auto& observer : observers_) {
observer.FullscreenDisablingAnimationDidFinish(this);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment