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 @@
class FullscreenController;
class AnimatedScopedFullscreenDisablerObserver;
@class AnimatedScopedFullscreenDisablerObserverListContainer;
// A helper object that increments FullscrenController's disabled counter for
// its entire lifetime after calling StartAnimation(). Any UI updates resulting
......@@ -29,13 +30,11 @@ class AnimatedScopedFullscreenDisabler {
void StartAnimation();
private:
// Called when the fullscreen disabling animation has finished.
void OnAnimationFinished();
// The FullscreenController being disabled by this object.
FullscreenController* controller_;
// The AnimatedScopedFullscreenDisablerObservers.
base::ObserverList<AnimatedScopedFullscreenDisablerObserver> observers_;
// A container object for the list of observers.
__strong AnimatedScopedFullscreenDisablerObserverListContainer*
observer_list_container_;
// Whether this disabler is contributing to |controller_|'s disabled counter.
bool disabling_ = false;
......@@ -51,11 +50,16 @@ class AnimatedScopedFullscreenDisablerObserver {
// Called when the fullscreen disabling animation begins and ends. If
// AnimatedScopedFullscreenDisabler::StartAnimation() is called and for a
// 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(
AnimatedScopedFullscreenDisabler* disabler){};
AnimatedScopedFullscreenDisabler* disabler) {}
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_
......@@ -12,25 +12,103 @@
#error "This file requires ARC support."
#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(
FullscreenController* controller)
: controller_(controller) {
DCHECK(controller_);
observer_list_container_ =
[[AnimatedScopedFullscreenDisablerObserverListContainer alloc]
initWithDisabler:this];
}
AnimatedScopedFullscreenDisabler::~AnimatedScopedFullscreenDisabler() {
if (disabling_)
controller_->DecrementDisabledCounter();
[observer_list_container_ onDisablerDestroyed];
}
void AnimatedScopedFullscreenDisabler::AddObserver(
AnimatedScopedFullscreenDisablerObserver* observer) {
observers_.AddObserver(observer);
[observer_list_container_ addObserver:observer];
}
void AnimatedScopedFullscreenDisabler::RemoveObserver(
AnimatedScopedFullscreenDisablerObserver* observer) {
observers_.RemoveObserver(observer);
[observer_list_container_ removeObserver:observer];
}
void AnimatedScopedFullscreenDisabler::StartAnimation() {
......@@ -43,24 +121,18 @@ void AnimatedScopedFullscreenDisabler::StartAnimation() {
if (controller_->IsEnabled()) {
// Increment the disabled counter in an animation block if the controller is
// not already disabled.
for (auto& observer : observers_) {
observer.FullscreenDisablingAnimationDidStart(this);
}
[observer_list_container_ onAnimationStarted];
__weak AnimatedScopedFullscreenDisablerObserverListContainer*
weak_observer_list_container = observer_list_container_;
[UIView animateWithDuration:ios::material::kDuration1
animations:^{
controller_->IncrementDisabledCounter();
}
completion:^(BOOL finished) {
OnAnimationFinished();
[weak_observer_list_container onAnimationFinished];
}];
} else {
// If |controller_| is already disabled, no animation is necessary.
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