// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/profiles/profile_shortcut_manager_win.h"

#include <shlobj.h>  // For SHChangeNotify().

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/path_service.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/shortcut.h"
#include "chrome/browser/app_icon_win.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile_info_cache_observer.h"
#include "chrome/browser/profiles/profile_info_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/product.h"
#include "chrome/installer/util/shell_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "grit/chrome_unscaled_resources.h"
#include "grit/chromium_strings.h"
#include "skia/ext/image_operations.h"
#include "skia/ext/platform_canvas.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/icon_util.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_family.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/skia_util.h"

using content::BrowserThread;

namespace {

// Name of the badged icon file generated for a given profile.
const char kProfileIconFileName[] = "Google Profile.ico";

// Characters that are not allowed in Windows filenames. Taken from
// http://msdn.microsoft.com/en-us/library/aa365247.aspx
const char16 kReservedCharacters[] = L"<>:\"/\\|?*\x01\x02\x03\x04\x05\x06\x07"
    L"\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19"
    L"\x1A\x1B\x1C\x1D\x1E\x1F";

// The maximum number of characters allowed in profile shortcuts' file names.
// Warning: migration code will be needed if this is changed later, since
// existing shortcuts might no longer be found if the name is generated
// differently than it was when a shortcut was originally created.
const int kMaxProfileShortcutFileNameLength = 64;

const int kProfileAvatarBadgeSize = 28;
const int kShortcutIconSize = 48;

const int kCurrentProfileIconVersion = 1;

// 2x sized profile avatar icons. Mirrors |kDefaultAvatarIconResources| in
// profile_info_cache.cc.
const int kProfileAvatarIconResources2x[] = {
  IDR_PROFILE_AVATAR_2X_0,
  IDR_PROFILE_AVATAR_2X_1,
  IDR_PROFILE_AVATAR_2X_2,
  IDR_PROFILE_AVATAR_2X_3,
  IDR_PROFILE_AVATAR_2X_4,
  IDR_PROFILE_AVATAR_2X_5,
  IDR_PROFILE_AVATAR_2X_6,
  IDR_PROFILE_AVATAR_2X_7,
  IDR_PROFILE_AVATAR_2X_8,
  IDR_PROFILE_AVATAR_2X_9,
  IDR_PROFILE_AVATAR_2X_10,
  IDR_PROFILE_AVATAR_2X_11,
  IDR_PROFILE_AVATAR_2X_12,
  IDR_PROFILE_AVATAR_2X_13,
  IDR_PROFILE_AVATAR_2X_14,
  IDR_PROFILE_AVATAR_2X_15,
  IDR_PROFILE_AVATAR_2X_16,
  IDR_PROFILE_AVATAR_2X_17,
  IDR_PROFILE_AVATAR_2X_18,
  IDR_PROFILE_AVATAR_2X_19,
  IDR_PROFILE_AVATAR_2X_20,
  IDR_PROFILE_AVATAR_2X_21,
  IDR_PROFILE_AVATAR_2X_22,
  IDR_PROFILE_AVATAR_2X_23,
  IDR_PROFILE_AVATAR_2X_24,
  IDR_PROFILE_AVATAR_2X_25,
};

// Badges |app_icon_bitmap| with |avatar_bitmap| at the bottom right corner and
// returns the resulting SkBitmap.
SkBitmap BadgeIcon(const SkBitmap& app_icon_bitmap,
                   const SkBitmap& avatar_bitmap,
                   int scale_factor) {
  // TODO(rlp): Share this chunk of code with
  // avatar_menu_button::DrawTaskBarDecoration.
  SkBitmap source_bitmap = avatar_bitmap;
  if ((avatar_bitmap.width() == scale_factor * profiles::kAvatarIconWidth) &&
      (avatar_bitmap.height() == scale_factor * profiles::kAvatarIconHeight)) {
    // Shave a couple of columns so the bitmap is more square. So when
    // resized to a square aspect ratio it looks pretty.
    gfx::Rect frame(scale_factor * profiles::kAvatarIconWidth,
                    scale_factor * profiles::kAvatarIconHeight);
    frame.Inset(scale_factor * 2, 0, scale_factor * 2, 0);
    avatar_bitmap.extractSubset(&source_bitmap, gfx::RectToSkIRect(frame));
  } else {
    NOTREACHED();
  }
  int avatar_badge_size = kProfileAvatarBadgeSize;
  if (app_icon_bitmap.width() != kShortcutIconSize) {
    avatar_badge_size =
        app_icon_bitmap.width() * kProfileAvatarBadgeSize / kShortcutIconSize;
  }
  SkBitmap sk_icon = skia::ImageOperations::Resize(
      source_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, avatar_badge_size,
      source_bitmap.height() * avatar_badge_size / source_bitmap.width());

  // Overlay the avatar on the icon, anchoring it to the bottom-right of the
  // icon.
  scoped_ptr<SkCanvas> offscreen_canvas(
      skia::CreateBitmapCanvas(app_icon_bitmap.width(),
                               app_icon_bitmap.height(),
                               false));
  DCHECK(offscreen_canvas);
  offscreen_canvas->drawBitmap(app_icon_bitmap, 0, 0);
  offscreen_canvas->drawBitmap(sk_icon,
                               app_icon_bitmap.width() - sk_icon.width(),
                               app_icon_bitmap.height() - sk_icon.height());
  const SkBitmap& badged_bitmap =
      offscreen_canvas->getDevice()->accessBitmap(false);
  SkBitmap badged_bitmap_copy;
  badged_bitmap.deepCopyTo(&badged_bitmap_copy, badged_bitmap.getConfig());
  return badged_bitmap_copy;
}

// Creates a desktop shortcut icon file (.ico) on the disk for a given profile,
// badging the browser distribution icon with the profile avatar.
// Returns a path to the shortcut icon file on disk, which is empty if this
// fails. Use index 0 when assigning the resulting file as the icon. If both
// given bitmaps are empty, an unbadged icon is created.
// |callback| will be run on successful icon creation.
// Returns the path to the created icon on success and an empty base::FilePath
// on failure.
// TODO(calamity): Ideally we'd just copy the app icon verbatim from the exe's
// resources in the case of an unbadged icon.
base::FilePath CreateOrUpdateShortcutIconForProfile(
    const base::FilePath& profile_path,
    const SkBitmap& avatar_bitmap_1x,
    const SkBitmap& avatar_bitmap_2x,
    const base::Closure& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  if (!base::PathExists(profile_path)) {
    LOG(ERROR) << "Profile directory " << profile_path.value()
               << " did not exist when trying to create profile icon";
    return base::FilePath();
  }

  scoped_ptr<SkBitmap> app_icon_bitmap(GetAppIconForSize(kShortcutIconSize));
  if (!app_icon_bitmap)
    return base::FilePath();

  gfx::ImageFamily badged_bitmaps;
  if (!avatar_bitmap_1x.empty()) {
    badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(
        BadgeIcon(*app_icon_bitmap, avatar_bitmap_1x, 1)));
  }

