blob: 24f288a3beaa676eddafef4c3c7ae248029477dd [file] [log] [blame]
[email protected]a1e63332014-07-03 06:58:411// 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
Michael Giuffrida26c50262017-06-07 17:54:505#include "extensions/browser/path_util.h"
[email protected]a1e63332014-07-03 06:58:416
dpapadd07974e32017-12-20 20:35:267#include "base/bind.h"
8#include "base/files/file_util.h"
[email protected]a1e63332014-07-03 06:58:419#include "base/path_service.h"
10#include "base/strings/sys_string_conversions.h"
dpapadd07974e32017-12-20 20:35:2611#include "base/task_runner_util.h"
12#include "base/threading/sequenced_task_runner_handle.h"
avia2f4804a2015-12-24 23:11:1313#include "build/build_config.h"
dpapadd07974e32017-12-20 20:35:2614#include "extensions/browser/extension_file_task_runner.h"
15#include "ui/base/l10n/l10n_util.h"
16#include "ui/base/text/bytes_formatting.h"
[email protected]a1e63332014-07-03 06:58:4117
18#if defined(OS_MACOSX)
19#include <CoreFoundation/CoreFoundation.h>
20#include "base/mac/foundation_util.h"
21#endif
22
[email protected]a1e63332014-07-03 06:58:4123namespace extensions {
24namespace path_util {
25
[email protected]a1e63332014-07-03 06:58:4126namespace {
[email protected]ff8004952014-08-08 01:03:5127#if defined(OS_MACOSX)
[email protected]a1e63332014-07-03 06:58:4128
29// Retrieves the localized display name for the base name of the given path.
30// If the path is not localized, this will just return the base name.
31std::string GetDisplayBaseName(const base::FilePath& path) {
32 base::ScopedCFTypeRef<CFURLRef> url(CFURLCreateFromFileSystemRepresentation(
33 NULL, (const UInt8*)path.value().c_str(), path.value().length(), true));
34 if (!url)
35 return path.BaseName().value();
36
37 CFStringRef str;
38 if (LSCopyDisplayNameForURL(url, &str) != noErr)
39 return path.BaseName().value();
40
41 std::string result(base::SysCFStringRefToUTF8(str));
42 CFRelease(str);
43 return result;
44}
45
[email protected]ff8004952014-08-08 01:03:5146#endif // defined(OS_MACOSX)
47
48const base::FilePath::CharType kHomeShortcut[] = FILE_PATH_LITERAL("~");
49
dpapadd07974e32017-12-20 20:35:2650void OnDirectorySizeCalculated(
51 int message_id,
52 base::OnceCallback<void(const base::string16&)> callback,
53 int64_t size_in_bytes) {
54 const int one_mebibyte_in_bytes = 1024 * 1024;
55 base::string16 response =
56 size_in_bytes < one_mebibyte_in_bytes
57 ? l10n_util::GetStringUTF16(message_id)
58 : ui::FormatBytesWithUnits(size_in_bytes, ui::DATA_UNITS_MEBIBYTE,
59 true);
60
61 std::move(callback).Run(response);
62}
63
[email protected]a1e63332014-07-03 06:58:4164} // namespace
65
66base::FilePath PrettifyPath(const base::FilePath& source_path) {
67 base::FilePath home_path;
Avi Drissman210441b72018-05-01 15:51:0068 if (source_path.empty() ||
69 !base::PathService::Get(base::DIR_HOME, &home_path)) {
[email protected]ff8004952014-08-08 01:03:5170 return source_path;
Avi Drissman210441b72018-05-01 15:51:0071 }
[email protected]ff8004952014-08-08 01:03:5172
73 base::FilePath display_path = base::FilePath(kHomeShortcut);
74 if (source_path == home_path)
75 return display_path;
76
77#if defined(OS_MACOSX)
[email protected]a1e63332014-07-03 06:58:4178 DCHECK(source_path.IsAbsolute());
79
80 // Break down the incoming path into components, and grab the display name
81 // for every component. This will match app bundles, ".localized" folders,
82 // and localized subfolders of the user's home directory.
83 // Don't grab the display name of the first component, i.e., "/", as it'll
84 // show up as the HDD name.
85 std::vector<base::FilePath::StringType> components;
86 source_path.GetComponents(&components);
[email protected]ff8004952014-08-08 01:03:5187 display_path = base::FilePath(components[0]);
[email protected]a1e63332014-07-03 06:58:4188 base::FilePath actual_path = display_path;
89 for (std::vector<base::FilePath::StringType>::iterator i =
90 components.begin() + 1; i != components.end(); ++i) {
91 actual_path = actual_path.Append(*i);
92 if (actual_path == home_path) {
[email protected]ff8004952014-08-08 01:03:5193 display_path = base::FilePath(kHomeShortcut);
[email protected]a1e63332014-07-03 06:58:4194 home_path = base::FilePath();
95 continue;
96 }
97 std::string display = GetDisplayBaseName(actual_path);
98 display_path = display_path.Append(display);
99 }
100 DCHECK_EQ(actual_path.value(), source_path.value());
101 return display_path;
[email protected]ff8004952014-08-08 01:03:51102#else // defined(OS_MACOSX)
103 if (home_path.AppendRelativePath(source_path, &display_path))
[email protected]a1e63332014-07-03 06:58:41104 return display_path;
105 return source_path;
[email protected]a1e63332014-07-03 06:58:41106#endif // defined(OS_MACOSX)
[email protected]ff8004952014-08-08 01:03:51107}
[email protected]a1e63332014-07-03 06:58:41108
dpapadd07974e32017-12-20 20:35:26109void CalculateAndFormatExtensionDirectorySize(
110 const base::FilePath& extension_path,
111 int message_id,
112 base::OnceCallback<void(const base::string16&)> callback) {
113 base::PostTaskAndReplyWithResult(
114 GetExtensionFileTaskRunner().get(), FROM_HERE,
115 base::BindOnce(&base::ComputeDirectorySize, extension_path),
116 base::BindOnce(&OnDirectorySizeCalculated, message_id,
117 std::move(callback)));
118}
119
David Bertonia38320b2018-04-02 20:38:07120base::FilePath ResolveHomeDirectory(const base::FilePath& path) {
121#if defined(OS_WIN)
122 return path;
123#else
124 const auto& value = path.value();
125 // Look for a path starting with the "~" character. It must be alone or
126 // followed by a separator.
127 if (value.empty() || value[0] != FILE_PATH_LITERAL('~') ||
128 (value.length() > 1 && !base::FilePath::IsSeparator(value[1]))) {
129 return path;
130 }
131 base::FilePath result;
Avi Drissman210441b72018-05-01 15:51:00132 base::PathService::Get(base::DIR_HOME, &result);
David Bertonia38320b2018-04-02 20:38:07133 // The user could specify "~" or "~/", so be safe.
134 if (value.length() > 2) {
135 result = result.Append(value.substr(2));
136 }
137 return result;
138#endif
139}
140
[email protected]a1e63332014-07-03 06:58:41141} // namespace path_util
142} // namespace extensions