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