  scoped_ptr<SkBitmap> large_app_icon_bitmap(
      GetAppIconForSize(IconUtil::kLargeIconSize));
  if (large_app_icon_bitmap && !avatar_bitmap_2x.empty()) {
    badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(
        BadgeIcon(*large_app_icon_bitmap, avatar_bitmap_2x, 2)));
  }

  // If we have no badged bitmaps, we should just use the default chrome icon.
  if (badged_bitmaps.empty()) {
    badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(*app_icon_bitmap));
    if (large_app_icon_bitmap) {
      badged_bitmaps.Add(
          gfx::Image::CreateFrom1xBitmap(*large_app_icon_bitmap));
    }
  }
  // Finally, write the .ico file containing this new bitmap.
  const base::FilePath icon_path =
      profiles::internal::GetProfileIconPath(profile_path);
  const bool had_icon = base::PathExists(icon_path);

  if (!IconUtil::CreateIconFileFromImageFamily(badged_bitmaps, icon_path)) {
    // This can happen in theory if the profile directory is deleted between the
    // beginning of this function and here; however this is extremely unlikely
    // and this check will help catch any regression where this call would start
    // failing constantly.
    NOTREACHED();
    return base::FilePath();
  }

  if (had_icon) {
    // This invalidates the Windows icon cache and causes the icon changes to
    // register with the taskbar and desktop. SHCNE_ASSOCCHANGED will cause a
    // desktop flash and we would like to avoid that if possible.
    SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
  } else {
    SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, icon_path.value().c_str(), NULL);
  }
  if (!callback.is_null())
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
  return icon_path;
}

