Chromium Code Reviews| 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 // This should match to the resource IDs used by SetWorkspaceIconOnFILEThread | |
| 393 // below. | |
| 394 int resource_ids[] = { | |
|
tapted
2017/05/01 08:43:45
nit: constexpr int kResourceIDs
or inline the arr
tzik
2017/05/02 17:58:36
Done. Inlined it into the loop.
| |
| 395 IDR_APPS_FOLDER_16, IDR_APPS_FOLDER_32, IDR_APPS_FOLDER_OVERLAY_128, | |
| 396 IDR_APPS_FOLDER_OVERLAY_512, | |
| 397 }; | |
| 398 | |
| 399 ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance(); | |
| 400 std::unique_ptr<ResourceIDToImage> result = | |
| 401 base::MakeUnique<ResourceIDToImage>(); | |
| 402 for (int id : resource_ids) | |
| 403 (*result)[id] = resource_bundle.GetNativeImageNamed(id); | |
| 404 return result; | |
| 405 } | |
| 406 | |
| 407 void SetWorkspaceIconOnFILEThread(const base::FilePath& apps_directory, | |
| 408 std::unique_ptr<ResourceIDToImage> images) { | |
| 409 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); | |
| 410 | |
| 411 base::scoped_nsobject<NSImage> folder_icon_image([[NSImage alloc] init]); | |
| 412 // Use complete assets for the small icon sizes. -[NSWorkspace setIcon:] has a | |
| 413 // bug when dealing with named NSImages where it incorrectly handles alpha | |
| 414 // premultiplication. This is most noticable with small assets since the 1px | |
| 415 // border is a much larger component of the small icons. | |
| 416 // See http://crbug.com/305373 for details. | |
| 417 auto found = images->find(IDR_APPS_FOLDER_16); | |
|
tapted
2017/05/01 08:43:45
for (int small_image_id : {IDR_APPS_FOLDER_16, IDR
tzik
2017/05/02 17:58:36
Done.
| |
| 418 DCHECK(found != images->end()); | |
| 419 [folder_icon_image addRepresentation:ImageRepForGFXImage(found->second)]; | |
| 420 | |
| 421 found = images->find(IDR_APPS_FOLDER_32); | |
| 422 DCHECK(found != images->end()); | |
| 423 [folder_icon_image addRepresentation:ImageRepForGFXImage(found->second)]; | |
| 424 | |
| 425 // Brand larger folder assets with an embossed app launcher logo to | |
| 426 // conserve distro size and for better consistency with changing hue | |
| 427 // across OSX versions. The folder is textured, so compresses poorly | |
| 428 // without this. | |
| 429 const int kBrandResourceIds[] = { | |
| 430 IDR_APPS_FOLDER_OVERLAY_128, IDR_APPS_FOLDER_OVERLAY_512, | |
| 431 }; | |
| 432 NSImage* base_image = [NSImage imageNamed:NSImageNameFolder]; | |
| 433 for (size_t i = 0; i < arraysize(kBrandResourceIds); ++i) { | |
|
tapted
2017/05/01 08:43:45
and I guess
for (int brand_image_id : {IDR_APPS
tzik
2017/05/02 17:58:36
Done.
| |
| 434 found = images->find(kBrandResourceIds[i]); | |
| 435 DCHECK(found != images->end()); | |
| 436 NSImageRep* with_overlay = | |
| 437 OverlayImageRep(base_image, ImageRepForGFXImage(found->second)); | |
| 438 DCHECK(with_overlay); | |
| 439 if (with_overlay) | |
| 440 [folder_icon_image addRepresentation:with_overlay]; | |
| 441 } | |
| 442 [[NSWorkspace sharedWorkspace] | |
| 443 setIcon:folder_icon_image | |
| 444 forFile:base::mac::FilePathToNSString(apps_directory) | |
| 445 options:0]; | |
| 446 | |
| 447 content::BrowserThread::DeleteSoon(content::BrowserThread::UI, FROM_HERE, | |
| 448 images.release()); | |
| 449 } | |
| 450 | |
| 384 // Adds a localized strings file for the Chrome Apps directory using the current | 451 // Adds a localized strings file for the Chrome Apps directory using the current |
| 385 // locale. OSX will use this for the display name. | 452 // locale. OSX will use this for the display name. |
| 386 // + Chrome Apps.localized (|apps_directory|) | 453 // + Chrome Apps.localized (|apps_directory|) |
| 387 // | + .localized | 454 // | + .localized |
| 388 // | | en.strings | 455 // | | en.strings |
| 389 // | | de.strings | 456 // | | de.strings |
| 390 void UpdateAppShortcutsSubdirLocalizedName( | 457 void UpdateAppShortcutsSubdirLocalizedName( |
| 391 const base::FilePath& apps_directory) { | 458 const base::FilePath& apps_directory) { |
| 392 base::FilePath localized = apps_directory.Append(".localized"); | 459 base::FilePath localized = apps_directory.Append(".localized"); |
| 393 if (!base::CreateDirectory(localized)) | 460 if (!base::CreateDirectory(localized)) |
| 394 return; | 461 return; |
| 395 | 462 |
| 396 base::FilePath directory_name = apps_directory.BaseName().RemoveExtension(); | 463 base::FilePath directory_name = apps_directory.BaseName().RemoveExtension(); |
| 397 base::string16 localized_name = | 464 base::string16 localized_name = |
| 398 shell_integration::GetAppShortcutsSubdirName(); | 465 shell_integration::GetAppShortcutsSubdirName(); |
| 399 NSDictionary* strings_dict = @{ | 466 NSDictionary* strings_dict = @{ |
| 400 base::mac::FilePathToNSString(directory_name) : | 467 base::mac::FilePathToNSString(directory_name) : |
| 401 base::SysUTF16ToNSString(localized_name) | 468 base::SysUTF16ToNSString(localized_name) |
| 402 }; | 469 }; |
| 403 | 470 |
| 404 std::string locale = l10n_util::NormalizeLocale( | 471 std::string locale = l10n_util::NormalizeLocale( |
| 405 l10n_util::GetApplicationLocale(std::string())); | 472 l10n_util::GetApplicationLocale(std::string())); |
| 406 | 473 |
| 407 NSString* strings_path = base::mac::FilePathToNSString( | 474 NSString* strings_path = base::mac::FilePathToNSString( |
| 408 localized.Append(locale + ".strings")); | 475 localized.Append(locale + ".strings")); |
| 409 [strings_dict writeToFile:strings_path | 476 [strings_dict writeToFile:strings_path |
| 410 atomically:YES]; | 477 atomically:YES]; |
| 411 | 478 |
| 412 base::scoped_nsobject<NSImage> folder_icon_image([[NSImage alloc] init]); | 479 content::BrowserThread::PostTaskAndReplyWithResult( |
| 413 | 480 content::BrowserThread::UI, FROM_HERE, |
| 414 // Use complete assets for the small icon sizes. -[NSWorkspace setIcon:] has a | 481 base::BindOnce(&GetImageResourcesOnUIThread), |
| 415 // bug when dealing with named NSImages where it incorrectly handles alpha | 482 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 } | 483 } |
| 442 | 484 |
| 443 void DeletePathAndParentIfEmpty(const base::FilePath& app_path) { | 485 void DeletePathAndParentIfEmpty(const base::FilePath& app_path) { |
| 444 DCHECK(!app_path.empty()); | 486 DCHECK(!app_path.empty()); |
| 445 base::DeleteFile(app_path, true); | 487 base::DeleteFile(app_path, true); |
| 446 base::FilePath apps_folder = app_path.DirName(); | 488 base::FilePath apps_folder = app_path.DirName(); |
| 447 if (base::IsDirectoryEmpty(apps_folder)) | 489 if (base::IsDirectoryEmpty(apps_folder)) |
| 448 base::DeleteFile(apps_folder, false); | 490 base::DeleteFile(apps_folder, false); |
| 449 } | 491 } |
| 450 | 492 |
| (...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1074 std::unique_ptr<web_app::ShortcutInfo> shortcut_info = | 1116 std::unique_ptr<web_app::ShortcutInfo> shortcut_info = |
| 1075 BuildShortcutInfoFromBundle(*it); | 1117 BuildShortcutInfoFromBundle(*it); |
| 1076 WebAppShortcutCreator shortcut_creator(it->DirName(), shortcut_info.get()); | 1118 WebAppShortcutCreator shortcut_creator(it->DirName(), shortcut_info.get()); |
| 1077 shortcut_creator.DeleteShortcuts(); | 1119 shortcut_creator.DeleteShortcuts(); |
| 1078 } | 1120 } |
| 1079 } | 1121 } |
| 1080 | 1122 |
| 1081 } // namespace internals | 1123 } // namespace internals |
| 1082 | 1124 |
| 1083 } // namespace web_app | 1125 } // namespace web_app |
| OLD | NEW |