OLD | NEW |
| (Empty) |
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 | |
5 #include "chrome/common/extensions/extension_resource.h" | |
6 | |
7 #include "base/file_util.h" | |
8 #include "base/logging.h" | |
9 #include "base/threading/thread_restrictions.h" | |
10 | |
11 ExtensionResource::ExtensionResource() : follow_symlinks_anywhere_(false) { | |
12 } | |
13 | |
14 ExtensionResource::ExtensionResource(const std::string& extension_id, | |
15 const base::FilePath& extension_root, | |
16 const base::FilePath& relative_path) | |
17 : extension_id_(extension_id), | |
18 extension_root_(extension_root), | |
19 relative_path_(relative_path), | |
20 follow_symlinks_anywhere_(false) { | |
21 } | |
22 | |
23 ExtensionResource::~ExtensionResource() {} | |
24 | |
25 void ExtensionResource::set_follow_symlinks_anywhere() { | |
26 follow_symlinks_anywhere_ = true; | |
27 } | |
28 | |
29 const base::FilePath& ExtensionResource::GetFilePath() const { | |
30 if (extension_root_.empty() || relative_path_.empty()) { | |
31 DCHECK(full_resource_path_.empty()); | |
32 return full_resource_path_; | |
33 } | |
34 | |
35 // We've already checked, just return last value. | |
36 if (!full_resource_path_.empty()) | |
37 return full_resource_path_; | |
38 | |
39 full_resource_path_ = GetFilePath( | |
40 extension_root_, relative_path_, | |
41 follow_symlinks_anywhere_ ? | |
42 FOLLOW_SYMLINKS_ANYWHERE : SYMLINKS_MUST_RESOLVE_WITHIN_ROOT); | |
43 return full_resource_path_; | |
44 } | |
45 | |
46 // static | |
47 base::FilePath ExtensionResource::GetFilePath( | |
48 const base::FilePath& extension_root, | |
49 const base::FilePath& relative_path, | |
50 SymlinkPolicy symlink_policy) { | |
51 // We need to resolve the parent references in the extension_root | |
52 // path on its own because IsParent doesn't like parent references. | |
53 base::FilePath clean_extension_root(extension_root); | |
54 if (!file_util::AbsolutePath(&clean_extension_root)) | |
55 return base::FilePath(); | |
56 | |
57 base::FilePath full_path = clean_extension_root.Append(relative_path); | |
58 | |
59 // If we are allowing the file to be a symlink outside of the root, then the | |
60 // path before resolving the symlink must still be within it. | |
61 if (symlink_policy == FOLLOW_SYMLINKS_ANYWHERE) { | |
62 std::vector<base::FilePath::StringType> components; | |
63 relative_path.GetComponents(&components); | |
64 int depth = 0; | |
65 | |
66 for (std::vector<base::FilePath::StringType>::const_iterator | |
67 i = components.begin(); i != components.end(); i++) { | |
68 if (*i == base::FilePath::kParentDirectory) { | |
69 depth--; | |
70 } else if (*i != base::FilePath::kCurrentDirectory) { | |
71 depth++; | |
72 } | |
73 if (depth < 0) { | |
74 return base::FilePath(); | |
75 } | |
76 } | |
77 } | |
78 | |
79 // We must resolve the absolute path of the combined path when | |
80 // the relative path contains references to a parent folder (i.e., '..'). | |
81 // We also check if the path exists because the posix version of AbsolutePath | |
82 // will fail if the path doesn't exist, and we want the same behavior on | |
83 // Windows... So until the posix and Windows version of AbsolutePath are | |
84 // unified, we need an extra call to PathExists, unfortunately. | |
85 // TODO(mad): Fix this once AbsolutePath is unified. | |
86 if (file_util::AbsolutePath(&full_path) && | |
87 file_util::PathExists(full_path) && | |
88 (symlink_policy == FOLLOW_SYMLINKS_ANYWHERE || | |
89 clean_extension_root.IsParent(full_path))) { | |
90 return full_path; | |
91 } | |
92 | |
93 return base::FilePath(); | |
94 } | |
95 | |
96 // Unit-testing helpers. | |
97 base::FilePath::StringType ExtensionResource::NormalizeSeperators( | |
98 const base::FilePath::StringType& path) const { | |
99 #if defined(FILE_PATH_USES_WIN_SEPARATORS) | |
100 base::FilePath::StringType win_path = path; | |
101 for (size_t i = 0; i < win_path.length(); i++) { | |
102 if (base::FilePath::IsSeparator(win_path[i])) | |
103 win_path[i] = base::FilePath::kSeparators[0]; | |
104 } | |
105 return win_path; | |
106 #else | |
107 return path; | |
108 #endif // FILE_PATH_USES_WIN_SEPARATORS | |
109 } | |
110 | |
111 bool ExtensionResource::ComparePathWithDefault( | |
112 const base::FilePath& path) const { | |
113 // Make sure we have a cached value to test against... | |
114 if (full_resource_path_.empty()) | |
115 GetFilePath(); | |
116 if (NormalizeSeperators(path.value()) == | |
117 NormalizeSeperators(full_resource_path_.value())) { | |
118 return true; | |
119 } else { | |
120 return false; | |
121 } | |
122 } | |
OLD | NEW |