// Updates the preferences with the current icon version on icon creation
// success.
void OnProfileIconCreateSuccess(base::FilePath profile_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (!g_browser_process->profile_manager())
    return;
  Profile* profile =
      g_browser_process->profile_manager()->GetProfileByPath(profile_path);
  if (profile) {
    profile->GetPrefs()->SetInteger(prefs::kProfileIconVersion,
                                    kCurrentProfileIconVersion);
  }
}

// Gets the user and system directories for desktop shortcuts. Parameters may
// be NULL if a directory type is not needed. Returns true on success.
bool GetDesktopShortcutsDirectories(
    base::FilePath* user_shortcuts_directory,
    base::FilePath* system_shortcuts_directory) {
  BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
  if (user_shortcuts_directory &&
      !ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
                                  distribution, ShellUtil::CURRENT_USER,
                                  user_shortcuts_directory)) {
    NOTREACHED();
    return false;
  }
  if (system_shortcuts_directory &&
      !ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
                                  distribution, ShellUtil::SYSTEM_LEVEL,
                                  system_shortcuts_directory)) {
    NOTREACHED();
    return false;
  }
  return true;
}

// Returns the long form of |path|, which will expand any shortened components
// like "foo~2" to their full names.
base::FilePath ConvertToLongPath(const base::FilePath& path) {
  const size_t length = GetLongPathName(path.value().c_str(), NULL, 0);
  if (length != 0 && length != path.value().length()) {
    std::vector<wchar_t> long_path(length);
    if (GetLongPathName(path.value().c_str(), &long_path[0], length) != 0)
      return base::FilePath(&long_path[0]);
  }
  return path;
}

// Returns true if the file at |path| is a Chrome shortcut and returns its
// command line in output parameter |command_line|.
bool IsChromeShortcut(const base::FilePath& path,
                      const base::FilePath& chrome_exe,
                      string16* command_line) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  if (path.Extension() != installer::kLnkExt)
    return false;

  base::FilePath target_path;
  if (!base::win::ResolveShortcut(path, &target_path, command_line))
    return false;
  // One of the paths may be in short (elided) form. Compare long paths to
  // ensure these are still properly matched.
  return ConvertToLongPath(target_path) == ConvertToLongPath(chrome_exe);
}

// Populates |paths| with the file paths of Chrome desktop shortcuts that have
// the specified |command_line|. If |include_empty_command_lines| is true,
// Chrome desktop shortcuts with empty command lines will also be included.
void ListDesktopShortcutsWithCommandLine(const base::FilePath& chrome_exe,
                                         const string16& command_line,
                                         bool include_empty_command_lines,
                                         std::vector<base::FilePath>* paths) {
  base::FilePath user_shortcuts_directory;
  if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory, NULL))
    return;

  base::FileEnumerator enumerator(user_shortcuts_directory, false,
                                  base::FileEnumerator::FILES);
  for (base::FilePath path = enumerator.Next(); !path.empty();
       path = enumerator.Next()) {
    string16 shortcut_command_line;
    if (!IsChromeShortcut(path, chrome_exe, &shortcut_command_line))
      continue;

    // TODO(asvitkine): Change this to build a CommandLine object and ensure all
    // args from |command_line| are present in the shortcut's CommandLine. This
    // will be more robust when |command_line| contains multiple args.
    if ((shortcut_command_line.empty() && include_empty_command_lines) ||
        (shortcut_command_line.find(command_line) != string16::npos)) {
      paths->push_back(path);
    }
  }
}

