Commit c2d8756e authored by Yi Su's avatar Yi Su Committed by Commit Bot

Copy both the image's url and data to pasteboard when CopyImage.

Current CopyImage only copies the image data to pasteboard. Image's url
should also be copied, so that user can paste it to text field.

Bug: 883674
Cq-Include-Trybots: luci.chromium.try:ios-simulator-cronet;luci.chromium.try:ios-simulator-full-configs
Change-Id: I30c9bd1018a5a2e4564b9bc7a40d69be325a4235
Reviewed-on: https://chromium-review.googlesource.com/1228061
Commit-Queue: Yi Su <mrsuyi@chromium.org>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#592012}
parent 8566083c
......@@ -4,9 +4,13 @@
#import "image_copier.h"
#include <MobileCoreServices/MobileCoreServices.h>
#import "base/strings/sys_string_conversions.h"
#include "base/task/post_task.h"
#include "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
#import "ios/chrome/browser/ui/image_util/image_util.h"
#import "ios/chrome/browser/web/image_fetch_tab_helper.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ios/web/public/web_task_traits.h"
......@@ -61,7 +65,7 @@ const int kNoActiveCopy = 0;
- (void)copyImageAtURL:(const GURL&)url
referrer:(const web::Referrer&)referrer
webState:(web::WebState*)webState {
// Dismisses current alert.
// Dismiss current alert.
[self.alertCoordinator stop];
__weak ImageCopier* weakSelf = self;
......@@ -74,7 +78,7 @@ const int kNoActiveCopy = 0;
[self.alertCoordinator
addItemWithTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)
action:^() {
// Cancels current copy and closes the alert.
// Cancel current copy and closes the alert.
weakSelf.activeID = kNoActiveCopy;
[weakSelf.alertCoordinator stop];
}
......@@ -93,20 +97,27 @@ const int kNoActiveCopy = 0;
ImageFetchTabHelper* tabHelper = ImageFetchTabHelper::FromWebState(webState);
DCHECK(tabHelper);
NSString* urlStr = base::SysUTF8ToNSString(url.spec());
tabHelper->GetImageData(url, referrer, ^(NSData* data) {
// Checks that the copy has not been canceled.
// Check that the copy has not been canceled.
if (callbackID == weakSelf.activeID) {
UIImage* image = [UIImage imageWithData:data];
if (image) {
UIPasteboard.generalPasteboard.image = image;
}
NSMutableDictionary* item =
[NSMutableDictionary dictionaryWithCapacity:3];
[item setValue:urlStr forKey:(__bridge NSString*)kUTTypeText];
[item setValue:[NSURL URLWithString:urlStr]
forKey:(__bridge NSString*)kUTTypeURL];
NSString* uti = GetImageUTIFromData(data);
if (uti)
[item setValue:data forKey:uti];
UIPasteboard.generalPasteboard.items =
[NSMutableArray arrayWithObject:item];
// Finishes this copy.
weakSelf.activeID = kNoActiveCopy;
[weakSelf.alertCoordinator stop];
}
});
// Delays launching alert by |kAlertDelayInMs|.
// Delay launching alert by |kAlertDelayInMs|.
base::PostDelayedTaskWithTraits(
FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
// Checks that the copy has not finished yet.
......
......@@ -35,4 +35,8 @@ UIImage* StretchableImageNamed(NSString* name,
// is nil, empty, or cannot be recognized, nil will be returned.
NSString* GetImageExtensionFromData(NSData* data);
// Returns the UTI by checking the first byte of image |data|. If |data|
// is nil, empty, or cannot be recognized, nil will be returned.
NSString* GetImageUTIFromData(NSData* data);
#endif // IOS_CHROME_BROWSER_UI_IMAGE_UTIL_IMAGE_UTIL_H_
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <MobileCoreServices/MobileCoreServices.h>
#import <UIKit/UIKit.h>
#import "ios/chrome/browser/ui/image_util/image_util.h"
......@@ -13,6 +14,16 @@
#error "This file requires ARC support."
#endif
namespace {
NSString* kImageExtensionJPG = @"jpg";
NSString* kImageExtensionPNG = @"png";
NSString* kImageExtensionTIF = @"tif";
NSString* kImageExtensionBMP = @"bmp";
NSString* kImageExtensionGIF = @"gif";
NSString* kImageExtensionICO = @"ico";
NSString* kImageExtensionWebP = @"webp";
}
UIColor* DominantColorForImage(const gfx::Image& image, CGFloat opacity) {
SkColor color = color_utils::CalculateKMeanColorOfBitmap(*image.ToSkBitmap());
UIColor* result = [UIColor colorWithRed:SkColorGetR(color) / 255.0
......@@ -58,28 +69,41 @@ NSString* GetImageExtensionFromData(NSData* data) {
const char* pdata = static_cast<const char*>(data.bytes);
switch (pdata[0]) {
case '\xFF':
return strncmp(pdata, "\xFF\xD8\xFF", 3) ? nil : @"jpg";
return strncmp(pdata, "\xFF\xD8\xFF", 3) ? nil : kImageExtensionJPG;
case '\x89':
return strncmp(pdata, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) ? nil
: @"png";
return strncmp(pdata, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8)
? nil
: kImageExtensionPNG;
case 'G':
return (strncmp(pdata, "GIF87a", 6) && strncmp(pdata, "GIF89a", 6))
? nil
: @"gif";
: kImageExtensionGIF;
case '\x49':
return strncmp(pdata, "\x49\x49\x2A\x00", 4) ? nil : @"tif";
return strncmp(pdata, "\x49\x49\x2A\x00", 4) ? nil : kImageExtensionTIF;
case '\x4D':
return strncmp(pdata, "\x4D\x4D\x00\x2A", 4) ? nil : @"tif";
return strncmp(pdata, "\x4D\x4D\x00\x2A", 4) ? nil : kImageExtensionTIF;
case 'B':
return strncmp(pdata, "BM", 2) ? nil : @"bmp";
return strncmp(pdata, "BM", 2) ? nil : kImageExtensionBMP;
case 'R':
return (strncmp(pdata, "RIFF", 4) || strncmp(pdata + 8, "WEBP", 4))
? nil
: @"webp";
: kImageExtensionWebP;
case '\0':
return strncmp(pdata, "\x00\x00\x01\x00", 4) ? nil : @"ico";
return strncmp(pdata, "\x00\x00\x01\x00", 4) ? nil : kImageExtensionICO;
default:
return nil;
}
return nil;
}
NSString* GetImageUTIFromData(NSData* data) {
static NSDictionary* dict = @{
kImageExtensionJPG : (__bridge NSString*)kUTTypeJPEG,
kImageExtensionPNG : (__bridge NSString*)kUTTypePNG,
kImageExtensionGIF : (__bridge NSString*)kUTTypeGIF,
kImageExtensionTIF : (__bridge NSString*)kUTTypeTIFF,
kImageExtensionBMP : (__bridge NSString*)kUTTypeBMP,
kImageExtensionICO : (__bridge NSString*)kUTTypeICO
};
return dict[GetImageExtensionFromData(data)];
}
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