| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "chrome/browser/web_applications/web_app_mac.h" | 5 #import "chrome/browser/web_applications/web_app_mac.h" |
| 6 | 6 |
| 7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <map> |
| 10 #include <utility> | 11 #include <utility> |
| 11 | 12 |
| 12 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 13 #include "base/files/file_enumerator.h" | 14 #include "base/files/file_enumerator.h" |
| 14 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 15 #include "base/files/scoped_temp_dir.h" | 16 #include "base/files/scoped_temp_dir.h" |
| 16 #include "base/mac/foundation_util.h" | 17 #include "base/mac/foundation_util.h" |
| 17 #import "base/mac/launch_services_util.h" | 18 #import "base/mac/launch_services_util.h" |
| 18 #include "base/mac/mac_util.h" | 19 #include "base/mac/mac_util.h" |
| 19 #include "base/mac/scoped_cftyperef.h" | 20 #include "base/mac/scoped_cftyperef.h" |
| 20 #include "base/mac/scoped_nsobject.h" | 21 #include "base/mac/scoped_nsobject.h" |
| 21 #include "base/macros.h" | 22 #include "base/macros.h" |
| 23 #include "base/memory/ptr_util.h" |
| 22 #include "base/memory/ref_counted.h" | 24 #include "base/memory/ref_counted.h" |
| 23 #include "base/metrics/histogram_macros.h" | 25 #include "base/metrics/histogram_macros.h" |
| 24 #include "base/path_service.h" | 26 #include "base/path_service.h" |
| 25 #include "base/process/process_handle.h" | 27 #include "base/process/process_handle.h" |
| 26 #include "base/strings/string16.h" | 28 #include "base/strings/string16.h" |
| 27 #include "base/strings/string_number_conversions.h" | 29 #include "base/strings/string_number_conversions.h" |
| 28 #include "base/strings/string_split.h" | 30 #include "base/strings/string_split.h" |
| 29 #include "base/strings/string_util.h" | 31 #include "base/strings/string_util.h" |
| 30 #include "base/strings/sys_string_conversions.h" | 32 #include "base/strings/sys_string_conversions.h" |
| 31 #include "base/strings/utf_string_conversions.h" | 33 #include "base/strings/utf_string_conversions.h" |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 operation:NSCompositeSourceOver | 368 operation:NSCompositeSourceOver |
| 367 fraction:1.0 | 369 fraction:1.0 |
| 368 respectFlipped:NO | 370 respectFlipped:NO |
| 369 hints:0]; | 371 hints:0]; |
| 370 [NSGraphicsContext restoreGraphicsState]; | 372 [NSGraphicsContext restoreGraphicsState]; |
| 371 return canvas.autorelease(); | 373 return canvas.autorelease(); |
| 372 } | 374 } |
| 373 | 375 |
| 374 // Helper function to extract the single NSImageRep held in a resource bundle | 376 // Helper function to extract the single NSImageRep held in a resource bundle |
| 375 // image. | 377 // image. |
| 376 NSImageRep* ImageRepForResource(int resource_id) { | 378 NSImageRep* ImageRepForGFXImage(const gfx::Image& image) { |
| 377 gfx::Image& image = | |
| 378 ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id); | |
| 379 NSArray* image_reps = [image.AsNSImage() representations]; | 379 NSArray* image_reps = [image.AsNSImage() representations]; |
| 380 DCHECK_EQ(1u, [image_reps count]); | 380 DCHECK_EQ(1u, [image_reps count]); |
| 381 return [image_reps objectAtIndex:0]; | 381 return [image_reps objectAtIndex:0]; |
| 382 } | 382 } |
| 383 | 383 |
| 384 using ResourceIDToImage = std::map<int, gfx::Image>; |
| 385 |
| 386 // Returns a map of gfx::Image used by SetWorkspaceIconOnFILEThread. |
| 387 // Since ui::ResourceBundle can be call only on UI thread, this function also |
| 388 // needs to run on UI thread. |
| 389 std::unique_ptr<ResourceIDToImage> GetImageResourcesOnUIThread() { |
| 390 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 391 |
| 392 ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance(); |
| 393 std::unique_ptr<ResourceIDToImage> result = |
| 394 base::MakeUnique<ResourceIDToImage>(); |
| 395 |
| 396 // These resource ID should match to the ones used by |
| 397 // SetWorkspaceIconOnFILEThread below. |
| 398 for (int id : {IDR_APPS_FOLDER_16, IDR_APPS_FOLDER_32, |
| 399 IDR_APPS_FOLDER_OVERLAY_128, IDR_APPS_FOLDER_OVERLAY_512}) |
| 400 (*result)[id] = resource_bundle.GetNativeImageNamed(id); |
| 401 return result; |
| 402 } |
| 403 |
| 404 void SetWorkspaceIconOnFILEThread(const base::FilePath& apps_directory, |
| 405 std::unique_ptr<ResourceIDToImage> images) { |
| 406 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); |
| 407 |
| 408 base::scoped_nsobject<NSImage> folder_icon_image([[NSImage alloc] init]); |
| 409 // Use complete assets for the small icon sizes. -[NSWorkspace setIcon:] has a |
| 410 // bug when dealing with named NSImages where it incorrectly handles alpha |
| 411 // premultiplication. This is most noticable with small assets since the 1px |
| 412 // border is a much larger component of the small icons. |
| 413 // See http://crbug.com/305373 for details. |
| 414 for (int id : {IDR_APPS_FOLDER_16, IDR_APPS_FOLDER_32}) { |
| 415 auto found = images->find(id); |
| 416 DCHECK(found != images->end()); |
| 417 [folder_icon_image addRepresentation:ImageRepForGFXImage(found->second)]; |
| 418 } |
| 419 |
| 420 // Brand larger folder assets with an embossed app launcher logo to |
| 421 // conserve distro size and for better consistency with changing hue |
| 422 // across OSX versions. The folder is textured, so compresses poorly |
| 423 // without this. |
| 424 NSImage* base_image = [NSImage imageNamed:NSImageNameFolder]; |
| 425 for (int id : {IDR_APPS_FOLDER_OVERLAY_128, IDR_APPS_FOLDER_OVERLAY_512}) { |
| 426 auto found = images->find(id); |
| 427 DCHECK(found != images->end()); |
| 428 NSImageRep* with_overlay = |
| 429 OverlayImageRep(base_image, ImageRepForGFXImage(found->second)); |
| 430 DCHECK(with_overlay); |
| 431 if (with_overlay) |
| 432 [folder_icon_image addRepresentation:with_overlay]; |
| 433 } |
| 434 [[NSWorkspace sharedWorkspace] |
| 435 setIcon:folder_icon_image |
| 436 forFile:base::mac::FilePathToNSString(apps_directory) |
| 437 options:0]; |
| 438 |
| 439 content::BrowserThread::DeleteSoon(content::BrowserThread::UI, FROM_HERE, |
| 440 images.release()); |
| 441 } |
| 442 |
| 384 // Adds a localized strings file for the Chrome Apps directory using the current | 443 // Adds a localized strings file for the Chrome Apps directory using the current |
| 385 // locale. OSX will use this for the display name. | 444 // locale. OSX will use this for the display name. |
| 386 // + Chrome Apps.localized (|apps_directory|) | 445 // + Chrome Apps.localized (|apps_directory|) |
| 387 // | + .localized | 446 // | + .localized |
| 388 // | | en.strings | 447 // | | en.strings |
| 389 // | | de.strings | 448 // | | de.strings |
| 390 void UpdateAppShortcutsSubdirLocalizedName( | 449 void UpdateAppShortcutsSubdirLocalizedName( |
| 391 const base::FilePath& apps_directory) { | 450 const base::FilePath& apps_directory) { |
| 392 base::FilePath localized = apps_directory.Append(".localized"); | 451 base::FilePath localized = apps_directory.Append(".localized"); |
| 393 if (!base::CreateDirectory(localized)) | 452 if (!base::CreateDirectory(localized)) |
| 394 return; | 453 return; |
| 395 | 454 |
| 396 base::FilePath directory_name = apps_directory.BaseName().RemoveExtension(); | 455 base::FilePath directory_name = apps_directory.BaseName().RemoveExtension(); |
| 397 base::string16 localized_name = | 456 base::string16 localized_name = |
| 398 shell_integration::GetAppShortcutsSubdirName(); | 457 shell_integration::GetAppShortcutsSubdirName(); |
| 399 NSDictionary* strings_dict = @{ | 458 NSDictionary* strings_dict = @{ |
| 400 base::mac::FilePathToNSString(directory_name) : | 459 base::mac::FilePathToNSString(directory_name) : |
| 401 base::SysUTF16ToNSString(localized_name) | 460 base::SysUTF16ToNSString(localized_name) |
| 402 }; | 461 }; |
| 403 | 462 |
| 404 std::string locale = l10n_util::NormalizeLocale( | 463 std::string locale = l10n_util::NormalizeLocale( |
| 405 l10n_util::GetApplicationLocale(std::string())); | 464 l10n_util::GetApplicationLocale(std::string())); |
| 406 | 465 |
| 407 NSString* strings_path = base::mac::FilePathToNSString( | 466 NSString* strings_path = base::mac::FilePathToNSString( |
| 408 localized.Append(locale + ".strings")); | 467 localized.Append(locale + ".strings")); |
| 409 [strings_dict writeToFile:strings_path | 468 [strings_dict writeToFile:strings_path |
| 410 atomically:YES]; | 469 atomically:YES]; |
| 411 | 470 |
| 412 base::scoped_nsobject<NSImage> folder_icon_image([[NSImage alloc] init]); | 471 content::BrowserThread::PostTaskAndReplyWithResult( |
| 413 | 472 content::BrowserThread::UI, FROM_HERE, |
| 414 // Use complete assets for the small icon sizes. -[NSWorkspace setIcon:] has a | 473 base::BindOnce(&GetImageResourcesOnUIThread), |
| 415 // bug when dealing with named NSImages where it incorrectly handles alpha | 474 base::BindOnce(&SetWorkspaceIconOnFILEThread, apps_directory)); |
| 416 // premultiplication. This is most noticable with small assets since the 1px | |
| 417 // border is a much larger component of the small icons. | |
| 418 // See http://crbug.com/305373 for details. | |
| 419 [folder_icon_image addRepresentation:ImageRepForResource(IDR_APPS_FOLDER_16)]; | |
| 420 [folder_icon_image addRepresentation:ImageRepForResource(IDR_APPS_FOLDER_32)]; | |
| 421 | |
| 422 // Brand larger folder assets with an embossed app launcher logo to conserve | |
| 423 // distro size and for better consistency with changing hue across OSX | |
| 424 // versions. The folder is textured, so compresses poorly without this. | |
| 425 const int kBrandResourceIds[] = { | |
| 426 IDR_APPS_FOLDER_OVERLAY_128, | |
| 427 IDR_APPS_FOLDER_OVERLAY_512, | |
| 428 }; | |
| 429 NSImage* base_image = [NSImage imageNamed:NSImageNameFolder]; | |
| 430 for (size_t i = 0; i < arraysize(kBrandResourceIds); ++i) { | |
| 431 NSImageRep* with_overlay = | |
| 432 OverlayImageRep(base_image, ImageRepForResource(kBrandResourceIds[i])); | |
| 433 DCHECK(with_overlay); | |
| 434 if (with_overlay) | |
| 435 [folder_icon_image addRepresentation:with_overlay]; | |
| 436 } | |
| 437 [[NSWorkspace sharedWorkspace] | |
| 438 setIcon:folder_icon_image | |
| 439 forFile:base::mac::FilePathToNSString(apps_directory) | |
| 440 options:0]; | |
| 441 } | 475 } |
| 442 | 476 |
| 443 void DeletePathAndParentIfEmpty(const base::FilePath& app_path) { | 477 void DeletePathAndParentIfEmpty(const base::FilePath& app_path) { |
| 444 DCHECK(!app_path.empty()); | 478 DCHECK(!app_path.empty()); |
| 445 base::DeleteFile(app_path, true); | 479 base::DeleteFile(app_path, true); |
| 446 base::FilePath apps_folder = app_path.DirName(); | 480 base::FilePath apps_folder = app_path.DirName(); |
| 447 if (base::IsDirectoryEmpty(apps_folder)) | 481 if (base::IsDirectoryEmpty(apps_folder)) |
| 448 base::DeleteFile(apps_folder, false); | 482 base::DeleteFile(apps_folder, false); |
| 449 } | 483 } |
| 450 | 484 |
| (...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1074 std::unique_ptr<web_app::ShortcutInfo> shortcut_info = | 1108 std::unique_ptr<web_app::ShortcutInfo> shortcut_info = |
| 1075 BuildShortcutInfoFromBundle(*it); | 1109 BuildShortcutInfoFromBundle(*it); |
| 1076 WebAppShortcutCreator shortcut_creator(it->DirName(), shortcut_info.get()); | 1110 WebAppShortcutCreator shortcut_creator(it->DirName(), shortcut_info.get()); |
| 1077 shortcut_creator.DeleteShortcuts(); | 1111 shortcut_creator.DeleteShortcuts(); |
| 1078 } | 1112 } |
| 1079 } | 1113 } |
| 1080 | 1114 |
| 1081 } // namespace internals | 1115 } // namespace internals |
| 1082 | 1116 |
| 1083 } // namespace web_app | 1117 } // namespace web_app |
| OLD | NEW |