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

Side by Side Diff: chrome/browser/profiles/profile_shortcut_manager_win.cc

Issue 14137032: Create profile .ico file on profile creation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rework Created 7 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
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 #include "chrome/browser/profiles/profile_shortcut_manager_win.h" 5 #include "chrome/browser/profiles/profile_shortcut_manager_win.h"
6 6
7 #include <shlobj.h> // For SHChangeNotify(). 7 #include <shlobj.h> // For SHChangeNotify().
8 8
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
(...skipping 26 matching lines...) Expand all
37 #include "ui/gfx/icon_util.h" 37 #include "ui/gfx/icon_util.h"
38 #include "ui/gfx/image/image.h" 38 #include "ui/gfx/image/image.h"
39 #include "ui/gfx/image/image_family.h" 39 #include "ui/gfx/image/image_family.h"
40 #include "ui/gfx/rect.h" 40 #include "ui/gfx/rect.h"
41 #include "ui/gfx/skia_util.h" 41 #include "ui/gfx/skia_util.h"
42 42
43 using content::BrowserThread; 43 using content::BrowserThread;
44 44
45 namespace { 45 namespace {
46 46
47 // Name of the badged icon file generated for a given profile.
48 const char kProfileIconFileName[] = "Google Profile.ico";
49
47 // Characters that are not allowed in Windows filenames. Taken from 50 // Characters that are not allowed in Windows filenames. Taken from
48 // http://msdn.microsoft.com/en-us/library/aa365247.aspx 51 // http://msdn.microsoft.com/en-us/library/aa365247.aspx
49 const char16 kReservedCharacters[] = L"<>:\"/\\|?*\x01\x02\x03\x04\x05\x06\x07" 52 const char16 kReservedCharacters[] = L"<>:\"/\\|?*\x01\x02\x03\x04\x05\x06\x07"
50 L"\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19" 53 L"\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19"
51 L"\x1A\x1B\x1C\x1D\x1E\x1F"; 54 L"\x1A\x1B\x1C\x1D\x1E\x1F";
52 55
53 // The maximum number of characters allowed in profile shortcuts' file names. 56 // The maximum number of characters allowed in profile shortcuts' file names.
54 // Warning: migration code will be needed if this is changed later, since 57 // Warning: migration code will be needed if this is changed later, since
55 // existing shortcuts might no longer be found if the name is generated 58 // existing shortcuts might no longer be found if the name is generated
56 // differently than it was when a shortcut was originally created. 59 // differently than it was when a shortcut was originally created.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 const SkBitmap& badged_bitmap = 135 const SkBitmap& badged_bitmap =
133 offscreen_canvas->getDevice()->accessBitmap(false); 136 offscreen_canvas->getDevice()->accessBitmap(false);
134 SkBitmap badged_bitmap_copy; 137 SkBitmap badged_bitmap_copy;
135 badged_bitmap.deepCopyTo(&badged_bitmap_copy, badged_bitmap.getConfig()); 138 badged_bitmap.deepCopyTo(&badged_bitmap_copy, badged_bitmap.getConfig());
136 return badged_bitmap_copy; 139 return badged_bitmap_copy;
137 } 140 }
138 141
139 // Creates a desktop shortcut icon file (.ico) on the disk for a given profile, 142 // Creates a desktop shortcut icon file (.ico) on the disk for a given profile,
140 // badging the browser distribution icon with the profile avatar. 143 // badging the browser distribution icon with the profile avatar.
141 // Returns a path to the shortcut icon file on disk, which is empty if this 144 // Returns a path to the shortcut icon file on disk, which is empty if this
142 // fails. Use index 0 when assigning the resulting file as the icon. 145 // fails. Use index 0 when assigning the resulting file as the icon. If both
143 base::FilePath CreateChromeDesktopShortcutIconForProfile( 146 // given bitmaps are empty, an unbadged icon is created.
147 // |is_create| should be true if we are creating the icon at a time when it
148 // is not possibly already in use. If it is false, we will refresh the Windows
149 // icon cache.
150 // TODO(calamity): Ideally we'd just copy the app icon verbatim from the exe's
151 // resources in the case of an unbadged icon.
152 base::FilePath CreateOrUpdateShortcutIconForProfile(
144 const base::FilePath& profile_path, 153 const base::FilePath& profile_path,
145 const SkBitmap& avatar_bitmap_1x, 154 const SkBitmap& avatar_bitmap_1x,
146 const SkBitmap& avatar_bitmap_2x) { 155 const SkBitmap& avatar_bitmap_2x,
156 bool is_icon_create) {
Alexei Svitkine (slow) 2013/05/24 14:43:51 Instead of passing this parameter, can this just c
calamity 2013/05/31 04:07:27 Done.
147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
148 scoped_ptr<SkBitmap> app_icon_bitmap(GetAppIconForSize(kShortcutIconSize)); 158 scoped_ptr<SkBitmap> app_icon_bitmap(GetAppIconForSize(kShortcutIconSize));
149 if (!app_icon_bitmap) 159 if (!app_icon_bitmap)
150 return base::FilePath(); 160 return base::FilePath();
151 161
152 gfx::ImageFamily badged_bitmaps; 162 gfx::ImageFamily badged_bitmaps;
153 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap( 163 if (!avatar_bitmap_1x.empty()) {
154 BadgeIcon(*app_icon_bitmap, avatar_bitmap_1x, 1)));
155
156 app_icon_bitmap = GetAppIconForSize(IconUtil::kLargeIconSize);
157 if (app_icon_bitmap) {
158 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap( 164 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(
159 BadgeIcon(*app_icon_bitmap, avatar_bitmap_2x, 2))); 165 BadgeIcon(*app_icon_bitmap, avatar_bitmap_1x, 1)));
160 } 166 }
161 167
168 scoped_ptr<SkBitmap> large_app_icon_bitmap(
169 GetAppIconForSize(IconUtil::kLargeIconSize));
170 if (large_app_icon_bitmap && !avatar_bitmap_2x.empty()) {
171 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(
172 BadgeIcon(*large_app_icon_bitmap, avatar_bitmap_2x, 2)));
173 }
174
175 // If we have no badged bitmaps, we should just use the default chrome icon.
176 if (badged_bitmaps.empty()) {
177 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(*app_icon_bitmap));
178 if (large_app_icon_bitmap) {
179 badged_bitmaps.Add(
180 gfx::Image::CreateFrom1xBitmap(*large_app_icon_bitmap));
181 }
182 }
162 // Finally, write the .ico file containing this new bitmap. 183 // Finally, write the .ico file containing this new bitmap.
163 const base::FilePath icon_path = 184 const base::FilePath icon_path =
164 profile_path.AppendASCII(profiles::internal::kProfileIconFileName); 185 profiles::internal::GetProfileIconPath(profile_path);
165 if (!IconUtil::CreateIconFileFromImageFamily(badged_bitmaps, icon_path)) 186
187 if (!IconUtil::CreateIconFileFromImageFamily(badged_bitmaps, icon_path)) {
188 NOTREACHED();
166 return base::FilePath(); 189 return base::FilePath();
190 }
167 191
192 if (is_icon_create) {
193 SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, icon_path.value().c_str(), NULL);
194 } else {
195 // This invalidates the Windows icon cache and causes the icon changes to
196 // register with the taskbar and desktop.
197 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT,
198 NULL, NULL);
199 }
168 return icon_path; 200 return icon_path;
169 } 201 }
170 202
171 // Gets the user and system directories for desktop shortcuts. Parameters may 203 // Gets the user and system directories for desktop shortcuts. Parameters may
172 // be NULL if a directory type is not needed. Returns true on success. 204 // be NULL if a directory type is not needed. Returns true on success.
173 bool GetDesktopShortcutsDirectories( 205 bool GetDesktopShortcutsDirectories(
174 base::FilePath* user_shortcuts_directory, 206 base::FilePath* user_shortcuts_directory,
175 base::FilePath* system_shortcuts_directory) { 207 base::FilePath* system_shortcuts_directory) {
176 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); 208 BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
177 if (user_shortcuts_directory && 209 if (user_shortcuts_directory &&
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 if (file_util::PathExists(possible_new_system_shortcut)) 324 if (file_util::PathExists(possible_new_system_shortcut))
293 file_util::Delete(old_shortcut_path, false); 325 file_util::Delete(old_shortcut_path, false);
294 else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path)) 326 else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path))
295 DLOG(ERROR) << "Could not rename Windows profile desktop shortcut."; 327 DLOG(ERROR) << "Could not rename Windows profile desktop shortcut.";
296 } else { 328 } else {
297 // If the shortcut does not exist, it may have been renamed by the user. In 329 // If the shortcut does not exist, it may have been renamed by the user. In
298 // that case, its name should not be changed. 330 // that case, its name should not be changed.
299 // It's also possible that a system-level shortcut exists instead - this 331 // It's also possible that a system-level shortcut exists instead - this
300 // should only be the case for the original Chrome shortcut from an 332 // should only be the case for the original Chrome shortcut from an
301 // installation. If that's the case, copy that one over - it will get its 333 // installation. If that's the case, copy that one over - it will get its
302 // properties updated by |CreateOrUpdateDesktopShortcutsForProfile()|. 334 // properties updated by
335 // |CreateOrUpdateDesktopShortcutsAndIconForProfile()|.
303 const base::FilePath possible_old_system_shortcut = 336 const base::FilePath possible_old_system_shortcut =
304 system_shortcuts_directory.Append(old_shortcut_filename); 337 system_shortcuts_directory.Append(old_shortcut_filename);
305 if (file_util::PathExists(possible_old_system_shortcut)) 338 if (file_util::PathExists(possible_old_system_shortcut))
306 file_util::CopyFile(possible_old_system_shortcut, new_shortcut_path); 339 file_util::CopyFile(possible_old_system_shortcut, new_shortcut_path);
307 } 340 }
308 } 341 }
309 342
343 struct CreateOrUpdateShortcutsParams {
344 CreateOrUpdateShortcutsParams() {}
345 ~CreateOrUpdateShortcutsParams() {}
346
347 base::FilePath profile_path;
348 string16 old_profile_name;
349 string16 profile_name;
350 SkBitmap avatar_image_1x;
351 SkBitmap avatar_image_2x;
352 ProfileShortcutManagerWin::CreateOrUpdateMode create_mode;
353 ProfileShortcutManagerWin::NonProfileShortcutAction action;
354 bool is_icon_create;
355 };
356
310 // Updates all desktop shortcuts for the given profile to have the specified 357 // Updates all desktop shortcuts for the given profile to have the specified
311 // parameters. If |create_mode| is CREATE_WHEN_NONE_FOUND, a new shortcut is 358 // parameters. If |create_mode| is CREATE_WHEN_NONE_FOUND, a new shortcut is
312 // created if no existing ones were found. Whether non-profile shortcuts should 359 // created if no existing ones were found. Whether non-profile shortcuts should
313 // be updated is specified by |action|. Must be called on the FILE thread. 360 // be updated is specified by |action|. Must be called on the FILE thread.
314 void CreateOrUpdateDesktopShortcutsForProfile( 361 void CreateOrUpdateDesktopShortcutsAndIconForProfile(
315 const base::FilePath& profile_path, 362 const CreateOrUpdateShortcutsParams& params) {
316 const string16& old_profile_name,
317 const string16& profile_name,
318 const SkBitmap& avatar_image_1x,
319 const SkBitmap& avatar_image_2x,
320 ProfileShortcutManagerWin::CreateOrUpdateMode create_mode,
321 ProfileShortcutManagerWin::NonProfileShortcutAction action) {
322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
323 364
365 base::FilePath shortcut_icon =
366 CreateOrUpdateShortcutIconForProfile(params.profile_path,
367 params.avatar_image_1x,
368 params.avatar_image_2x,
369 params.is_icon_create);
370 if (shortcut_icon.empty()) {
371 NOTREACHED();
372 return;
373 }
374 if (params.create_mode == ProfileShortcutManagerWin::CREATE_ICON_ONLY)
375 return;
376
324 base::FilePath chrome_exe; 377 base::FilePath chrome_exe;
325 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 378 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
326 NOTREACHED(); 379 NOTREACHED();
327 return; 380 return;
328 } 381 }
329 382
330 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); 383 BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
331 // Ensure that the distribution supports creating shortcuts. If it doesn't, 384 // Ensure that the distribution supports creating shortcuts. If it doesn't,
332 // the following code may result in NOTREACHED() being hit. 385 // the following code may result in NOTREACHED() being hit.
333 DCHECK(distribution->CanCreateDesktopShortcuts()); 386 DCHECK(distribution->CanCreateDesktopShortcuts());
334 387
335 if (old_profile_name != profile_name) { 388 if (params.old_profile_name != params.profile_name) {
336 const string16 old_shortcut_filename = 389 const string16 old_shortcut_filename =
337 profiles::internal::GetShortcutFilenameForProfile(old_profile_name, 390 profiles::internal::GetShortcutFilenameForProfile(
338 distribution); 391 params.old_profile_name,
392 distribution);
339 const string16 new_shortcut_filename = 393 const string16 new_shortcut_filename =
340 profiles::internal::GetShortcutFilenameForProfile(profile_name, 394 profiles::internal::GetShortcutFilenameForProfile(params.profile_name,
341 distribution); 395 distribution);
342 RenameChromeDesktopShortcutForProfile(old_shortcut_filename, 396 RenameChromeDesktopShortcutForProfile(old_shortcut_filename,
343 new_shortcut_filename); 397 new_shortcut_filename);
344 } 398 }
345 399
346 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); 400 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
347 installer::Product product(distribution); 401 installer::Product product(distribution);
348 product.AddDefaultShortcutProperties(chrome_exe, &properties); 402 product.AddDefaultShortcutProperties(chrome_exe, &properties);
349 403
350 const string16 command_line = 404 const string16 command_line =
351 profiles::internal::CreateProfileShortcutFlags(profile_path); 405 profiles::internal::CreateProfileShortcutFlags(params.profile_path);
352 406
353 // Only set the profile-specific properties when |profile_name| is non empty. 407 // Only set the profile-specific properties when |profile_name| is non empty.
354 // If it is empty, it means the shortcut being created should be a regular, 408 // If it is empty, it means the shortcut being created should be a regular,
355 // non-profile Chrome shortcut. 409 // non-profile Chrome shortcut.
356 if (!profile_name.empty()) { 410 if (!params.profile_name.empty()) {
357 const base::FilePath shortcut_icon =
358 CreateChromeDesktopShortcutIconForProfile(profile_path,
359 avatar_image_1x,
360 avatar_image_2x);
361 if (!shortcut_icon.empty()) 411 if (!shortcut_icon.empty())
362 properties.set_icon(shortcut_icon, 0); 412 properties.set_icon(shortcut_icon, 0);
363 properties.set_arguments(command_line); 413 properties.set_arguments(command_line);
364 } else { 414 } else {
365 // Set the arguments explicitly to the empty string to ensure that 415 // Set the arguments explicitly to the empty string to ensure that
366 // |ShellUtil::CreateOrUpdateShortcut| updates that part of the shortcut. 416 // |ShellUtil::CreateOrUpdateShortcut| updates that part of the shortcut.
367 properties.set_arguments(string16()); 417 properties.set_arguments(string16());
368 } 418 }
369 419
370 ShellUtil::ShortcutOperation operation = 420 ShellUtil::ShortcutOperation operation =
371 ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING; 421 ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING;
372 422
373 std::vector<base::FilePath> shortcuts; 423 std::vector<base::FilePath> shortcuts;
374 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, 424 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line,
375 action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS, 425 params.action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS,
376 &shortcuts); 426 &shortcuts);
377 if (create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND && 427 if (params.create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND &&
378 shortcuts.empty()) { 428 shortcuts.empty()) {
379 const string16 shortcut_name = 429 const string16 shortcut_name =
380 profiles::internal::GetShortcutFilenameForProfile(profile_name, 430 profiles::internal::GetShortcutFilenameForProfile(params.profile_name,
381 distribution); 431 distribution);
382 shortcuts.push_back(base::FilePath(shortcut_name)); 432 shortcuts.push_back(base::FilePath(shortcut_name));
383 operation = ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL; 433 operation = ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL;
384 } 434 }
385 435
386 for (size_t i = 0; i < shortcuts.size(); ++i) { 436 for (size_t i = 0; i < shortcuts.size(); ++i) {
387 const base::FilePath shortcut_name = 437 const base::FilePath shortcut_name =
388 shortcuts[i].BaseName().RemoveExtension(); 438 shortcuts[i].BaseName().RemoveExtension();
389 properties.set_shortcut_name(shortcut_name.value()); 439 properties.set_shortcut_name(shortcut_name.value());
390 ShellUtil::CreateOrUpdateShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, 440 ShellUtil::CreateOrUpdateShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
(...skipping 12 matching lines...) Expand all
403 file_util::FileEnumerator::FILES); 453 file_util::FileEnumerator::FILES);
404 for (base::FilePath path = enumerator.Next(); !path.empty(); 454 for (base::FilePath path = enumerator.Next(); !path.empty();
405 path = enumerator.Next()) { 455 path = enumerator.Next()) {
406 if (IsChromeShortcut(path, chrome_exe, NULL)) 456 if (IsChromeShortcut(path, chrome_exe, NULL))
407 return true; 457 return true;
408 } 458 }
409 459
410 return false; 460 return false;
411 } 461 }
412 462
413 // Deletes all desktop shortcuts for the specified profile and also removes the 463 // Deletes all desktop shortcuts for the specified profile. If
414 // corresponding icon file. If |ensure_shortcuts_remain| is true, then a regular 464 // |ensure_shortcuts_remain| is true, then a regular non-profile shortcut will
415 // non-profile shortcut will be created if this function would otherwise delete 465 // be created if this function would otherwise delete the last Chrome desktop
416 // the last Chrome desktop shortcut(s). Must be called on the FILE thread. 466 // shortcut(s). Must be called on the FILE thread.
417 void DeleteDesktopShortcutsAndIconFile(const base::FilePath& profile_path, 467 void DeleteDesktopShortcuts(const base::FilePath& profile_path,
418 bool ensure_shortcuts_remain) { 468 bool ensure_shortcuts_remain) {
419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 469 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
420 470
421 base::FilePath chrome_exe; 471 base::FilePath chrome_exe;
422 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 472 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
423 NOTREACHED(); 473 NOTREACHED();
424 return; 474 return;
425 } 475 }
426 476
427 const string16 command_line = 477 const string16 command_line =
428 profiles::internal::CreateProfileShortcutFlags(profile_path); 478 profiles::internal::CreateProfileShortcutFlags(profile_path);
429 std::vector<base::FilePath> shortcuts; 479 std::vector<base::FilePath> shortcuts;
430 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false, 480 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false,
431 &shortcuts); 481 &shortcuts);
432 482
433 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); 483 BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
434 for (size_t i = 0; i < shortcuts.size(); ++i) { 484 for (size_t i = 0; i < shortcuts.size(); ++i) {
435 // Use file_util::Delete() instead of ShellUtil::RemoveShortcut(), as the 485 // Use file_util::Delete() instead of ShellUtil::RemoveShortcut(), as the
436 // latter causes non-profile taskbar shortcuts to be unpinned. 486 // latter causes non-profile taskbar shortcuts to be unpinned.
437 file_util::Delete(shortcuts[i], false); 487 file_util::Delete(shortcuts[i], false);
438 // Notify the shell that the shortcut was deleted to ensure desktop refresh. 488 // Notify the shell that the shortcut was deleted to ensure desktop refresh.
439 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(), 489 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(),
440 NULL); 490 NULL);
441 } 491 }
442 492
443 const base::FilePath icon_path =
444 profile_path.AppendASCII(profiles::internal::kProfileIconFileName);
445 file_util::Delete(icon_path, false);
446
447 // If |ensure_shortcuts_remain| is true and deleting this profile caused the 493 // If |ensure_shortcuts_remain| is true and deleting this profile caused the
448 // last shortcuts to be removed, re-create a regular non-profile shortcut. 494 // last shortcuts to be removed, re-create a regular non-profile shortcut.
449 const bool had_shortcuts = !shortcuts.empty(); 495 const bool had_shortcuts = !shortcuts.empty();
450 if (ensure_shortcuts_remain && had_shortcuts && 496 if (ensure_shortcuts_remain && had_shortcuts &&
451 !ChromeDesktopShortcutsExist(chrome_exe)) { 497 !ChromeDesktopShortcutsExist(chrome_exe)) {
452 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); 498 BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
453 // Ensure that the distribution supports creating shortcuts. If it doesn't, 499 // Ensure that the distribution supports creating shortcuts. If it doesn't,
454 // the following code may result in NOTREACHED() being hit. 500 // the following code may result in NOTREACHED() being hit.
455 DCHECK(distribution->CanCreateDesktopShortcuts()); 501 DCHECK(distribution->CanCreateDesktopShortcuts());
456 installer::Product product(distribution); 502 installer::Product product(distribution);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 SkBitmap bitmap_copy; 564 SkBitmap bitmap_copy;
519 image_bitmap->deepCopyTo(&bitmap_copy, image_bitmap->getConfig()); 565 image_bitmap->deepCopyTo(&bitmap_copy, image_bitmap->getConfig());
520 return bitmap_copy; 566 return bitmap_copy;
521 } 567 }
522 568
523 } // namespace 569 } // namespace
524 570
525 namespace profiles { 571 namespace profiles {
526 namespace internal { 572 namespace internal {
527 573
528 const char kProfileIconFileName[] = "Google Profile.ico"; 574 base::FilePath GetProfileIconPath(const base::FilePath& profile_path) {
575 return profile_path.AppendASCII(kProfileIconFileName);
576 }
529 577
530 string16 GetShortcutFilenameForProfile(const string16& profile_name, 578 string16 GetShortcutFilenameForProfile(const string16& profile_name,
531 BrowserDistribution* distribution) { 579 BrowserDistribution* distribution) {
532 string16 shortcut_name; 580 string16 shortcut_name;
533 if (!profile_name.empty()) { 581 if (!profile_name.empty()) {
534 shortcut_name.append(SanitizeShortcutProfileNameString(profile_name)); 582 shortcut_name.append(SanitizeShortcutProfileNameString(profile_name));
535 shortcut_name.append(L" - "); 583 shortcut_name.append(L" - ");
536 shortcut_name.append(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); 584 shortcut_name.append(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
537 } else { 585 } else {
538 shortcut_name.append(distribution->GetAppShortCutName()); 586 shortcut_name.append(distribution->GetAppShortCutName());
539 } 587 }
540 return shortcut_name + installer::kLnkExt; 588 return shortcut_name + installer::kLnkExt;
541 } 589 }
542 590
543 string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) { 591 string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) {
544 return base::StringPrintf(L"--%ls=\"%ls\"", 592 return base::StringPrintf(L"--%ls=\"%ls\"",
545 ASCIIToUTF16(switches::kProfileDirectory).c_str(), 593 ASCIIToUTF16(switches::kProfileDirectory).c_str(),
546 profile_path.BaseName().value().c_str()); 594 profile_path.BaseName().value().c_str());
547 } 595 }
548 596
549 } // namespace internal 597 } // namespace internal
550 } // namespace profiles 598 } // namespace profiles
551 599
552 // static 600 // static
553 bool ProfileShortcutManager::IsFeatureEnabled() { 601 bool ProfileShortcutManager::IsFeatureEnabled() {
554 return BrowserDistribution::GetDistribution()->CanCreateDesktopShortcuts() && 602 return BrowserDistribution::GetDistribution()->CanCreateDesktopShortcuts() &&
555 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir) && 603 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir);
556 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kShowAppList);
557 } 604 }
558 605
559 // static 606 // static
560 ProfileShortcutManager* ProfileShortcutManager::Create( 607 ProfileShortcutManager* ProfileShortcutManager::Create(
561 ProfileManager* manager) { 608 ProfileManager* manager) {
562 return new ProfileShortcutManagerWin(manager); 609 return new ProfileShortcutManagerWin(manager);
563 } 610 }
564 611
565 ProfileShortcutManagerWin::ProfileShortcutManagerWin(ProfileManager* manager) 612 ProfileShortcutManagerWin::ProfileShortcutManagerWin(ProfileManager* manager)
566 : profile_manager_(manager) { 613 : profile_manager_(manager) {
567 DCHECK_EQ( 614 DCHECK_EQ(
568 arraysize(kProfileAvatarIconResources2x), 615 arraysize(kProfileAvatarIconResources2x),
569 profile_manager_->GetProfileInfoCache().GetDefaultAvatarIconCount()); 616 profile_manager_->GetProfileInfoCache().GetDefaultAvatarIconCount());
570 617
571 profile_manager_->GetProfileInfoCache().AddObserver(this); 618 profile_manager_->GetProfileInfoCache().AddObserver(this);
572 } 619 }
573 620
574 ProfileShortcutManagerWin::~ProfileShortcutManagerWin() { 621 ProfileShortcutManagerWin::~ProfileShortcutManagerWin() {
575 profile_manager_->GetProfileInfoCache().RemoveObserver(this); 622 profile_manager_->GetProfileInfoCache().RemoveObserver(this);
576 } 623 }
577 624
625 void ProfileShortcutManagerWin::CreateProfileIcon(
626 const base::FilePath& profile_path) {
627 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_ICON_ONLY,
628 IGNORE_NON_PROFILE_SHORTCUTS, true);
629 }
630
631 void ProfileShortcutManagerWin::UpdateProfileIcon(
632 const base::FilePath& profile_path) {
633 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_ICON_ONLY,
634 IGNORE_NON_PROFILE_SHORTCUTS, false);
635 }
636
578 void ProfileShortcutManagerWin::CreateProfileShortcut( 637 void ProfileShortcutManagerWin::CreateProfileShortcut(
579 const base::FilePath& profile_path) { 638 const base::FilePath& profile_path) {
580 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND, 639 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND,
581 IGNORE_NON_PROFILE_SHORTCUTS); 640 IGNORE_NON_PROFILE_SHORTCUTS, true);
582 } 641 }
583 642
584 void ProfileShortcutManagerWin::RemoveProfileShortcuts( 643 void ProfileShortcutManagerWin::RemoveProfileShortcuts(
585 const base::FilePath& profile_path) { 644 const base::FilePath& profile_path) {
586 BrowserThread::PostTask( 645 BrowserThread::PostTask(
587 BrowserThread::FILE, FROM_HERE, 646 BrowserThread::FILE, FROM_HERE,
588 base::Bind(&DeleteDesktopShortcutsAndIconFile, profile_path, false)); 647 base::Bind(&DeleteDesktopShortcuts, profile_path, false));
589 } 648 }
590 649
591 void ProfileShortcutManagerWin::HasProfileShortcuts( 650 void ProfileShortcutManagerWin::HasProfileShortcuts(
592 const base::FilePath& profile_path, 651 const base::FilePath& profile_path,
593 const base::Callback<void(bool)>& callback) { 652 const base::Callback<void(bool)>& callback) {
594 BrowserThread::PostTaskAndReplyWithResult( 653 BrowserThread::PostTaskAndReplyWithResult(
595 BrowserThread::FILE, FROM_HERE, 654 BrowserThread::FILE, FROM_HERE,
596 base::Bind(&HasAnyProfileShortcuts, profile_path), callback); 655 base::Bind(&HasAnyProfileShortcuts, profile_path), callback);
597 } 656 }
598 657
599 void ProfileShortcutManagerWin::OnProfileAdded( 658 void ProfileShortcutManagerWin::OnProfileAdded(
600 const base::FilePath& profile_path) { 659 const base::FilePath& profile_path) {
601 const size_t profile_count = 660 const size_t profile_count =
602 profile_manager_->GetProfileInfoCache().GetNumberOfProfiles(); 661 profile_manager_->GetProfileInfoCache().GetNumberOfProfiles();
603 if (profile_count == 1) { 662 if (profile_count == 1) {
604 CreateOrUpdateShortcutsForProfileAtPath(profile_path, 663 CreateOrUpdateShortcutsForProfileAtPath(profile_path,
605 CREATE_WHEN_NONE_FOUND, 664 CREATE_WHEN_NONE_FOUND,
606 UPDATE_NON_PROFILE_SHORTCUTS); 665 UPDATE_NON_PROFILE_SHORTCUTS,
607 } else if (profile_count == 2) { 666 false);
608 CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path), 667 } else {
609 UPDATE_EXISTING_ONLY, 668 CreateProfileIcon(profile_path);
610 UPDATE_NON_PROFILE_SHORTCUTS); 669 if (profile_count == 2) {
670 CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path),
671 UPDATE_EXISTING_ONLY,
672 UPDATE_NON_PROFILE_SHORTCUTS,
673 true);
674 }
611 } 675 }
612 } 676 }
613 677
614 void ProfileShortcutManagerWin::OnProfileWillBeRemoved( 678 void ProfileShortcutManagerWin::OnProfileWillBeRemoved(
615 const base::FilePath& profile_path) { 679 const base::FilePath& profile_path) {
616 } 680 }
617 681
618 void ProfileShortcutManagerWin::OnProfileWasRemoved( 682 void ProfileShortcutManagerWin::OnProfileWasRemoved(
619 const base::FilePath& profile_path, 683 const base::FilePath& profile_path,
620 const string16& profile_name) { 684 const string16& profile_name) {
621 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); 685 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
622 // If there is only one profile remaining, remove the badging information 686 // If there is only one profile remaining, remove the badging information
623 // from an existing shortcut. 687 // from an existing shortcut.
624 const bool deleting_down_to_last_profile = (cache.GetNumberOfProfiles() == 1); 688 const bool deleting_down_to_last_profile = (cache.GetNumberOfProfiles() == 1);
625 if (deleting_down_to_last_profile) { 689 if (deleting_down_to_last_profile) {
690 // This is needed to unbadge the icon.
626 CreateOrUpdateShortcutsForProfileAtPath(cache.GetPathOfProfileAtIndex(0), 691 CreateOrUpdateShortcutsForProfileAtPath(cache.GetPathOfProfileAtIndex(0),
627 UPDATE_EXISTING_ONLY, 692 UPDATE_EXISTING_ONLY,
628 IGNORE_NON_PROFILE_SHORTCUTS); 693 IGNORE_NON_PROFILE_SHORTCUTS,
694 false);
629 } 695 }
630 696
631 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 697 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
632 base::Bind(&DeleteDesktopShortcutsAndIconFile, 698 base::Bind(&DeleteDesktopShortcuts,
633 profile_path, 699 profile_path,
634 deleting_down_to_last_profile)); 700 deleting_down_to_last_profile));
635 } 701 }
636 702
637 void ProfileShortcutManagerWin::OnProfileNameChanged( 703 void ProfileShortcutManagerWin::OnProfileNameChanged(
638 const base::FilePath& profile_path, 704 const base::FilePath& profile_path,
639 const string16& old_profile_name) { 705 const string16& old_profile_name) {
640 CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY, 706 CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY,
641 IGNORE_NON_PROFILE_SHORTCUTS); 707 IGNORE_NON_PROFILE_SHORTCUTS, false);
642 } 708 }
643 709
644 void ProfileShortcutManagerWin::OnProfileAvatarChanged( 710 void ProfileShortcutManagerWin::OnProfileAvatarChanged(
645 const base::FilePath& profile_path) { 711 const base::FilePath& profile_path) {
646 CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY, 712 UpdateProfileIcon(profile_path);
647 IGNORE_NON_PROFILE_SHORTCUTS);
648 } 713 }
649 714
650 base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath( 715 base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath(
651 const base::FilePath& profile_path) { 716 const base::FilePath& profile_path) {
652 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); 717 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
653 DCHECK_EQ(2U, cache.GetNumberOfProfiles()); 718 DCHECK_EQ(2U, cache.GetNumberOfProfiles());
654 // Get the index of the current profile, in order to find the index of the 719 // Get the index of the current profile, in order to find the index of the
655 // other profile. 720 // other profile.
656 size_t current_profile_index = cache.GetIndexOfProfileWithPath(profile_path); 721 size_t current_profile_index = cache.GetIndexOfProfileWithPath(profile_path);
657 size_t other_profile_index = (current_profile_index == 0) ? 1 : 0; 722 size_t other_profile_index = (current_profile_index == 0) ? 1 : 0;
658 return cache.GetPathOfProfileAtIndex(other_profile_index); 723 return cache.GetPathOfProfileAtIndex(other_profile_index);
659 } 724 }
660 725
661 void ProfileShortcutManagerWin::CreateOrUpdateShortcutsForProfileAtPath( 726 void ProfileShortcutManagerWin::CreateOrUpdateShortcutsForProfileAtPath(
662 const base::FilePath& profile_path, 727 const base::FilePath& profile_path,
663 CreateOrUpdateMode create_mode, 728 CreateOrUpdateMode create_mode,
664 NonProfileShortcutAction action) { 729 NonProfileShortcutAction action,
730 bool is_icon_create) {
731 CreateOrUpdateShortcutsParams params;
732 params.profile_path = profile_path;
733 params.create_mode = create_mode;
734 params.action = action;
735 params.is_icon_create = is_icon_create;
736
665 ProfileInfoCache* cache = &profile_manager_->GetProfileInfoCache(); 737 ProfileInfoCache* cache = &profile_manager_->GetProfileInfoCache();
666 size_t profile_index = cache->GetIndexOfProfileWithPath(profile_path); 738 size_t profile_index = cache->GetIndexOfProfileWithPath(profile_path);
667 if (profile_index == std::string::npos) 739 if (profile_index == std::string::npos)
668 return; 740 return;
669 bool remove_badging = cache->GetNumberOfProfiles() == 1; 741 bool remove_badging = cache->GetNumberOfProfiles() == 1;
670 742
671 string16 old_shortcut_appended_name = 743 params.old_profile_name =
672 cache->GetShortcutNameOfProfileAtIndex(profile_index); 744 cache->GetShortcutNameOfProfileAtIndex(profile_index);
673 745
674 // Exit early if the mode is to update existing profile shortcuts only and 746 // Exit early if the mode is to update existing profile shortcuts only and
675 // none were ever created for this profile, per the shortcut name not being 747 // none were ever created for this profile, per the shortcut name not being
676 // set in the profile info cache. 748 // set in the profile info cache.
677 if (old_shortcut_appended_name.empty() && 749 if (params.old_profile_name.empty() &&
678 create_mode == UPDATE_EXISTING_ONLY && 750 create_mode == UPDATE_EXISTING_ONLY &&
679 action == IGNORE_NON_PROFILE_SHORTCUTS) { 751 action == IGNORE_NON_PROFILE_SHORTCUTS) {
680 return; 752 return;
681 } 753 }
682 754
683 string16 new_shortcut_appended_name;
684 if (!remove_badging) 755 if (!remove_badging)
685 new_shortcut_appended_name = cache->GetNameOfProfileAtIndex(profile_index); 756 params.profile_name = cache->GetNameOfProfileAtIndex(profile_index);
686 757
687 SkBitmap avatar_bitmap_copy_1x;
688 SkBitmap avatar_bitmap_copy_2x;
689 if (!remove_badging) { 758 if (!remove_badging) {
690 const size_t icon_index = 759 const size_t icon_index =
691 cache->GetAvatarIconIndexOfProfileAtIndex(profile_index); 760 cache->GetAvatarIconIndexOfProfileAtIndex(profile_index);
692 const int resource_id_1x = 761 const int resource_id_1x =
693 cache->GetDefaultAvatarIconResourceIDAtIndex(icon_index); 762 cache->GetDefaultAvatarIconResourceIDAtIndex(icon_index);
694 const int resource_id_2x = kProfileAvatarIconResources2x[icon_index]; 763 const int resource_id_2x = kProfileAvatarIconResources2x[icon_index];
695 // Make a copy of the SkBitmaps to ensure that we can safely use the image 764 // Make a copy of the SkBitmaps to ensure that we can safely use the image
696 // data on the FILE thread. 765 // data on the FILE thread.
697 avatar_bitmap_copy_1x = GetImageResourceSkBitmapCopy(resource_id_1x); 766 params.avatar_image_1x = GetImageResourceSkBitmapCopy(resource_id_1x);
698 avatar_bitmap_copy_2x = GetImageResourceSkBitmapCopy(resource_id_2x); 767 params.avatar_image_2x = GetImageResourceSkBitmapCopy(resource_id_2x);
699 } 768 }
700 BrowserThread::PostTask( 769 BrowserThread::PostTask(
701 BrowserThread::FILE, FROM_HERE, 770 BrowserThread::FILE, FROM_HERE,
702 base::Bind(&CreateOrUpdateDesktopShortcutsForProfile, profile_path, 771 base::Bind(&CreateOrUpdateDesktopShortcutsAndIconForProfile, params));
703 old_shortcut_appended_name, new_shortcut_appended_name,
704 avatar_bitmap_copy_1x, avatar_bitmap_copy_2x, create_mode,
705 action));
706 772
707 cache->SetShortcutNameOfProfileAtIndex(profile_index, 773 cache->SetShortcutNameOfProfileAtIndex(profile_index,
708 new_shortcut_appended_name); 774 params.profile_name);
709 } 775 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698