1// Copyright 2016 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/media/webrtc/window_icon_util.h" 6 7#import <Cocoa/Cocoa.h> 8 9#include "base/mac/foundation_util.h" 10#include "base/mac/scoped_cftyperef.h" 11#include "base/stl_util.h" 12#include "third_party/libyuv/include/libyuv/convert_argb.h" 13 14gfx::ImageSkia GetWindowIcon(content::DesktopMediaID id) { 15 DCHECK(id.type == content::DesktopMediaID::TYPE_WINDOW); 16 17 CGWindowID ids[1]; 18 ids[0] = id.id; 19 base::ScopedCFTypeRef<CFArrayRef> window_id_array(CFArrayCreate( 20 nullptr, reinterpret_cast<const void**>(&ids), base::size(ids), nullptr)); 21 base::ScopedCFTypeRef<CFArrayRef> window_array( 22 CGWindowListCreateDescriptionFromArray(window_id_array)); 23 if (!window_array || 0 == CFArrayGetCount(window_array)) { 24 return gfx::ImageSkia(); 25 } 26 27 CFDictionaryRef window = base::mac::CFCastStrict<CFDictionaryRef>( 28 CFArrayGetValueAtIndex(window_array, 0)); 29 CFNumberRef pid_ref = 30 base::mac::GetValueFromDictionary<CFNumberRef>(window, kCGWindowOwnerPID); 31 32 int pid; 33 CFNumberGetValue(pid_ref, kCFNumberIntType, &pid); 34 35 NSImage* icon_image = 36 [[NSRunningApplication runningApplicationWithProcessIdentifier:pid] icon]; 37 38 // Icon's NSImage defaults to the smallest which can be only 32x32. 39 NSRect proposed_rect = NSMakeRect(0, 0, 128, 128); 40 CGImageRef cg_icon_image = 41 [icon_image CGImageForProposedRect:&proposed_rect context:nil hints:nil]; 42 43 // 4 components of 8 bits each. 44 if (CGImageGetBitsPerPixel(cg_icon_image) != 32 || 45 CGImageGetBitsPerComponent(cg_icon_image) != 8) { 46 return gfx::ImageSkia(); 47 } 48 49 // Premultiplied alpha and last (alpha channel is next to the blue channel) 50 if (CGImageGetAlphaInfo(cg_icon_image) != kCGImageAlphaPremultipliedLast) { 51 return gfx::ImageSkia(); 52 } 53 54 // Ensure BGR like. 55 int byte_order = CGImageGetBitmapInfo(cg_icon_image) & kCGBitmapByteOrderMask; 56 if (byte_order != kCGBitmapByteOrderDefault && 57 byte_order != kCGBitmapByteOrder32Big) { 58 return gfx::ImageSkia(); 59 } 60 61 CGDataProviderRef provider = CGImageGetDataProvider(cg_icon_image); 62 base::ScopedCFTypeRef<CFDataRef> cf_data(CGDataProviderCopyData(provider)); 63 64 int width = CGImageGetWidth(cg_icon_image); 65 int height = CGImageGetHeight(cg_icon_image); 66 int src_stride = CGImageGetBytesPerRow(cg_icon_image); 67 const uint8_t* src_data = CFDataGetBytePtr(cf_data); 68 69 SkBitmap result; 70 result.allocN32Pixels(width, height, false /* no-premultiplied */); 71 72 uint8_t* pixels_data = reinterpret_cast<uint8_t*>(result.getPixels()); 73 74 libyuv::ABGRToARGB(src_data, src_stride, pixels_data, result.rowBytes(), 75 width, height); 76 77 return gfx::ImageSkia::CreateFrom1xBitmap(result); 78} 79