Commit ef9515a6 authored by Robbie Gibson's avatar Robbie Gibson Committed by Commit Bot

[iOS] Use new clipboard recent content async apis in Today widget

The new async APIs don't get the actual clipboard content when checking
if the clipboard contains a url/image. This prevents them from
triggering the new iOS 14 pasteboard access notification at bad times.

Bug: 1110845
Change-Id: I8aa3989dae03999a319dc937f23432cff1f9ad81
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2325173Reviewed-by: default avatarOlivier Robin <olivierrobin@chromium.org>
Commit-Queue: Robbie Gibson <rkgibson@google.com>
Cr-Commit-Position: refs/heads/master@{#793547}
parent 3d90f272
...@@ -30,8 +30,7 @@ typedef NS_ENUM(NSInteger, CopiedContentType) { ...@@ -30,8 +30,7 @@ typedef NS_ENUM(NSInteger, CopiedContentType) {
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
- (void)setCopiedContentType:(CopiedContentType)type - (void)setCopiedContentType:(CopiedContentType)type;
copiedText:(NSString*)copiedText;
@end @end
......
...@@ -24,8 +24,6 @@ const CGFloat kURLButtonMargin = 10; ...@@ -24,8 +24,6 @@ const CGFloat kURLButtonMargin = 10;
// The type of the copied content // The type of the copied content
@property(nonatomic) CopiedContentType type; @property(nonatomic) CopiedContentType type;
// The copied text to be displayed if the type supports showing the string.
@property(nonatomic, copy) NSString* copiedText;
// The copied URL label containing the URL or a placeholder text. // The copied URL label containing the URL or a placeholder text.
@property(nonatomic, strong) UILabel* copiedContentLabel; @property(nonatomic, strong) UILabel* copiedContentLabel;
// The copied URL title label containing the title of the copied URL button. // The copied URL title label containing the title of the copied URL button.
...@@ -38,7 +36,7 @@ const CGFloat kURLButtonMargin = 10; ...@@ -38,7 +36,7 @@ const CGFloat kURLButtonMargin = 10;
@property(nonatomic, strong) UIVisualEffectView* primaryEffectView; @property(nonatomic, strong) UIVisualEffectView* primaryEffectView;
@property(nonatomic, strong) UIVisualEffectView* secondaryEffectView; @property(nonatomic, strong) UIVisualEffectView* secondaryEffectView;
// Updates the view to show the currently set |type| and |copiedText|. // Updates the view to show the currently set |type|.
- (void)updateUI; - (void)updateUI;
@end @end
...@@ -173,7 +171,7 @@ const CGFloat kURLButtonMargin = 10; ...@@ -173,7 +171,7 @@ const CGFloat kURLButtonMargin = 10;
[_copiedContentLabel.trailingAnchor [_copiedContentLabel.trailingAnchor
constraintEqualToAnchor:_openCopiedContentTitleLabel.trailingAnchor], constraintEqualToAnchor:_openCopiedContentTitleLabel.trailingAnchor],
]]; ]];
[self setCopiedContentType:CopiedContentTypeNone copiedText:nil]; [self setCopiedContentType:CopiedContentTypeNone];
self.highlightableViews = @[ self.highlightableViews = @[
_hairlineView, _copiedButtonView, _openCopiedContentTitleLabel, _hairlineView, _copiedButtonView, _openCopiedContentTitleLabel,
_copiedContentLabel _copiedContentLabel
...@@ -182,10 +180,8 @@ const CGFloat kURLButtonMargin = 10; ...@@ -182,10 +180,8 @@ const CGFloat kURLButtonMargin = 10;
return self; return self;
} }
- (void)setCopiedContentType:(CopiedContentType)type - (void)setCopiedContentType:(CopiedContentType)type {
copiedText:(NSString*)copiedText {
self.type = type; self.type = type;
self.copiedText = copiedText;
[self updateUI]; [self updateUI];
} }
...@@ -224,12 +220,10 @@ const CGFloat kURLButtonMargin = 10; ...@@ -224,12 +220,10 @@ const CGFloat kURLButtonMargin = 10;
} }
case CopiedContentTypeURL: { case CopiedContentTypeURL: {
titleText = NSLocalizedString(@"IDS_IOS_OPEN_COPIED_LINK", nil); titleText = NSLocalizedString(@"IDS_IOS_OPEN_COPIED_LINK", nil);
contentText = self.copiedText;
break; break;
} }
case CopiedContentTypeString: { case CopiedContentTypeString: {
titleText = NSLocalizedString(@"IDS_IOS_OPEN_COPIED_TEXT", nil); titleText = NSLocalizedString(@"IDS_IOS_OPEN_COPIED_TEXT", nil);
contentText = self.copiedText;
break; break;
} }
case CopiedContentTypeImage: { case CopiedContentTypeImage: {
......
...@@ -44,10 +44,8 @@ typedef NS_ENUM(NSInteger, CopiedContentType); ...@@ -44,10 +44,8 @@ typedef NS_ENUM(NSInteger, CopiedContentType);
// Gets the height of the widget. // Gets the height of the widget.
- (CGFloat)widgetHeight; - (CGFloat)widgetHeight;
// Sets the copied content type. |copiedText| should be provided if the content // Sets the copied content type.
// type requires textual data, otherwise it should be nil. - (void)setCopiedContentType:(CopiedContentType)type;
- (void)setCopiedContentType:(CopiedContentType)type
copiedText:(NSString*)copiedText;
@end @end
......
...@@ -210,9 +210,8 @@ const CGFloat kMaxContentSize = 421; ...@@ -210,9 +210,8 @@ const CGFloat kMaxContentSize = 421;
return [self actionContentHeight] + [self copiedURLSectionHeight]; return [self actionContentHeight] + [self copiedURLSectionHeight];
} }
- (void)setCopiedContentType:(CopiedContentType)type - (void)setCopiedContentType:(CopiedContentType)type {
copiedText:(NSString*)copiedText { [self.copiedURLSection setCopiedContentType:type];
[self.copiedURLSection setCopiedContentType:type copiedText:copiedText];
} }
@end @end
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
@interface SearchWidgetViewController ()<SearchWidgetViewActionTarget> @interface SearchWidgetViewController ()<SearchWidgetViewActionTarget>
@property(nonatomic, weak) SearchWidgetView* widgetView; @property(nonatomic, weak) SearchWidgetView* widgetView;
@property(nonatomic, strong, nullable) NSString* copiedText;
@property(nonatomic, strong, nullable) UIImage* copiedImage;
@property(nonatomic) CopiedContentType copiedContentType; @property(nonatomic) CopiedContentType copiedContentType;
@property(nonatomic, strong) @property(nonatomic, strong)
ClipboardRecentContentImplIOS* clipboardRecentContent; ClipboardRecentContentImplIOS* clipboardRecentContent;
...@@ -96,13 +94,26 @@ ...@@ -96,13 +94,26 @@
- (void)widgetPerformUpdateWithCompletionHandler: - (void)widgetPerformUpdateWithCompletionHandler:
(void (^)(NCUpdateResult))completionHandler { (void (^)(NCUpdateResult))completionHandler {
completionHandler([self updateWidget] ? NCUpdateResultNewData [self updateWidgetWithCompletionHandler:^(BOOL updates) {
: NCUpdateResultNoData); completionHandler(updates ? NCUpdateResultNewData : NCUpdateResultNoData);
}];
}
- (void)updateWidget {
[self updateWidgetWithCompletionHandler:^(BOOL updates) {
if (updates && self.extensionContext.widgetActiveDisplayMode ==
NCWidgetDisplayModeExpanded) {
CGSize maxSize = [self.extensionContext
widgetMaximumSizeForDisplayMode:NCWidgetDisplayModeExpanded];
self.preferredContentSize =
CGSizeMake(maxSize.width, [self.widgetView widgetHeight]);
}
}];
} }
// Updates the widget with latest data from the clipboard. Returns whether any // Updates the widget with latest data from the clipboard. Calls completion
// visual updates occurred. // handler with whether any updates occured..
- (BOOL)updateWidget { - (void)updateWidgetWithCompletionHandler:(void (^)(BOOL))completionHandler {
NSUserDefaults* sharedDefaults = app_group::GetGroupUserDefaults(); NSUserDefaults* sharedDefaults = app_group::GetGroupUserDefaults();
NSString* fieldTrialKey = NSString* fieldTrialKey =
base::SysUTF8ToNSString(app_group::kChromeExtensionFieldTrialPreference); base::SysUTF8ToNSString(app_group::kChromeExtensionFieldTrialPreference);
...@@ -113,35 +124,25 @@ ...@@ -113,35 +124,25 @@
self.supportsSearchByImage = self.supportsSearchByImage =
[sharedDefaults boolForKey:supportsSearchByImageKey]; [sharedDefaults boolForKey:supportsSearchByImageKey];
NSString* copiedText; NSSet* wantedTypes = [NSSet
UIImage* copiedImage; setWithArray:@[ ContentTypeURL, ContentTypeText, ContentTypeImage ]];
CopiedContentType type = CopiedContentTypeNone;
[self.clipboardRecentContent
if (UIImage* image = [self getCopiedImageFromClipboard]) { hasContentMatchingTypes:wantedTypes
copiedImage = image; completionHandler:^(NSSet<ContentType>* matchedTypes) {
type = CopiedContentTypeImage; CopiedContentType newType = CopiedContentTypeNone;
} else if (NSURL* url = if (self.supportsSearchByImage &&
[self.clipboardRecentContent recentURLFromClipboard]) { [matchedTypes containsObject:ContentTypeImage]) {
copiedText = url.absoluteString; newType = CopiedContentTypeImage;
type = CopiedContentTypeURL; } else if ([matchedTypes containsObject:ContentTypeURL]) {
} else if (NSString* text = newType = CopiedContentTypeURL;
[self.clipboardRecentContent recentTextFromClipboard]) { } else if ([matchedTypes containsObject:ContentTypeText]) {
copiedText = text; newType = CopiedContentTypeString;
type = CopiedContentTypeString;
}
return [self setCopiedContentType:type
copiedText:copiedText
copiedImage:copiedImage];
}
// Helper method to encapsulate checking whether the current search engine
// supports search-by-image and getting the copied image.
- (UIImage*)getCopiedImageFromClipboard {
if (!self.supportsSearchByImage) {
return nil;
} }
return [self.clipboardRecentContent recentImageFromClipboard]; dispatch_async(dispatch_get_main_queue(), ^{
completionHandler([self updateCopiedContentType:newType]);
});
}];
} }
- (void)viewWillTransitionToSize:(CGSize)size - (void)viewWillTransitionToSize:(CGSize)size
...@@ -201,25 +202,47 @@ ...@@ -201,25 +202,47 @@
} }
- (void)openCopiedContent:(id)sender { - (void)openCopiedContent:(id)sender {
DCHECK([self verifyCopiedContentType]);
switch (self.copiedContentType) { switch (self.copiedContentType) {
case CopiedContentTypeURL: case CopiedContentTypeURL: {
[self.command prepareToOpenURL:[NSURL URLWithString:self.copiedText]]; [self.clipboardRecentContent
recentURLFromClipboardAsync:^(NSURL* copiedURL) {
if (!copiedURL) {
return;
}
[self.command prepareToOpenURL:copiedURL];
[self.command executeInApp];
}];
break; break;
case CopiedContentTypeString: }
[self.command prepareToSearchText:self.copiedText]; case CopiedContentTypeString: {
[self.clipboardRecentContent
recentTextFromClipboardAsync:^(NSString* copiedText) {
if (!copiedText) {
return;
}
[self.command prepareToSearchText:copiedText];
[self.command executeInApp];
}];
break; break;
}
case CopiedContentTypeImage: { case CopiedContentTypeImage: {
// Resize image before converting to NSData so we can store less data. [self.clipboardRecentContent
UIImage* resizedImage = ResizeImageForSearchByImage(self.copiedImage); recentImageFromClipboardAsync:^(UIImage* copiedImage) {
if (!copiedImage) {
return;
}
// Resize image before converting to NSData so we can store less
// data.
UIImage* resizedImage = ResizeImageForSearchByImage(copiedImage);
[self.command prepareToSearchImage:resizedImage]; [self.command prepareToSearchImage:resizedImage];
[self.command executeInApp];
}];
break; break;
} }
case CopiedContentTypeNone: case CopiedContentTypeNone:
NOTREACHED(); NOTREACHED();
return; return;
} }
[self.command executeInApp];
} }
#pragma mark - internal #pragma mark - internal
...@@ -241,38 +264,15 @@ ...@@ -241,38 +264,15 @@
forKey:app_group::kSearchExtensionDisplayCount]; forKey:app_group::kSearchExtensionDisplayCount];
} }
// Sets the copied content type. |copiedText| should be provided if the content // Sets the copied content type returns YES if the screen needs updating and NO
// type requires textual data, otherwise it should be nil. Likewise, // otherwise. This must only be called on the main thread.
// |copiedImage| should be provided if the content type requires image data. - (BOOL)updateCopiedContentType:(CopiedContentType)type {
// Also saves the data and returns YES if the screen needs updating and NO if (self.copiedContentType == type) {
// otherwise.
- (BOOL)setCopiedContentType:(CopiedContentType)type
copiedText:(NSString*)copiedText
copiedImage:(UIImage*)copiedImage {
if (self.copiedContentType == type &&
[self.copiedText isEqualToString:copiedText] &&
[self.copiedImage isEqual:copiedImage]) {
return NO; return NO;
} }
self.copiedContentType = type; self.copiedContentType = type;
self.copiedText = copiedText; [self.widgetView setCopiedContentType:self.copiedContentType];
self.copiedImage = copiedImage;
[self.widgetView setCopiedContentType:self.copiedContentType
copiedText:self.copiedText];
return YES; return YES;
} }
// Verifies that the current copied content type has the required data with it.
- (BOOL)verifyCopiedContentType {
switch (self.copiedContentType) {
case CopiedContentTypeString:
case CopiedContentTypeURL:
return self.copiedText;
case CopiedContentTypeImage:
return self.copiedImage;
case CopiedContentTypeNone:
return true;
}
}
@end @end
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