// Renames the given desktop shortcut and informs the shell of this change.
bool RenameDesktopShortcut(const base::FilePath& old_shortcut_path,
                           const base::FilePath& new_shortcut_path) {
  if (!base::Move(old_shortcut_path, new_shortcut_path))
    return false;

  // Notify the shell of the rename, which allows the icon to keep its position
  // on the desktop when renamed. Note: This only works if either SHCNF_FLUSH or
  // SHCNF_FLUSHNOWAIT is specified as a flag.
  SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT,
                 old_shortcut_path.value().c_str(),
                 new_shortcut_path.value().c_str());
  return true;
}

// Renames an existing Chrome desktop profile shortcut. Must be called on the
// FILE thread.
void RenameChromeDesktopShortcutForProfile(
    const string16& old_shortcut_filename,
    const string16& new_shortcut_filename) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  base::FilePath user_shortcuts_directory;
  base::FilePath system_shortcuts_directory;
  if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory,
                                      &system_shortcuts_directory)) {
    return;
  }

  const base::FilePath old_shortcut_path =
      user_shortcuts_directory.Append(old_shortcut_filename);
  const base::FilePath new_shortcut_path =
      user_shortcuts_directory.Append(new_shortcut_filename);

  if (base::PathExists(old_shortcut_path)) {
    // Rename the old shortcut unless a system-level shortcut exists at the
    // destination, in which case the old shortcut is simply deleted.
    const base::FilePath possible_new_system_shortcut =
        system_shortcuts_directory.Append(new_shortcut_filename);
    if (base::PathExists(possible_new_system_shortcut))
      base::DeleteFile(old_shortcut_path, false);
    else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path))
      DLOG(ERROR) << "Could not rename Windows profile desktop shortcut.";
  } else {
    // If the shortcut does not exist, it may have been renamed by the user. In
    // that case, its name should not be changed.
    // It's also possible that a system-level shortcut exists instead - this
    // should only be the case for the original Chrome shortcut from an
    // installation. If that's the case, copy that one over - it will get its
    // properties updated by
    // |CreateOrUpdateDesktopShortcutsAndIconForProfile()|.
    const base::FilePath possible_old_system_shortcut =
        system_shortcuts_directory.Append(old_shortcut_filename);
    if (base::PathExists(possible_old_system_shortcut))
      base::CopyFile(possible_old_system_shortcut, new_shortcut_path);
  }
}

struct CreateOrUpdateShortcutsParams {
  CreateOrUpdateShortcutsParams(
      base::FilePath profile_path,
      ProfileShortcutManagerWin::CreateOrUpdateMode create_mode,
      ProfileShortcutManagerWin::NonProfileShortcutAction action)
      : profile_path(profile_path), create_mode(create_mode), action(action) {}
  ~CreateOrUpdateShortcutsParams() {}

  ProfileShortcutManagerWin::CreateOrUpdateMode create_mode;
  ProfileShortcutManagerWin::NonProfileShortcutAction action;

  // The path for this profile.
  base::FilePath profile_path;
  // The profile name before this update. Empty on create.
  string16 old_profile_name;
  // The new profile name.
  string16 profile_name;
  // Avatar images for this profile.
  SkBitmap avatar_image_1x;
  SkBitmap avatar_image_2x;
};

