1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/filesystem/file_system_impl.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "components/filesystem/directory_impl.h"
#include "components/filesystem/file_system_app.h"
#include "mojo/application/public/cpp/application_connection.h"
#include "url/gurl.h"
#if defined(OS_WIN)
#include "base/base_paths_win.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#elif defined(OS_ANDROID)
#include "base/base_paths_android.h"
#include "base/path_service.h"
#elif defined(OS_LINUX)
#include "base/environment.h"
#include "base/nix/xdg_util.h"
#elif defined(OS_MACOSX)
#include "base/base_paths_mac.h"
#include "base/path_service.h"
#endif
namespace filesystem {
namespace {
const char kEscapeChar = ',';
const char kUserDataDir[] = "user-data-dir";
} // namespace filesystem
FileSystemImpl::FileSystemImpl(FileSystemApp* app,
mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<FileSystem> request)
: app_(app),
remote_application_url_(connection->GetRemoteApplicationURL()),
binding_(this, request.Pass()) {
}
FileSystemImpl::~FileSystemImpl() {
}
void FileSystemImpl::OpenFileSystem(const mojo::String& file_system,
mojo::InterfaceRequest<Directory> directory,
FileSystemClientPtr client,
const OpenFileSystemCallback& callback) {
// Set only if the |DirectoryImpl| will own a temporary directory.
scoped_ptr<base::ScopedTempDir> temp_dir;
base::FilePath path;
if (file_system.get() == std::string("temp")) {
temp_dir.reset(new base::ScopedTempDir);
CHECK(temp_dir->CreateUniqueTempDir());
path = temp_dir->path();
} else if (file_system.get() == std::string("origin")) {
base::FilePath base_profile_dir = GetSystemProfileDir();
// Sanitize the url for disk access.
//
// TODO(erg): While it's currently impossible, we need to deal with http://
// URLs that have a path. (Or make the decision that these file systems are
// path bound, not origin bound.)
std::string sanitized_origin;
BuildSanitizedOrigin(remote_application_url_, &sanitized_origin);
#if defined(OS_WIN)
path = base_profile_dir.Append(base::UTF8ToWide(sanitized_origin));
#else
path = base_profile_dir.Append(sanitized_origin);
#endif
if (!base::PathExists(path))
base::CreateDirectory(path);
}
if (!path.empty()) {
DirectoryImpl* dir_impl =
new DirectoryImpl(directory.Pass(), path, temp_dir.Pass());
app_->RegisterDirectoryToClient(dir_impl, client.Pass());
callback.Run(FILE_ERROR_OK);
} else {
callback.Run(FILE_ERROR_FAILED);
}
}
base::FilePath FileSystemImpl::GetSystemProfileDir() const {
base::FilePath path;
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(kUserDataDir)) {
path = command_line->GetSwitchValuePath(kUserDataDir);
} else {
#if defined(OS_WIN)
CHECK(PathService::Get(base::DIR_LOCAL_APP_DATA, &path));
path = path.Append(FILE_PATH_LITERAL("mandoline"));
#elif defined(OS_LINUX)
scoped_ptr<base::Environment> env(base::Environment::Create());
base::FilePath config_dir(
base::nix::GetXDGDirectory(env.get(),
base::nix::kXdgConfigHomeEnvVar,
base::nix::kDotConfigDir));
path = config_dir.Append("mandoline");
#elif defined(OS_MACOSX)
CHECK(PathService::Get(base::DIR_APP_DATA, &path));
path = path.Append("Mandoline Shell");
#elif defined(OS_ANDROID)
CHECK(PathService::Get(base::DIR_ANDROID_APP_DATA, &path));
path = path.Append(FILE_PATH_LITERAL("mandoline"));
#else
NOTIMPLEMENTED();
#endif
}
if (!base::PathExists(path))
base::CreateDirectory(path);
return path;
}
void FileSystemImpl::BuildSanitizedOrigin(
const std::string& origin,
std::string* sanitized_origin) {
// We take the origin string, and encode it in a way safe for filesystem
// access. This is vaguely based on //net/tools/dump_cache/
// url_to_filename_encoder.h; that file strips out schemes, and does weird
// things with subdirectories. We do follow the basic algorithm used there,
// including using ',' as our escape character.
for (size_t i = 0; i < origin.length(); ++i) {
unsigned char ch = origin[i];
char encoded[3];
int encoded_len;
if ((ch == '_') || (ch == '.') || (ch == '=') || (ch == '+') ||
(ch == '-') || (('0' <= ch) && (ch <= '9')) ||
(('A' <= ch) && (ch <= 'Z')) || (('a' <= ch) && (ch <= 'z'))) {
encoded[0] = ch;
encoded_len = 1;
} else {
encoded[0] = kEscapeChar;
encoded[1] = ch / 16;
encoded[1] += (encoded[1] >= 10) ? 'A' - 10 : '0';
encoded[2] = ch % 16;
encoded[2] += (encoded[2] >= 10) ? 'A' - 10 : '0';
encoded_len = 3;
}
sanitized_origin->append(encoded, encoded_len);
}
}
} // namespace filesystem
|