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> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
| 15 #include "base/path_service.h" | 15 #include "base/path_service.h" |
| 16 #include "base/prefs/pref_service.h" | |
| 16 #include "base/string16.h" | 17 #include "base/string16.h" |
| 17 #include "base/string_util.h" | 18 #include "base/string_util.h" |
| 18 #include "base/stringprintf.h" | 19 #include "base/stringprintf.h" |
| 19 #include "base/utf_string_conversions.h" | 20 #include "base/utf_string_conversions.h" |
| 20 #include "base/win/shortcut.h" | 21 #include "base/win/shortcut.h" |
| 21 #include "chrome/browser/app_icon_win.h" | 22 #include "chrome/browser/app_icon_win.h" |
| 22 #include "chrome/browser/browser_process.h" | 23 #include "chrome/browser/browser_process.h" |
| 23 #include "chrome/browser/profiles/profile_info_cache_observer.h" | 24 #include "chrome/browser/profiles/profile_info_cache_observer.h" |
| 24 #include "chrome/browser/profiles/profile_info_util.h" | 25 #include "chrome/browser/profiles/profile_info_util.h" |
| 25 #include "chrome/browser/profiles/profile_manager.h" | 26 #include "chrome/browser/profiles/profile_manager.h" |
| 26 #include "chrome/browser/shell_integration.h" | 27 #include "chrome/browser/shell_integration.h" |
| 28 #include "chrome/common/chrome_notification_types.h" | |
| 27 #include "chrome/common/chrome_switches.h" | 29 #include "chrome/common/chrome_switches.h" |
| 30 #include "chrome/common/pref_names.h" | |
| 28 #include "chrome/installer/util/browser_distribution.h" | 31 #include "chrome/installer/util/browser_distribution.h" |
| 29 #include "chrome/installer/util/product.h" | 32 #include "chrome/installer/util/product.h" |
| 30 #include "chrome/installer/util/shell_util.h" | 33 #include "chrome/installer/util/shell_util.h" |
| 31 #include "content/public/browser/browser_thread.h" | 34 #include "content/public/browser/browser_thread.h" |
| 35 #include "content/public/browser/notification_service.h" | |
| 32 #include "grit/chrome_unscaled_resources.h" | 36 #include "grit/chrome_unscaled_resources.h" |
| 33 #include "grit/chromium_strings.h" | 37 #include "grit/chromium_strings.h" |
| 34 #include "skia/ext/image_operations.h" | 38 #include "skia/ext/image_operations.h" |
| 35 #include "skia/ext/platform_canvas.h" | 39 #include "skia/ext/platform_canvas.h" |
| 36 #include "ui/base/l10n/l10n_util.h" | 40 #include "ui/base/l10n/l10n_util.h" |
| 37 #include "ui/base/resource/resource_bundle.h" | 41 #include "ui/base/resource/resource_bundle.h" |
| 38 #include "ui/gfx/icon_util.h" | 42 #include "ui/gfx/icon_util.h" |
| 39 #include "ui/gfx/image/image.h" | 43 #include "ui/gfx/image/image.h" |
| 40 #include "ui/gfx/image/image_family.h" | 44 #include "ui/gfx/image/image_family.h" |
| 41 #include "ui/gfx/rect.h" | 45 #include "ui/gfx/rect.h" |
| 42 #include "ui/gfx/skia_util.h" | 46 #include "ui/gfx/skia_util.h" |
| 43 | 47 |
| 44 using content::BrowserThread; | 48 using content::BrowserThread; |
| 45 | 49 |
| 46 namespace { | 50 namespace { |
| 47 | 51 |
| 52 // Name of the badged icon file generated for a given profile. | |
| 53 const char kProfileIconFileName[] = "Google Profile.ico"; | |
| 54 | |
| 48 // Characters that are not allowed in Windows filenames. Taken from | 55 // Characters that are not allowed in Windows filenames. Taken from |
| 49 // http://msdn.microsoft.com/en-us/library/aa365247.aspx | 56 // http://msdn.microsoft.com/en-us/library/aa365247.aspx |
| 50 const char16 kReservedCharacters[] = L"<>:\"/\\|?*\x01\x02\x03\x04\x05\x06\x07" | 57 const char16 kReservedCharacters[] = L"<>:\"/\\|?*\x01\x02\x03\x04\x05\x06\x07" |
| 51 L"\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19" | 58 L"\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19" |
| 52 L"\x1A\x1B\x1C\x1D\x1E\x1F"; | 59 L"\x1A\x1B\x1C\x1D\x1E\x1F"; |
| 53 | 60 |
| 54 // The maximum number of characters allowed in profile shortcuts' file names. | 61 // The maximum number of characters allowed in profile shortcuts' file names. |
| 55 // Warning: migration code will be needed if this is changed later, since | 62 // Warning: migration code will be needed if this is changed later, since |
| 56 // existing shortcuts might no longer be found if the name is generated | 63 // existing shortcuts might no longer be found if the name is generated |
| 57 // differently than it was when a shortcut was originally created. | 64 // differently than it was when a shortcut was originally created. |
| 58 const int kMaxProfileShortcutFileNameLength = 64; | 65 const int kMaxProfileShortcutFileNameLength = 64; |
| 59 | 66 |
| 60 const int kProfileAvatarBadgeSize = 28; | 67 const int kProfileAvatarBadgeSize = 28; |
| 61 const int kShortcutIconSize = 48; | 68 const int kShortcutIconSize = 48; |
| 62 | 69 |
| 70 const int kCurrentProfileIconVersion = 1; | |
| 71 | |
| 63 // 2x sized profile avatar icons. Mirrors |kDefaultAvatarIconResources| in | 72 // 2x sized profile avatar icons. Mirrors |kDefaultAvatarIconResources| in |
| 64 // profile_info_cache.cc. | 73 // profile_info_cache.cc. |
| 65 const int kProfileAvatarIconResources2x[] = { | 74 const int kProfileAvatarIconResources2x[] = { |
| 66 IDR_PROFILE_AVATAR_2X_0, | 75 IDR_PROFILE_AVATAR_2X_0, |
| 67 IDR_PROFILE_AVATAR_2X_1, | 76 IDR_PROFILE_AVATAR_2X_1, |
| 68 IDR_PROFILE_AVATAR_2X_2, | 77 IDR_PROFILE_AVATAR_2X_2, |
| 69 IDR_PROFILE_AVATAR_2X_3, | 78 IDR_PROFILE_AVATAR_2X_3, |
| 70 IDR_PROFILE_AVATAR_2X_4, | 79 IDR_PROFILE_AVATAR_2X_4, |
| 71 IDR_PROFILE_AVATAR_2X_5, | 80 IDR_PROFILE_AVATAR_2X_5, |
| 72 IDR_PROFILE_AVATAR_2X_6, | 81 IDR_PROFILE_AVATAR_2X_6, |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 const SkBitmap& badged_bitmap = | 142 const SkBitmap& badged_bitmap = |
| 134 offscreen_canvas->getDevice()->accessBitmap(false); | 143 offscreen_canvas->getDevice()->accessBitmap(false); |
| 135 SkBitmap badged_bitmap_copy; | 144 SkBitmap badged_bitmap_copy; |
| 136 badged_bitmap.deepCopyTo(&badged_bitmap_copy, badged_bitmap.getConfig()); | 145 badged_bitmap.deepCopyTo(&badged_bitmap_copy, badged_bitmap.getConfig()); |
| 137 return badged_bitmap_copy; | 146 return badged_bitmap_copy; |
| 138 } | 147 } |
| 139 | 148 |
| 140 // Creates a desktop shortcut icon file (.ico) on the disk for a given profile, | 149 // Creates a desktop shortcut icon file (.ico) on the disk for a given profile, |
| 141 // badging the browser distribution icon with the profile avatar. | 150 // badging the browser distribution icon with the profile avatar. |
| 142 // Returns a path to the shortcut icon file on disk, which is empty if this | 151 // Returns a path to the shortcut icon file on disk, which is empty if this |
| 143 // fails. Use index 0 when assigning the resulting file as the icon. | 152 // fails. Use index 0 when assigning the resulting file as the icon. If both |
| 144 base::FilePath CreateChromeDesktopShortcutIconForProfile( | 153 // given bitmaps are empty, an unbadged icon is created. |
| 154 // |is_create| should be true if we are creating the icon at a time when it | |
|
gab
2013/06/18 15:36:58
There is no such |is_create| parameter..?
calamity
2013/06/27 08:10:11
Done.
| |
| 155 // is not possibly already in use. If it is false, we will refresh the Windows | |
| 156 // icon cache. | |
| 157 // TODO(calamity): Ideally we'd just copy the app icon verbatim from the exe's | |
| 158 // resources in the case of an unbadged icon. | |
| 159 base::FilePath CreateOrUpdateShortcutIconForProfile( | |
| 145 const base::FilePath& profile_path, | 160 const base::FilePath& profile_path, |
| 146 const SkBitmap& avatar_bitmap_1x, | 161 const SkBitmap& avatar_bitmap_1x, |
| 147 const SkBitmap& avatar_bitmap_2x) { | 162 const SkBitmap& avatar_bitmap_2x, |
| 163 const base::Closure& callback) { | |
|
gab
2013/06/18 15:36:58
Explain what is |callback| in the method comment a
calamity
2013/06/27 08:10:11
Done.
| |
| 148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 149 scoped_ptr<SkBitmap> app_icon_bitmap(GetAppIconForSize(kShortcutIconSize)); | 165 scoped_ptr<SkBitmap> app_icon_bitmap(GetAppIconForSize(kShortcutIconSize)); |
| 150 if (!app_icon_bitmap) | 166 if (!app_icon_bitmap) |
| 151 return base::FilePath(); | 167 return base::FilePath(); |
|
gab
2013/06/18 15:36:58
Also add to the method comment about what it retur
calamity
2013/06/27 08:10:11
Done.
| |
| 152 | 168 |
| 153 gfx::ImageFamily badged_bitmaps; | 169 gfx::ImageFamily badged_bitmaps; |
| 154 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap( | 170 if (!avatar_bitmap_1x.empty()) { |
| 155 BadgeIcon(*app_icon_bitmap, avatar_bitmap_1x, 1))); | |
| 156 | |
| 157 app_icon_bitmap = GetAppIconForSize(IconUtil::kLargeIconSize); | |
| 158 if (app_icon_bitmap) { | |
| 159 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap( | 171 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap( |
| 160 BadgeIcon(*app_icon_bitmap, avatar_bitmap_2x, 2))); | 172 BadgeIcon(*app_icon_bitmap, avatar_bitmap_1x, 1))); |
| 161 } | 173 } |
| 162 | 174 |
| 175 scoped_ptr<SkBitmap> large_app_icon_bitmap( | |
| 176 GetAppIconForSize(IconUtil::kLargeIconSize)); | |
| 177 if (large_app_icon_bitmap && !avatar_bitmap_2x.empty()) { | |
| 178 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap( | |
| 179 BadgeIcon(*large_app_icon_bitmap, avatar_bitmap_2x, 2))); | |
| 180 } | |
| 181 | |
| 182 // If we have no badged bitmaps, we should just use the default chrome icon. | |
| 183 if (badged_bitmaps.empty()) { | |
| 184 badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(*app_icon_bitmap)); | |
| 185 if (large_app_icon_bitmap) { | |
| 186 badged_bitmaps.Add( | |
| 187 gfx::Image::CreateFrom1xBitmap(*large_app_icon_bitmap)); | |
| 188 } | |
| 189 } | |
| 163 // Finally, write the .ico file containing this new bitmap. | 190 // Finally, write the .ico file containing this new bitmap. |
| 164 const base::FilePath icon_path = | 191 const base::FilePath icon_path = |
| 165 profile_path.AppendASCII(profiles::internal::kProfileIconFileName); | 192 profiles::internal::GetProfileIconPath(profile_path); |
| 166 if (!IconUtil::CreateIconFileFromImageFamily(badged_bitmaps, icon_path)) | 193 const bool had_icon = file_util::PathExists(icon_path); |
| 194 | |
| 195 if (!IconUtil::CreateIconFileFromImageFamily(badged_bitmaps, icon_path)) { | |
| 196 NOTREACHED(); | |
| 167 return base::FilePath(); | 197 return base::FilePath(); |
| 198 } | |
| 168 | 199 |
| 200 if (had_icon) { | |
| 201 // This invalidates the Windows icon cache and causes the icon changes to | |
| 202 // register with the taskbar and desktop. SHCNE_ASSOCCHANGED will cause a | |
| 203 // desktop flash and we would like to avoid that if possible. | |
| 204 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, | |
|
gab
2013/06/18 15:36:58
I don't think SHCNF_FLUSHNOWAIT is necessary here,
calamity
2013/06/27 08:10:11
Done.
| |
| 205 NULL, NULL); | |
| 206 } else { | |
| 207 SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, icon_path.value().c_str(), NULL); | |
| 208 } | |
| 209 if (!callback.is_null()) | |
| 210 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | |
| 169 return icon_path; | 211 return icon_path; |
| 170 } | 212 } |
| 171 | 213 |
| 214 void OnProfileIconCreateSuccess(Profile* profile) { | |
|
Alexei Svitkine (slow)
2013/06/18 15:27:19
Nit: Add a comment.
calamity
2013/06/27 08:10:11
Done.
| |
| 215 profile->GetPrefs()->SetInteger(prefs::kProfileIconVersion, | |
| 216 kCurrentProfileIconVersion); | |
|
gab
2013/06/18 15:36:58
In the current design, this will never be tried ag
| |
| 217 } | |
| 218 | |
| 172 // Gets the user and system directories for desktop shortcuts. Parameters may | 219 // Gets the user and system directories for desktop shortcuts. Parameters may |
| 173 // be NULL if a directory type is not needed. Returns true on success. | 220 // be NULL if a directory type is not needed. Returns true on success. |
| 174 bool GetDesktopShortcutsDirectories( | 221 bool GetDesktopShortcutsDirectories( |
| 175 base::FilePath* user_shortcuts_directory, | 222 base::FilePath* user_shortcuts_directory, |
| 176 base::FilePath* system_shortcuts_directory) { | 223 base::FilePath* system_shortcuts_directory) { |
| 177 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 224 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); |
| 178 if (user_shortcuts_directory && | 225 if (user_shortcuts_directory && |
| 179 !ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, | 226 !ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, |
| 180 distribution, ShellUtil::CURRENT_USER, | 227 distribution, ShellUtil::CURRENT_USER, |
| 181 user_shortcuts_directory)) { | 228 user_shortcuts_directory)) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 if (file_util::PathExists(possible_new_system_shortcut)) | 340 if (file_util::PathExists(possible_new_system_shortcut)) |
| 294 file_util::Delete(old_shortcut_path, false); | 341 file_util::Delete(old_shortcut_path, false); |
| 295 else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path)) | 342 else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path)) |
| 296 DLOG(ERROR) << "Could not rename Windows profile desktop shortcut."; | 343 DLOG(ERROR) << "Could not rename Windows profile desktop shortcut."; |
| 297 } else { | 344 } else { |
| 298 // If the shortcut does not exist, it may have been renamed by the user. In | 345 // If the shortcut does not exist, it may have been renamed by the user. In |
| 299 // that case, its name should not be changed. | 346 // that case, its name should not be changed. |
| 300 // It's also possible that a system-level shortcut exists instead - this | 347 // It's also possible that a system-level shortcut exists instead - this |
| 301 // should only be the case for the original Chrome shortcut from an | 348 // should only be the case for the original Chrome shortcut from an |
| 302 // installation. If that's the case, copy that one over - it will get its | 349 // installation. If that's the case, copy that one over - it will get its |
| 303 // properties updated by |CreateOrUpdateDesktopShortcutsForProfile()|. | 350 // properties updated by |
| 351 // |CreateOrUpdateDesktopShortcutsAndIconForProfile()|. | |
| 304 const base::FilePath possible_old_system_shortcut = | 352 const base::FilePath possible_old_system_shortcut = |
| 305 system_shortcuts_directory.Append(old_shortcut_filename); | 353 system_shortcuts_directory.Append(old_shortcut_filename); |
| 306 if (file_util::PathExists(possible_old_system_shortcut)) | 354 if (file_util::PathExists(possible_old_system_shortcut)) |
| 307 file_util::CopyFile(possible_old_system_shortcut, new_shortcut_path); | 355 file_util::CopyFile(possible_old_system_shortcut, new_shortcut_path); |
| 308 } | 356 } |
| 309 } | 357 } |
| 310 | 358 |
| 359 struct CreateOrUpdateShortcutsParams { | |
|
gab
2013/06/18 15:36:58
How about adding the callback to this list as well
calamity
2013/06/27 08:10:11
This doesn't avoid needing the parameter in Create
| |
| 360 CreateOrUpdateShortcutsParams( | |
| 361 base::FilePath profile_path, | |
| 362 ProfileShortcutManagerWin::CreateOrUpdateMode create_mode, | |
| 363 ProfileShortcutManagerWin::NonProfileShortcutAction action) | |
| 364 : profile_path(profile_path), create_mode(create_mode), action(action) {} | |
| 365 ~CreateOrUpdateShortcutsParams() {} | |
| 366 | |
| 367 ProfileShortcutManagerWin::CreateOrUpdateMode create_mode; | |
| 368 ProfileShortcutManagerWin::NonProfileShortcutAction action; | |
| 369 | |
| 370 // The path for this profile. | |
| 371 base::FilePath profile_path; | |
| 372 // The profile name before this update. Empty on create. | |
| 373 string16 old_profile_name; | |
| 374 // The new profile name. | |
| 375 string16 profile_name; | |
| 376 // Avatar images for this profile. | |
| 377 SkBitmap avatar_image_1x; | |
| 378 SkBitmap avatar_image_2x; | |
| 379 }; | |
| 380 | |
| 311 // Updates all desktop shortcuts for the given profile to have the specified | 381 // Updates all desktop shortcuts for the given profile to have the specified |
| 312 // parameters. If |create_mode| is CREATE_WHEN_NONE_FOUND, a new shortcut is | 382 // parameters. If |create_mode| is CREATE_WHEN_NONE_FOUND, a new shortcut is |
| 313 // created if no existing ones were found. Whether non-profile shortcuts should | 383 // created if no existing ones were found. Whether non-profile shortcuts should |
| 314 // be updated is specified by |action|. Must be called on the FILE thread. | 384 // be updated is specified by |action|. Must be called on the FILE thread. |
|
gab
2013/06/18 15:36:58
This comment now refers to parameters that were mo
gab
2013/06/18 15:36:58
Add a param comment for |callback|.
calamity
2013/06/27 08:10:11
Done.
calamity
2013/06/27 08:10:11
Done.
| |
| 315 void CreateOrUpdateDesktopShortcutsForProfile( | 385 void CreateOrUpdateDesktopShortcutsAndIconForProfile( |
| 316 const base::FilePath& profile_path, | 386 const CreateOrUpdateShortcutsParams& params, |
| 317 const string16& old_profile_name, | 387 const base::Closure& callback) { |
| 318 const string16& profile_name, | |
| 319 const SkBitmap& avatar_image_1x, | |
| 320 const SkBitmap& avatar_image_2x, | |
| 321 ProfileShortcutManagerWin::CreateOrUpdateMode create_mode, | |
| 322 ProfileShortcutManagerWin::NonProfileShortcutAction action) { | |
| 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 388 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 324 | 389 |
| 390 const base::FilePath shortcut_icon = | |
| 391 CreateOrUpdateShortcutIconForProfile(params.profile_path, | |
|
gab
2013/06/18 15:36:58
Shouldn't this only be called if the pref is < tha
calamity
2013/06/27 08:10:11
This is the codepath that CreateOrUpdateProfileIco
| |
| 392 params.avatar_image_1x, | |
| 393 params.avatar_image_2x, | |
| 394 callback); | |
| 395 if (shortcut_icon.empty()) { | |
| 396 NOTREACHED(); | |
| 397 return; | |
| 398 } | |
| 399 if (params.create_mode == | |
| 400 ProfileShortcutManagerWin::CREATE_OR_UPDATE_ICON_ONLY) { | |
| 401 return; | |
| 402 } | |
| 403 | |
| 325 base::FilePath chrome_exe; | 404 base::FilePath chrome_exe; |
| 326 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { | 405 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { |
| 327 NOTREACHED(); | 406 NOTREACHED(); |
| 328 return; | 407 return; |
| 329 } | 408 } |
| 330 | 409 |
| 331 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 410 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); |
| 332 // Ensure that the distribution supports creating shortcuts. If it doesn't, | 411 // Ensure that the distribution supports creating shortcuts. If it doesn't, |
| 333 // the following code may result in NOTREACHED() being hit. | 412 // the following code may result in NOTREACHED() being hit. |
| 334 DCHECK(distribution->CanCreateDesktopShortcuts()); | 413 DCHECK(distribution->CanCreateDesktopShortcuts()); |
| 335 | 414 |
| 336 if (old_profile_name != profile_name) { | 415 if (params.old_profile_name != params.profile_name) { |
| 337 const string16 old_shortcut_filename = | 416 const string16 old_shortcut_filename = |
| 338 profiles::internal::GetShortcutFilenameForProfile(old_profile_name, | 417 profiles::internal::GetShortcutFilenameForProfile( |
| 339 distribution); | 418 params.old_profile_name, |
| 419 distribution); | |
| 340 const string16 new_shortcut_filename = | 420 const string16 new_shortcut_filename = |
| 341 profiles::internal::GetShortcutFilenameForProfile(profile_name, | 421 profiles::internal::GetShortcutFilenameForProfile(params.profile_name, |
| 342 distribution); | 422 distribution); |
| 343 RenameChromeDesktopShortcutForProfile(old_shortcut_filename, | 423 RenameChromeDesktopShortcutForProfile(old_shortcut_filename, |
| 344 new_shortcut_filename); | 424 new_shortcut_filename); |
| 345 } | 425 } |
| 346 | 426 |
| 347 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); | 427 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); |
| 348 installer::Product product(distribution); | 428 installer::Product product(distribution); |
| 349 product.AddDefaultShortcutProperties(chrome_exe, &properties); | 429 product.AddDefaultShortcutProperties(chrome_exe, &properties); |
| 350 | 430 |
| 351 const string16 command_line = | 431 const string16 command_line = |
| 352 profiles::internal::CreateProfileShortcutFlags(profile_path); | 432 profiles::internal::CreateProfileShortcutFlags(params.profile_path); |
| 353 | 433 |
| 354 // Only set the profile-specific properties when |profile_name| is non empty. | 434 // Only set the profile-specific properties when |profile_name| is non empty. |
| 355 // If it is empty, it means the shortcut being created should be a regular, | 435 // If it is empty, it means the shortcut being created should be a regular, |
| 356 // non-profile Chrome shortcut. | 436 // non-profile Chrome shortcut. |
| 357 if (!profile_name.empty()) { | 437 if (!params.profile_name.empty()) { |
| 358 const base::FilePath shortcut_icon = | |
| 359 CreateChromeDesktopShortcutIconForProfile(profile_path, | |
| 360 avatar_image_1x, | |
| 361 avatar_image_2x); | |
| 362 if (!shortcut_icon.empty()) | |
| 363 properties.set_icon(shortcut_icon, 0); | |
| 364 properties.set_arguments(command_line); | 438 properties.set_arguments(command_line); |
| 439 properties.set_icon(shortcut_icon, 0); | |
| 365 } else { | 440 } else { |
| 366 // Set the arguments explicitly to the empty string to ensure that | 441 // Set the arguments explicitly to the empty string to ensure that |
| 367 // |ShellUtil::CreateOrUpdateShortcut| updates that part of the shortcut. | 442 // |ShellUtil::CreateOrUpdateShortcut| updates that part of the shortcut. |
| 368 properties.set_arguments(string16()); | 443 properties.set_arguments(string16()); |
| 369 } | 444 } |
| 370 | 445 |
| 371 properties.set_app_id( | 446 properties.set_app_id( |
| 372 ShellIntegration::GetChromiumModelIdForProfile(profile_path)); | 447 ShellIntegration::GetChromiumModelIdForProfile(params.profile_path)); |
| 373 | 448 |
| 374 ShellUtil::ShortcutOperation operation = | 449 ShellUtil::ShortcutOperation operation = |
| 375 ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING; | 450 ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING; |
| 376 | 451 |
| 377 std::vector<base::FilePath> shortcuts; | 452 std::vector<base::FilePath> shortcuts; |
| 378 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, | 453 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, |
| 379 action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS, | 454 params.action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS, |
| 380 &shortcuts); | 455 &shortcuts); |
| 381 if (create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND && | 456 if (params.create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND && |
| 382 shortcuts.empty()) { | 457 shortcuts.empty()) { |
| 383 const string16 shortcut_name = | 458 const string16 shortcut_name = |
| 384 profiles::internal::GetShortcutFilenameForProfile(profile_name, | 459 profiles::internal::GetShortcutFilenameForProfile(params.profile_name, |
| 385 distribution); | 460 distribution); |
| 386 shortcuts.push_back(base::FilePath(shortcut_name)); | 461 shortcuts.push_back(base::FilePath(shortcut_name)); |
| 387 operation = ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL; | 462 operation = ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL; |
| 388 } | 463 } |
| 389 | 464 |
| 390 for (size_t i = 0; i < shortcuts.size(); ++i) { | 465 for (size_t i = 0; i < shortcuts.size(); ++i) { |
| 391 const base::FilePath shortcut_name = | 466 const base::FilePath shortcut_name = |
| 392 shortcuts[i].BaseName().RemoveExtension(); | 467 shortcuts[i].BaseName().RemoveExtension(); |
| 393 properties.set_shortcut_name(shortcut_name.value()); | 468 properties.set_shortcut_name(shortcut_name.value()); |
| 394 ShellUtil::CreateOrUpdateShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, | 469 ShellUtil::CreateOrUpdateShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 407 file_util::FileEnumerator::FILES); | 482 file_util::FileEnumerator::FILES); |
| 408 for (base::FilePath path = enumerator.Next(); !path.empty(); | 483 for (base::FilePath path = enumerator.Next(); !path.empty(); |
| 409 path = enumerator.Next()) { | 484 path = enumerator.Next()) { |
| 410 if (IsChromeShortcut(path, chrome_exe, NULL)) | 485 if (IsChromeShortcut(path, chrome_exe, NULL)) |
| 411 return true; | 486 return true; |
| 412 } | 487 } |
| 413 | 488 |
| 414 return false; | 489 return false; |
| 415 } | 490 } |
| 416 | 491 |
| 417 // Deletes all desktop shortcuts for the specified profile and also removes the | 492 // Deletes all desktop shortcuts for the specified profile. If |
| 418 // corresponding icon file. If |ensure_shortcuts_remain| is true, then a regular | 493 // |ensure_shortcuts_remain| is true, then a regular non-profile shortcut will |
| 419 // non-profile shortcut will be created if this function would otherwise delete | 494 // be created if this function would otherwise delete the last Chrome desktop |
| 420 // the last Chrome desktop shortcut(s). Must be called on the FILE thread. | 495 // shortcut(s). Must be called on the FILE thread. |
| 421 void DeleteDesktopShortcutsAndIconFile(const base::FilePath& profile_path, | 496 void DeleteDesktopShortcuts(const base::FilePath& profile_path, |
| 422 bool ensure_shortcuts_remain) { | 497 bool ensure_shortcuts_remain) { |
| 423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 498 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 424 | 499 |
| 425 base::FilePath chrome_exe; | 500 base::FilePath chrome_exe; |
| 426 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { | 501 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { |
| 427 NOTREACHED(); | 502 NOTREACHED(); |
| 428 return; | 503 return; |
| 429 } | 504 } |
| 430 | 505 |
| 431 const string16 command_line = | 506 const string16 command_line = |
| 432 profiles::internal::CreateProfileShortcutFlags(profile_path); | 507 profiles::internal::CreateProfileShortcutFlags(profile_path); |
| 433 std::vector<base::FilePath> shortcuts; | 508 std::vector<base::FilePath> shortcuts; |
| 434 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false, | 509 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false, |
| 435 &shortcuts); | 510 &shortcuts); |
| 436 | 511 |
| 437 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 512 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); |
| 438 for (size_t i = 0; i < shortcuts.size(); ++i) { | 513 for (size_t i = 0; i < shortcuts.size(); ++i) { |
| 439 // Use file_util::Delete() instead of ShellUtil::RemoveShortcut(), as the | 514 // Use file_util::Delete() instead of ShellUtil::RemoveShortcut(), as the |
| 440 // latter causes non-profile taskbar shortcuts to be unpinned. | 515 // latter causes non-profile taskbar shortcuts to be unpinned. |
| 441 file_util::Delete(shortcuts[i], false); | 516 file_util::Delete(shortcuts[i], false); |
| 442 // Notify the shell that the shortcut was deleted to ensure desktop refresh. | 517 // Notify the shell that the shortcut was deleted to ensure desktop refresh. |
| 443 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(), | 518 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(), |
| 444 NULL); | 519 NULL); |
| 445 } | 520 } |
| 446 | 521 |
| 447 const base::FilePath icon_path = | |
| 448 profile_path.AppendASCII(profiles::internal::kProfileIconFileName); | |
| 449 file_util::Delete(icon_path, false); | |
| 450 | |
| 451 // If |ensure_shortcuts_remain| is true and deleting this profile caused the | 522 // If |ensure_shortcuts_remain| is true and deleting this profile caused the |
| 452 // last shortcuts to be removed, re-create a regular non-profile shortcut. | 523 // last shortcuts to be removed, re-create a regular non-profile shortcut. |
| 453 const bool had_shortcuts = !shortcuts.empty(); | 524 const bool had_shortcuts = !shortcuts.empty(); |
| 454 if (ensure_shortcuts_remain && had_shortcuts && | 525 if (ensure_shortcuts_remain && had_shortcuts && |
| 455 !ChromeDesktopShortcutsExist(chrome_exe)) { | 526 !ChromeDesktopShortcutsExist(chrome_exe)) { |
| 456 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 527 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); |
| 457 // Ensure that the distribution supports creating shortcuts. If it doesn't, | 528 // Ensure that the distribution supports creating shortcuts. If it doesn't, |
| 458 // the following code may result in NOTREACHED() being hit. | 529 // the following code may result in NOTREACHED() being hit. |
| 459 DCHECK(distribution->CanCreateDesktopShortcuts()); | 530 DCHECK(distribution->CanCreateDesktopShortcuts()); |
| 460 installer::Product product(distribution); | 531 installer::Product product(distribution); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 522 SkBitmap bitmap_copy; | 593 SkBitmap bitmap_copy; |
| 523 image_bitmap->deepCopyTo(&bitmap_copy, image_bitmap->getConfig()); | 594 image_bitmap->deepCopyTo(&bitmap_copy, image_bitmap->getConfig()); |
| 524 return bitmap_copy; | 595 return bitmap_copy; |
| 525 } | 596 } |
| 526 | 597 |
| 527 } // namespace | 598 } // namespace |
| 528 | 599 |
| 529 namespace profiles { | 600 namespace profiles { |
| 530 namespace internal { | 601 namespace internal { |
| 531 | 602 |
| 532 const char kProfileIconFileName[] = "Google Profile.ico"; | 603 base::FilePath GetProfileIconPath(const base::FilePath& profile_path) { |
| 604 return profile_path.AppendASCII(kProfileIconFileName); | |
| 605 } | |
| 533 | 606 |
| 534 string16 GetShortcutFilenameForProfile(const string16& profile_name, | 607 string16 GetShortcutFilenameForProfile(const string16& profile_name, |
| 535 BrowserDistribution* distribution) { | 608 BrowserDistribution* distribution) { |
| 536 string16 shortcut_name; | 609 string16 shortcut_name; |
| 537 if (!profile_name.empty()) { | 610 if (!profile_name.empty()) { |
| 538 shortcut_name.append(SanitizeShortcutProfileNameString(profile_name)); | 611 shortcut_name.append(SanitizeShortcutProfileNameString(profile_name)); |
| 539 shortcut_name.append(L" - "); | 612 shortcut_name.append(L" - "); |
| 540 shortcut_name.append(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); | 613 shortcut_name.append(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); |
| 541 } else { | 614 } else { |
| 542 shortcut_name.append(distribution->GetAppShortCutName()); | 615 shortcut_name.append(distribution->GetAppShortCutName()); |
| 543 } | 616 } |
| 544 return shortcut_name + installer::kLnkExt; | 617 return shortcut_name + installer::kLnkExt; |
| 545 } | 618 } |
| 546 | 619 |
| 547 string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) { | 620 string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) { |
| 548 return base::StringPrintf(L"--%ls=\"%ls\"", | 621 return base::StringPrintf(L"--%ls=\"%ls\"", |
| 549 ASCIIToUTF16(switches::kProfileDirectory).c_str(), | 622 ASCIIToUTF16(switches::kProfileDirectory).c_str(), |
| 550 profile_path.BaseName().value().c_str()); | 623 profile_path.BaseName().value().c_str()); |
| 551 } | 624 } |
| 552 | 625 |
| 553 } // namespace internal | 626 } // namespace internal |
| 554 } // namespace profiles | 627 } // namespace profiles |
| 555 | 628 |
| 556 // static | 629 // static |
| 557 bool ProfileShortcutManager::IsFeatureEnabled() { | 630 bool ProfileShortcutManager::IsFeatureEnabled() { |
| 558 return BrowserDistribution::GetDistribution()->CanCreateDesktopShortcuts() && | 631 return BrowserDistribution::GetDistribution()->CanCreateDesktopShortcuts() && |
| 559 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir) && | 632 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir); |
|
gab
2013/06/18 15:36:58
I still don't like that this is disabled for --use
calamity
2013/06/27 08:10:11
This isn't a problem. Once relaunch details on bro
gab
2013/06/27 14:18:56
Ah, so the plan is to keep the runtime badging cod
Alexei Svitkine (slow)
2013/06/27 15:53:08
I think this discussion is outside the scope of th
gab
2013/06/27 17:55:44
Right, what I meant is that if the relaunch detail
| |
| 560 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kShowAppList); | |
|
gab
2013/06/18 15:36:58
Can this be done in a precursor CL? I feel this on
calamity
2013/06/27 08:10:11
Done.
| |
| 561 } | 633 } |
| 562 | 634 |
| 563 // static | 635 // static |
| 564 ProfileShortcutManager* ProfileShortcutManager::Create( | 636 ProfileShortcutManager* ProfileShortcutManager::Create( |
| 565 ProfileManager* manager) { | 637 ProfileManager* manager) { |
| 566 return new ProfileShortcutManagerWin(manager); | 638 return new ProfileShortcutManagerWin(manager); |
| 567 } | 639 } |
| 568 | 640 |
| 569 ProfileShortcutManagerWin::ProfileShortcutManagerWin(ProfileManager* manager) | 641 ProfileShortcutManagerWin::ProfileShortcutManagerWin(ProfileManager* manager) |
| 570 : profile_manager_(manager) { | 642 : profile_manager_(manager) { |
| 571 DCHECK_EQ( | 643 DCHECK_EQ( |
| 572 arraysize(kProfileAvatarIconResources2x), | 644 arraysize(kProfileAvatarIconResources2x), |
| 573 profile_manager_->GetProfileInfoCache().GetDefaultAvatarIconCount()); | 645 profile_manager_->GetProfileInfoCache().GetDefaultAvatarIconCount()); |
| 574 | 646 |
| 647 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, | |
|
Alexei Svitkine (slow)
2013/06/18 15:27:19
Add a comment to explain this is for profile icon
Alexei Svitkine (slow)
2013/06/18 15:44:32
Hmm, is this notified only when a profile gets _cr
calamity
2013/06/27 08:10:11
I'm fairly sure it's on load. It's in profile_impl
gab
2013/06/27 14:18:56
Ah ok I see, it seems to be when the Profile objec
gab
2013/07/05 13:47:24
Did you try this to confirm?
calamity
2013/07/08 07:45:49
Yeah, works as expected. Put a print and it comes
| |
| 648 content::NotificationService::AllSources()); | |
| 649 | |
| 575 profile_manager_->GetProfileInfoCache().AddObserver(this); | 650 profile_manager_->GetProfileInfoCache().AddObserver(this); |
| 576 } | 651 } |
| 577 | 652 |
| 578 ProfileShortcutManagerWin::~ProfileShortcutManagerWin() { | 653 ProfileShortcutManagerWin::~ProfileShortcutManagerWin() { |
| 579 profile_manager_->GetProfileInfoCache().RemoveObserver(this); | 654 profile_manager_->GetProfileInfoCache().RemoveObserver(this); |
| 580 } | 655 } |
| 581 | 656 |
| 657 void ProfileShortcutManagerWin::CreateOrUpdateProfileIcon( | |
| 658 const base::FilePath& profile_path, | |
| 659 const base::Closure& callback) { | |
| 660 CreateOrUpdateShortcutsForProfileAtPath(profile_path, | |
| 661 CREATE_OR_UPDATE_ICON_ONLY, | |
|
gab
2013/06/27 14:18:56
Instead of introducing CREATE_OR_UPDATE_ICON_ONLY
Alexei Svitkine (slow)
2013/06/27 15:53:08
Seems like a reasonable suggestion to me, just add
calamity
2013/07/05 08:04:33
I'll still need to get the avatar resources...? I'
gab
2013/07/05 13:47:24
Ah, yes, my bad I hadn't noticed this called into
Alexei Svitkine (slow)
2013/07/05 15:14:24
Right, I remember now why I was okay with the curr
| |
| 662 IGNORE_NON_PROFILE_SHORTCUTS, | |
| 663 callback); | |
| 664 } | |
| 665 | |
| 582 void ProfileShortcutManagerWin::CreateProfileShortcut( | 666 void ProfileShortcutManagerWin::CreateProfileShortcut( |
| 583 const base::FilePath& profile_path) { | 667 const base::FilePath& profile_path) { |
| 584 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND, | 668 CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND, |
| 585 IGNORE_NON_PROFILE_SHORTCUTS); | 669 IGNORE_NON_PROFILE_SHORTCUTS, |
| 670 base::Closure()); | |
| 586 } | 671 } |
| 587 | 672 |
| 588 void ProfileShortcutManagerWin::RemoveProfileShortcuts( | 673 void ProfileShortcutManagerWin::RemoveProfileShortcuts( |
| 589 const base::FilePath& profile_path) { | 674 const base::FilePath& profile_path) { |
| 590 BrowserThread::PostTask( | 675 BrowserThread::PostTask( |
| 591 BrowserThread::FILE, FROM_HERE, | 676 BrowserThread::FILE, FROM_HERE, |
| 592 base::Bind(&DeleteDesktopShortcutsAndIconFile, profile_path, false)); | 677 base::Bind(&DeleteDesktopShortcuts, profile_path, false)); |
| 593 } | 678 } |
| 594 | 679 |
| 595 void ProfileShortcutManagerWin::HasProfileShortcuts( | 680 void ProfileShortcutManagerWin::HasProfileShortcuts( |
| 596 const base::FilePath& profile_path, | 681 const base::FilePath& profile_path, |
| 597 const base::Callback<void(bool)>& callback) { | 682 const base::Callback<void(bool)>& callback) { |
| 598 BrowserThread::PostTaskAndReplyWithResult( | 683 BrowserThread::PostTaskAndReplyWithResult( |
| 599 BrowserThread::FILE, FROM_HERE, | 684 BrowserThread::FILE, FROM_HERE, |
| 600 base::Bind(&HasAnyProfileShortcuts, profile_path), callback); | 685 base::Bind(&HasAnyProfileShortcuts, profile_path), callback); |
| 601 } | 686 } |
| 602 | 687 |
| 603 void ProfileShortcutManagerWin::OnProfileAdded( | 688 void ProfileShortcutManagerWin::OnProfileAdded( |
| 604 const base::FilePath& profile_path) { | 689 const base::FilePath& profile_path) { |
| 690 CreateOrUpdateProfileIcon(profile_path, base::Closure()); | |
| 605 if (profile_manager_->GetProfileInfoCache().GetNumberOfProfiles() == 2) { | 691 if (profile_manager_->GetProfileInfoCache().GetNumberOfProfiles() == 2) { |
| 606 // When the second profile is added, make existing non-profile shortcuts | 692 // When the second profile is added, make existing non-profile shortcuts |
| 607 // point to the first profile and be badged/named appropriately. | 693 // point to the first profile and be badged/named appropriately. |
| 608 CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path), | 694 CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path), |
| 609 UPDATE_EXISTING_ONLY, | 695 UPDATE_EXISTING_ONLY, |
| 610 UPDATE_NON_PROFILE_SHORTCUTS); | 696 UPDATE_NON_PROFILE_SHORTCUTS, |
| 697 base::Closure()); | |
| 611 } | 698 } |
| 612 } | 699 } |
| 613 | 700 |
| 614 void ProfileShortcutManagerWin::OnProfileWillBeRemoved( | 701 void ProfileShortcutManagerWin::OnProfileWillBeRemoved( |
| 615 const base::FilePath& profile_path) { | 702 const base::FilePath& profile_path) { |
| 616 } | 703 } |
| 617 | 704 |
| 618 void ProfileShortcutManagerWin::OnProfileWasRemoved( | 705 void ProfileShortcutManagerWin::OnProfileWasRemoved( |
| 619 const base::FilePath& profile_path, | 706 const base::FilePath& profile_path, |
| 620 const string16& profile_name) { | 707 const string16& profile_name) { |
| 621 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); | 708 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); |
| 622 // If there is only one profile remaining, remove the badging information | 709 // If there is only one profile remaining, remove the badging information |
| 623 // from an existing shortcut. | 710 // from an existing shortcut. |
| 624 const bool deleting_down_to_last_profile = (cache.GetNumberOfProfiles() == 1); | 711 const bool deleting_down_to_last_profile = (cache.GetNumberOfProfiles() == 1); |
| 625 if (deleting_down_to_last_profile) { | 712 if (deleting_down_to_last_profile) { |
| 713 // This is needed to unbadge the icon. | |
| 626 CreateOrUpdateShortcutsForProfileAtPath(cache.GetPathOfProfileAtIndex(0), | 714 CreateOrUpdateShortcutsForProfileAtPath(cache.GetPathOfProfileAtIndex(0), |
| 627 UPDATE_EXISTING_ONLY, | 715 UPDATE_EXISTING_ONLY, |
| 628 IGNORE_NON_PROFILE_SHORTCUTS); | 716 IGNORE_NON_PROFILE_SHORTCUTS, |
| 717 base::Closure()); | |
| 629 } | 718 } |
| 630 | 719 |
| 631 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 720 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 632 base::Bind(&DeleteDesktopShortcutsAndIconFile, | 721 base::Bind(&DeleteDesktopShortcuts, |
| 633 profile_path, | 722 profile_path, |
| 634 deleting_down_to_last_profile)); | 723 deleting_down_to_last_profile)); |
| 635 } | 724 } |
| 636 | 725 |
| 637 void ProfileShortcutManagerWin::OnProfileNameChanged( | 726 void ProfileShortcutManagerWin::OnProfileNameChanged( |
| 638 const base::FilePath& profile_path, | 727 const base::FilePath& profile_path, |
| 639 const string16& old_profile_name) { | 728 const string16& old_profile_name) { |
| 640 CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY, | 729 CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY, |
| 641 IGNORE_NON_PROFILE_SHORTCUTS); | 730 IGNORE_NON_PROFILE_SHORTCUTS, |
| 731 base::Closure()); | |
| 642 } | 732 } |
| 643 | 733 |
| 644 void ProfileShortcutManagerWin::OnProfileAvatarChanged( | 734 void ProfileShortcutManagerWin::OnProfileAvatarChanged( |
| 645 const base::FilePath& profile_path) { | 735 const base::FilePath& profile_path) { |
| 646 CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY, | 736 CreateOrUpdateProfileIcon(profile_path, base::Closure()); |
| 647 IGNORE_NON_PROFILE_SHORTCUTS); | |
| 648 } | 737 } |
| 649 | 738 |
| 650 base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath( | 739 base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath( |
| 651 const base::FilePath& profile_path) { | 740 const base::FilePath& profile_path) { |
| 652 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); | 741 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); |
| 653 DCHECK_EQ(2U, cache.GetNumberOfProfiles()); | 742 DCHECK_EQ(2U, cache.GetNumberOfProfiles()); |
| 654 // Get the index of the current profile, in order to find the index of the | 743 // Get the index of the current profile, in order to find the index of the |
| 655 // other profile. | 744 // other profile. |
| 656 size_t current_profile_index = cache.GetIndexOfProfileWithPath(profile_path); | 745 size_t current_profile_index = cache.GetIndexOfProfileWithPath(profile_path); |
| 657 size_t other_profile_index = (current_profile_index == 0) ? 1 : 0; | 746 size_t other_profile_index = (current_profile_index == 0) ? 1 : 0; |
| 658 return cache.GetPathOfProfileAtIndex(other_profile_index); | 747 return cache.GetPathOfProfileAtIndex(other_profile_index); |
| 659 } | 748 } |
| 660 | 749 |
| 661 void ProfileShortcutManagerWin::CreateOrUpdateShortcutsForProfileAtPath( | 750 void ProfileShortcutManagerWin::CreateOrUpdateShortcutsForProfileAtPath( |
| 662 const base::FilePath& profile_path, | 751 const base::FilePath& profile_path, |
| 663 CreateOrUpdateMode create_mode, | 752 CreateOrUpdateMode create_mode, |
| 664 NonProfileShortcutAction action) { | 753 NonProfileShortcutAction action, |
| 754 const base::Closure& callback) { | |
| 755 CreateOrUpdateShortcutsParams params(profile_path, create_mode, action); | |
| 756 | |
| 665 ProfileInfoCache* cache = &profile_manager_->GetProfileInfoCache(); | 757 ProfileInfoCache* cache = &profile_manager_->GetProfileInfoCache(); |
| 666 size_t profile_index = cache->GetIndexOfProfileWithPath(profile_path); | 758 size_t profile_index = cache->GetIndexOfProfileWithPath(profile_path); |
| 667 if (profile_index == std::string::npos) | 759 if (profile_index == std::string::npos) |
| 668 return; | 760 return; |
| 669 bool remove_badging = cache->GetNumberOfProfiles() == 1; | 761 bool remove_badging = cache->GetNumberOfProfiles() == 1; |
| 670 | 762 |
| 671 string16 old_shortcut_appended_name = | 763 params.old_profile_name = |
| 672 cache->GetShortcutNameOfProfileAtIndex(profile_index); | 764 cache->GetShortcutNameOfProfileAtIndex(profile_index); |
| 673 | 765 |
| 674 // Exit early if the mode is to update existing profile shortcuts only and | 766 // 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 | 767 // none were ever created for this profile, per the shortcut name not being |
| 676 // set in the profile info cache. | 768 // set in the profile info cache. |
| 677 if (old_shortcut_appended_name.empty() && | 769 if (params.old_profile_name.empty() && |
| 678 create_mode == UPDATE_EXISTING_ONLY && | 770 create_mode == UPDATE_EXISTING_ONLY && |
| 679 action == IGNORE_NON_PROFILE_SHORTCUTS) { | 771 action == IGNORE_NON_PROFILE_SHORTCUTS) { |
| 680 return; | 772 return; |
| 681 } | 773 } |
| 682 | 774 |
| 683 string16 new_shortcut_appended_name; | 775 if (!remove_badging) { |
| 684 if (!remove_badging) | 776 params.profile_name = cache->GetNameOfProfileAtIndex(profile_index); |
| 685 new_shortcut_appended_name = cache->GetNameOfProfileAtIndex(profile_index); | |
| 686 | 777 |
| 687 SkBitmap avatar_bitmap_copy_1x; | |
| 688 SkBitmap avatar_bitmap_copy_2x; | |
| 689 if (!remove_badging) { | |
| 690 const size_t icon_index = | 778 const size_t icon_index = |
| 691 cache->GetAvatarIconIndexOfProfileAtIndex(profile_index); | 779 cache->GetAvatarIconIndexOfProfileAtIndex(profile_index); |
| 692 const int resource_id_1x = | 780 const int resource_id_1x = |
| 693 cache->GetDefaultAvatarIconResourceIDAtIndex(icon_index); | 781 cache->GetDefaultAvatarIconResourceIDAtIndex(icon_index); |
| 694 const int resource_id_2x = kProfileAvatarIconResources2x[icon_index]; | 782 const int resource_id_2x = kProfileAvatarIconResources2x[icon_index]; |
| 695 // Make a copy of the SkBitmaps to ensure that we can safely use the image | 783 // Make a copy of the SkBitmaps to ensure that we can safely use the image |
| 696 // data on the FILE thread. | 784 // data on the FILE thread. |
| 697 avatar_bitmap_copy_1x = GetImageResourceSkBitmapCopy(resource_id_1x); | 785 params.avatar_image_1x = GetImageResourceSkBitmapCopy(resource_id_1x); |
| 698 avatar_bitmap_copy_2x = GetImageResourceSkBitmapCopy(resource_id_2x); | 786 params.avatar_image_2x = GetImageResourceSkBitmapCopy(resource_id_2x); |
| 699 } | 787 } |
| 700 BrowserThread::PostTask( | 788 BrowserThread::PostTask( |
| 701 BrowserThread::FILE, FROM_HERE, | 789 BrowserThread::FILE, FROM_HERE, |
| 702 base::Bind(&CreateOrUpdateDesktopShortcutsForProfile, profile_path, | 790 base::Bind(&CreateOrUpdateDesktopShortcutsAndIconForProfile, params, |
| 703 old_shortcut_appended_name, new_shortcut_appended_name, | 791 callback)); |
| 704 avatar_bitmap_copy_1x, avatar_bitmap_copy_2x, create_mode, | |
| 705 action)); | |
| 706 | 792 |
| 707 cache->SetShortcutNameOfProfileAtIndex(profile_index, | 793 cache->SetShortcutNameOfProfileAtIndex(profile_index, |
| 708 new_shortcut_appended_name); | 794 params.profile_name); |
| 709 } | 795 } |
| 796 | |
| 797 void ProfileShortcutManagerWin::Observe( | |
| 798 int type, | |
| 799 const content::NotificationSource& source, | |
| 800 const content::NotificationDetails& details) { | |
| 801 switch (type) { | |
|
Alexei Svitkine (slow)
2013/06/18 15:27:19
How about:
if (type != chrome::NOTIFICATION_PROFI
calamity
2013/06/27 08:10:11
Other files such as:
-chrome/browser/android/chrom
gab
2013/06/27 14:18:56
Yea, I like the switch personally and have seen th
Alexei Svitkine (slow)
2013/06/27 15:53:08
Fair enough, keep the switch then. :)
| |
| 802 case chrome::NOTIFICATION_PROFILE_CREATED: { | |
|
gab
2013/06/27 14:18:56
Add a comment above this stipulating your findings
gab
2013/07/05 13:47:24
Ping on this -- mostly for my sanity as I don't li
calamity
2013/07/08 07:45:49
Done.
| |
| 803 Profile* profile = | |
| 804 content::Source<Profile>(source).ptr()->GetOriginalProfile(); | |
| 805 if (profile->GetPrefs()->GetInteger(prefs::kProfileIconVersion) < | |
|
Alexei Svitkine (slow)
2013/06/18 15:27:19
I suggest moving this to another anonymous functio
calamity
2013/06/27 08:10:11
Done.
| |
| 806 kCurrentProfileIconVersion) { | |
|
gab
2013/06/18 15:36:58
I think this condition needs to be check every tim
calamity
2013/06/27 08:10:11
NOTIFICATION_PROFILE_CREATED was recommended by sa
| |
| 807 // Ensure the profile's icon file has been created. | |
| 808 CreateOrUpdateProfileIcon( | |
| 809 profile->GetPath(), | |
| 810 base::Bind(&OnProfileIconCreateSuccess, profile)); | |
| 811 } | |
| 812 break; | |
| 813 } | |
| 814 default: | |
| 815 NOTREACHED(); | |
|
sail
2013/06/18 05:10:21
break;?
calamity
2013/06/27 08:10:11
Done.
| |
| 816 } | |
| 817 } | |
| OLD | NEW |