// Updates all desktop shortcuts for the given profile to have the specified
// parameters. If |params.create_mode| is CREATE_WHEN_NONE_FOUND, a new shortcut
// is created if no existing ones were found. Whether non-profile shortcuts
// should be updated is specified by |params.action|. Must be called on the FILE
// thread. |callback| is called on successful icon creation.
void CreateOrUpdateDesktopShortcutsAndIconForProfile(
    const CreateOrUpdateShortcutsParams& params,
    const base::Closure& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  const base::FilePath shortcut_icon =
      CreateOrUpdateShortcutIconForProfile(params.profile_path,
                                           params.avatar_image_1x,
                                           params.avatar_image_2x,
                                           callback);
  if (shortcut_icon.empty() ||
      params.create_mode ==
          ProfileShortcutManagerWin::CREATE_OR_UPDATE_ICON_ONLY) {
    return;
  }

  base::FilePath chrome_exe;
  if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
    NOTREACHED();
    return;
  }

  BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
  // Ensure that the distribution supports creating shortcuts. If it doesn't,
  // the following code may result in NOTREACHED() being hit.
  DCHECK(distribution->CanCreateDesktopShortcuts());

  if (params.old_profile_name != params.profile_name) {
    const string16 old_shortcut_filename =
        profiles::internal::GetShortcutFilenameForProfile(
            params.old_profile_name,
            distribution);
    const string16 new_shortcut_filename =
        profiles::internal::GetShortcutFilenameForProfile(params.profile_name,
                                                          distribution);
    RenameChromeDesktopShortcutForProfile(old_shortcut_filename,
                                          new_shortcut_filename);
  }

  ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
  installer::Product product(distribution);
  product.AddDefaultShortcutProperties(chrome_exe, &properties);

  const string16 command_line =
      profiles::internal::CreateProfileShortcutFlags(params.profile_path);

  // Only set the profile-specific properties when |profile_name| is non empty.
  // If it is empty, it means the shortcut being created should be a regular,
  // non-profile Chrome shortcut.
  if (!params.profile_name.empty()) {
    properties.set_arguments(command_line);
    properties.set_icon(shortcut_icon, 0);
  } else {
    // Set the arguments explicitly to the empty string to ensure that
    // |ShellUtil::CreateOrUpdateShortcut| updates that part of the shortcut.
    properties.set_arguments(string16());
  }

  properties.set_app_id(
      ShellIntegration::GetChromiumModelIdForProfile(params.profile_path));

  ShellUtil::ShortcutOperation operation =
      ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING;

  std::vector<base::FilePath> shortcuts;
  ListDesktopShortcutsWithCommandLine(chrome_exe, command_line,
      params.action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS,
      &shortcuts);
  if (params.create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND &&
      shortcuts.empty()) {
    const string16 shortcut_name =
        profiles::internal::GetShortcutFilenameForProfile(params.profile_name,
                                                          distribution);
    shortcuts.push_back(base::FilePath(shortcut_name));
    operation = ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL;
  }

  for (size_t i = 0; i < shortcuts.size(); ++i) {
    const base::FilePath shortcut_name =
        shortcuts[i].BaseName().RemoveExtension();
    properties.set_shortcut_name(shortcut_name.value());
    ShellUtil::CreateOrUpdateShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
        distribution, properties, operation);
  }
}

// Returns true if any desktop shortcuts exist with target |chrome_exe|,
// regardless of their command line arguments.
bool ChromeDesktopShortcutsExist(const base::FilePath& chrome_exe) {
  base::FilePath user_shortcuts_directory;
  if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory, NULL))
    return false;

  base::FileEnumerator enumerator(user_shortcuts_directory, false,
                                  base::FileEnumerator::FILES);
  for (base::FilePath path = enumerator.Next(); !path.empty();
       path = enumerator.Next()) {
    if (IsChromeShortcut(path, chrome_exe, NULL))
      return true;
  }

  return false;
}

