From 4c39eb32b0d2be479b9a0856186c6dfeccae6b96 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Wed, 2 Feb 2022 23:01:05 +0100 Subject: [PATCH] refactor: use QuickLookThumbnailing where applicable (#32456) --- BUILD.gn | 2 + .../api/electron_api_native_image_mac.mm | 103 +++++++++++++----- 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 3aa40b4855f8..7fe689d592bd 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -501,6 +501,8 @@ source_set("electron_lib") { "StoreKit.framework", ] + weak_frameworks = [ "QuickLookThumbnailing.framework" ] + sources += [ "shell/browser/ui/views/autofill_popup_view.cc", "shell/browser/ui/views/autofill_popup_view.h", diff --git a/shell/common/api/electron_api_native_image_mac.mm b/shell/common/api/electron_api_native_image_mac.mm index 68aacfdf28b2..60f3765a3def 100644 --- a/shell/common/api/electron_api_native_image_mac.mm +++ b/shell/common/api/electron_api_native_image_mac.mm @@ -10,8 +10,10 @@ #import #import +#import #include "base/mac/foundation_util.h" +#include "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "gin/arguments.h" #include "shell/common/gin_converters/image_converter.h" @@ -53,32 +55,81 @@ v8::Local NativeImage::CreateThumbnailFromPath( } CGSize cg_size = size.ToCGSize(); - base::ScopedCFTypeRef cfurl = base::mac::FilePathToCFURL(path); - base::ScopedCFTypeRef ql_thumbnail( - QLThumbnailCreate(kCFAllocatorDefault, cfurl, cg_size, NULL)); - __block gin_helper::Promise p = std::move(promise); - // we do not want to blocking the main thread while waiting for quicklook to - // generate the thumbnail - QLThumbnailDispatchAsync( - ql_thumbnail, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, /*flags*/ 0), ^{ - base::ScopedCFTypeRef cg_thumbnail( - QLThumbnailCopyImage(ql_thumbnail)); - if (cg_thumbnail) { - NSImage* result = - [[[NSImage alloc] initWithCGImage:cg_thumbnail - size:cg_size] autorelease]; - gfx::Image thumbnail(result); - dispatch_async(dispatch_get_main_queue(), ^{ - p.Resolve(thumbnail); - }); - } else { - dispatch_async(dispatch_get_main_queue(), ^{ - p.RejectWithErrorMessage("unable to retrieve thumbnail preview " - "image for the given path"); - }); - } - }); + + if (@available(macOS 10.15, *)) { + NSURL* nsurl = base::mac::FilePathToNSURL(path); + + // We need to explicitly check if the user has passed an invalid path + // because QLThumbnailGenerationRequest will generate a stock file icon + // and pass silently if we do not. + if (![[NSFileManager defaultManager] fileExistsAtPath:[nsurl path]]) { + promise.RejectWithErrorMessage( + "unable to retrieve thumbnail preview image for the given path"); + return handle; + } + + NSScreen* screen = [[NSScreen screens] firstObject]; + base::scoped_nsobject request( + [[QLThumbnailGenerationRequest alloc] + initWithFileAtURL:nsurl + size:cg_size + scale:[screen backingScaleFactor] + representationTypes: + QLThumbnailGenerationRequestRepresentationTypeAll]); + __block gin_helper::Promise p = std::move(promise); + [[QLThumbnailGenerator sharedGenerator] + generateBestRepresentationForRequest:request + completionHandler:^( + QLThumbnailRepresentation* thumbnail, + NSError* error) { + if (error || !thumbnail) { + std::string err_msg( + [error.localizedDescription UTF8String]); + dispatch_async(dispatch_get_main_queue(), ^{ + p.RejectWithErrorMessage( + "unable to retrieve thumbnail preview " + "image for the given path: " + + err_msg); + }); + } else { + NSImage* result = [[[NSImage alloc] + initWithCGImage:[thumbnail CGImage] + size:cg_size] autorelease]; + gfx::Image image(result); + dispatch_async(dispatch_get_main_queue(), ^{ + p.Resolve(image); + }); + } + }]; + } else { + base::ScopedCFTypeRef cfurl = base::mac::FilePathToCFURL(path); + base::ScopedCFTypeRef ql_thumbnail( + QLThumbnailCreate(kCFAllocatorDefault, cfurl, cg_size, NULL)); + __block gin_helper::Promise p = std::move(promise); + // Do not block the main thread waiting for quicklook to generate the + // thumbnail. + QLThumbnailDispatchAsync( + ql_thumbnail, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, /*flags*/ 0), ^{ + base::ScopedCFTypeRef cg_thumbnail( + QLThumbnailCopyImage(ql_thumbnail)); + if (cg_thumbnail) { + NSImage* result = + [[[NSImage alloc] initWithCGImage:cg_thumbnail + size:cg_size] autorelease]; + gfx::Image thumbnail(result); + dispatch_async(dispatch_get_main_queue(), ^{ + p.Resolve(thumbnail); + }); + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + p.RejectWithErrorMessage("unable to retrieve thumbnail preview " + "image for the given path"); + }); + } + }); + } + return handle; }