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

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

Issue 10837352: Update profile desktop shortcuts (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Fixed issues and added a unit test for update Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/profiles/profile_shortcut_manager.h" 5 #include "chrome/browser/profiles/profile_shortcut_manager.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/path_service.h" 12 #include "base/path_service.h"
13 #include "base/stringprintf.h" 13 #include "base/stringprintf.h"
14 #include "base/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
15 #include "chrome/browser/app_icon_win.h" 15 #include "chrome/browser/app_icon_win.h"
16 #include "chrome/browser/browser_process.h" 16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/prefs/pref_service.h" 17 #include "chrome/browser/prefs/pref_service.h"
18 #include "chrome/browser/profiles/profile_info_cache.h" 18 #include "chrome/browser/profiles/profile_info_cache_observer.h"
19 #include "chrome/browser/profiles/profile_info_util.h" 19 #include "chrome/browser/profiles/profile_info_util.h"
20 #include "chrome/browser/profiles/profile_manager.h" 20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/common/chrome_constants.h" 21 #include "chrome/common/chrome_constants.h"
22 #include "chrome/common/chrome_switches.h" 22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/pref_names.h" 23 #include "chrome/common/pref_names.h"
24 #include "chrome/installer/util/auto_launch_util.h" 24 #include "chrome/installer/util/auto_launch_util.h"
25 #include "chrome/installer/util/browser_distribution.h" 25 #include "chrome/installer/util/browser_distribution.h"
26 #include "chrome/installer/util/shell_util.h" 26 #include "chrome/installer/util/shell_util.h"
27 #include "content/public/browser/browser_thread.h" 27 #include "content/public/browser/browser_thread.h"
28 #include "grit/generated_resources.h" 28 #include "grit/generated_resources.h"
(...skipping 12 matching lines...) Expand all
41 const int kProfileAvatarShortcutBadgeHeight = 28; 41 const int kProfileAvatarShortcutBadgeHeight = 28;
42 const int kShortcutIconSize = 48; 42 const int kShortcutIconSize = 48;
43 43
44 // Creates a desktop shortcut icon file (.ico) on the disk for a given profile, 44 // Creates a desktop shortcut icon file (.ico) on the disk for a given profile,
45 // badging the browser distribution icon with the profile avatar. 45 // badging the browser distribution icon with the profile avatar.
46 // |profile_base_dir| is the base directory (and key) of the profile. Returns 46 // |profile_base_dir| is the base directory (and key) of the profile. Returns
47 // a path to the shortcut icon file on disk, which is empty if this fails. 47 // a path to the shortcut icon file on disk, which is empty if this fails.
48 // Use index 0 when assigning the resulting file as the icon. 48 // Use index 0 when assigning the resulting file as the icon.
49 FilePath CreateChromeDesktopShortcutIconForProfile( 49 FilePath CreateChromeDesktopShortcutIconForProfile(
50 const FilePath& profile_path, 50 const FilePath& profile_path,
51 const gfx::Image& avatar_image) { 51 const SkBitmap& avatar_bitmap) {
52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
53 const SkBitmap* avatar_bitmap = avatar_image.ToSkBitmap();
54 HICON app_icon_handle = GetAppIconForSize(kShortcutIconSize); 53 HICON app_icon_handle = GetAppIconForSize(kShortcutIconSize);
55 scoped_ptr<SkBitmap> app_icon_bitmap( 54 scoped_ptr<SkBitmap> app_icon_bitmap(
56 IconUtil::CreateSkBitmapFromHICON(app_icon_handle)); 55 IconUtil::CreateSkBitmapFromHICON(app_icon_handle));
57 DestroyIcon(app_icon_handle); 56 DestroyIcon(app_icon_handle);
58 if (!app_icon_bitmap.get()) 57 if (!app_icon_bitmap.get())
59 return FilePath(); 58 return FilePath();
60 59
61 // TODO(hallielaine): Share this chunk of code with 60 // TODO(hallielaine): Share this chunk of code with
62 // avatar_menu_button::DrawTaskBarDecoration. 61 // avatar_menu_button::DrawTaskBarDecoration.
63 const SkBitmap* source_bitmap = NULL; 62 const SkBitmap* source_bitmap = NULL;
64 SkBitmap squarer_bitmap; 63 SkBitmap squarer_bitmap;
65 if ((avatar_bitmap->width() == profiles::kAvatarIconWidth) && 64 if ((avatar_bitmap.width() == profiles::kAvatarIconWidth) &&
66 (avatar_bitmap->height() == profiles::kAvatarIconHeight)) { 65 (avatar_bitmap.height() == profiles::kAvatarIconHeight)) {
67 // Shave a couple of columns so the bitmap is more square. So when 66 // Shave a couple of columns so the bitmap is more square. So when
68 // resized to a square aspect ratio it looks pretty. 67 // resized to a square aspect ratio it looks pretty.
69 int x = 2; 68 int x = 2;
70 avatar_bitmap->extractSubset(&squarer_bitmap, SkIRect::MakeXYWH(x, 0, 69 avatar_bitmap.extractSubset(&squarer_bitmap, SkIRect::MakeXYWH(x, 0,
71 profiles::kAvatarIconWidth - x * 2, profiles::kAvatarIconHeight)); 70 profiles::kAvatarIconWidth - x * 2, profiles::kAvatarIconHeight));
72 source_bitmap = &squarer_bitmap; 71 source_bitmap = &squarer_bitmap;
73 } else { 72 } else {
74 source_bitmap = avatar_bitmap; 73 source_bitmap = &avatar_bitmap;
75 } 74 }
76 SkBitmap sk_icon = skia::ImageOperations::Resize( 75 SkBitmap sk_icon = skia::ImageOperations::Resize(
77 *source_bitmap, 76 *source_bitmap,
78 skia::ImageOperations::RESIZE_LANCZOS3, 77 skia::ImageOperations::RESIZE_LANCZOS3,
79 kProfileAvatarShortcutBadgeWidth, 78 kProfileAvatarShortcutBadgeWidth,
80 kProfileAvatarShortcutBadgeHeight); 79 kProfileAvatarShortcutBadgeHeight);
81 80
82 // Overlay the avatar on the icon, anchoring it to the bottom-right of the 81 // Overlay the avatar on the icon, anchoring it to the bottom-right of the
83 // icon. 82 // icon.
84 scoped_ptr<SkCanvas> offscreen_canvas( 83 scoped_ptr<SkCanvas> offscreen_canvas(
(...skipping 23 matching lines...) Expand all
108 profile_path.BaseName().value().c_str()); 107 profile_path.BaseName().value().c_str());
109 } 108 }
110 109
111 // Wrap a ShellUtil function that returns a bool so it can be posted in a 110 // Wrap a ShellUtil function that returns a bool so it can be posted in a
112 // task to the FILE thread. 111 // task to the FILE thread.
113 void CallShellUtilBoolFunction( 112 void CallShellUtilBoolFunction(
114 const base::Callback<bool(void)>& bool_function) { 113 const base::Callback<bool(void)>& bool_function) {
115 bool_function.Run(); 114 bool_function.Run();
116 } 115 }
117 116
117 // Renames an existing Chrome desktop profile shortcut. Must be called on the
118 // FILE thread.
119 void RenameChromeDesktopShortcutForProfile(
120 const string16& old_shortcut,
sail 2012/08/23 18:46:44 variable names could be more descriptive (i.e. sho
Halli 2012/08/24 02:56:49 Done.
121 const string16& new_shortcut) {
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
123 FilePath shortcut_path;
124 if (ShellUtil::GetDesktopPath(false, // User's directory instead of system.
125 &shortcut_path)) {
126 FilePath old_profile = shortcut_path.Append(old_shortcut);
127 FilePath new_profile = shortcut_path.Append(new_shortcut);
128 file_util::Move(old_profile, new_profile);
sail 2012/08/23 18:46:44 if this fails can you log the error
Halli 2012/08/24 02:56:49 Done.
129 }
130 }
131
132 // Updates the arguments to a Chrome desktop shortcut for a profile. Must be
sail 2012/08/23 18:46:44 Comment doesn't match the function.
Halli 2012/08/24 02:56:49 n/a function has been removed On 2012/08/23 18:46:
133 // called on the FILE thread.
134 void UpdateChromeDesktopShortcutForProfile(
gab 2012/08/23 18:32:39 You do not need a whole new function to do this, s
Halli 2012/08/24 02:56:49 Done.
135 const string16& shortcut,
sail 2012/08/23 18:46:44 same as above, need more descriptive name
Halli 2012/08/24 02:56:49 n/a function has been removed On 2012/08/23 18:46:
136 const string16& arguments,
sail 2012/08/23 18:46:44 same, maybe exe_arguments?
Halli 2012/08/24 02:56:49 n/a function has been removed On 2012/08/23 18:46:
137 const FilePath& profile_path,
138 const SkBitmap& avatar_bitmap) {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
140 FilePath shortcut_path;
141 if (!ShellUtil::GetDesktopPath(false, &shortcut_path))
142 return;
143
144 shortcut_path = shortcut_path.Append(shortcut);
145 FilePath chrome_exe;
146 if (!PathService::Get(base::FILE_EXE, &chrome_exe))
147 return;
148 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
149 string16 description;
150 if (!dist)
151 return;
152 else
153 description = WideToUTF16(dist->GetAppDescription());
154 FilePath icon_path = avatar_bitmap.isNull() ?
sail 2012/08/23 18:46:44 when can the avatar bitmap be null? can this be ch
Halli 2012/08/24 02:56:49 It should be DCHECK(!avatar_image.empty()) before
155 FilePath() :
156 CreateChromeDesktopShortcutIconForProfile(profile_path, avatar_bitmap);
157
158 ShellUtil::UpdateChromeShortcut(
159 dist,
160 chrome_exe.value(),
161 shortcut_path.value(),
162 arguments,
163 description,
164 icon_path.empty() ? chrome_exe.value() : icon_path.value(),
165 icon_path.empty() ? dist->GetIconIndex() : 0,
166 ShellUtil::SHORTCUT_NO_OPTIONS);
167 }
168
169 void CompleteProfileShortcutCreation(
sail 2012/08/23 18:46:44 function level comments. also function name is not
Halli 2012/08/24 02:56:49 Done.
170 const FilePath& profile_path, const string16& profile_name,
sail 2012/08/23 18:46:44 one line per parameter would be easier to read
Halli 2012/08/24 02:56:49 Done.
171 const SkBitmap& avatar_image) {
172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
173 FilePath shortcut_icon = CreateChromeDesktopShortcutIconForProfile(
174 profile_path, avatar_image);
175
176 FilePath chrome_exe;
177 if (!PathService::Get(base::FILE_EXE, &chrome_exe))
178 return;
179 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
180 string16 description;
sail 2012/08/23 18:46:44 variable declaration can be combined with assignme
Halli 2012/08/24 02:56:49 Done.
181 if (!dist)
182 return;
183 description = WideToUTF16(dist->GetAppDescription());
184
185 ShellUtil::CreateChromeDesktopShortcut(
186 dist,
187 chrome_exe.value(),
188 description,
189 profile_name,
190 CreateProfileShortcutFlags(profile_path),
191 shortcut_icon.empty() ? chrome_exe.value() : shortcut_icon.value(),
192 shortcut_icon.empty() ? dist->GetIconIndex() : 0,
193 ShellUtil::CURRENT_USER,
194 ShellUtil::SHORTCUT_CREATE_ALWAYS);
195 }
196
118 } // namespace 197 } // namespace
119 198
120 class ProfileShortcutManagerWin : public ProfileShortcutManager { 199 class ProfileShortcutManagerWin : public ProfileShortcutManager,
200 public ProfileInfoCacheObserver {
121 public: 201 public:
122 ProfileShortcutManagerWin(); 202 ProfileShortcutManagerWin();
123 virtual ~ProfileShortcutManagerWin(); 203 virtual ~ProfileShortcutManagerWin();
124 204
125 virtual void CreateChromeDesktopShortcut( 205 virtual void CreateChromeDesktopShortcut(
126 const FilePath& profile_path, const string16& profile_name, 206 const FilePath& profile_path, const string16& profile_name,
127 const gfx::Image& avatar_image) OVERRIDE; 207 const gfx::Image& avatar_image) OVERRIDE;
128 virtual void DeleteChromeDesktopShortcut(const FilePath& profile_path) 208 virtual void DeleteChromeDesktopShortcut(const FilePath& profile_path,
129 OVERRIDE; 209 const string16& profile_name) OVERRIDE;
130 210
131 private: 211 virtual void OnProfileAdded(const FilePath& profile_path) OVERRIDE;
132 struct ProfileShortcutInfo { 212 virtual void OnProfileWillBeRemoved(const FilePath& profile_path) OVERRIDE;
133 string16 flags; 213 virtual void OnProfileWasRemoved(const FilePath& profile_path,
134 string16 profile_name; 214 const string16& profile_name) OVERRIDE;
135 gfx::Image avatar_image; 215 virtual void OnProfileNameChanged(const FilePath& profile_path,
216 const string16& old_profile_name) OVERRIDE;
217 virtual void OnProfileAvatarChanged(const FilePath& profile_path) OVERRIDE;
136 218
137 ProfileShortcutInfo()
138 : flags(string16()),
139 profile_name(string16()),
140 avatar_image(gfx::Image()) {
141 }
142
143 ProfileShortcutInfo(
144 string16 p_flags,
145 string16 p_profile_name,
146 gfx::Image p_avatar_image)
147 : flags(p_flags),
148 profile_name(p_profile_name),
149 avatar_image(p_avatar_image) {
150 }
151 };
152
153 // TODO(hallielaine): Repopulate this map on chrome session startup
154 typedef std::map<FilePath, ProfileShortcutInfo> ProfileShortcutsMap;
155 ProfileShortcutsMap profile_shortcuts_;
156 }; 219 };
157 220
158 // static 221 // static
159 bool ProfileShortcutManager::IsFeatureEnabled() { 222 bool ProfileShortcutManager::IsFeatureEnabled() {
160 if (CommandLine::ForCurrentProcess()->HasSwitch( 223 if (CommandLine::ForCurrentProcess()->HasSwitch(
161 switches::kProfileDesktopShortcuts)) { 224 switches::kProfileDesktopShortcuts)) {
162 return true; 225 return true;
163 } 226 }
164 return false; 227 return false;
165 } 228 }
166 229
167 // static 230 // static
168 ProfileShortcutManager* ProfileShortcutManager::Create() { 231 ProfileShortcutManager* ProfileShortcutManager::Create(
169 return new ProfileShortcutManagerWin(); 232 ProfileInfoCache& cache) {
233 ProfileShortcutManagerWin* manager = new ProfileShortcutManagerWin();
234 cache.AddObserver(manager);
sail 2012/08/23 18:46:44 you might also need a RemoveObserver() call somewh
Halli 2012/08/24 02:56:49 Done.
235 return manager;
170 } 236 }
171 237
172 ProfileShortcutManagerWin::ProfileShortcutManagerWin() { 238 ProfileShortcutManagerWin::ProfileShortcutManagerWin() {
173 } 239 }
174 240
175 ProfileShortcutManagerWin::~ProfileShortcutManagerWin() { 241 ProfileShortcutManagerWin::~ProfileShortcutManagerWin() {
176 } 242 }
177 243
178 void ProfileShortcutManagerWin::CreateChromeDesktopShortcut( 244 void ProfileShortcutManagerWin::CreateChromeDesktopShortcut(
179 const FilePath& profile_path, const string16& profile_name, 245 const FilePath& profile_path, const string16& profile_name,
180 const gfx::Image& avatar_image) { 246 const gfx::Image& avatar_image) {
181 FilePath shortcut_icon = CreateChromeDesktopShortcutIconForProfile( 247 const SkBitmap* avatar_bitmap = avatar_image.ToSkBitmap();
182 profile_path, avatar_image); 248 SkBitmap avatar_bitmap_copy;
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 249 if (avatar_bitmap->deepCopyTo(&avatar_bitmap_copy,
sail 2012/08/23 18:46:44 this should just be a DCHECK I think, otherwise t
Halli 2012/08/24 02:56:49 Done.
184 FilePath chrome_exe; 250 avatar_bitmap->getConfig())) {
185 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) 251 BrowserThread::PostTask(
186 return; 252 BrowserThread::FILE, FROM_HERE,
187 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 253 base::Bind(&CompleteProfileShortcutCreation,
188 string16 description; 254 profile_path, profile_name, avatar_bitmap_copy));
189 if (!dist)
190 return;
191 description = WideToUTF16(dist->GetAppDescription());
192
193 // Add the profile to the map if it doesn't exist already
194 if (!profile_shortcuts_.count(profile_path)) {
195 string16 flags = CreateProfileShortcutFlags(profile_path);
196 profile_shortcuts_.insert(std::make_pair(profile_path,
197 ProfileShortcutInfo(flags, profile_name,
198 avatar_image)));
199 } 255 }
200
201 ShellUtil::CreateChromeDesktopShortcut(
202 dist,
203 chrome_exe.value(),
204 description,
205 profile_shortcuts_[profile_path].profile_name,
206 profile_shortcuts_[profile_path].flags,
207 shortcut_icon.empty() ? chrome_exe.value() : shortcut_icon.value(),
208 shortcut_icon.empty() ? dist->GetIconIndex() : 0,
209 ShellUtil::CURRENT_USER,
210 ShellUtil::SHORTCUT_CREATE_ALWAYS);
211 } 256 }
212 257
213 void ProfileShortcutManagerWin::DeleteChromeDesktopShortcut( 258 void ProfileShortcutManagerWin::DeleteChromeDesktopShortcut(
214 const FilePath& profile_path) { 259 const FilePath& profile_path, const string16& profile_name) {
215 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 260 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
216 string16 shortcut; 261 string16 shortcut;
217 // If we can find the shortcut, delete it 262 // If we can find the shortcut, delete it
218 if (ShellUtil::GetChromeShortcutName(dist, false, 263 if (ShellUtil::GetChromeShortcutName(dist, false,
219 profile_shortcuts_[profile_path].profile_name, &shortcut)) { 264 profile_name, &shortcut)) {
sail 2012/08/23 18:46:44 is this indentation correct?
Halli 2012/08/24 02:56:49 Done.
220 std::vector<string16> appended_names(1, shortcut); 265 std::vector<string16> appended_names(1, shortcut);
221 BrowserThread::PostTask( 266 BrowserThread::PostTask(
222 BrowserThread::FILE, FROM_HERE, 267 BrowserThread::FILE, FROM_HERE,
223 base::Bind(&CallShellUtilBoolFunction, base::Bind( 268 base::Bind(&CallShellUtilBoolFunction, base::Bind(
224 &ShellUtil::RemoveChromeDesktopShortcutsWithAppendedNames, 269 &ShellUtil::RemoveChromeDesktopShortcutsWithAppendedNames,
225 appended_names))); 270 appended_names)));
226 profile_shortcuts_.erase(profile_path);
227 } 271 }
228 } 272 }
229 273
274 void ProfileShortcutManagerWin::OnProfileAdded(const FilePath& profile_path) {
275 }
276
277 void ProfileShortcutManagerWin::OnProfileWillBeRemoved(
278 const FilePath& profile_path) {
279 }
280
281 void ProfileShortcutManagerWin::OnProfileWasRemoved(
282 const FilePath& profile_path,
283 const string16& profile_name) {
284 }
285
286 void ProfileShortcutManagerWin::OnProfileNameChanged(
287 const FilePath& profile_path,
288 const string16& old_profile_name) {
289 ProfileInfoCache& cache =
290 g_browser_process->profile_manager()->GetProfileInfoCache();
sail 2012/08/23 18:46:44 It's weird that you're accessing the cache through
Halli 2012/08/24 02:56:49 Done.
291
292 size_t profile_index = cache.GetIndexOfProfileWithPath(profile_path);
293 if (profile_index == std::string::npos)
294 return;
295
296 string16 new_profile_name =
297 cache.GetNameOfProfileAtIndex(profile_index);
298
299 string16 old_shortcut;
300 string16 new_shortcut;
301 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
302 if (ShellUtil::GetChromeShortcutName(
303 dist, false, old_profile_name, &old_shortcut) &&
304 ShellUtil::GetChromeShortcutName(
305 dist, false, new_profile_name, &new_shortcut)) {
306 BrowserThread::PostTask(
307 BrowserThread::FILE, FROM_HERE,
308 base::Bind(&RenameChromeDesktopShortcutForProfile,
309 old_shortcut,
310 new_shortcut));
311 }
312 }
313
314 void ProfileShortcutManagerWin::OnProfileAvatarChanged(
315 const FilePath& profile_path) {
316 ProfileInfoCache& cache =
317 g_browser_process->profile_manager()->GetProfileInfoCache();
318
319 size_t profile_index = cache.GetIndexOfProfileWithPath(profile_path);
320 if (profile_index == std::string::npos)
321 return;
322
323 string16 profile_name =
324 cache.GetNameOfProfileAtIndex(profile_index);
325 string16 shortcut;
326
327 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
328 if (ShellUtil::GetChromeShortcutName(
329 dist, false, profile_name, &shortcut)) {
330 size_t new_icon_index = cache.GetAvatarIconIndexOfProfileAtIndex(
331 profile_index);
332 gfx::Image avatar_image =
333 ResourceBundle::GetSharedInstance().GetNativeImageNamed(
334 cache.GetDefaultAvatarIconResourceIDAtIndex(new_icon_index));
sail 2012/08/23 18:46:44 indentation is wrong
Halli 2012/08/24 02:56:49 Done.
335
336 const SkBitmap* avatar_bitmap = avatar_image.ToSkBitmap();
337 SkBitmap avatar_bitmap_copy;
338 if (avatar_bitmap->deepCopyTo(&avatar_bitmap_copy,
sail 2012/08/23 18:46:44 same comment as the above deepCopyTo call
Halli 2012/08/24 02:56:49 Done.
339 avatar_bitmap->getConfig())) {
340 BrowserThread::PostTask(
341 BrowserThread::FILE, FROM_HERE,
342 base::Bind(&UpdateChromeDesktopShortcutForProfile,
343 shortcut,
344 CreateProfileShortcutFlags(profile_path),
345 profile_path, avatar_bitmap_copy));
346 }
347 }
348 }
349
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698