// Deletes all desktop shortcuts for the specified profile. If
// |ensure_shortcuts_remain| is true, then a regular non-profile shortcut will
// be created if this function would otherwise delete the last Chrome desktop
// shortcut(s). Must be called on the FILE thread.
void DeleteDesktopShortcuts(const base::FilePath& profile_path,
                            bool ensure_shortcuts_remain) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  base::FilePath chrome_exe;
  if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
    NOTREACHED();
    return;
  }

  const string16 command_line =
      profiles::internal::CreateProfileShortcutFlags(profile_path);
  std::vector<base::FilePath> shortcuts;
  ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false,
                                      &shortcuts);

  for (size_t i = 0; i < shortcuts.size(); ++i) {
    // Use base::DeleteFile() instead of ShellUtil::RemoveShortcut(), as the
    // latter causes non-profile taskbar shortcuts to be unpinned.
    base::DeleteFile(shortcuts[i], false);
    // Notify the shell that the shortcut was deleted to ensure desktop refresh.
    SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(),
                   NULL);
  }

  // If |ensure_shortcuts_remain| is true and deleting this profile caused the
  // last shortcuts to be removed, re-create a regular non-profile shortcut.
  const bool had_shortcuts = !shortcuts.empty();
  if (ensure_shortcuts_remain && had_shortcuts &&
      !ChromeDesktopShortcutsExist(chrome_exe)) {
    BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
    // Ensure that the distribution supports creating shortcuts. If it doesn't,
    // the following code may result in NOTREACHED() being hit.
    DCHECK(distribution->CanCreateDesktopShortcuts());
    installer::Product product(distribution);

    ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
    product.AddDefaultShortcutProperties(chrome_exe, &properties);
    properties.set_shortcut_name(
        profiles::internal::GetShortcutFilenameForProfile(string16(),
                                                          distribution));
    ShellUtil::CreateOrUpdateShortcut(
        ShellUtil::SHORTCUT_LOCATION_DESKTOP, distribution, properties,
        ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL);
  }
}

// Returns true if profile at |profile_path| has any shortcuts. Does not
// consider non-profile shortcuts. Must be called on the FILE thread.
bool HasAnyProfileShortcuts(const base::FilePath& profile_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  base::FilePath chrome_exe;
  if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
    NOTREACHED();
    return false;
  }

  const string16 command_line =
      profiles::internal::CreateProfileShortcutFlags(profile_path);
  std::vector<base::FilePath> shortcuts;
  ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false,
                                      &shortcuts);
  return !shortcuts.empty();
}

// Replaces any reserved characters with spaces, and trims the resulting string
// to prevent any leading and trailing spaces. Also makes sure that the
// resulting filename doesn't exceed |kMaxProfileShortcutFileNameLength|.
// TODO(macourteau): find a way to limit the total path's length to MAX_PATH
// instead of limiting the profile's name to |kMaxProfileShortcutFileNameLength|
// characters.
string16 SanitizeShortcutProfileNameString(const string16& profile_name) {
  string16 sanitized = profile_name;
  size_t pos = sanitized.find_first_of(kReservedCharacters);
  while (pos != string16::npos) {
    sanitized[pos] = L' ';
    pos = sanitized.find_first_of(kReservedCharacters, pos + 1);
  }

  TrimWhitespace(sanitized, TRIM_LEADING, &sanitized);
  if (sanitized.size() > kMaxProfileShortcutFileNameLength)
    sanitized.erase(kMaxProfileShortcutFileNameLength);
  TrimWhitespace(sanitized, TRIM_TRAILING, &sanitized);

  return sanitized;
}

// Returns a copied SkBitmap for the given resource id that can be safely passed
// to another thread.
SkBitmap GetImageResourceSkBitmapCopy(int resource_id) {
  const gfx::Image image =
      ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
  DCHECK(!image.IsEmpty());

  const SkBitmap* image_bitmap = image.ToSkBitmap();
  SkBitmap bitmap_copy;
  image_bitmap->deepCopyTo(&bitmap_copy, image_bitmap->getConfig());
  return bitmap_copy;
}

}  // namespace

