1 // Copyright (c) 2011 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
ExtensionResource()11 ExtensionResource::ExtensionResource() {
12 }
13
ExtensionResource(const std::string & extension_id,const FilePath & extension_root,const FilePath & relative_path)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 }
21
~ExtensionResource()22 ExtensionResource::~ExtensionResource() {}
23
GetFilePath() const24 const 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
30 // We've already checked, just return last value.
31 if (!full_resource_path_.empty())
32 return full_resource_path_;
33
34 full_resource_path_ =
35 GetFilePath(extension_root_, relative_path_);
36 return full_resource_path_;
37 }
38
39 // static
GetFilePath(const FilePath & extension_root,const FilePath & relative_path)40 FilePath ExtensionResource::GetFilePath(
41 const FilePath& extension_root, const FilePath& relative_path) {
42 // We need to resolve the parent references in the extension_root
43 // path on its own because IsParent doesn't like parent references.
44 FilePath clean_extension_root(extension_root);
45 if (!file_util::AbsolutePath(&clean_extension_root))
46 return FilePath();
47
48 FilePath full_path = clean_extension_root.Append(relative_path);
49
50 // We must resolve the absolute path of the combined path when
51 // the relative path contains references to a parent folder (i.e., '..').
52 // We also check if the path exists because the posix version of AbsolutePath
53 // will fail if the path doesn't exist, and we want the same behavior on
54 // Windows... So until the posix and Windows version of AbsolutePath are
55 // unified, we need an extra call to PathExists, unfortunately.
56 // TODO(mad): Fix this once AbsolutePath is unified.
57 if (file_util::AbsolutePath(&full_path) &&
58 file_util::PathExists(full_path) &&
59 clean_extension_root.IsParent(full_path)) {
60 return full_path;
61 }
62
63 return FilePath();
64 }
65
66 // Unit-testing helpers.
NormalizeSeperators(const FilePath::StringType & path) const67 FilePath::StringType ExtensionResource::NormalizeSeperators(
68 const FilePath::StringType& path) const {
69 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
70 FilePath::StringType win_path = path;
71 for (size_t i = 0; i < win_path.length(); i++) {
72 if (FilePath::IsSeparator(win_path[i]))
73 win_path[i] = FilePath::kSeparators[0];
74 }
75 return win_path;
76 #else
77 return path;
78 #endif // FILE_PATH_USES_WIN_SEPARATORS
79 }
80
ComparePathWithDefault(const FilePath & path) const81 bool ExtensionResource::ComparePathWithDefault(const FilePath& path) const {
82 // Make sure we have a cached value to test against...
83 if (full_resource_path_.empty())
84 GetFilePath();
85 if (NormalizeSeperators(path.value()) ==
86 NormalizeSeperators(full_resource_path_.value())) {
87 return true;
88 } else {
89 return false;
90 }
91 }
92