Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: chrome/browser/web_applications/web_app_mac.mm

Issue 2841433003: Do not touch ui::ResourceBundle on non-UI thread in web_app_mac.mm (Closed)
Patch Set: fix Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698