namespace profiles {
namespace internal {

base::FilePath GetProfileIconPath(const base::FilePath& profile_path) {
  return profile_path.AppendASCII(kProfileIconFileName);
}

string16 GetShortcutFilenameForProfile(const string16& profile_name,
                                       BrowserDistribution* distribution) {
  string16 shortcut_name;
  if (!profile_name.empty()) {
    shortcut_name.append(SanitizeShortcutProfileNameString(profile_name));
    shortcut_name.append(L" - ");
    shortcut_name.append(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
  } else {
    shortcut_name.append(distribution->GetAppShortCutName());
  }
  return shortcut_name + installer::kLnkExt;
}

string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) {
  return base::StringPrintf(L"--%ls=\"%ls\"",
                            ASCIIToUTF16(switches::kProfileDirectory).c_str(),
                            profile_path.BaseName().value().c_str());
}

}  // namespace internal
}  // namespace profiles

// static
bool ProfileShortcutManager::IsFeatureEnabled() {
  return BrowserDistribution::GetDistribution()->CanCreateDesktopShortcuts() &&
      !CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir);
}

// static
ProfileShortcutManager* ProfileShortcutManager::Create(
    ProfileManager* manager) {
  return new ProfileShortcutManagerWin(manager);
}

ProfileShortcutManagerWin::ProfileShortcutManagerWin(ProfileManager* manager)
    : profile_manager_(manager) {
  DCHECK_EQ(
      arraysize(kProfileAvatarIconResources2x),
      profile_manager_->GetProfileInfoCache().GetDefaultAvatarIconCount());

  registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
                 content::NotificationService::AllSources());

  profile_manager_->GetProfileInfoCache().AddObserver(this);
}

ProfileShortcutManagerWin::~ProfileShortcutManagerWin() {
  profile_manager_->GetProfileInfoCache().RemoveObserver(this);
}

void ProfileShortcutManagerWin::CreateOrUpdateProfileIcon(
    const base::FilePath& profile_path,
    const base::Closure& callback) {
  CreateOrUpdateShortcutsForProfileAtPath(profile_path,
                                          CREATE_OR_UPDATE_ICON_ONLY,
                                          IGNORE_NON_PROFILE_SHORTCUTS,
                                          callback);
}

void ProfileShortcutManagerWin::CreateProfileShortcut(
    const base::FilePath& profile_path) {
  CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND,
                                          IGNORE_NON_PROFILE_SHORTCUTS,
                                          base::Closure());
}

void ProfileShortcutManagerWin::RemoveProfileShortcuts(
    const base::FilePath& profile_path) {
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&DeleteDesktopShortcuts, profile_path, false));
}

void ProfileShortcutManagerWin::HasProfileShortcuts(
    const base::FilePath& profile_path,
    const base::Callback<void(bool)>& callback) {
  BrowserThread::PostTaskAndReplyWithResult(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&HasAnyProfileShortcuts, profile_path), callback);
}

void ProfileShortcutManagerWin::OnProfileAdded(
    const base::FilePath& profile_path) {
  CreateOrUpdateProfileIcon(profile_path, base::Closure());
  if (profile_manager_->GetProfileInfoCache().GetNumberOfProfiles() == 2) {
    // When the second profile is added, make existing non-profile shortcuts
    // point to the first profile and be badged/named appropriately.
    CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path),
                                            UPDATE_EXISTING_ONLY,
                                            UPDATE_NON_PROFILE_SHORTCUTS,
                                            base::Closure());
  }
}

void ProfileShortcutManagerWin::OnProfileWasRemoved(
    const base::FilePath& profile_path,
    const string16& profile_name) {
  const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
  // If there is only one profile remaining, remove the badging information
  // from an existing shortcut.
  const bool deleting_down_to_last_profile = (cache.GetNumberOfProfiles() == 1);
  if (deleting_down_to_last_profile) {
    // This is needed to unbadge the icon.
    CreateOrUpdateShortcutsForProfileAtPath(cache.GetPathOfProfileAtIndex(0),
                                            UPDATE_EXISTING_ONLY,
                                            IGNORE_NON_PROFILE_SHORTCUTS,
                                            base::Closure());
  }

  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                          base::Bind(&DeleteDesktopShortcuts,
                                     profile_path,
                                     deleting_down_to_last_profile));
}

