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