Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/DeviceStorageFileSystem.h"
9 #include "DeviceStorage.h"
10 #include "mozilla/Preferences.h"
11 #include "mozilla/dom/Directory.h"
12 #include "mozilla/dom/FileSystemUtils.h"
13 #include "nsCOMPtr.h"
14 #include "nsDebug.h"
15 #include "nsDeviceStorage.h"
16 #include "nsIDOMFile.h"
17 #include "nsIFile.h"
18 #include "nsPIDOMWindow.h"
20 namespace mozilla {
21 namespace dom {
23 DeviceStorageFileSystem::DeviceStorageFileSystem(
24 const nsAString& aStorageType,
25 const nsAString& aStorageName)
26 : mDeviceStorage(nullptr)
27 {
28 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
30 mStorageType = aStorageType;
31 mStorageName = aStorageName;
33 // Generate the string representation of the file system.
34 mString.AppendLiteral("devicestorage-");
35 mString.Append(mStorageType);
36 mString.AppendLiteral("-");
37 mString.Append(mStorageName);
39 mIsTesting =
40 mozilla::Preferences::GetBool("device.storage.prompt.testing", false);
42 // Get the permission name required to access the file system.
43 nsresult rv =
44 DeviceStorageTypeChecker::GetPermissionForType(mStorageType, mPermission);
45 NS_WARN_IF(NS_FAILED(rv));
47 // Get the local path of the file system root.
48 // Since the child process is not allowed to access the file system, we only
49 // do this from the parent process.
50 if (!FileSystemUtils::IsParentProcess()) {
51 return;
52 }
53 nsCOMPtr<nsIFile> rootFile;
54 DeviceStorageFile::GetRootDirectoryForType(aStorageType,
55 aStorageName,
56 getter_AddRefs(rootFile));
58 NS_WARN_IF(!rootFile || NS_FAILED(rootFile->GetPath(mLocalRootPath)));
59 FileSystemUtils::LocalPathToNormalizedPath(mLocalRootPath,
60 mNormalizedLocalRootPath);
62 // DeviceStorageTypeChecker is a singleton object and must be initialized on
63 // the main thread. We initialize it here so that we can use it on the worker
64 // thread.
65 DebugOnly<DeviceStorageTypeChecker*> typeChecker
66 = DeviceStorageTypeChecker::CreateOrGet();
67 MOZ_ASSERT(typeChecker);
68 }
70 DeviceStorageFileSystem::~DeviceStorageFileSystem()
71 {
72 }
74 void
75 DeviceStorageFileSystem::Init(nsDOMDeviceStorage* aDeviceStorage)
76 {
77 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
78 MOZ_ASSERT(aDeviceStorage);
79 mDeviceStorage = aDeviceStorage;
80 }
82 void
83 DeviceStorageFileSystem::Shutdown()
84 {
85 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
86 mDeviceStorage = nullptr;
87 mShutdown = true;
88 }
90 nsPIDOMWindow*
91 DeviceStorageFileSystem::GetWindow() const
92 {
93 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
94 if (!mDeviceStorage) {
95 return nullptr;
96 }
97 return mDeviceStorage->GetOwner();
98 }
100 already_AddRefed<nsIFile>
101 DeviceStorageFileSystem::GetLocalFile(const nsAString& aRealPath) const
102 {
103 MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
104 "Should be on parent process!");
105 nsAutoString localPath;
106 FileSystemUtils::NormalizedPathToLocalPath(aRealPath, localPath);
107 localPath = mLocalRootPath + localPath;
108 nsCOMPtr<nsIFile> file;
109 nsresult rv = NS_NewLocalFile(localPath, false, getter_AddRefs(file));
110 if (NS_WARN_IF(NS_FAILED(rv))) {
111 return nullptr;
112 }
113 return file.forget();
114 }
116 bool
117 DeviceStorageFileSystem::GetRealPath(nsIDOMFile* aFile, nsAString& aRealPath) const
118 {
119 MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
120 "Should be on parent process!");
121 MOZ_ASSERT(aFile, "aFile Should not be null.");
123 aRealPath.Truncate();
125 nsAutoString filePath;
126 if (NS_FAILED(aFile->GetMozFullPathInternal(filePath))) {
127 return false;
128 }
130 return LocalPathToRealPath(filePath, aRealPath);
131 }
133 const nsAString&
134 DeviceStorageFileSystem::GetRootName() const
135 {
136 return mStorageName;
137 }
139 bool
140 DeviceStorageFileSystem::IsSafeFile(nsIFile* aFile) const
141 {
142 MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
143 "Should be on parent process!");
144 MOZ_ASSERT(aFile);
146 // Check if this file belongs to this storage.
147 nsAutoString path;
148 if (NS_FAILED(aFile->GetPath(path))) {
149 return false;
150 }
151 if (!LocalPathToRealPath(path, path)) {
152 return false;
153 }
155 // Check if the file type is compatible with the storage type.
156 DeviceStorageTypeChecker* typeChecker
157 = DeviceStorageTypeChecker::CreateOrGet();
158 MOZ_ASSERT(typeChecker);
159 return typeChecker->Check(mStorageType, aFile);
160 }
162 bool
163 DeviceStorageFileSystem::IsSafeDirectory(Directory* aDir) const
164 {
165 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
166 MOZ_ASSERT(aDir);
167 nsRefPtr<FileSystemBase> fs = aDir->GetFileSystem();
168 MOZ_ASSERT(fs);
169 // Check if the given directory is from this storage.
170 return fs->ToString() == mString;
171 }
173 bool
174 DeviceStorageFileSystem::LocalPathToRealPath(const nsAString& aLocalPath,
175 nsAString& aRealPath) const
176 {
177 nsAutoString path;
178 FileSystemUtils::LocalPathToNormalizedPath(aLocalPath, path);
179 if (!FileSystemUtils::IsDescendantPath(mNormalizedLocalRootPath, path)) {
180 aRealPath.Truncate();
181 return false;
182 }
183 aRealPath = Substring(path, mNormalizedLocalRootPath.Length());
184 return true;
185 }
187 } // namespace dom
188 } // namespace mozilla