void ProfileShortcutManagerWin::OnProfileNameChanged(
    const base::FilePath& profile_path,
    const string16& old_profile_name) {
  CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY,
                                          IGNORE_NON_PROFILE_SHORTCUTS,
                                          base::Closure());
}

void ProfileShortcutManagerWin::OnProfileAvatarChanged(
    const base::FilePath& profile_path) {
  CreateOrUpdateProfileIcon(profile_path, base::Closure());
}

base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath(
    const base::FilePath& profile_path) {
  const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
  DCHECK_EQ(2U, cache.GetNumberOfProfiles());
  // Get the index of the current profile, in order to find the index of the
  // other profile.
  size_t current_profile_index = cache.GetIndexOfProfileWithPath(profile_path);
  size_t other_profile_index = (current_profile_index == 0) ? 1 : 0;
  return cache.GetPathOfProfileAtIndex(other_profile_index);
}

void ProfileShortcutManagerWin::CreateOrUpdateShortcutsForProfileAtPath(
    const base::FilePath& profile_path,
    CreateOrUpdateMode create_mode,
    NonProfileShortcutAction action,
    const base::Closure& callback) {
  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
      BrowserThread::CurrentlyOn(BrowserThread::UI));
  CreateOrUpdateShortcutsParams params(profile_path, create_mode, action);

  ProfileInfoCache* cache = &profile_manager_->GetProfileInfoCache();
  size_t profile_index = cache->GetIndexOfProfileWithPath(profile_path);
  if (profile_index == std::string::npos)
    return;
  bool remove_badging = cache->GetNumberOfProfiles() == 1;

  params.old_profile_name =
      cache->GetShortcutNameOfProfileAtIndex(profile_index);

  // Exit early if the mode is to update existing profile shortcuts only and
  // none were ever created for this profile, per the shortcut name not being
  // set in the profile info cache.
  if (params.old_profile_name.empty() &&
      create_mode == UPDATE_EXISTING_ONLY &&
      action == IGNORE_NON_PROFILE_SHORTCUTS) {
    return;
  }

  if (!remove_badging) {
    params.profile_name = cache->GetNameOfProfileAtIndex(profile_index);

    const size_t icon_index =
        cache->GetAvatarIconIndexOfProfileAtIndex(profile_index);
    const int resource_id_1x =
        cache->GetDefaultAvatarIconResourceIDAtIndex(icon_index);
    const int resource_id_2x = kProfileAvatarIconResources2x[icon_index];
    // Make a copy of the SkBitmaps to ensure that we can safely use the image
    // data on the FILE thread.
    params.avatar_image_1x = GetImageResourceSkBitmapCopy(resource_id_1x);
    params.avatar_image_2x = GetImageResourceSkBitmapCopy(resource_id_2x);
  }
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&CreateOrUpdateDesktopShortcutsAndIconForProfile, params,
                 callback));

  cache->SetShortcutNameOfProfileAtIndex(profile_index,
                                         params.profile_name);
}

void ProfileShortcutManagerWin::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  switch (type) {
    // This notification is triggered when a profile is loaded.
    case chrome::NOTIFICATION_PROFILE_CREATED: {
      Profile* profile =
          content::Source<Profile>(source).ptr()->GetOriginalProfile();
      if (profile->GetPrefs()->GetInteger(prefs::kProfileIconVersion) <
          kCurrentProfileIconVersion) {
        // Ensure the profile's icon file has been created.
        CreateOrUpdateProfileIcon(
            profile->GetPath(),
            base::Bind(&OnProfileIconCreateSuccess, profile->GetPath()));
      }
      break;
    }
    default:
      NOTREACHED();
      break;
  }
}
