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 "xwalk/application/common/application_resource.h"
9 #include "base/file_util.h"
10 #include "base/logging.h"
11 #include "base/threading/thread_restrictions.h"
14 namespace application {
16 const base::FilePath::StringType WGT_LOCALE_DIRECTORY =
17 FILE_PATH_LITERAL("locales");
20 ApplicationResource::ApplicationResource() : follow_symlinks_anywhere_(false) {
23 ApplicationResource::ApplicationResource(const std::string& application_id,
24 const base::FilePath& application_root,
25 const base::FilePath& relative_path)
26 : application_id_(application_id),
27 application_root_(application_root),
28 relative_path_(relative_path),
29 follow_symlinks_anywhere_(false) {
32 ApplicationResource::~ApplicationResource() {}
34 void ApplicationResource::set_follow_symlinks_anywhere() {
35 follow_symlinks_anywhere_ = true;
38 const base::FilePath& ApplicationResource::GetFilePath() const {
39 if (application_root_.empty() || relative_path_.empty()) {
40 DCHECK(full_resource_path_.empty());
41 return full_resource_path_;
44 // We've already checked, just return last value.
45 if (!full_resource_path_.empty())
46 return full_resource_path_;
48 for (std::list<std::string>::const_iterator it = locales_.begin();
49 it != locales_.end(); ++it) {
50 full_resource_path_ = GetFilePath(
52 base::FilePath(WGT_LOCALE_DIRECTORY)
53 .AppendASCII(*it).Append(relative_path_),
54 follow_symlinks_anywhere_ ?
55 FOLLOW_SYMLINKS_ANYWHERE : SYMLINKS_MUST_RESOLVE_WITHIN_ROOT);
56 if (!full_resource_path_.empty())
57 return full_resource_path_;
59 full_resource_path_ = GetFilePath(
60 application_root_, relative_path_,
61 follow_symlinks_anywhere_ ?
62 FOLLOW_SYMLINKS_ANYWHERE : SYMLINKS_MUST_RESOLVE_WITHIN_ROOT);
63 return full_resource_path_;
67 base::FilePath ApplicationResource::GetFilePath(
68 const base::FilePath& application_root,
69 const base::FilePath& relative_path,
70 SymlinkPolicy symlink_policy) {
71 // We need to resolve the parent references in the application_root
72 // path on its own because IsParent doesn't like parent references.
73 base::FilePath clean_application_root(
74 base::MakeAbsoluteFilePath(application_root));
75 if (clean_application_root.empty())
76 return base::FilePath();
78 base::FilePath full_path = clean_application_root.Append(relative_path);
80 // If we are allowing the file to be a symlink outside of the root, then the
81 // path before resolving the symlink must still be within it.
82 if (symlink_policy == FOLLOW_SYMLINKS_ANYWHERE) {
83 std::vector<base::FilePath::StringType> components;
84 relative_path.GetComponents(&components);
87 for (std::vector<base::FilePath::StringType>::const_iterator
88 i = components.begin(); i != components.end(); i++) {
89 if (*i == base::FilePath::kParentDirectory) {
91 } else if (*i != base::FilePath::kCurrentDirectory) {
95 return base::FilePath();
100 // We must resolve the absolute path of the combined path when
101 // the relative path contains references to a parent folder (i.e., '..').
102 // We also check if the path exists because the posix version of
103 // MakeAbsoluteFilePath will fail if the path doesn't exist, and we want the
104 // same behavior on Windows... So until the posix and Windows version of
105 // MakeAbsoluteFilePath are unified, we need an extra call to PathExists,
107 // TODO(mad): Fix this once MakeAbsoluteFilePath is unified.
108 full_path = base::MakeAbsoluteFilePath(full_path);
109 if (base::PathExists(full_path) &&
110 (symlink_policy == FOLLOW_SYMLINKS_ANYWHERE ||
111 clean_application_root.IsParent(full_path))) {
115 return base::FilePath();
118 // Unit-testing helpers.
119 base::FilePath::StringType ApplicationResource::NormalizeSeperators(
120 const base::FilePath::StringType& path) const {
121 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
122 base::FilePath::StringType win_path = path;
123 for (size_t i = 0; i < win_path.length(); i++) {
124 if (base::FilePath::IsSeparator(win_path[i]))
125 win_path[i] = base::FilePath::kSeparators[0];
130 #endif // FILE_PATH_USES_WIN_SEPARATORS
133 bool ApplicationResource::ComparePathWithDefault(
134 const base::FilePath& path) const {
135 // Make sure we have a cached value to test against...
136 if (full_resource_path_.empty())
138 if (NormalizeSeperators(path.value()) ==
139 NormalizeSeperators(full_resource_path_.value())) {
146 } // namespace application