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 #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 Loading... | |
| 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 Loading... | |
| 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 // TODO(calamity): Ideally we'd just copy the app icon verbatim from the exe's | |
| 148 // resources in the case of an unbadged icon. | |
| 149 base::FilePath CreateOrUpdateShortcutIconForProfile( | |
| 144 const base::FilePath& profile_path, | 150 const base::FilePath& profile_path, | 
| 145 const SkBitmap& avatar_bitmap_1x, | 151 const SkBitmap& avatar_bitmap_1x, | 
| 146 const SkBitmap& avatar_bitmap_2x) { | 152 const SkBitmap& avatar_bitmap_2x) { | 
| 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 
| 148 scoped_ptr<SkBitmap> app_icon_bitmap(GetAppIconForSize(kShortcutIconSize)); | 154 scoped_ptr<SkBitmap> app_icon_bitmap(GetAppIconForSize(kShortcutIconSize)); | 
| 149 if (!app_icon_bitmap.get()) | 155 if (!app_icon_bitmap.get()) | 
| 150 return base::FilePath(); | 156 return base::FilePath(); | 
| 151 | 157 | 
| 152 gfx::ImageFamily badged_bitmaps; | 158 gfx::ImageFamily badged_bitmaps; | 
| 153 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap( | 159 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.get()) { | |
| 158 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap( | 160 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap( | 
| 159 BadgeIcon(*app_icon_bitmap, avatar_bitmap_2x, 2))); | 161 BadgeIcon(*app_icon_bitmap, avatar_bitmap_1x, 1))); | 
| 160 } | 162 } | 
| 161 | 163 | 
| 164 scoped_ptr<SkBitmap> large_app_icon_bitmap( | |
| 165 GetAppIconForSize(IconUtil::kLargeIconSize)); | |
| 166 if (large_app_icon_bitmap.get() && !avatar_bitmap_2x.empty()) { | |
| 167 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap( | |
| 168 BadgeIcon(*large_app_icon_bitmap, avatar_bitmap_2x, 2))); | |
| 169 } | |
| 170 | |
| 171 // If we have no badged bitmaps, we should just use the default chrome icon. | |
| 172 if (badged_bitmaps.empty()) { | |
| 173 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(*app_icon_bitmap)); | |
| 174 if (large_app_icon_bitmap.get()) { | |
| 175 badged_bitmaps.Add( | |
| 176 gfx::Image::CreateFrom1xBitmap(*large_app_icon_bitmap)); | |
| 177 } | |
| 178 } | |
| 162 // Finally, write the .ico file containing this new bitmap. | 179 // Finally, write the .ico file containing this new bitmap. | 
| 163 const base::FilePath icon_path = | 180 const base::FilePath icon_path = | 
| 164 profile_path.AppendASCII(profiles::internal::kProfileIconFileName); | 181 profiles::internal::GetProfileIconPath(profile_path); | 
| 165 if (!IconUtil::CreateIconFileFromImageFamily(badged_bitmaps, icon_path)) | |
| 166 return base::FilePath(); | |
| 167 | 182 | 
| 183 if (IconUtil::ShouldUpdateIcon(icon_path, badged_bitmaps)) { | |
| 184 if (IconUtil::SaveIconWithCheckSum(icon_path, badged_bitmaps)) { | |
| 185 // This invalidates the Windows icon cache and causes the icon changes to | |
| 186 // register with the taskbar an desktop. | |
| 
 
gab
2013/05/09 13:43:56
nit: s/an/and
 
calamity
2013/05/24 08:58:48
Done.
 
 | |
| 187 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, | |
| 188 NULL, NULL); | |
| 189 } | |
| 190 } | |
| 168 return icon_path; | 191 return icon_path; | 
| 169 } | 192 } | 
| 170 | 193 | 
| 171 // Gets the user and system directories for desktop shortcuts. Parameters may | 194 // 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. | 195 // be NULL if a directory type is not needed. Returns true on success. | 
| 173 bool GetDesktopShortcutsDirectories( | 196 bool GetDesktopShortcutsDirectories( | 
| 174 base::FilePath* user_shortcuts_directory, | 197 base::FilePath* user_shortcuts_directory, | 
| 175 base::FilePath* system_shortcuts_directory) { | 198 base::FilePath* system_shortcuts_directory) { | 
| 176 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 199 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 
| 177 if (user_shortcuts_directory && | 200 if (user_shortcuts_directory && | 
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 292 if (file_util::PathExists(possible_new_system_shortcut)) | 315 if (file_util::PathExists(possible_new_system_shortcut)) | 
| 293 file_util::Delete(old_shortcut_path, false); | 316 file_util::Delete(old_shortcut_path, false); | 
| 294 else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path)) | 317 else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path)) | 
| 295 DLOG(ERROR) << "Could not rename Windows profile desktop shortcut."; | 318 DLOG(ERROR) << "Could not rename Windows profile desktop shortcut."; | 
| 296 } else { | 319 } else { | 
| 297 // If the shortcut does not exist, it may have been renamed by the user. In | 320 // If the shortcut does not exist, it may have been renamed by the user. In | 
| 298 // that case, its name should not be changed. | 321 // that case, its name should not be changed. | 
| 299 // It's also possible that a system-level shortcut exists instead - this | 322 // 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 | 323 // 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 | 324 // installation. If that's the case, copy that one over - it will get its | 
| 302 // properties updated by |CreateOrUpdateDesktopShortcutsForProfile()|. | 325 // properties updated by | 
| 326 // |CreateOrUpdateDesktopShortcutsAndIconForProfile()|. | |
| 303 const base::FilePath possible_old_system_shortcut = | 327 const base::FilePath possible_old_system_shortcut = | 
| 304 system_shortcuts_directory.Append(old_shortcut_filename); | 328 system_shortcuts_directory.Append(old_shortcut_filename); | 
| 305 if (file_util::PathExists(possible_old_system_shortcut)) | 329 if (file_util::PathExists(possible_old_system_shortcut)) | 
| 306 file_util::CopyFile(possible_old_system_shortcut, new_shortcut_path); | 330 file_util::CopyFile(possible_old_system_shortcut, new_shortcut_path); | 
| 307 } | 331 } | 
| 308 } | 332 } | 
| 309 | 333 | 
| 310 // Updates all desktop shortcuts for the given profile to have the specified | 334 // 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 | 335 // 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 | 336 // 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. | 337 // be updated is specified by |action|. Must be called on the FILE thread. | 
| 314 void CreateOrUpdateDesktopShortcutsForProfile( | 338 void CreateOrUpdateDesktopShortcutsAndIconForProfile( | 
| 315 const base::FilePath& profile_path, | 339 const base::FilePath& profile_path, | 
| 316 const string16& old_profile_name, | 340 const string16& old_profile_name, | 
| 317 const string16& profile_name, | 341 const string16& profile_name, | 
| 318 const SkBitmap& avatar_image_1x, | 342 const SkBitmap& avatar_image_1x, | 
| 319 const SkBitmap& avatar_image_2x, | 343 const SkBitmap& avatar_image_2x, | 
| 320 ProfileShortcutManagerWin::CreateOrUpdateMode create_mode, | 344 ProfileShortcutManagerWin::CreateOrUpdateMode create_mode, | 
| 321 ProfileShortcutManagerWin::NonProfileShortcutAction action) { | 345 ProfileShortcutManagerWin::NonProfileShortcutAction action) { | 
| 322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 
| 323 | 347 | 
| 348 base::FilePath shortcut_icon = | |
| 349 CreateOrUpdateShortcutIconForProfile(profile_path, | |
| 350 avatar_image_1x, | |
| 351 avatar_image_2x); | |
| 352 if (shortcut_icon.empty()) { | |
| 353 NOTREACHED(); | |
| 354 return; | |
| 355 } | |
| 356 if (create_mode == ProfileShortcutManagerWin::CREATE_ICON_ONLY) | |
| 357 return; | |
| 358 | |
| 324 base::FilePath chrome_exe; | 359 base::FilePath chrome_exe; | 
| 325 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { | 360 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { | 
| 326 NOTREACHED(); | 361 NOTREACHED(); | 
| 327 return; | 362 return; | 
| 328 } | 363 } | 
| 329 | 364 | 
| 330 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 365 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 
| 331 // Ensure that the distribution supports creating shortcuts. If it doesn't, | 366 // Ensure that the distribution supports creating shortcuts. If it doesn't, | 
| 332 // the following code may result in NOTREACHED() being hit. | 367 // the following code may result in NOTREACHED() being hit. | 
| 333 DCHECK(distribution->CanCreateDesktopShortcuts()); | 368 DCHECK(distribution->CanCreateDesktopShortcuts()); | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 347 installer::Product product(distribution); | 382 installer::Product product(distribution); | 
| 348 product.AddDefaultShortcutProperties(chrome_exe, &properties); | 383 product.AddDefaultShortcutProperties(chrome_exe, &properties); | 
| 349 | 384 | 
| 350 const string16 command_line = | 385 const string16 command_line = | 
| 351 profiles::internal::CreateProfileShortcutFlags(profile_path); | 386 profiles::internal::CreateProfileShortcutFlags(profile_path); | 
| 352 | 387 | 
| 353 // Only set the profile-specific properties when |profile_name| is non empty. | 388 // 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, | 389 // If it is empty, it means the shortcut being created should be a regular, | 
| 355 // non-profile Chrome shortcut. | 390 // non-profile Chrome shortcut. | 
| 356 if (!profile_name.empty()) { | 391 if (!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()) | 392 if (!shortcut_icon.empty()) | 
| 362 properties.set_icon(shortcut_icon, 0); | 393 properties.set_icon(shortcut_icon, 0); | 
| 363 properties.set_arguments(command_line); | 394 properties.set_arguments(command_line); | 
| 364 } else { | 395 } else { | 
| 365 // Set the arguments explicitly to the empty string to ensure that | 396 // Set the arguments explicitly to the empty string to ensure that | 
| 366 // |ShellUtil::CreateOrUpdateShortcut| updates that part of the shortcut. | 397 // |ShellUtil::CreateOrUpdateShortcut| updates that part of the shortcut. | 
| 367 properties.set_arguments(string16()); | 398 properties.set_arguments(string16()); | 
| 368 } | 399 } | 
| 369 | 400 | 
| 370 ShellUtil::ShortcutOperation operation = | 401 ShellUtil::ShortcutOperation operation = | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 file_util::FileEnumerator::FILES); | 434 file_util::FileEnumerator::FILES); | 
| 404 for (base::FilePath path = enumerator.Next(); !path.empty(); | 435 for (base::FilePath path = enumerator.Next(); !path.empty(); | 
| 405 path = enumerator.Next()) { | 436 path = enumerator.Next()) { | 
| 406 if (IsChromeShortcut(path, chrome_exe, NULL)) | 437 if (IsChromeShortcut(path, chrome_exe, NULL)) | 
| 407 return true; | 438 return true; | 
| 408 } | 439 } | 
| 409 | 440 | 
| 410 return false; | 441 return false; | 
| 411 } | 442 } | 
| 412 | 443 | 
| 413 // Deletes all desktop shortcuts for the specified profile and also removes the | 444 // Deletes all desktop shortcuts for the specified profile. If | 
| 414 // corresponding icon file. If |ensure_shortcuts_remain| is true, then a regular | 445 // |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 | 446 // 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. | 447 // shortcut(s). Must be called on the FILE thread. | 
| 417 void DeleteDesktopShortcutsAndIconFile(const base::FilePath& profile_path, | 448 void DeleteDesktopShortcuts(const base::FilePath& profile_path, | 
| 418 bool ensure_shortcuts_remain) { | 449 bool ensure_shortcuts_remain) { | 
| 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 450 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 
| 420 | 451 | 
| 421 base::FilePath chrome_exe; | 452 base::FilePath chrome_exe; | 
| 422 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { | 453 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { | 
| 423 NOTREACHED(); | 454 NOTREACHED(); | 
| 424 return; | 455 return; | 
| 425 } | 456 } | 
| 426 | 457 | 
| 427 const string16 command_line = | 458 const string16 command_line = | 
| 428 profiles::internal::CreateProfileShortcutFlags(profile_path); | 459 profiles::internal::CreateProfileShortcutFlags(profile_path); | 
| 429 std::vector<base::FilePath> shortcuts; | 460 std::vector<base::FilePath> shortcuts; | 
| 430 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false, | 461 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false, | 
| 431 &shortcuts); | 462 &shortcuts); | 
| 432 | 463 | 
| 433 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 464 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 
| 434 for (size_t i = 0; i < shortcuts.size(); ++i) { | 465 for (size_t i = 0; i < shortcuts.size(); ++i) { | 
| 435 // Use file_util::Delete() instead of ShellUtil::RemoveShortcut(), as the | 466 // Use file_util::Delete() instead of ShellUtil::RemoveShortcut(), as the | 
| 436 // latter causes non-profile taskbar shortcuts to be unpinned. | 467 // latter causes non-profile taskbar shortcuts to be unpinned. | 
| 437 file_util::Delete(shortcuts[i], false); | 468 file_util::Delete(shortcuts[i], false); | 
| 438 // Notify the shell that the shortcut was deleted to ensure desktop refresh. | 469 // Notify the shell that the shortcut was deleted to ensure desktop refresh. | 
| 439 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(), | 470 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(), | 
| 440 NULL); | 471 NULL); | 
| 441 } | 472 } | 
| 442 | 473 | 
| 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 | 474 // 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. | 475 // last shortcuts to be removed, re-create a regular non-profile shortcut. | 
| 449 const bool had_shortcuts = !shortcuts.empty(); | 476 const bool had_shortcuts = !shortcuts.empty(); | 
| 450 if (ensure_shortcuts_remain && had_shortcuts && | 477 if (ensure_shortcuts_remain && had_shortcuts && | 
| 451 !ChromeDesktopShortcutsExist(chrome_exe)) { | 478 !ChromeDesktopShortcutsExist(chrome_exe)) { | 
| 452 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 479 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 
| 453 // Ensure that the distribution supports creating shortcuts. If it doesn't, | 480 // Ensure that the distribution supports creating shortcuts. If it doesn't, | 
| 454 // the following code may result in NOTREACHED() being hit. | 481 // the following code may result in NOTREACHED() being hit. | 
| 455 DCHECK(distribution->CanCreateDesktopShortcuts()); | 482 DCHECK(distribution->CanCreateDesktopShortcuts()); | 
| 456 installer::Product product(distribution); | 483 installer::Product product(distribution); | 
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 518 SkBitmap bitmap_copy; | 545 SkBitmap bitmap_copy; | 
| 519 image_bitmap->deepCopyTo(&bitmap_copy, image_bitmap->getConfig()); | 546 image_bitmap->deepCopyTo(&bitmap_copy, image_bitmap->getConfig()); | 
| 520 return bitmap_copy; | 547 return bitmap_copy; | 
| 521 } | 548 } | 
| 522 | 549 | 
| 523 } // namespace | 550 } // namespace | 
| 524 | 551 | 
| 525 namespace profiles { | 552 namespace profiles { | 
| 526 namespace internal { | 553 namespace internal { | 
| 527 | 554 | 
| 528 const char kProfileIconFileName[] = "Google Profile.ico"; | 555 base::FilePath GetProfileIconPath(const base::FilePath& profile_path) { | 
| 556 return profile_path.AppendASCII(kProfileIconFileName); | |
| 557 } | |
| 529 | 558 | 
| 530 string16 GetShortcutFilenameForProfile(const string16& profile_name, | 559 string16 GetShortcutFilenameForProfile(const string16& profile_name, | 
| 531 BrowserDistribution* distribution) { | 560 BrowserDistribution* distribution) { | 
| 532 string16 shortcut_name; | 561 string16 shortcut_name; | 
| 533 if (!profile_name.empty()) { | 562 if (!profile_name.empty()) { | 
| 534 shortcut_name.append(SanitizeShortcutProfileNameString(profile_name)); | 563 shortcut_name.append(SanitizeShortcutProfileNameString(profile_name)); | 
| 535 shortcut_name.append(L" - "); | 564 shortcut_name.append(L" - "); | 
| 536 shortcut_name.append(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); | 565 shortcut_name.append(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); | 
| 537 } else { | 566 } else { | 
| 538 shortcut_name.append(distribution->GetAppShortCutName()); | 567 shortcut_name.append(distribution->GetAppShortCutName()); | 
| (...skipping 29 matching lines...) Expand all Loading... | |
| 568 arraysize(kProfileAvatarIconResources2x), | 597 arraysize(kProfileAvatarIconResources2x), | 
| 569 profile_manager_->GetProfileInfoCache().GetDefaultAvatarIconCount()); | 598 profile_manager_->GetProfileInfoCache().GetDefaultAvatarIconCount()); | 
| 570 | 599 | 
| 571 profile_manager_->GetProfileInfoCache().AddObserver(this); | 600 profile_manager_->GetProfileInfoCache().AddObserver(this); | 
| 572 } | 601 } | 
| 573 | 602 | 
| 574 ProfileShortcutManagerWin::~ProfileShortcutManagerWin() { | 603 ProfileShortcutManagerWin::~ProfileShortcutManagerWin() { | 
| 575 profile_manager_->GetProfileInfoCache().RemoveObserver(this); | 604 profile_manager_->GetProfileInfoCache().RemoveObserver(this); | 
| 576 } | 605 } | 
| 577 | 606 | 
| 607 void ProfileShortcutManagerWin::CreateProfileIcon( | |
| 
 
Alexei Svitkine (slow)
2013/05/09 16:45:47
Nit: Rename to "CreateOrUpdateProfileIcon".
 
calamity
2013/05/24 08:58:48
Split this into CreateProfileIcon and UpdateProfil
 
 | |
| 608 const base::FilePath& profile_path) { | |
| 609 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_ICON_ONLY, | |
| 610 IGNORE_NON_PROFILE_SHORTCUTS); | |
| 611 } | |
| 612 | |
| 578 void ProfileShortcutManagerWin::CreateProfileShortcut( | 613 void ProfileShortcutManagerWin::CreateProfileShortcut( | 
| 579 const base::FilePath& profile_path) { | 614 const base::FilePath& profile_path) { | 
| 580 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND, | 615 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND, | 
| 581 IGNORE_NON_PROFILE_SHORTCUTS); | 616 IGNORE_NON_PROFILE_SHORTCUTS); | 
| 582 } | 617 } | 
| 583 | 618 | 
| 584 void ProfileShortcutManagerWin::RemoveProfileShortcuts( | 619 void ProfileShortcutManagerWin::RemoveProfileShortcuts( | 
| 585 const base::FilePath& profile_path) { | 620 const base::FilePath& profile_path) { | 
| 586 BrowserThread::PostTask( | 621 BrowserThread::PostTask( | 
| 587 BrowserThread::FILE, FROM_HERE, | 622 BrowserThread::FILE, FROM_HERE, | 
| 588 base::Bind(&DeleteDesktopShortcutsAndIconFile, profile_path, false)); | 623 base::Bind(&DeleteDesktopShortcuts, profile_path, false)); | 
| 589 } | 624 } | 
| 590 | 625 | 
| 591 void ProfileShortcutManagerWin::HasProfileShortcuts( | 626 void ProfileShortcutManagerWin::HasProfileShortcuts( | 
| 592 const base::FilePath& profile_path, | 627 const base::FilePath& profile_path, | 
| 593 const base::Callback<void(bool)>& callback) { | 628 const base::Callback<void(bool)>& callback) { | 
| 594 BrowserThread::PostTaskAndReplyWithResult( | 629 BrowserThread::PostTaskAndReplyWithResult( | 
| 595 BrowserThread::FILE, FROM_HERE, | 630 BrowserThread::FILE, FROM_HERE, | 
| 596 base::Bind(&HasAnyProfileShortcuts, profile_path), callback); | 631 base::Bind(&HasAnyProfileShortcuts, profile_path), callback); | 
| 597 } | 632 } | 
| 598 | 633 | 
| 599 void ProfileShortcutManagerWin::OnProfileAdded( | 634 void ProfileShortcutManagerWin::OnProfileAdded( | 
| 600 const base::FilePath& profile_path) { | 635 const base::FilePath& profile_path) { | 
| 601 const size_t profile_count = | 636 const size_t profile_count = | 
| 602 profile_manager_->GetProfileInfoCache().GetNumberOfProfiles(); | 637 profile_manager_->GetProfileInfoCache().GetNumberOfProfiles(); | 
| 603 if (profile_count == 1) { | 638 if (profile_count == 1) { | 
| 604 CreateOrUpdateShortcutsForProfileAtPath(profile_path, | 639 CreateOrUpdateShortcutsForProfileAtPath(profile_path, | 
| 605 CREATE_WHEN_NONE_FOUND, | 640 CREATE_WHEN_NONE_FOUND, | 
| 606 UPDATE_NON_PROFILE_SHORTCUTS); | 641 UPDATE_NON_PROFILE_SHORTCUTS); | 
| 607 } else if (profile_count == 2) { | 642 } else { | 
| 608 CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path), | 643 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_ICON_ONLY, | 
| 
 
gab
2013/05/09 13:43:56
Simply call CreateProfileIcon(profile_path); here,
 
calamity
2013/05/24 08:58:48
Done.
 
 | |
| 609 UPDATE_EXISTING_ONLY, | 644 IGNORE_NON_PROFILE_SHORTCUTS); | 
| 610 UPDATE_NON_PROFILE_SHORTCUTS); | 645 if (profile_count == 2) { | 
| 646 CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path), | |
| 647 UPDATE_EXISTING_ONLY, | |
| 648 UPDATE_NON_PROFILE_SHORTCUTS); | |
| 649 } | |
| 611 } | 650 } | 
| 612 } | 651 } | 
| 613 | 652 | 
| 614 void ProfileShortcutManagerWin::OnProfileWillBeRemoved( | 653 void ProfileShortcutManagerWin::OnProfileWillBeRemoved( | 
| 615 const base::FilePath& profile_path) { | 654 const base::FilePath& profile_path) { | 
| 616 } | 655 } | 
| 617 | 656 | 
| 618 void ProfileShortcutManagerWin::OnProfileWasRemoved( | 657 void ProfileShortcutManagerWin::OnProfileWasRemoved( | 
| 619 const base::FilePath& profile_path, | 658 const base::FilePath& profile_path, | 
| 620 const string16& profile_name) { | 659 const string16& profile_name) { | 
| 621 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); | 660 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); | 
| 622 // If there is only one profile remaining, remove the badging information | 661 // If there is only one profile remaining, remove the badging information | 
| 623 // from an existing shortcut. | 662 // from an existing shortcut. | 
| 624 const bool deleting_down_to_last_profile = (cache.GetNumberOfProfiles() == 1); | 663 const bool deleting_down_to_last_profile = (cache.GetNumberOfProfiles() == 1); | 
| 625 if (deleting_down_to_last_profile) { | 664 if (deleting_down_to_last_profile) { | 
| 665 // This is needed to unbadge the icon. | |
| 626 CreateOrUpdateShortcutsForProfileAtPath(cache.GetPathOfProfileAtIndex(0), | 666 CreateOrUpdateShortcutsForProfileAtPath(cache.GetPathOfProfileAtIndex(0), | 
| 627 UPDATE_EXISTING_ONLY, | 667 UPDATE_EXISTING_ONLY, | 
| 628 IGNORE_NON_PROFILE_SHORTCUTS); | 668 IGNORE_NON_PROFILE_SHORTCUTS); | 
| 629 } | 669 } | 
| 630 | 670 | 
| 631 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 671 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 
| 632 base::Bind(&DeleteDesktopShortcutsAndIconFile, | 672 base::Bind(&DeleteDesktopShortcuts, | 
| 633 profile_path, | 673 profile_path, | 
| 634 deleting_down_to_last_profile)); | 674 deleting_down_to_last_profile)); | 
| 635 } | 675 } | 
| 636 | 676 | 
| 637 void ProfileShortcutManagerWin::OnProfileNameChanged( | 677 void ProfileShortcutManagerWin::OnProfileNameChanged( | 
| 638 const base::FilePath& profile_path, | 678 const base::FilePath& profile_path, | 
| 639 const string16& old_profile_name) { | 679 const string16& old_profile_name) { | 
| 640 CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY, | 680 CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY, | 
| 641 IGNORE_NON_PROFILE_SHORTCUTS); | 681 IGNORE_NON_PROFILE_SHORTCUTS); | 
| 642 } | 682 } | 
| 643 | 683 | 
| 644 void ProfileShortcutManagerWin::OnProfileAvatarChanged( | 684 void ProfileShortcutManagerWin::OnProfileAvatarChanged( | 
| 645 const base::FilePath& profile_path) { | 685 const base::FilePath& profile_path) { | 
| 646 CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY, | 686 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_ICON_ONLY, | 
| 
 
Alexei Svitkine (slow)
2013/05/09 16:45:47
Nit: Call "CreateOrUpdateProfileIcon".
 
calamity
2013/05/24 08:58:48
Done.
 
 | |
| 647 IGNORE_NON_PROFILE_SHORTCUTS); | 687 IGNORE_NON_PROFILE_SHORTCUTS); | 
| 648 } | 688 } | 
| 649 | 689 | 
| 650 base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath( | 690 base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath( | 
| 651 const base::FilePath& profile_path) { | 691 const base::FilePath& profile_path) { | 
| 652 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); | 692 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); | 
| 653 DCHECK_EQ(2U, cache.GetNumberOfProfiles()); | 693 DCHECK_EQ(2U, cache.GetNumberOfProfiles()); | 
| 654 // Get the index of the current profile, in order to find the index of the | 694 // Get the index of the current profile, in order to find the index of the | 
| 655 // other profile. | 695 // other profile. | 
| 656 size_t current_profile_index = cache.GetIndexOfProfileWithPath(profile_path); | 696 size_t current_profile_index = cache.GetIndexOfProfileWithPath(profile_path); | 
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 692 const int resource_id_1x = | 732 const int resource_id_1x = | 
| 693 cache->GetDefaultAvatarIconResourceIDAtIndex(icon_index); | 733 cache->GetDefaultAvatarIconResourceIDAtIndex(icon_index); | 
| 694 const int resource_id_2x = kProfileAvatarIconResources2x[icon_index]; | 734 const int resource_id_2x = kProfileAvatarIconResources2x[icon_index]; | 
| 695 // Make a copy of the SkBitmaps to ensure that we can safely use the image | 735 // Make a copy of the SkBitmaps to ensure that we can safely use the image | 
| 696 // data on the FILE thread. | 736 // data on the FILE thread. | 
| 697 avatar_bitmap_copy_1x = GetImageResourceSkBitmapCopy(resource_id_1x); | 737 avatar_bitmap_copy_1x = GetImageResourceSkBitmapCopy(resource_id_1x); | 
| 698 avatar_bitmap_copy_2x = GetImageResourceSkBitmapCopy(resource_id_2x); | 738 avatar_bitmap_copy_2x = GetImageResourceSkBitmapCopy(resource_id_2x); | 
| 699 } | 739 } | 
| 700 BrowserThread::PostTask( | 740 BrowserThread::PostTask( | 
| 701 BrowserThread::FILE, FROM_HERE, | 741 BrowserThread::FILE, FROM_HERE, | 
| 702 base::Bind(&CreateOrUpdateDesktopShortcutsForProfile, profile_path, | 742 base::Bind(&CreateOrUpdateDesktopShortcutsAndIconForProfile, profile_path, | 
| 703 old_shortcut_appended_name, new_shortcut_appended_name, | 743 old_shortcut_appended_name, new_shortcut_appended_name, | 
| 704 avatar_bitmap_copy_1x, avatar_bitmap_copy_2x, create_mode, | 744 avatar_bitmap_copy_1x, avatar_bitmap_copy_2x, create_mode, | 
| 705 action)); | 745 action)); | 
| 706 | 746 | 
| 707 cache->SetShortcutNameOfProfileAtIndex(profile_index, | 747 cache->SetShortcutNameOfProfileAtIndex(profile_index, | 
| 708 new_shortcut_appended_name); | 748 new_shortcut_appended_name); | 
| 709 } | 749 } | 
| OLD | NEW |