path_util.cc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. #include "extensions/browser/path_util.h"
  5. #include "base/bind.h"
  6. #include "base/files/file_util.h"
  7. #include "base/path_service.h"
  8. #include "base/strings/sys_string_conversions.h"
  9. #include "base/task/task_runner_util.h"
  10. #include "base/threading/sequenced_task_runner_handle.h"
  11. #include "build/build_config.h"
  12. #include "extensions/browser/extension_file_task_runner.h"
  13. #include "ui/base/l10n/l10n_util.h"
  14. #include "ui/base/text/bytes_formatting.h"
  15. #if BUILDFLAG(IS_MAC)
  16. #include <CoreFoundation/CoreFoundation.h>
  17. #include "base/mac/foundation_util.h"
  18. #endif
  19. namespace extensions {
  20. namespace path_util {
  21. namespace {
  22. #if BUILDFLAG(IS_MAC)
  23. // Retrieves the localized display name for the base name of the given path.
  24. // If the path is not localized, this will just return the base name.
  25. std::string GetDisplayBaseName(const base::FilePath& path) {
  26. base::ScopedCFTypeRef<CFURLRef> url(CFURLCreateFromFileSystemRepresentation(
  27. NULL, (const UInt8*)path.value().c_str(), path.value().length(), true));
  28. if (!url)
  29. return path.BaseName().value();
  30. CFStringRef str;
  31. if (LSCopyDisplayNameForURL(url, &str) != noErr)
  32. return path.BaseName().value();
  33. std::string result(base::SysCFStringRefToUTF8(str));
  34. CFRelease(str);
  35. return result;
  36. }
  37. #endif // BUILDFLAG(IS_MAC)
  38. const base::FilePath::CharType kHomeShortcut[] = FILE_PATH_LITERAL("~");
  39. void OnDirectorySizeCalculated(
  40. int message_id,
  41. base::OnceCallback<void(const std::u16string&)> callback,
  42. int64_t size_in_bytes) {
  43. const int one_mebibyte_in_bytes = 1024 * 1024;
  44. std::u16string response =
  45. size_in_bytes < one_mebibyte_in_bytes
  46. ? l10n_util::GetStringUTF16(message_id)
  47. : ui::FormatBytesWithUnits(size_in_bytes, ui::DATA_UNITS_MEBIBYTE,
  48. true);
  49. std::move(callback).Run(response);
  50. }
  51. } // namespace
  52. base::FilePath PrettifyPath(const base::FilePath& source_path) {
  53. base::FilePath home_path;
  54. if (source_path.empty() ||
  55. !base::PathService::Get(base::DIR_HOME, &home_path)) {
  56. return source_path;
  57. }
  58. base::FilePath display_path = base::FilePath(kHomeShortcut);
  59. if (source_path == home_path)
  60. return display_path;
  61. #if BUILDFLAG(IS_MAC)
  62. DCHECK(source_path.IsAbsolute());
  63. // Break down the incoming path into components, and grab the display name
  64. // for every component. This will match app bundles, ".localized" folders,
  65. // and localized subfolders of the user's home directory.
  66. // Don't grab the display name of the first component, i.e., "/", as it'll
  67. // show up as the HDD name.
  68. std::vector<base::FilePath::StringType> components =
  69. source_path.GetComponents();
  70. display_path = base::FilePath(components[0]);
  71. base::FilePath actual_path = display_path;
  72. for (std::vector<base::FilePath::StringType>::iterator i =
  73. components.begin() + 1; i != components.end(); ++i) {
  74. actual_path = actual_path.Append(*i);
  75. if (actual_path == home_path) {
  76. display_path = base::FilePath(kHomeShortcut);
  77. home_path = base::FilePath();
  78. continue;
  79. }
  80. std::string display = GetDisplayBaseName(actual_path);
  81. display_path = display_path.Append(display);
  82. }
  83. DCHECK_EQ(actual_path.value(), source_path.value());
  84. return display_path;
  85. #else // BUILDFLAG(IS_MAC)
  86. if (home_path.AppendRelativePath(source_path, &display_path))
  87. return display_path;
  88. return source_path;
  89. #endif // BUILDFLAG(IS_MAC)
  90. }
  91. void CalculateAndFormatExtensionDirectorySize(
  92. const base::FilePath& extension_path,
  93. int message_id,
  94. base::OnceCallback<void(const std::u16string&)> callback) {
  95. base::PostTaskAndReplyWithResult(
  96. GetExtensionFileTaskRunner().get(), FROM_HERE,
  97. base::BindOnce(&base::ComputeDirectorySize, extension_path),
  98. base::BindOnce(&OnDirectorySizeCalculated, message_id,
  99. std::move(callback)));
  100. }
  101. base::FilePath ResolveHomeDirectory(const base::FilePath& path) {
  102. #if BUILDFLAG(IS_WIN)
  103. return path;
  104. #else
  105. const auto& value = path.value();
  106. // Look for a path starting with the "~" character. It must be alone or
  107. // followed by a separator.
  108. if (value.empty() || value[0] != FILE_PATH_LITERAL('~') ||
  109. (value.length() > 1 && !base::FilePath::IsSeparator(value[1]))) {
  110. return path;
  111. }
  112. base::FilePath result;
  113. base::PathService::Get(base::DIR_HOME, &result);
  114. // The user could specify "~" or "~/", so be safe.
  115. if (value.length() > 2) {
  116. result = result.Append(value.substr(2));
  117. }
  118. return result;
  119. #endif
  120. }
  121. } // namespace path_util
  122. } // namespace extensions