OLD | NEW |
---|---|
(Empty) | |
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 "native_client/src/trusted/plugin/local_temp_file.h" | |
6 | |
7 #include "native_client/src/include/portability_io.h" | |
8 #include "native_client/src/shared/platform/nacl_check.h" | |
9 #include "native_client/src/trusted/plugin/plugin.h" | |
10 #include "native_client/src/trusted/plugin/utility.h" | |
11 | |
12 #include "ppapi/c/ppb_file_io.h" | |
13 #include "ppapi/cpp/file_io.h" | |
14 #include "ppapi/cpp/file_ref.h" | |
15 #include "ppapi/cpp/file_system.h" | |
16 | |
17 ////////////////////////////////////////////////////////////////////// | |
18 // Local temporary file access. | |
19 ////////////////////////////////////////////////////////////////////// | |
20 namespace plugin { | |
21 | |
22 namespace { | |
23 nacl::string Random32CharHexString(struct NaClDescRng* rng) { | |
24 struct NaClDesc* desc = reinterpret_cast<struct NaClDesc*>(rng); | |
25 const struct NaClDescVtbl* vtbl = | |
26 reinterpret_cast<const struct NaClDescVtbl*>(desc->base.vtbl); | |
27 | |
28 nacl::string hex_string; | |
29 const int32_t kTempFileNameWords = 4; | |
30 for (int32_t i = 0; i < kTempFileNameWords; ++i) { | |
31 int32_t num; | |
32 CHECK(sizeof num == vtbl->Read(desc, | |
33 reinterpret_cast<char*>(&num), | |
34 sizeof num)); | |
35 char frag[16]; | |
36 SNPRINTF(frag, sizeof frag, "%08x", num); | |
37 hex_string += nacl::string(frag); | |
38 } | |
39 return hex_string; | |
40 } | |
41 | |
42 // Some constants for PnaclFileDescPair::GetFD readability. | |
43 const bool kReadOnly = false; | |
44 const bool kWriteable = true; | |
45 } // namespace | |
46 | |
47 uint32_t LocalTempFile::next_identifier = 0; | |
48 const nacl::string LocalTempFile::kPnaclTempDir = "/.pnacl"; | |
49 | |
50 LocalTempFile::LocalTempFile(Plugin* plugin, | |
51 pp::FileSystem* file_system) | |
52 : plugin_(plugin), | |
53 file_system_(file_system) { | |
54 PLUGIN_PRINTF(("LocalTempFile::LocalTempFile (plugin=%p, " | |
55 "file_system=%p)\n", | |
56 static_cast<void*>(plugin), static_cast<void*>(file_system))); | |
57 Initialize(); | |
58 } | |
59 | |
60 LocalTempFile::LocalTempFile(Plugin* plugin, | |
61 pp::FileSystem* file_system, | |
62 const nacl::string &filename) | |
63 : plugin_(plugin), | |
64 file_system_(file_system), | |
65 filename_(kPnaclTempDir + "/" + filename) { | |
jvoung - send to chromium...
2012/05/15 23:51:05
Maybe we could just have the constructor take an a
Derek Schuff
2012/05/16 16:47:46
Done.
| |
66 PLUGIN_PRINTF(("LocalTempFile::LocalTempFile (plugin=%p, " | |
67 "file_system=%p, filename=%s)\n", | |
68 static_cast<void*>(plugin), static_cast<void*>(file_system), | |
69 filename.c_str())); | |
70 file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); | |
71 Initialize(); | |
72 } | |
73 | |
74 void LocalTempFile::Initialize() { | |
75 callback_factory_.Initialize(this); | |
76 rng_desc_ = (struct NaClDescRng *) malloc(sizeof *rng_desc_); | |
77 CHECK(rng_desc_ != NULL); | |
78 CHECK(NaClDescRngCtor(rng_desc_)); | |
79 file_io_trusted_ = static_cast<const PPB_FileIOTrusted*>( | |
80 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE)); | |
81 ++next_identifier; | |
82 SNPRINTF(reinterpret_cast<char *>(identifier_), sizeof identifier_, | |
83 "%"NACL_PRIu32, next_identifier); | |
84 } | |
85 | |
86 LocalTempFile::~LocalTempFile() { | |
87 PLUGIN_PRINTF(("LocalTempFile::~LocalTempFile\n")); | |
88 NaClDescUnref(reinterpret_cast<NaClDesc*>(rng_desc_)); | |
89 } | |
90 | |
91 void LocalTempFile::OpenWrite(const pp::CompletionCallback& cb) { | |
92 done_callback_ = cb; | |
93 // If we don't already have a filename, generate one. | |
94 if (filename_ == "") { | |
95 // Get a random temp file name. | |
96 filename_ = kPnaclTempDir + "/" + Random32CharHexString(rng_desc_); | |
97 // Remember the ref used to open for writing and reading. | |
98 file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); | |
99 } | |
100 PLUGIN_PRINTF(("LocalTempFile::OpenWrite: %s\n", filename_.c_str())); | |
101 // Open the writeable file. | |
102 write_io_.reset(new pp::FileIO(plugin_)); | |
103 pp::CompletionCallback open_write_cb = | |
104 callback_factory_.NewCallback(&LocalTempFile::WriteFileDidOpen); | |
105 write_io_->Open(*file_ref_, | |
106 PP_FILEOPENFLAG_WRITE | | |
107 PP_FILEOPENFLAG_CREATE | | |
108 PP_FILEOPENFLAG_EXCLUSIVE, | |
109 open_write_cb); | |
110 } | |
111 | |
112 int32_t LocalTempFile::GetFD(int32_t pp_error, | |
113 const pp::Resource& resource, | |
114 bool is_writable) { | |
115 PLUGIN_PRINTF(("LocalTempFile::GetFD (pp_error=%"NACL_PRId32 | |
116 ", is_writable=%d)\n", pp_error, is_writable)); | |
117 if (pp_error != PP_OK) { | |
118 PLUGIN_PRINTF(("LocalTempFile::GetFD pp_error != PP_OK\n")); | |
119 return -1; | |
120 } | |
121 int32_t file_desc = | |
122 file_io_trusted_->GetOSFileDescriptor(resource.pp_resource()); | |
123 #if NACL_WINDOWS | |
124 // Convert the Windows HANDLE from Pepper to a POSIX file descriptor. | |
125 int32_t open_flags = ((is_writable ? _O_RDWR : _O_RDONLY) | _O_BINARY); | |
126 int32_t posix_desc = _open_osfhandle(file_desc, open_flags); | |
127 if (posix_desc == -1) { | |
128 // Close the Windows HANDLE if it can't be converted. | |
129 CloseHandle(reinterpret_cast<HANDLE>(file_desc)); | |
130 PLUGIN_PRINTF(("LocalTempFile::GetFD _open_osfhandle failed.\n")); | |
131 return NACL_NO_FILE_DESC; | |
132 } | |
133 file_desc = posix_desc; | |
134 #endif | |
135 int32_t file_desc_ok_to_close = DUP(file_desc); | |
136 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) { | |
137 PLUGIN_PRINTF(("LocalTempFile::GetFD dup failed.\n")); | |
138 return -1; | |
139 } | |
140 return file_desc_ok_to_close; | |
141 } | |
142 | |
143 void LocalTempFile::WriteFileDidOpen(int32_t pp_error) { | |
144 PLUGIN_PRINTF(("LocalTempFile::WriteFileDidOpen (pp_error=%" | |
145 NACL_PRId32")\n", pp_error)); | |
146 if (pp_error == PP_ERROR_FILEEXISTS) { | |
147 // Filenames clashed, retry. | |
148 filename_ = ""; | |
149 OpenWrite(done_callback_); | |
150 } | |
151 // Run the client's completion callback. | |
152 pp::Core* core = pp::Module::Get()->core(); | |
153 if (pp_error != PP_OK) { | |
154 core->CallOnMainThread(0, done_callback_, pp_error); | |
155 return; | |
156 } | |
157 // Remember the object temporary file descriptor. | |
158 int32_t fd = GetFD(pp_error, *write_io_, kWriteable); | |
159 if (fd < 0) { | |
160 core->CallOnMainThread(0, done_callback_, pp_error); | |
161 return; | |
162 } | |
163 // The descriptor for a writeable file needs to have quota management. | |
164 write_wrapper_.reset( | |
165 plugin_->wrapper_factory()->MakeFileDescQuota(fd, O_RDWR, identifier_)); | |
166 core->CallOnMainThread(0, done_callback_, PP_OK); | |
167 } | |
168 | |
169 void LocalTempFile::OpenRead(const pp::CompletionCallback& cb) { | |
170 PLUGIN_PRINTF(("LocalTempFile::OpenRead: %s\n", filename_.c_str())); | |
171 done_callback_ = cb; | |
172 // Open the read only file. | |
173 read_io_.reset(new pp::FileIO(plugin_)); | |
174 pp::CompletionCallback open_read_cb = | |
175 callback_factory_.NewCallback(&LocalTempFile::ReadFileDidOpen); | |
176 read_io_->Open(*file_ref_, PP_FILEOPENFLAG_READ, open_read_cb); | |
177 } | |
178 | |
179 void LocalTempFile::ReadFileDidOpen(int32_t pp_error) { | |
180 PLUGIN_PRINTF(("LocalTempFile::ReadFileDidOpen (pp_error=%" | |
181 NACL_PRId32")\n", pp_error)); | |
182 // Run the client's completion callback. | |
183 pp::Core* core = pp::Module::Get()->core(); | |
184 if (pp_error != PP_OK) { | |
185 core->CallOnMainThread(0, done_callback_, pp_error); | |
186 return; | |
187 } | |
188 // Remember the object temporary file descriptor. | |
189 int32_t fd = GetFD(pp_error, *read_io_, kReadOnly); | |
190 if (fd < 0) { | |
191 core->CallOnMainThread(0, done_callback_, PP_ERROR_FAILED); | |
192 return; | |
193 } | |
194 read_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY)); | |
195 core->CallOnMainThread(0, done_callback_, PP_OK); | |
196 } | |
197 | |
198 void LocalTempFile::Close(const pp::CompletionCallback& cb) { | |
199 PLUGIN_PRINTF(("LocalTempFile::Close: %s\n", filename_.c_str())); | |
200 // Close the open DescWrappers and FileIOs. | |
201 if (write_io_.get() != NULL) { | |
202 write_io_->Close(); | |
203 } | |
204 write_wrapper_.reset(NULL); | |
205 write_io_.reset(NULL); | |
206 if (read_io_.get() != NULL) { | |
207 read_io_->Close(); | |
208 } | |
209 read_wrapper_.reset(NULL); | |
210 read_io_.reset(NULL); | |
211 // Run the client's completion callback. | |
212 pp::Core* core = pp::Module::Get()->core(); | |
213 core->CallOnMainThread(0, cb, PP_OK); | |
214 } | |
215 | |
216 void LocalTempFile::Delete(const pp::CompletionCallback& cb) { | |
217 PLUGIN_PRINTF(("LocalTempFile::Delete: %s\n", filename_.c_str())); | |
218 file_ref_->Delete(cb); | |
219 } | |
220 | |
221 void LocalTempFile::Rename(const nacl::string& new_name, | |
222 const pp::CompletionCallback& cb) { | |
223 // Rename the temporary file. | |
224 filename_ = kPnaclTempDir + "/" + new_name; | |
225 PLUGIN_PRINTF(("LocalTempFile::Rename %s to %s\n", | |
226 file_ref_->GetName().AsString().c_str(), | |
227 filename_.c_str())); | |
228 // Remember the old ref until the rename is complete. | |
229 old_ref_.reset(file_ref_.release()); | |
230 file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); | |
231 old_ref_->Rename(*file_ref_, cb); | |
232 } | |
233 | |
234 void LocalTempFile::FinishRename() { | |
235 // Now we can release the old ref. | |
236 old_ref_.reset(NULL); | |
237 } | |
238 | |
239 } // namespace plugin | |
OLD | NEW |