1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/path_util.h"
6
7#include "base/path_service.h"
8#include "base/strings/sys_string_conversions.h"
9
10#if defined(OS_MACOSX)
11#include <CoreFoundation/CoreFoundation.h>
12#include "base/mac/foundation_util.h"
13#endif
14
15#if defined(OS_CHROMEOS)
16#include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
17#endif
18
19namespace extensions {
20namespace path_util {
21
22namespace {
23#if defined(OS_MACOSX)
24
25// Retrieves the localized display name for the base name of the given path.
26// If the path is not localized, this will just return the base name.
27std::string GetDisplayBaseName(const base::FilePath& path) {
28  base::ScopedCFTypeRef<CFURLRef> url(CFURLCreateFromFileSystemRepresentation(
29      NULL, (const UInt8*)path.value().c_str(), path.value().length(), true));
30  if (!url)
31    return path.BaseName().value();
32
33  CFStringRef str;
34  if (LSCopyDisplayNameForURL(url, &str) != noErr)
35    return path.BaseName().value();
36
37  std::string result(base::SysCFStringRefToUTF8(str));
38  CFRelease(str);
39  return result;
40}
41
42#endif  // defined(OS_MACOSX)
43
44const base::FilePath::CharType kHomeShortcut[] = FILE_PATH_LITERAL("~");
45
46}  // namespace
47
48base::FilePath PrettifyPath(const base::FilePath& source_path) {
49  base::FilePath home_path;
50  if (source_path.empty() || !PathService::Get(base::DIR_HOME, &home_path))
51    return source_path;
52
53  base::FilePath display_path = base::FilePath(kHomeShortcut);
54  if (source_path == home_path)
55    return display_path;
56
57#if defined(OS_MACOSX)
58  DCHECK(source_path.IsAbsolute());
59
60  // Break down the incoming path into components, and grab the display name
61  // for every component. This will match app bundles, ".localized" folders,
62  // and localized subfolders of the user's home directory.
63  // Don't grab the display name of the first component, i.e., "/", as it'll
64  // show up as the HDD name.
65  std::vector<base::FilePath::StringType> components;
66  source_path.GetComponents(&components);
67  display_path = base::FilePath(components[0]);
68  base::FilePath actual_path = display_path;
69  for (std::vector<base::FilePath::StringType>::iterator i =
70           components.begin() + 1; i != components.end(); ++i) {
71    actual_path = actual_path.Append(*i);
72    if (actual_path == home_path) {
73      display_path = base::FilePath(kHomeShortcut);
74      home_path = base::FilePath();
75      continue;
76    }
77    std::string display = GetDisplayBaseName(actual_path);
78    display_path = display_path.Append(display);
79  }
80  DCHECK_EQ(actual_path.value(), source_path.value());
81  return display_path;
82#else  // defined(OS_MACOSX)
83  if (home_path.AppendRelativePath(source_path, &display_path))
84    return display_path;
85  return source_path;
86#endif  // defined(OS_MACOSX)
87}
88
89}  // namespace path_util
90}  // namespace extensions
91