extension_resource.cc 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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
  3. // found in the LICENSE file.
  4. #include "extensions/common/extension_resource.h"
  5. #include "base/check.h"
  6. #include "base/files/file_util.h"
  7. namespace extensions {
  8. ExtensionResource::ExtensionResource() : follow_symlinks_anywhere_(false) {}
  9. ExtensionResource::ExtensionResource(const ExtensionId& extension_id,
  10. const base::FilePath& extension_root,
  11. const base::FilePath& relative_path)
  12. : extension_id_(extension_id),
  13. extension_root_(extension_root),
  14. relative_path_(relative_path),
  15. follow_symlinks_anywhere_(false) {}
  16. ExtensionResource::ExtensionResource(const ExtensionResource& other) = default;
  17. ExtensionResource::ExtensionResource(ExtensionResource&& other) = default;
  18. ExtensionResource& ExtensionResource::operator=(ExtensionResource&& other) =
  19. default;
  20. ExtensionResource::~ExtensionResource() = default;
  21. void ExtensionResource::set_follow_symlinks_anywhere() {
  22. follow_symlinks_anywhere_ = true;
  23. }
  24. const base::FilePath& ExtensionResource::GetFilePath() const {
  25. if (extension_root_.empty() || relative_path_.empty()) {
  26. DCHECK(full_resource_path_.empty());
  27. return full_resource_path_;
  28. }
  29. // We've already checked, just return last value.
  30. if (!full_resource_path_.empty())
  31. return full_resource_path_;
  32. full_resource_path_ = GetFilePath(
  33. extension_root_, relative_path_,
  34. follow_symlinks_anywhere_ ?
  35. FOLLOW_SYMLINKS_ANYWHERE : SYMLINKS_MUST_RESOLVE_WITHIN_ROOT);
  36. return full_resource_path_;
  37. }
  38. // static
  39. base::FilePath ExtensionResource::GetFilePath(
  40. const base::FilePath& extension_root,
  41. const base::FilePath& relative_path,
  42. SymlinkPolicy symlink_policy) {
  43. // We need to resolve the parent references in the extension_root
  44. // path on its own because IsParent doesn't like parent references.
  45. base::FilePath clean_extension_root(
  46. base::MakeAbsoluteFilePath(extension_root));
  47. if (clean_extension_root.empty())
  48. return base::FilePath();
  49. base::FilePath full_path = clean_extension_root.Append(relative_path);
  50. // If we are allowing the file to be a symlink outside of the root, then the
  51. // path before resolving the symlink must still be within it.
  52. if (symlink_policy == FOLLOW_SYMLINKS_ANYWHERE) {
  53. std::vector<base::FilePath::StringType> components =
  54. relative_path.GetComponents();
  55. int depth = 0;
  56. for (std::vector<base::FilePath::StringType>::const_iterator
  57. i = components.begin(); i != components.end(); i++) {
  58. if (*i == base::FilePath::kParentDirectory) {
  59. depth--;
  60. } else if (*i != base::FilePath::kCurrentDirectory) {
  61. depth++;
  62. }
  63. if (depth < 0) {
  64. return base::FilePath();
  65. }
  66. }
  67. }
  68. // We must resolve the absolute path of the combined path when
  69. // the relative path contains references to a parent folder (i.e., '..').
  70. // We also check if the path exists because the posix version of
  71. // MakeAbsoluteFilePath will fail if the path doesn't exist, and we want the
  72. // same behavior on Windows... So until the posix and Windows version of
  73. // MakeAbsoluteFilePath are unified, we need an extra call to PathExists,
  74. // unfortunately.
  75. // TODO(mad): Fix this once MakeAbsoluteFilePath is unified.
  76. full_path = base::MakeAbsoluteFilePath(full_path);
  77. if (base::PathExists(full_path) &&
  78. (symlink_policy == FOLLOW_SYMLINKS_ANYWHERE ||
  79. clean_extension_root.IsParent(full_path))) {
  80. return full_path;
  81. }
  82. return base::FilePath();
  83. }
  84. } // namespace extensions