blob: 7eeab923143259a4483541dbaf50eb9b242b4bef [file] [log] [blame]
[email protected]cc6db922011-12-10 16:54:221// 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 "ppapi/shared_impl/ppb_file_io_shared.h"
6
7#include <string.h>
8
9#include "base/bind.h"
10#include "base/logging.h"
11#include "base/message_loop.h"
12#include "ppapi/c/pp_errors.h"
13#include "ppapi/shared_impl/file_type_conversion.h"
14#include "ppapi/shared_impl/time_conversion.h"
15#include "ppapi/thunk/enter.h"
16#include "ppapi/thunk/ppb_file_ref_api.h"
17
18namespace ppapi {
19
20using thunk::EnterResourceNoLock;
21using thunk::PPB_FileIO_API;
22using thunk::PPB_FileRef_API;
23
24PPB_FileIO_Shared::CallbackEntry::CallbackEntry()
25 : read_buffer(NULL),
26 info(NULL) {
[email protected]cc6db922011-12-10 16:54:2227}
28
29PPB_FileIO_Shared::CallbackEntry::CallbackEntry(const CallbackEntry& entry)
30 : callback(entry.callback),
31 read_buffer(entry.read_buffer),
32 info(entry.info) {
33}
34
35PPB_FileIO_Shared::CallbackEntry::~CallbackEntry() {
36}
37
38PPB_FileIO_Shared::PPB_FileIO_Shared(PP_Instance instance)
39 : Resource(instance),
40 file_system_type_(PP_FILESYSTEMTYPE_INVALID),
41 file_open_(false),
42 pending_op_(OPERATION_NONE) {
43}
44
45PPB_FileIO_Shared::PPB_FileIO_Shared(const HostResource& host_resource)
46 : Resource(host_resource),
47 file_system_type_(PP_FILESYSTEMTYPE_INVALID),
48 file_open_(false),
49 pending_op_(OPERATION_NONE) {
50}
51
52PPB_FileIO_Shared::~PPB_FileIO_Shared() {
[email protected]cc6db922011-12-10 16:54:2253}
54
55thunk::PPB_FileIO_API* PPB_FileIO_Shared::AsPPB_FileIO_API() {
56 return this;
57}
58
59int32_t PPB_FileIO_Shared::Open(PP_Resource file_ref,
60 int32_t open_flags,
61 PP_CompletionCallback callback) {
62 EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, true);
63 if (enter.failed())
64 return PP_ERROR_BADRESOURCE;
65
66 int32_t rv = CommonCallValidation(false, OPERATION_EXCLUSIVE, callback);
67 if (rv != PP_OK)
68 return rv;
69
70 PP_FileSystemType type = enter.object()->GetFileSystemType();
71 if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
72 type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
73 type != PP_FILESYSTEMTYPE_EXTERNAL)
74 return PP_ERROR_FAILED;
75 file_system_type_ = type;
76
77 return OpenValidated(file_ref, enter.object(), open_flags, callback);
78}
79
80int32_t PPB_FileIO_Shared::Query(PP_FileInfo* info,
81 PP_CompletionCallback callback) {
82 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
83 if (rv != PP_OK)
84 return rv;
85 if (!info)
86 return PP_ERROR_BADARGUMENT;
87 return QueryValidated(info, callback);
88}
89
90int32_t PPB_FileIO_Shared::Touch(PP_Time last_access_time,
91 PP_Time last_modified_time,
92 PP_CompletionCallback callback) {
93 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
94 if (rv != PP_OK)
95 return rv;
96 return TouchValidated(last_access_time, last_modified_time, callback);
97}
98
99int32_t PPB_FileIO_Shared::Read(int64_t offset,
100 char* buffer,
101 int32_t bytes_to_read,
102 PP_CompletionCallback callback) {
103 int32_t rv = CommonCallValidation(true, OPERATION_READ, callback);
104 if (rv != PP_OK)
105 return rv;
106 return ReadValidated(offset, buffer, bytes_to_read, callback);
107}
108
109int32_t PPB_FileIO_Shared::Write(int64_t offset,
110 const char* buffer,
111 int32_t bytes_to_write,
112 PP_CompletionCallback callback) {
113 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback);
114 if (rv != PP_OK)
115 return rv;
116 return WriteValidated(offset, buffer, bytes_to_write, callback);
117}
118
119int32_t PPB_FileIO_Shared::SetLength(int64_t length,
120 PP_CompletionCallback callback) {
121 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
122 if (rv != PP_OK)
123 return rv;
124 return SetLengthValidated(length, callback);
125}
126
127int32_t PPB_FileIO_Shared::Flush(PP_CompletionCallback callback) {
128 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
129 if (rv != PP_OK)
130 return rv;
131 return FlushValidated(callback);
132}
133
134void PPB_FileIO_Shared::ExecuteGeneralCallback(int32_t pp_error) {
135 RunAndRemoveFirstPendingCallback(pp_error);
136}
137
138void PPB_FileIO_Shared::ExecuteOpenFileCallback(int32_t pp_error) {
139 if (pp_error == PP_OK)
140 file_open_ = true;
141 ExecuteGeneralCallback(pp_error);
142}
143
144void PPB_FileIO_Shared::ExecuteQueryCallback(int32_t pp_error,
145 const PP_FileInfo& info) {
146 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty() ||
147 !callbacks_.front().info) {
148 NOTREACHED();
149 return;
150 }
151 *callbacks_.front().info = info;
152 RunAndRemoveFirstPendingCallback(pp_error);
153}
154
155void PPB_FileIO_Shared::ExecuteReadCallback(int32_t pp_error,
156 const char* data) {
157 if (pending_op_ != OPERATION_READ || callbacks_.empty()) {
158 NOTREACHED();
159 return;
160 }
161
162 char* read_buffer = callbacks_.front().read_buffer;
163 DCHECK(data);
164 DCHECK(read_buffer);
165
166 // The result code contains the number of bytes if it's positive.
167 if (pp_error > 0)
168 memcpy(read_buffer, data, pp_error);
169 RunAndRemoveFirstPendingCallback(pp_error);
170}
171
172int32_t PPB_FileIO_Shared::CommonCallValidation(
173 bool should_be_open,
174 OperationType new_op,
175 PP_CompletionCallback callback) {
176 // Only asynchronous operation is supported.
177 if (!callback.func)
178 return PP_ERROR_BLOCKS_MAIN_THREAD;
179
180 if (should_be_open) {
181 if (!file_open_)
182 return PP_ERROR_FAILED;
183 } else {
184 if (file_open_)
185 return PP_ERROR_FAILED;
186 }
187
188 if (pending_op_ != OPERATION_NONE &&
189 (pending_op_ != new_op || pending_op_ == OPERATION_EXCLUSIVE)) {
190 return PP_ERROR_INPROGRESS;
191 }
192
193 return PP_OK;
194}
195
196void PPB_FileIO_Shared::RegisterCallback(OperationType op,
197 PP_CompletionCallback callback,
198 char* read_buffer,
199 PP_FileInfo* info) {
200 DCHECK(callback.func);
201 DCHECK(pending_op_ == OPERATION_NONE ||
202 (pending_op_ != OPERATION_EXCLUSIVE && pending_op_ == op));
203
204 CallbackEntry entry;
[email protected]614888b2012-01-05 06:18:12205 entry.callback = new TrackedCallback(this, callback);
[email protected]cc6db922011-12-10 16:54:22206 entry.read_buffer = read_buffer;
207 entry.info = info;
208 callbacks_.push_back(entry);
209
210 pending_op_ = op;
211}
212
213void PPB_FileIO_Shared::RunAndRemoveFirstPendingCallback(int32_t result) {
214 DCHECK(!callbacks_.empty());
215
216 CallbackEntry front = callbacks_.front();
217 callbacks_.pop_front();
218 if (callbacks_.empty())
219 pending_op_ = OPERATION_NONE;
220
[email protected]614888b2012-01-05 06:18:12221 front.callback->Run(result);
[email protected]cc6db922011-12-10 16:54:22222}
223
224} // namespace ppapi