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

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

Issue 1540543002: Uniquify profile shortcut name. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix review notes. Created 4 years, 11 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
« no previous file with comments | « chrome/browser/profiles/profile_shortcut_manager_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/profiles/profile_shortcut_manager_win.h" 5 #include "chrome/browser/profiles/profile_shortcut_manager_win.h"
6 6
7 #include <shlobj.h> // For SHChangeNotify(). 7 #include <shlobj.h> // For SHChangeNotify().
8 8
9 #include <algorithm>
10 #include <set>
9 #include <string> 11 #include <string>
10 #include <vector> 12 #include <vector>
11 13
12 #include "base/bind.h" 14 #include "base/bind.h"
13 #include "base/command_line.h" 15 #include "base/command_line.h"
14 #include "base/files/file_enumerator.h" 16 #include "base/files/file_enumerator.h"
15 #include "base/files/file_util.h" 17 #include "base/files/file_util.h"
16 #include "base/path_service.h" 18 #include "base/path_service.h"
17 #include "base/prefs/pref_service.h" 19 #include "base/prefs/pref_service.h"
18 #include "base/strings/string16.h" 20 #include "base/strings/string16.h"
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 return false; 284 return false;
283 285
284 base::FilePath target_path; 286 base::FilePath target_path;
285 if (!base::win::ResolveShortcut(path, &target_path, command_line)) 287 if (!base::win::ResolveShortcut(path, &target_path, command_line))
286 return false; 288 return false;
287 // One of the paths may be in short (elided) form. Compare long paths to 289 // One of the paths may be in short (elided) form. Compare long paths to
288 // ensure these are still properly matched. 290 // ensure these are still properly matched.
289 return ConvertToLongPath(target_path) == ConvertToLongPath(chrome_exe); 291 return ConvertToLongPath(target_path) == ConvertToLongPath(chrome_exe);
290 } 292 }
291 293
292 // Populates |paths| with the file paths of Chrome desktop shortcuts that have 294 // Checks if |path| is the Chrome desktop shortcut (|chrome_exe|) that have
293 // the specified |command_line|. If |include_empty_command_lines| is true, 295 // the specified |command_line|. If |include_empty_command_lines| is true,
294 // Chrome desktop shortcuts with empty command lines will also be included. 296 // Chrome desktop shortcuts with empty command lines will also be included.
Alexei Svitkine (slow) 2016/01/15 18:01:38 This comment doesn't seem to be applicable to the
Michael K. (Yandex Team) 2016/01/18 09:37:54 I've looked through the code and it seems that com
295 void ListDesktopShortcutsWithCommandLine(const base::FilePath& chrome_exe, 297 struct ChromeCommandLineFilter {
296 const base::string16& command_line, 298 const base::FilePath& chrome_exe;
297 bool include_empty_command_lines, 299 const base::string16& command_line;
298 std::vector<base::FilePath>* paths) { 300 bool include_empty_command_lines;
299 base::FilePath user_shortcuts_directory;
300 if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory, NULL))
301 return;
302 301
303 base::FileEnumerator enumerator(user_shortcuts_directory, false, 302 ChromeCommandLineFilter(const base::FilePath& chrome_exe,
304 base::FileEnumerator::FILES); 303 const base::string16& command_line,
305 for (base::FilePath path = enumerator.Next(); !path.empty(); 304 bool include_empty_command_lines)
306 path = enumerator.Next()) { 305 : chrome_exe(chrome_exe),
306 command_line(command_line),
307 include_empty_command_lines(include_empty_command_lines) {}
308
309 bool operator()(const base::FilePath& path) const {
307 base::string16 shortcut_command_line; 310 base::string16 shortcut_command_line;
308 if (!IsChromeShortcut(path, chrome_exe, &shortcut_command_line)) 311 if (!IsChromeShortcut(path, chrome_exe, &shortcut_command_line))
309 continue; 312 return false;
310 313
311 // TODO(asvitkine): Change this to build a CommandLine object and ensure all 314 // TODO(asvitkine): Change this to build a CommandLine object and ensure all
312 // args from |command_line| are present in the shortcut's CommandLine. This 315 // args from |command_line| are present in the shortcut's CommandLine. This
313 // will be more robust when |command_line| contains multiple args. 316 // will be more robust when |command_line| contains multiple args.
314 if ((shortcut_command_line.empty() && include_empty_command_lines) || 317 if ((shortcut_command_line.empty() && include_empty_command_lines) ||
315 (shortcut_command_line.find(command_line) != base::string16::npos)) { 318 (shortcut_command_line.find(command_line) != base::string16::npos)) {
316 paths->push_back(path); 319 return true;
317 } 320 }
321 return false;
318 } 322 }
323 };
324
325 // Get the file paths of desktop files and folders optionally filtered
326 // by |filter|.
327 std::set<base::FilePath> ListUserDesktopContents(
328 const ChromeCommandLineFilter* filter) {
329 std::set<base::FilePath> res;
Alexei Svitkine (slow) 2016/01/15 18:01:38 Nit: result
Michael K. (Yandex Team) 2016/01/18 09:37:54 Done.
330
331 base::FilePath user_shortcuts_directory;
332 if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory, nullptr))
333 return res;
334
335 base::FileEnumerator enumerator(
336 user_shortcuts_directory, false,
337 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
338 for (base::FilePath path = enumerator.Next(); !path.empty();
339 path = enumerator.Next()) {
340 if (!filter || (*filter)(path))
341 res.insert(path);
342 }
343 return res;
319 } 344 }
320 345
321 // Renames the given desktop shortcut and informs the shell of this change. 346 // Renames the given desktop shortcut and informs the shell of this change.
322 bool RenameDesktopShortcut(const base::FilePath& old_shortcut_path, 347 bool RenameDesktopShortcut(const base::FilePath& old_shortcut_path,
323 const base::FilePath& new_shortcut_path) { 348 const base::FilePath& new_shortcut_path) {
324 if (!base::Move(old_shortcut_path, new_shortcut_path)) 349 if (!base::Move(old_shortcut_path, new_shortcut_path))
325 return false; 350 return false;
326 351
327 // Notify the shell of the rename, which allows the icon to keep its position 352 // Notify the shell of the rename, which allows the icon to keep its position
328 // on the desktop when renamed. Note: This only works if either SHCNF_FLUSH or 353 // on the desktop when renamed. Note: This only works if either SHCNF_FLUSH or
329 // SHCNF_FLUSHNOWAIT is specified as a flag. 354 // SHCNF_FLUSHNOWAIT is specified as a flag.
330 SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, 355 SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT,
331 old_shortcut_path.value().c_str(), 356 old_shortcut_path.value().c_str(),
332 new_shortcut_path.value().c_str()); 357 new_shortcut_path.value().c_str());
333 return true; 358 return true;
334 } 359 }
335 360
336 // Renames an existing Chrome desktop profile shortcut. Must be called on the 361 // Renames an existing Chrome desktop profile shortcut. Must be called on the
337 // FILE thread. 362 // FILE thread.
Alexei Svitkine (slow) 2016/01/15 18:01:38 Document the new params.
Michael K. (Yandex Team) 2016/01/18 09:37:54 Done.
338 void RenameChromeDesktopShortcutForProfile( 363 void RenameChromeDesktopShortcutForProfile(
339 const base::string16& old_shortcut_filename, 364 const base::string16& old_profile_name,
340 const base::string16& new_shortcut_filename) { 365 const base::string16& new_profile_name,
366 std::set<base::FilePath>* profile_shortcuts,
367 std::set<base::FilePath>* desktop_contents) {
368 DCHECK(profile_shortcuts);
369 DCHECK(desktop_contents);
341 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 370 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
342 371
343 base::FilePath user_shortcuts_directory; 372 base::FilePath user_shortcuts_directory;
344 base::FilePath system_shortcuts_directory; 373 base::FilePath system_shortcuts_directory;
345 if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory, 374 if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory,
346 &system_shortcuts_directory)) { 375 &system_shortcuts_directory)) {
347 return; 376 return;
348 } 377 }
349 378
350 const base::FilePath old_shortcut_path = 379 BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
351 user_shortcuts_directory.Append(old_shortcut_filename); 380
381 // Get a new unique shortcut name.
382 const base::string16 new_shortcut_filename =
383 profiles::internal::GetUniqueShortcutFilenameForProfile(
384 new_profile_name, distribution, *desktop_contents);
352 const base::FilePath new_shortcut_path = 385 const base::FilePath new_shortcut_path =
353 user_shortcuts_directory.Append(new_shortcut_filename); 386 user_shortcuts_directory.Append(new_shortcut_filename);
354 387
355 if (base::PathExists(old_shortcut_path)) { 388 if (!profile_shortcuts->empty()) {
389 // From all profile_shortcuts choose only with known (canonical) name.
390 profiles::internal::ShortcutFilenameMatcher matcher(old_profile_name,
391 distribution);
392 auto it = std::find_if(profile_shortcuts->begin(), profile_shortcuts->end(),
393 [&matcher](const base::FilePath& p) {
394 return matcher.IsCanonical(p.BaseName().value());
395 });
396 // If all profile_shortcuts were renamed by user, respect it and do not
397 // rename.
398 if (it == profile_shortcuts->end())
399 return;
400 const base::FilePath old_shortcut_path = *it;
401
356 // Rename the old shortcut unless a system-level shortcut exists at the 402 // Rename the old shortcut unless a system-level shortcut exists at the
357 // destination, in which case the old shortcut is simply deleted. 403 // destination, in which case the old shortcut is simply deleted.
358 const base::FilePath possible_new_system_shortcut = 404 const base::FilePath possible_new_system_shortcut =
359 system_shortcuts_directory.Append(new_shortcut_filename); 405 system_shortcuts_directory.Append(new_shortcut_filename);
360 if (base::PathExists(possible_new_system_shortcut)) 406 if (base::PathExists(possible_new_system_shortcut)) {
361 base::DeleteFile(old_shortcut_path, false); 407 if (base::DeleteFile(old_shortcut_path, false)) {
362 else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path)) 408 profile_shortcuts->erase(old_shortcut_path);
363 DLOG(ERROR) << "Could not rename Windows profile desktop shortcut."; 409 desktop_contents->erase(old_shortcut_path);
410 } else {
411 DLOG(ERROR) << "Could not delete Windows profile desktop shortcut.";
412 }
413 } else {
414 if (RenameDesktopShortcut(old_shortcut_path, new_shortcut_path)) {
415 profile_shortcuts->erase(old_shortcut_path);
416 desktop_contents->erase(old_shortcut_path);
417 profile_shortcuts->insert(new_shortcut_path);
418 desktop_contents->insert(new_shortcut_path);
419 } else {
420 DLOG(ERROR) << "Could not rename Windows profile desktop shortcut.";
421 }
422 }
364 } else { 423 } else {
365 // If the shortcut does not exist, it may have been renamed by the user. In 424 // If the shortcut does not exist, it may have been deleted by the user.
366 // that case, its name should not be changed.
367 // It's also possible that a system-level shortcut exists instead - this 425 // It's also possible that a system-level shortcut exists instead - this
368 // should only be the case for the original Chrome shortcut from an 426 // should only be the case for the original Chrome shortcut from an
369 // installation. If that's the case, copy that one over - it will get its 427 // installation. If that's the case, copy that one over - it will get its
370 // properties updated by 428 // properties updated by
371 // |CreateOrUpdateDesktopShortcutsAndIconForProfile()|. 429 // |CreateOrUpdateDesktopShortcutsAndIconForProfile()|.
430 const auto old_shortcut_filename =
431 profiles::internal::GetShortcutFilenameForProfile(old_profile_name,
432 distribution);
372 const base::FilePath possible_old_system_shortcut = 433 const base::FilePath possible_old_system_shortcut =
373 system_shortcuts_directory.Append(old_shortcut_filename); 434 system_shortcuts_directory.Append(old_shortcut_filename);
374 if (base::PathExists(possible_old_system_shortcut)) 435 if (base::PathExists(possible_old_system_shortcut)) {
375 base::CopyFile(possible_old_system_shortcut, new_shortcut_path); 436 if (base::CopyFile(possible_old_system_shortcut, new_shortcut_path)) {
437 profile_shortcuts->insert(new_shortcut_path);
438 desktop_contents->insert(new_shortcut_path);
439 } else {
440 DLOG(ERROR) << "Could not copy Windows profile desktop shortcut.";
441 }
442 }
376 } 443 }
377 } 444 }
378 445
379 struct CreateOrUpdateShortcutsParams { 446 struct CreateOrUpdateShortcutsParams {
380 CreateOrUpdateShortcutsParams( 447 CreateOrUpdateShortcutsParams(
381 base::FilePath profile_path, 448 base::FilePath profile_path,
382 ProfileShortcutManagerWin::CreateOrUpdateMode create_mode, 449 ProfileShortcutManagerWin::CreateOrUpdateMode create_mode,
383 ProfileShortcutManagerWin::NonProfileShortcutAction action) 450 ProfileShortcutManagerWin::NonProfileShortcutAction action)
384 : create_mode(create_mode), action(action), profile_path(profile_path) {} 451 : create_mode(create_mode), action(action), profile_path(profile_path) {}
385 ~CreateOrUpdateShortcutsParams() {} 452 ~CreateOrUpdateShortcutsParams() {}
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 488 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
422 NOTREACHED(); 489 NOTREACHED();
423 return; 490 return;
424 } 491 }
425 492
426 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); 493 BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
427 // Ensure that the distribution supports creating shortcuts. If it doesn't, 494 // Ensure that the distribution supports creating shortcuts. If it doesn't,
428 // the following code may result in NOTREACHED() being hit. 495 // the following code may result in NOTREACHED() being hit.
429 DCHECK(distribution->CanCreateDesktopShortcuts()); 496 DCHECK(distribution->CanCreateDesktopShortcuts());
430 497
498 std::set<base::FilePath> desktop_contents = ListUserDesktopContents(nullptr);
499
500 const base::string16 command_line =
501 profiles::internal::CreateProfileShortcutFlags(params.profile_path);
502 ChromeCommandLineFilter filter(
503 chrome_exe, command_line,
504 params.action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS);
505
506 std::set<base::FilePath> shortcuts;
507 // Do not call ListUserDesktopContents again (but with filter) to avoid
508 // excess work inside it. Just reuse non-filtered desktop_contents.
509 // We need both of them (desktop_contents and shortcuts) later.
510 std::copy_if(desktop_contents.begin(), desktop_contents.end(),
511 std::inserter(shortcuts, shortcuts.begin()), filter);
512
431 if (params.old_profile_name != params.profile_name) { 513 if (params.old_profile_name != params.profile_name) {
432 const base::string16 old_shortcut_filename = 514 RenameChromeDesktopShortcutForProfile(params.old_profile_name,
433 profiles::internal::GetShortcutFilenameForProfile( 515 params.profile_name, &shortcuts,
434 params.old_profile_name, 516 &desktop_contents);
435 distribution);
436 const base::string16 new_shortcut_filename =
437 profiles::internal::GetShortcutFilenameForProfile(params.profile_name,
438 distribution);
439 RenameChromeDesktopShortcutForProfile(old_shortcut_filename,
440 new_shortcut_filename);
441 } 517 }
442 518
443 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); 519 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
444 installer::Product product(distribution); 520 installer::Product product(distribution);
445 product.AddDefaultShortcutProperties(chrome_exe, &properties); 521 product.AddDefaultShortcutProperties(chrome_exe, &properties);
446 522
447 const base::string16 command_line =
448 profiles::internal::CreateProfileShortcutFlags(params.profile_path);
449 523
450 // Only set the profile-specific properties when |profile_name| is non empty. 524 // Only set the profile-specific properties when |profile_name| is non empty.
451 // If it is empty, it means the shortcut being created should be a regular, 525 // If it is empty, it means the shortcut being created should be a regular,
452 // non-profile Chrome shortcut. 526 // non-profile Chrome shortcut.
453 if (!params.profile_name.empty()) { 527 if (!params.profile_name.empty()) {
454 properties.set_arguments(command_line); 528 properties.set_arguments(command_line);
455 properties.set_icon(shortcut_icon, 0); 529 properties.set_icon(shortcut_icon, 0);
456 } else { 530 } else {
457 // Set the arguments explicitly to the empty string to ensure that 531 // Set the arguments explicitly to the empty string to ensure that
458 // |ShellUtil::CreateOrUpdateShortcut| updates that part of the shortcut. 532 // |ShellUtil::CreateOrUpdateShortcut| updates that part of the shortcut.
459 properties.set_arguments(base::string16()); 533 properties.set_arguments(base::string16());
460 } 534 }
461 535
462 properties.set_app_id( 536 properties.set_app_id(
463 ShellIntegration::GetChromiumModelIdForProfile(params.profile_path)); 537 ShellIntegration::GetChromiumModelIdForProfile(params.profile_path));
464 538
465 ShellUtil::ShortcutOperation operation = 539 ShellUtil::ShortcutOperation operation =
466 ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING; 540 ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING;
467 541
468 std::vector<base::FilePath> shortcuts;
469 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line,
470 params.action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS,
471 &shortcuts);
472 if (params.create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND && 542 if (params.create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND &&
473 shortcuts.empty()) { 543 shortcuts.empty()) {
474 const base::string16 shortcut_name = 544 const base::string16 shortcut_name =
475 profiles::internal::GetShortcutFilenameForProfile(params.profile_name, 545 profiles::internal::GetUniqueShortcutFilenameForProfile(
476 distribution); 546 params.profile_name, distribution, desktop_contents);
477 shortcuts.push_back(base::FilePath(shortcut_name)); 547 shortcuts.insert(base::FilePath(shortcut_name));
478 operation = ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL; 548 operation = ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL;
479 } 549 }
480 550
481 for (size_t i = 0; i < shortcuts.size(); ++i) { 551 for (const auto& shortcut : shortcuts) {
482 const base::FilePath shortcut_name = 552 const base::FilePath shortcut_name = shortcut.BaseName().RemoveExtension();
483 shortcuts[i].BaseName().RemoveExtension();
484 properties.set_shortcut_name(shortcut_name.value()); 553 properties.set_shortcut_name(shortcut_name.value());
485 ShellUtil::CreateOrUpdateShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, 554 ShellUtil::CreateOrUpdateShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
486 distribution, properties, operation); 555 distribution, properties, operation);
487 } 556 }
488 } 557 }
489 558
490 // Returns true if any desktop shortcuts exist with target |chrome_exe|, 559 // Returns true if any desktop shortcuts exist with target |chrome_exe|,
491 // regardless of their command line arguments. 560 // regardless of their command line arguments.
492 bool ChromeDesktopShortcutsExist(const base::FilePath& chrome_exe) { 561 bool ChromeDesktopShortcutsExist(const base::FilePath& chrome_exe) {
493 base::FilePath user_shortcuts_directory; 562 base::FilePath user_shortcuts_directory;
(...skipping 20 matching lines...) Expand all
514 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 583 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
515 584
516 base::FilePath chrome_exe; 585 base::FilePath chrome_exe;
517 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 586 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
518 NOTREACHED(); 587 NOTREACHED();
519 return; 588 return;
520 } 589 }
521 590
522 const base::string16 command_line = 591 const base::string16 command_line =
523 profiles::internal::CreateProfileShortcutFlags(profile_path); 592 profiles::internal::CreateProfileShortcutFlags(profile_path);
524 std::vector<base::FilePath> shortcuts; 593 ChromeCommandLineFilter filter(chrome_exe, command_line, false);
525 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false, 594 const std::set<base::FilePath> shortcuts = ListUserDesktopContents(&filter);
526 &shortcuts);
527 595
528 for (size_t i = 0; i < shortcuts.size(); ++i) { 596 for (const auto& shortcut : shortcuts) {
529 // Use base::DeleteFile() instead of ShellUtil::RemoveShortcuts(), as the 597 // Use base::DeleteFile() instead of ShellUtil::RemoveShortcuts(), as the
530 // latter causes non-profile taskbar shortcuts to be removed since it 598 // latter causes non-profile taskbar shortcuts to be removed since it
531 // doesn't consider the command-line of the shortcuts it deletes. 599 // doesn't consider the command-line of the shortcuts it deletes.
532 // TODO(huangs): Refactor with ShellUtil::RemoveShortcuts(). 600 // TODO(huangs): Refactor with ShellUtil::RemoveShortcuts().
533 base::win::UnpinShortcutFromTaskbar(shortcuts[i]); 601 base::win::UnpinShortcutFromTaskbar(shortcut);
534 base::DeleteFile(shortcuts[i], false); 602 base::DeleteFile(shortcut, false);
535 // Notify the shell that the shortcut was deleted to ensure desktop refresh. 603 // Notify the shell that the shortcut was deleted to ensure desktop refresh.
536 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(), 604 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcut.value().c_str(), nullptr);
537 NULL);
538 } 605 }
539 606
540 // If |ensure_shortcuts_remain| is true and deleting this profile caused the 607 // If |ensure_shortcuts_remain| is true and deleting this profile caused the
541 // last shortcuts to be removed, re-create a regular non-profile shortcut. 608 // last shortcuts to be removed, re-create a regular non-profile shortcut.
542 const bool had_shortcuts = !shortcuts.empty(); 609 const bool had_shortcuts = !shortcuts.empty();
543 if (ensure_shortcuts_remain && had_shortcuts && 610 if (ensure_shortcuts_remain && had_shortcuts &&
544 !ChromeDesktopShortcutsExist(chrome_exe)) { 611 !ChromeDesktopShortcutsExist(chrome_exe)) {
545 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); 612 BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
546 // Ensure that the distribution supports creating shortcuts. If it doesn't, 613 // Ensure that the distribution supports creating shortcuts. If it doesn't,
547 // the following code may result in NOTREACHED() being hit. 614 // the following code may result in NOTREACHED() being hit.
(...skipping 17 matching lines...) Expand all
565 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 632 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
566 633
567 base::FilePath chrome_exe; 634 base::FilePath chrome_exe;
568 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 635 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
569 NOTREACHED(); 636 NOTREACHED();
570 return false; 637 return false;
571 } 638 }
572 639
573 const base::string16 command_line = 640 const base::string16 command_line =
574 profiles::internal::CreateProfileShortcutFlags(profile_path); 641 profiles::internal::CreateProfileShortcutFlags(profile_path);
575 std::vector<base::FilePath> shortcuts; 642 ChromeCommandLineFilter filter(chrome_exe, command_line, false);
576 ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false, 643 const std::set<base::FilePath> shortcuts = ListUserDesktopContents(&filter);
577 &shortcuts);
578 return !shortcuts.empty(); 644 return !shortcuts.empty();
579 } 645 }
580 646
581 // Replaces any reserved characters with spaces, and trims the resulting string 647 // Replaces any reserved characters with spaces, and trims the resulting string
582 // to prevent any leading and trailing spaces. Also makes sure that the 648 // to prevent any leading and trailing spaces. Also makes sure that the
583 // resulting filename doesn't exceed |kMaxProfileShortcutFileNameLength|. 649 // resulting filename doesn't exceed |kMaxProfileShortcutFileNameLength|.
584 // TODO(macourteau): find a way to limit the total path's length to MAX_PATH 650 // TODO(macourteau): find a way to limit the total path's length to MAX_PATH
585 // instead of limiting the profile's name to |kMaxProfileShortcutFileNameLength| 651 // instead of limiting the profile's name to |kMaxProfileShortcutFileNameLength|
586 // characters. 652 // characters.
587 base::string16 SanitizeShortcutProfileNameString( 653 base::string16 SanitizeShortcutProfileNameString(
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 shortcut_name.append(SanitizeShortcutProfileNameString(profile_name)); 702 shortcut_name.append(SanitizeShortcutProfileNameString(profile_name));
637 shortcut_name.append(L" - "); 703 shortcut_name.append(L" - ");
638 shortcut_name.append(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); 704 shortcut_name.append(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
639 } else { 705 } else {
640 shortcut_name.append( 706 shortcut_name.append(
641 distribution->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME)); 707 distribution->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME));
642 } 708 }
643 return shortcut_name + installer::kLnkExt; 709 return shortcut_name + installer::kLnkExt;
644 } 710 }
645 711
712 base::string16 GetUniqueShortcutFilenameForProfile(
713 const base::string16& profile_name,
714 BrowserDistribution* distribution,
715 const std::set<base::FilePath>& excludes) {
716 std::set<base::string16> excludes_names;
717 std::transform(excludes.begin(), excludes.end(),
718 std::inserter(excludes_names, excludes_names.begin()),
719 [](const base::FilePath& e) { return e.BaseName().value(); });
720
721 const auto base_name =
722 GetShortcutFilenameForProfile(profile_name, distribution);
723 auto name = base_name;
724 for (int uniquifier = 1; excludes_names.count(name) > 0; ++uniquifier)
Alexei Svitkine (slow) 2016/01/15 18:01:38 Nit: {}'s
Michael K. (Yandex Team) 2016/01/18 09:37:54 Done.
725 name = base::FilePath(base_name)
Alexei Svitkine (slow) 2016/01/15 18:01:38 Move the FilePath outside the loop.
Michael K. (Yandex Team) 2016/01/18 09:37:54 Acknowledged.
726 .InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", uniquifier))
727 .value();
728 return name;
729 }
730
731 // Corresponds to GetUniqueShortcutFilenameForProfile.
732 ShortcutFilenameMatcher::ShortcutFilenameMatcher(
733 const base::string16& profile_name,
734 BrowserDistribution* distribution)
735 : profile_shortcut_filename_(
736 GetShortcutFilenameForProfile(profile_name, distribution)),
737 lnk_ext_(installer::kLnkExt),
738 profile_shortcut_name_(profile_shortcut_filename_) {
739 DCHECK(profile_shortcut_name_.ends_with(lnk_ext_));
740 profile_shortcut_name_.remove_suffix(lnk_ext_.size());
741 }
742
743 bool ShortcutFilenameMatcher::IsCanonical(
744 const base::string16& filename) const {
745 if (filename == profile_shortcut_filename_)
746 return true;
747
748 base::StringPiece16 shortcut_suffix(filename);
749 if (!shortcut_suffix.starts_with(profile_shortcut_name_))
750 return false;
751 shortcut_suffix.remove_prefix(profile_shortcut_name_.size());
752
753 if (!shortcut_suffix.ends_with(lnk_ext_))
754 return false;
755 shortcut_suffix.remove_suffix(lnk_ext_.size());
756
757 if (shortcut_suffix.size() < 4 || !shortcut_suffix.starts_with(L" (") ||
758 !shortcut_suffix.ends_with(L")")) {
759 return false;
760 }
761 return std::all_of(shortcut_suffix.begin() + 2, shortcut_suffix.end() - 1,
762 iswdigit);
763 }
764
646 base::string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) { 765 base::string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) {
647 return base::StringPrintf(L"--%ls=\"%ls\"", 766 return base::StringPrintf(L"--%ls=\"%ls\"",
648 base::ASCIIToUTF16( 767 base::ASCIIToUTF16(
649 switches::kProfileDirectory).c_str(), 768 switches::kProfileDirectory).c_str(),
650 profile_path.BaseName().value().c_str()); 769 profile_path.BaseName().value().c_str());
651 } 770 }
652 771
653 } // namespace internal 772 } // namespace internal
654 } // namespace profiles 773 } // namespace profiles
655 774
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 // Ensure the profile's icon file has been created. 996 // Ensure the profile's icon file has been created.
878 CreateOrUpdateProfileIcon(profile->GetPath()); 997 CreateOrUpdateProfileIcon(profile->GetPath());
879 } 998 }
880 break; 999 break;
881 } 1000 }
882 default: 1001 default:
883 NOTREACHED(); 1002 NOTREACHED();
884 break; 1003 break;
885 } 1004 }
886 } 1005 }
OLDNEW
« no previous file with comments | « chrome/browser/profiles/profile_shortcut_manager_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698