Commit 56be3bcf authored by edchin's avatar edchin Committed by Commit Bot

[ios] Use properties over ivars in SnapshotGenerator

This CL fixes a retain cycle that was caused by using an ivar in an
asynchronous block. The block retains self when an ivar is used.
This CL also more broadly replaces ivars with properties in the same
file.

Bug: 918032
Change-Id: I26c867931ad96574f19420f58465e2d14c43ce43
Reviewed-on: https://chromium-review.googlesource.com/c/1393015Reviewed-by: default avatarEric Noyau <noyau@chromium.org>
Reviewed-by: default avataredchin <edchin@chromium.org>
Commit-Queue: edchin <edchin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#619922}
parent 3cfc9fc9
...@@ -48,12 +48,16 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -48,12 +48,16 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
// Property providing access to the snapshot's cache. May be nil. // Property providing access to the snapshot's cache. May be nil.
@property(nonatomic, readonly) SnapshotCache* snapshotCache; @property(nonatomic, readonly) SnapshotCache* snapshotCache;
// The unique ID for the web state.
@property(nonatomic, copy) NSString* sessionID;
// The associated web state.
@property(nonatomic, assign) web::WebState* webState;
@end @end
@implementation SnapshotGenerator { @implementation SnapshotGenerator {
std::unique_ptr<web::WebStateObserver> _webStateObserver; std::unique_ptr<web::WebStateObserver> _webStateObserver;
NSString* _snapshotSessionId;
web::WebState* _webState;
} }
- (instancetype)initWithWebState:(web::WebState*)webState - (instancetype)initWithWebState:(web::WebState*)webState
...@@ -62,7 +66,7 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -62,7 +66,7 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
DCHECK(webState); DCHECK(webState);
DCHECK(snapshotSessionId); DCHECK(snapshotSessionId);
_webState = webState; _webState = webState;
_snapshotSessionId = snapshotSessionId; _sessionID = snapshotSessionId;
_webStateObserver = std::make_unique<web::WebStateObserverBridge>(self); _webStateObserver = std::make_unique<web::WebStateObserverBridge>(self);
_webState->AddObserver(_webStateObserver.get()); _webState->AddObserver(_webStateObserver.get());
...@@ -81,7 +85,7 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -81,7 +85,7 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
- (void)retrieveSnapshot:(void (^)(UIImage*))callback { - (void)retrieveSnapshot:(void (^)(UIImage*))callback {
DCHECK(callback); DCHECK(callback);
if (self.snapshotCache) { if (self.snapshotCache) {
[self.snapshotCache retrieveImageForSessionID:_snapshotSessionId [self.snapshotCache retrieveImageForSessionID:self.sessionID
callback:callback]; callback:callback];
} else { } else {
callback(nil); callback(nil);
...@@ -103,7 +107,7 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -103,7 +107,7 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
SnapshotCache* snapshotCache = self.snapshotCache; SnapshotCache* snapshotCache = self.snapshotCache;
if (snapshotCache) { if (snapshotCache) {
[snapshotCache retrieveGreyImageForSessionID:_snapshotSessionId [snapshotCache retrieveGreyImageForSessionID:self.sessionID
callback:wrappedCallback]; callback:wrappedCallback];
} else { } else {
wrappedCallback(nil); wrappedCallback(nil);
...@@ -113,17 +117,18 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -113,17 +117,18 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
- (UIImage*)updateSnapshot { - (UIImage*)updateSnapshot {
UIImage* snapshot = [self generateSnapshotWithOverlays:YES]; UIImage* snapshot = [self generateSnapshotWithOverlays:YES];
if (snapshot) { if (snapshot) {
[self.snapshotCache setImage:snapshot withSessionID:_snapshotSessionId]; [self.snapshotCache setImage:snapshot withSessionID:self.sessionID];
} }
return snapshot; return snapshot;
} }
- (void)updateWebViewSnapshotWithCompletion:(void (^)(UIImage*))completion { - (void)updateWebViewSnapshotWithCompletion:(void (^)(UIImage*))completion {
DCHECK(_webState); DCHECK(self.webState);
UIView* snapshotView = [self.delegate snapshotGenerator:self UIView* snapshotView = [self.delegate snapshotGenerator:self
baseViewForWebState:_webState]; baseViewForWebState:self.webState];
CGRect snapshotFrame = [_webState->GetView() convertRect:[self snapshotFrame] CGRect snapshotFrame =
fromView:snapshotView]; [self.webState->GetView() convertRect:[self snapshotFrame]
fromView:snapshotView];
if (CGRectIsEmpty(snapshotFrame)) { if (CGRectIsEmpty(snapshotFrame)) {
if (completion) { if (completion) {
base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI}, base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI},
...@@ -138,36 +143,19 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -138,36 +143,19 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
<< ": snapshotFrame.size.width=" << size.width; << ": snapshotFrame.size.width=" << size.width;
DCHECK(std::isnormal(size.height) && (size.height > 0)) DCHECK(std::isnormal(size.height) && (size.height > 0))
<< ": snapshotFrame.size.height=" << size.height; << ": snapshotFrame.size.height=" << size.height;
NSArray<SnapshotOverlay*>* overlays = [_delegate snapshotGenerator:self NSArray<SnapshotOverlay*>* overlays =
snapshotOverlaysForWebState:_webState]; [self.delegate snapshotGenerator:self
snapshotOverlaysForWebState:self.webState];
[_delegate snapshotGenerator:self willUpdateSnapshotForWebState:_webState]; [self.delegate snapshotGenerator:self
willUpdateSnapshotForWebState:self.webState];
__weak SnapshotGenerator* weakSelf = self; __weak SnapshotGenerator* weakSelf = self;
_webState->TakeSnapshot( self.webState->TakeSnapshot(
snapshotFrame, base::BindOnce(^(const gfx::Image& image) { snapshotFrame, base::BindOnce(^(const gfx::Image& image) {
SnapshotGenerator* strongSelf = weakSelf; UIImage* snapshot = [weakSelf snapshotWithOverlays:overlays
if (!strongSelf || !_webState) image:image
return; frame:snapshotFrame];
UIImage* snapshot = nil; [weakSelf updateSnapshotCacheWithImage:snapshot];
if (!image.IsEmpty()) {
snapshot = image.ToUIImage();
if (overlays.count > 0) {
snapshot = [strongSelf snapshotWithOverlays:overlays
snapshot:snapshot
frame:snapshotFrame];
}
}
if (snapshot) {
[strongSelf.snapshotCache setImage:snapshot
withSessionID:_snapshotSessionId];
} else {
// Remove any stale snapshot since the snapshot failed.
[strongSelf.snapshotCache
removeImageWithSessionID:_snapshotSessionId];
}
[_delegate snapshotGenerator:self
didUpdateSnapshotForWebState:_webState
withImage:snapshot];
if (completion) if (completion)
completion(snapshot); completion(snapshot);
})); }));
...@@ -179,24 +167,25 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -179,24 +167,25 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
return nil; return nil;
NSArray<SnapshotOverlay*>* overlays = NSArray<SnapshotOverlay*>* overlays =
shouldAddOverlay ? [_delegate snapshotGenerator:self shouldAddOverlay ? [self.delegate snapshotGenerator:self
snapshotOverlaysForWebState:_webState] snapshotOverlaysForWebState:self.webState]
: nil; : nil;
[_delegate snapshotGenerator:self willUpdateSnapshotForWebState:_webState]; [self.delegate snapshotGenerator:self
UIView* view = [_delegate snapshotGenerator:self willUpdateSnapshotForWebState:self.webState];
baseViewForWebState:_webState]; UIView* view = [self.delegate snapshotGenerator:self
baseViewForWebState:self.webState];
UIImage* snapshot = [self generateSnapshotForView:view UIImage* snapshot = [self generateSnapshotForView:view
withRect:frame withRect:frame
overlays:overlays]; overlays:overlays];
[_delegate snapshotGenerator:self [self.delegate snapshotGenerator:self
didUpdateSnapshotForWebState:_webState didUpdateSnapshotForWebState:self.webState
withImage:snapshot]; withImage:snapshot];
return snapshot; return snapshot;
} }
- (void)removeSnapshot { - (void)removeSnapshot {
[self.snapshotCache removeImageWithSessionID:_snapshotSessionId]; [self.snapshotCache removeImageWithSessionID:self.sessionID];
} }
#pragma mark - Private methods #pragma mark - Private methods
...@@ -206,19 +195,19 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -206,19 +195,19 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
- (CGRect)snapshotFrame { - (CGRect)snapshotFrame {
// Do not generate a snapshot if web usage is disabled (as the WebState's // Do not generate a snapshot if web usage is disabled (as the WebState's
// view is blank in that case). // view is blank in that case).
if (!_webState->IsWebUsageEnabled()) if (!self.webState->IsWebUsageEnabled())
return CGRectZero; return CGRectZero;
// Do not generate a snapshot if the delegate says the WebState view is // Do not generate a snapshot if the delegate says the WebState view is
// not ready (this generally mean a placeholder is displayed). // not ready (this generally mean a placeholder is displayed).
if (_delegate && ![_delegate snapshotGenerator:self if (self.delegate && ![self.delegate snapshotGenerator:self
canTakeSnapshotForWebState:_webState]) canTakeSnapshotForWebState:self.webState])
return CGRectZero; return CGRectZero;
UIView* view = [_delegate snapshotGenerator:self UIView* view = [self.delegate snapshotGenerator:self
baseViewForWebState:_webState]; baseViewForWebState:self.webState];
UIEdgeInsets headerInsets = [_delegate snapshotGenerator:self UIEdgeInsets headerInsets = [self.delegate snapshotGenerator:self
snapshotEdgeInsetsForWebState:_webState]; snapshotEdgeInsetsForWebState:self.webState];
return UIEdgeInsetsInsetRect(view.bounds, headerInsets); return UIEdgeInsetsInsetRect(view.bounds, headerInsets);
} }
...@@ -286,11 +275,15 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -286,11 +275,15 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
return image; return image;
} }
// Returns an image of the |snapshot| overlaid with |overlays| with the given // Returns an image of the |image| overlaid with |overlays| with the given
// |frame|. // |frame|.
- (UIImage*)snapshotWithOverlays:(NSArray<SnapshotOverlay*>*)overlays - (UIImage*)snapshotWithOverlays:(NSArray<SnapshotOverlay*>*)overlays
snapshot:(UIImage*)snapshot image:(const gfx::Image&)image
frame:(CGRect)frame { frame:(CGRect)frame {
if (image.IsEmpty())
return nil;
if (overlays.count == 0)
return image.ToUIImage();
CGSize size = frame.size; CGSize size = frame.size;
DCHECK(std::isnormal(size.width) && (size.width > 0)) DCHECK(std::isnormal(size.width) && (size.width > 0))
<< ": size.width=" << size.width; << ": size.width=" << size.width;
...@@ -302,7 +295,7 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -302,7 +295,7 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
CGContext* context = UIGraphicsGetCurrentContext(); CGContext* context = UIGraphicsGetCurrentContext();
DCHECK(context); DCHECK(context);
CGContextSaveGState(context); CGContextSaveGState(context);
[snapshot drawAtPoint:CGPointZero]; [image.ToUIImage() drawAtPoint:CGPointZero];
for (SnapshotOverlay* overlay in overlays) { for (SnapshotOverlay* overlay in overlays) {
// Render the overlay view at the desired offset. It is achieved // Render the overlay view at the desired offset. It is achieved
// by shifting origin of context because view frame is ignored when // by shifting origin of context because view frame is ignored when
...@@ -327,11 +320,25 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) { ...@@ -327,11 +320,25 @@ BOOL ViewHierarchyContainsWKWebView(UIView* view) {
return snapshotWithOverlays; return snapshotWithOverlays;
} }
// Updates the snapshot cache with |snapshot|.
- (void)updateSnapshotCacheWithImage:(UIImage*)snapshot {
if (snapshot) {
[self.snapshotCache setImage:snapshot withSessionID:self.sessionID];
} else {
// Remove any stale snapshot since the snapshot failed.
[self.snapshotCache removeImageWithSessionID:self.sessionID];
}
[self.delegate snapshotGenerator:self
didUpdateSnapshotForWebState:self.webState
withImage:snapshot];
}
#pragma mark - Properties #pragma mark - Properties
- (SnapshotCache*)snapshotCache { - (SnapshotCache*)snapshotCache {
return SnapshotCacheFactory::GetForBrowserState( return SnapshotCacheFactory::GetForBrowserState(
ios::ChromeBrowserState::FromBrowserState(_webState->GetBrowserState())); ios::ChromeBrowserState::FromBrowserState(
self.webState->GetBrowserState()));
} }
#pragma mark - CRWWebStateObserver #pragma mark - CRWWebStateObserver
......
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