profile_shortcut_manager_win.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_shortcut_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string16.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/app_icon_win.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/pref_service.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_info_cache_observer.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_info_util.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/auto_launch_util.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/browser_distribution.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/product.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/shell_util.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/image_operations.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/platform_canvas.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/icon_util.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kProfileIconFileName[] = "Google Profile.ico"; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kProfileAvatarShortcutBadgeWidth = 28; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kProfileAvatarShortcutBadgeHeight = 28; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kShortcutIconSize = 48; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a desktop shortcut icon file (.ico) on the disk for a given profile, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// badging the browser distribution icon with the profile avatar. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a path to the shortcut icon file on disk, which is empty if this 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fails. Use index 0 when assigning the resulting file as the icon. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilePath CreateChromeDesktopShortcutIconForProfile( 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& profile_path, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap& avatar_bitmap) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HICON app_icon_handle = GetAppIconForSize(kShortcutIconSize); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SkBitmap> app_icon_bitmap( 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconUtil::CreateSkBitmapFromHICON(app_icon_handle)); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DestroyIcon(app_icon_handle); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!app_icon_bitmap.get()) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FilePath(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rlp): Share this chunk of code with 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avatar_menu_button::DrawTaskBarDecoration. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap* source_bitmap = NULL; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmap squarer_bitmap; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((avatar_bitmap.width() == profiles::kAvatarIconWidth) && 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (avatar_bitmap.height() == profiles::kAvatarIconHeight)) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shave a couple of columns so the bitmap is more square. So when 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resized to a square aspect ratio it looks pretty. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = 2; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avatar_bitmap.extractSubset(&squarer_bitmap, SkIRect::MakeXYWH(x, 0, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profiles::kAvatarIconWidth - x * 2, profiles::kAvatarIconHeight)); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_bitmap = &squarer_bitmap; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_bitmap = &avatar_bitmap; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmap sk_icon = skia::ImageOperations::Resize( 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *source_bitmap, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) skia::ImageOperations::RESIZE_LANCZOS3, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kProfileAvatarShortcutBadgeWidth, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kProfileAvatarShortcutBadgeHeight); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Overlay the avatar on the icon, anchoring it to the bottom-right of the 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SkCanvas> offscreen_canvas( 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) skia::CreateBitmapCanvas(app_icon_bitmap->width(), 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) app_icon_bitmap->height(), 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false)); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(offscreen_canvas.get()); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offscreen_canvas->drawBitmap(*app_icon_bitmap, 0, 0); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offscreen_canvas->drawBitmap( 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sk_icon, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) app_icon_bitmap->width() - kProfileAvatarShortcutBadgeWidth, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) app_icon_bitmap->height() - kProfileAvatarShortcutBadgeHeight); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap& final_bitmap = 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offscreen_canvas->getDevice()->accessBitmap(false); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally, write the .ico file containing this new bitmap. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath icon_path = profile_path.AppendASCII(kProfileIconFileName); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IconUtil::CreateIconFileFromSkBitmap(final_bitmap, icon_path)) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FilePath(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return icon_path; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 CreateProfileShortcutFlags(const FilePath& profile_path) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(L"--%ls=\"%ls\"", 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16(switches::kProfileDirectory).c_str(), 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_path.BaseName().value().c_str()); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wrap a ShellUtil/FileUtil function that returns a bool so it can be posted 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in a task to the FILE thread. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CallBoolFunction( 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Callback<bool(void)>& bool_function) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool_function.Run(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Renames an existing Chrome desktop profile shortcut. Must be called on the 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FILE thread. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RenameChromeDesktopShortcutForProfile( 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& old_shortcut_file, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& new_shortcut_file) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath shortcut_path; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::CURRENT_USER, &shortcut_path)) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath old_shortcut_path = shortcut_path.Append(old_shortcut_file); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath new_shortcut_path = shortcut_path.Append(new_shortcut_file); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file_util::Move(old_shortcut_path, new_shortcut_path)) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Could not rename Windows profile desktop shortcut."; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Create or update a profile desktop shortcut. Must be called on the FILE 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateOrUpdateProfileDesktopShortcut( 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& profile_path, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& profile_name, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap& avatar_image, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool create) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath shortcut_icon = 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateChromeDesktopShortcutIconForProfile(profile_path, avatar_image); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_exe; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::Product product(dist); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) product.AddDefaultShortcutProperties(chrome_exe, &properties); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) properties.set_arguments(CreateProfileShortcutFlags(profile_path)); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shortcut_icon.empty()) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) properties.set_icon(shortcut_icon, 0); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) properties.set_shortcut_name( 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileShortcutManager::GetShortcutNameForProfile(profile_name)); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::ShortcutOperation operation = 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create ? ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS : 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::CreateOrUpdateShortcut( 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist, properties, operation); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProfileShortcutManagerWin : public ProfileShortcutManager, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public ProfileInfoCacheObserver { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ProfileShortcutManagerWin(ProfileManager* manager); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ProfileShortcutManagerWin(); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void CreateProfileShortcut(const FilePath& profile_path) OVERRIDE; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProfileInfoCacheObserver: 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnProfileAdded(const FilePath& profile_path) OVERRIDE; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnProfileWillBeRemoved(const FilePath& profile_path) OVERRIDE; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnProfileWasRemoved(const FilePath& profile_path, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& profile_name) OVERRIDE; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnProfileNameChanged(const FilePath& profile_path, 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& old_profile_name) OVERRIDE; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnProfileAvatarChanged(const FilePath& profile_path) OVERRIDE; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartProfileShortcutNameChange(const FilePath& profile_path, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& old_profile_name); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gives the profile path of an alternate profile than |profile_path|. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Must only be called when the number profiles is 2. 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath GetOtherProfilePath(const FilePath& profile_path); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdateShortcutForProfileAtPath(const FilePath& profile_path, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool create_always); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileManager* profile_manager_; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ProfileShortcutManagerWin); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileShortcutManager::IsFeatureEnabled() { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileShortcutManager* ProfileShortcutManager::Create( 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileManager* manager) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new ProfileShortcutManagerWin(manager); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 ProfileShortcutManager::GetShortcutNameForProfile( 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& profile_name) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 shortcut_name(dist->GetAppShortCutName()); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_name.append(L" ("); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_name.append(profile_name); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_name.append(L")"); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shortcut_name; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileShortcutManagerWin::ProfileShortcutManagerWin(ProfileManager* manager) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : profile_manager_(manager) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_manager_->GetProfileInfoCache().AddObserver(this); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileShortcutManagerWin::~ProfileShortcutManagerWin() { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_manager_->GetProfileInfoCache().RemoveObserver(this); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileShortcutManagerWin::CreateProfileShortcut( 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& profile_path) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateShortcutForProfileAtPath(profile_path, true); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileShortcutManagerWin::OnProfileAdded(const FilePath& profile_path) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_manager_->GetProfileInfoCache().GetNumberOfProfiles() == 1) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateShortcutForProfileAtPath(profile_path, true); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if ( 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_manager_->GetProfileInfoCache().GetNumberOfProfiles() == 2) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateShortcutForProfileAtPath( 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetOtherProfilePath(profile_path), false); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileShortcutManagerWin::OnProfileWillBeRemoved( 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& profile_path) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileShortcutManagerWin::OnProfileWasRemoved( 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& profile_path, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& profile_name) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is only one profile remaining, remove the badging information 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from an existing shortcut. 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_manager_->GetProfileInfoCache().GetNumberOfProfiles() == 1) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateShortcutForProfileAtPath( 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_manager_->GetProfileInfoCache().GetPathOfProfileAtIndex(0), 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 profile_name_updated; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_manager_->GetProfileInfoCache().GetNumberOfProfiles() != 0) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_name_updated = profile_name; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_exe; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (PathService::Get(base::FILE_EXE, &chrome_exe)) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CallBoolFunction, base::Bind( 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ShellUtil::RemoveShortcut, 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::SHORTCUT_LOCATION_DESKTOP, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dist, chrome_exe.value(), ShellUtil::CURRENT_USER, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &GetShortcutNameForProfile(profile_name_updated)))); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath icon_path = profile_path.AppendASCII(kProfileIconFileName); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CallBoolFunction, base::Bind( 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &file_util::Delete, icon_path, false))); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileShortcutManagerWin::OnProfileNameChanged( 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& profile_path, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& old_profile_name) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateShortcutForProfileAtPath(profile_path, false); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileShortcutManagerWin::OnProfileAvatarChanged( 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& profile_path) { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateShortcutForProfileAtPath(profile_path, false); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileShortcutManagerWin::StartProfileShortcutNameChange( 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& profile_path, 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& old_profile_name) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t profile_index = profile_manager_->GetProfileInfoCache(). 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetIndexOfProfileWithPath(profile_path); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_index == std::string::npos) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the shortcut will have an appended name, get the profile name. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 new_profile_name = 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (profile_manager_->GetProfileInfoCache().GetNumberOfProfiles() == 1) ? 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16() : 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_manager_->GetProfileInfoCache(). 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetNameOfProfileAtIndex(profile_index); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 old_shortcut_file(GetShortcutNameForProfile(old_profile_name)); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 new_shortcut_file(GetShortcutNameForProfile(new_profile_name)); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&RenameChromeDesktopShortcutForProfile, 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_shortcut_file, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_shortcut_file)); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilePath ProfileShortcutManagerWin::GetOtherProfilePath( 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& profile_path) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(2U, profile_manager_->GetProfileInfoCache().GetNumberOfProfiles()); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the index of the current profile, in order to find the index of the 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other profile. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t current_profile_index = profile_manager_->GetProfileInfoCache(). 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetIndexOfProfileWithPath(profile_path); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t other_profile_index = (current_profile_index == 0) ? 1 : 0; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return profile_manager_->GetProfileInfoCache(). 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetPathOfProfileAtIndex(other_profile_index); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileShortcutManagerWin::UpdateShortcutForProfileAtPath( 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& profile_path, 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool create_always) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t profile_index = profile_manager_->GetProfileInfoCache(). 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetIndexOfProfileWithPath(profile_path); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_index == std::string::npos) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool remove_badging = profile_manager_->GetProfileInfoCache(). 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetNumberOfProfiles() == 1; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 old_shortcut_appended_name = 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_manager_->GetProfileInfoCache(). 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetShortcutNameOfProfileAtIndex(profile_index); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 new_shortcut_appended_name; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!remove_badging) { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_shortcut_appended_name = 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_manager_->GetProfileInfoCache(). 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetNameOfProfileAtIndex(profile_index); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!create_always && 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_shortcut_appended_name != old_shortcut_appended_name) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartProfileShortcutNameChange(profile_path, old_shortcut_appended_name); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmap profile_avatar_bitmap_copy; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!remove_badging) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t profile_icon_index = profile_manager_->GetProfileInfoCache(). 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAvatarIconIndexOfProfileAtIndex(profile_index); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Image profile_avatar_image = ResourceBundle::GetSharedInstance(). 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetNativeImageNamed( 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_manager_->GetProfileInfoCache(). 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDefaultAvatarIconResourceIDAtIndex(profile_icon_index)); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!profile_avatar_image.IsEmpty()); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap* profile_avatar_bitmap = 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_avatar_image.ToSkBitmap(); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make a copy of the SkBitmap to ensure that we can safely use the image 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data on the FILE thread. 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_avatar_bitmap->deepCopyTo( 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &profile_avatar_bitmap_copy, profile_avatar_bitmap->getConfig()); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CreateOrUpdateProfileDesktopShortcut, 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_path, new_shortcut_appended_name, 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_avatar_bitmap_copy, create_always)); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_manager_->GetProfileInfoCache().SetShortcutNameOfProfileAtIndex( 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_index, new_shortcut_appended_name); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385