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.
5 #include "chrome/common/extensions/extension_resource.h"
7 #include "base/file_util.h"
8 #include "base/logging.h"
9 #include "base/threading/thread_restrictions.h"
11 ExtensionResource::ExtensionResource() : follow_symlinks_anywhere_(false) {
14 ExtensionResource::ExtensionResource(const std::string
& extension_id
,
15 const FilePath
& extension_root
,
16 const FilePath
& relative_path
)
17 : extension_id_(extension_id
),
18 extension_root_(extension_root
),
19 relative_path_(relative_path
),
20 follow_symlinks_anywhere_(false) {
23 ExtensionResource::~ExtensionResource() {}
25 void ExtensionResource::set_follow_symlinks_anywhere() {
26 follow_symlinks_anywhere_
= true;
29 const FilePath
& ExtensionResource::GetFilePath() const {
30 if (extension_root_
.empty() || relative_path_
.empty()) {
31 DCHECK(full_resource_path_
.empty());
32 return full_resource_path_
;
35 // We've already checked, just return last value.
36 if (!full_resource_path_
.empty())
37 return full_resource_path_
;
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_
;
47 FilePath
ExtensionResource::GetFilePath(
48 const FilePath
& extension_root
,
49 const 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 FilePath
clean_extension_root(extension_root
);
54 if (!file_util::AbsolutePath(&clean_extension_root
))
57 FilePath full_path
= clean_extension_root
.Append(relative_path
);
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
<FilePath::StringType
> components
;
63 relative_path
.GetComponents(&components
);
66 for (std::vector
<FilePath::StringType
>::const_iterator
67 i
= components
.begin(); i
!= components
.end(); i
++) {
68 if (*i
== FilePath::kParentDirectory
) {
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
))) {
96 // Unit-testing helpers.
97 FilePath::StringType
ExtensionResource::NormalizeSeperators(
98 const FilePath::StringType
& path
) const {
99 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
100 FilePath::StringType win_path
= path
;
101 for (size_t i
= 0; i
< win_path
.length(); i
++) {
102 if (FilePath::IsSeparator(win_path
[i
]))
103 win_path
[i
] = FilePath::kSeparators
[0];
108 #endif // FILE_PATH_USES_WIN_SEPARATORS
111 bool ExtensionResource::ComparePathWithDefault(const FilePath
& path
) const {
112 // Make sure we have a cached value to test against...
113 if (full_resource_path_
.empty())
115 if (NormalizeSeperators(path
.value()) ==
116 NormalizeSeperators(full_resource_path_
.value())) {