Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: ppapi/proxy/ppb_file_chooser_proxy.cc

Issue 10544089: Implement the file chooser as a new resource "host" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 "ppapi/proxy/ppb_file_chooser_proxy.h"
6
7 #include <queue>
8
9 #include "base/bind.h"
10 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
11 #include "ppapi/c/pp_errors.h"
12 #include "ppapi/c/private/ppb_proxy_private.h"
13 #include "ppapi/c/trusted/ppb_file_chooser_trusted.h"
14 #include "ppapi/proxy/enter_proxy.h"
15 #include "ppapi/proxy/host_dispatcher.h"
16 #include "ppapi/proxy/plugin_dispatcher.h"
17 #include "ppapi/proxy/ppapi_messages.h"
18 #include "ppapi/proxy/ppb_file_ref_proxy.h"
19 #include "ppapi/proxy/serialized_var.h"
20 #include "ppapi/shared_impl/array_writer.h"
21 #include "ppapi/shared_impl/ppapi_globals.h"
22 #include "ppapi/shared_impl/resource_tracker.h"
23 #include "ppapi/shared_impl/tracked_callback.h"
24 #include "ppapi/shared_impl/var.h"
25 #include "ppapi/thunk/resource_creation_api.h"
26 #include "ppapi/thunk/thunk.h"
27
28 using ppapi::thunk::PPB_FileChooser_API;
29
30 namespace ppapi {
31 namespace proxy {
32
33 namespace {
34 InterfaceProxy* CreateFileChooserProxy(Dispatcher* dispatcher) {
35 return new PPB_FileChooser_Proxy(dispatcher);
36 }
37
38 class FileChooser : public Resource,
39 public PPB_FileChooser_API {
40 public:
41 FileChooser(const HostResource& resource);
42 virtual ~FileChooser();
43
44 // Resource overrides.
45 virtual PPB_FileChooser_API* AsPPB_FileChooser_API() OVERRIDE;
46
47 // PPB_FileChooser_API implementation.
48 virtual int32_t Show(const PP_ArrayOutput& output,
49 scoped_refptr<TrackedCallback> callback) OVERRIDE;
50 virtual int32_t ShowWithoutUserGesture(
51 PP_Bool save_as,
52 PP_Var suggested_file_name,
53 const PP_ArrayOutput& output,
54 scoped_refptr<TrackedCallback> callback);
55 virtual int32_t Show0_5(scoped_refptr<TrackedCallback> callback) OVERRIDE;
56 virtual PP_Resource GetNextChosenFile() OVERRIDE;
57 virtual int32_t ShowWithoutUserGesture0_5(
58 PP_Bool save_as,
59 PP_Var suggested_file_name,
60 scoped_refptr<TrackedCallback> callback) OVERRIDE;
61
62 // Handles the choose complete notification from the host.
63 void ChooseComplete(
64 int32_t result_code,
65 const std::vector<PPB_FileRef_CreateInfo>& chosen_files);
66
67 private:
68 int32_t Show(bool require_user_gesture,
69 PP_Bool save_as,
70 PP_Var suggested_file_name,
71 scoped_refptr<TrackedCallback> callback);
72
73 // When using v0.6 of the API, contains the array output info.
74 ArrayWriter output_;
75
76 scoped_refptr<TrackedCallback> current_show_callback_;
77
78 // When using v0.5 of the API, contains all files returned by the current
79 // show callback that haven't yet been given to the plugin. The plugin will
80 // repeatedly call us to get the next file, and we'll vend those out of this
81 // queue, removing them when ownership has transferred to the plugin.
82 std::queue<PP_Resource> file_queue_;
83
84 DISALLOW_COPY_AND_ASSIGN(FileChooser);
85 };
86
87 FileChooser::FileChooser(const HostResource& resource)
88 : Resource(OBJECT_IS_PROXY, resource) {
89 }
90
91 FileChooser::~FileChooser() {
92 // Any existing files we haven't transferred ownership to the plugin need
93 // to be freed.
94 ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
95 while (!file_queue_.empty()) {
96 tracker->ReleaseResource(file_queue_.front());
97 file_queue_.pop();
98 }
99 }
100
101 PPB_FileChooser_API* FileChooser::AsPPB_FileChooser_API() {
102 return this;
103 }
104
105 int32_t FileChooser::Show(const PP_ArrayOutput& output,
106 scoped_refptr<TrackedCallback> callback) {
107 int32_t result = Show(true, PP_FALSE, PP_MakeUndefined(), callback);
108 if (result == PP_OK_COMPLETIONPENDING)
109 output_.set_pp_array_output(output);
110 return result;
111 }
112
113 int32_t FileChooser::ShowWithoutUserGesture(
114 PP_Bool save_as,
115 PP_Var suggested_file_name,
116 const PP_ArrayOutput& output,
117 scoped_refptr<TrackedCallback> callback) {
118 int32_t result = Show(false, save_as, suggested_file_name, callback);
119 if (result == PP_OK_COMPLETIONPENDING)
120 output_.set_pp_array_output(output);
121 return result;
122 }
123
124 int32_t FileChooser::Show0_5(scoped_refptr<TrackedCallback> callback) {
125 return Show(true, PP_FALSE, PP_MakeUndefined(), callback);
126 }
127
128 int32_t FileChooser::ShowWithoutUserGesture0_5(
129 PP_Bool save_as,
130 PP_Var suggested_file_name,
131 scoped_refptr<TrackedCallback> callback) {
132 return Show(false, save_as, suggested_file_name, callback);
133 }
134
135 int32_t FileChooser::Show(bool require_user_gesture,
136 PP_Bool save_as,
137 PP_Var suggested_file_name,
138 scoped_refptr<TrackedCallback> callback) {
139 if (TrackedCallback::IsPending(current_show_callback_))
140 return PP_ERROR_INPROGRESS; // Can't show more than once.
141
142 current_show_callback_ = callback;
143 PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
144 dispatcher->Send(
145 new PpapiHostMsg_PPBFileChooser_Show(
146 API_ID_PPB_FILE_CHOOSER,
147 host_resource(),
148 save_as,
149 SerializedVarSendInput(dispatcher, suggested_file_name),
150 require_user_gesture));
151 return PP_OK_COMPLETIONPENDING;
152 }
153
154 PP_Resource FileChooser::GetNextChosenFile() {
155 if (file_queue_.empty())
156 return 0;
157
158 // Return the next resource in the queue. These resource have already been
159 // addrefed (they're currently owned by the FileChooser) and returning them
160 // transfers ownership of that reference to the plugin.
161 PP_Resource next = file_queue_.front();
162 file_queue_.pop();
163 return next;
164 }
165
166 void FileChooser::ChooseComplete(
167 int32_t result_code,
168 const std::vector<PPB_FileRef_CreateInfo>& chosen_files) {
169 if (output_.is_valid()) {
170 // Using v0.6 of the API with the output array.
171 std::vector<PP_Resource> files;
172 for (size_t i = 0; i < chosen_files.size(); i++)
173 files.push_back(PPB_FileRef_Proxy::DeserializeFileRef(chosen_files[i]));
174 output_.StoreResourceVector(files);
175 } else {
176 // Convert each of the passed in file infos to resources. These will be
177 // owned by the FileChooser object until they're passed to the plugin.
178 DCHECK(file_queue_.empty());
179 for (size_t i = 0; i < chosen_files.size(); i++) {
180 file_queue_.push(PPB_FileRef_Proxy::DeserializeFileRef(
181 chosen_files[i]));
182 }
183 }
184
185 // Notify the plugin of the new data.
186 TrackedCallback::ClearAndRun(&current_show_callback_, result_code);
187 // DANGER: May delete |this|!
188 }
189
190 } // namespace
191
192 PPB_FileChooser_Proxy::PPB_FileChooser_Proxy(Dispatcher* dispatcher)
193 : InterfaceProxy(dispatcher),
194 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
195 }
196
197 PPB_FileChooser_Proxy::~PPB_FileChooser_Proxy() {
198 }
199
200 // static
201 PP_Resource PPB_FileChooser_Proxy::CreateProxyResource(
202 PP_Instance instance,
203 PP_FileChooserMode_Dev mode,
204 const char* accept_types) {
205 Dispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
206 if (!dispatcher)
207 return 0;
208
209 HostResource result;
210 dispatcher->Send(new PpapiHostMsg_PPBFileChooser_Create(
211 API_ID_PPB_FILE_CHOOSER, instance,
212 mode,
213 accept_types ? accept_types : "",
214 &result));
215
216 if (result.is_null())
217 return 0;
218 return (new FileChooser(result))->GetReference();
219 }
220
221 bool PPB_FileChooser_Proxy::OnMessageReceived(const IPC::Message& msg) {
222 bool handled = true;
223 IPC_BEGIN_MESSAGE_MAP(PPB_FileChooser_Proxy, msg)
224 // Plugin -> host messages.
225 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileChooser_Create, OnMsgCreate)
226 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileChooser_Show, OnMsgShow)
227
228 // Host -> plugin messages.
229 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileChooser_ChooseComplete,
230 OnMsgChooseComplete)
231 IPC_MESSAGE_UNHANDLED(handled = false)
232 IPC_END_MESSAGE_MAP()
233 return handled;
234 }
235
236 void PPB_FileChooser_Proxy::OnMsgCreate(
237 PP_Instance instance,
238 int mode,
239 std::string accept_types,
240 HostResource* result) {
241 thunk::EnterResourceCreation enter(instance);
242 if (enter.succeeded()) {
243 result->SetHostResource(instance, enter.functions()->CreateFileChooser(
244 instance,
245 static_cast<PP_FileChooserMode_Dev>(mode),
246 accept_types.c_str()));
247 }
248 }
249
250 void PPB_FileChooser_Proxy::OnMsgShow(
251 const HostResource& chooser,
252 PP_Bool save_as,
253 SerializedVarReceiveInput suggested_file_name,
254 bool require_user_gesture) {
255 scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output(
256 new RefCountedArrayOutputAdapter<PP_Resource>);
257 EnterHostFromHostResourceForceCallback<PPB_FileChooser_API> enter(
258 chooser,
259 callback_factory_.NewOptionalCallback(
260 &PPB_FileChooser_Proxy::OnShowCallback, output, chooser));
261 if (enter.succeeded()) {
262 if (require_user_gesture) {
263 enter.SetResult(enter.object()->Show(output->pp_array_output(),
264 enter.callback()));
265 } else {
266 enter.SetResult(enter.object()->ShowWithoutUserGesture(
267 save_as,
268 suggested_file_name.Get(dispatcher()),
269 output->pp_array_output(),
270 enter.callback()));
271 }
272 }
273 }
274
275 void PPB_FileChooser_Proxy::OnMsgChooseComplete(
276 const HostResource& chooser,
277 int32_t result_code,
278 const std::vector<PPB_FileRef_CreateInfo>& chosen_files) {
279 EnterPluginFromHostResource<PPB_FileChooser_API> enter(chooser);
280 if (enter.succeeded()) {
281 static_cast<FileChooser*>(enter.object())->ChooseComplete(
282 result_code, chosen_files);
283 }
284 }
285
286 void PPB_FileChooser_Proxy::OnShowCallback(
287 int32_t result,
288 scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> >
289 output,
290 HostResource chooser) {
291 EnterHostFromHostResource<PPB_FileChooser_API> enter(chooser);
292
293 std::vector<PPB_FileRef_CreateInfo> files;
294 if (enter.succeeded() && result == PP_OK) {
295 PPB_FileRef_Proxy* file_ref_proxy = static_cast<PPB_FileRef_Proxy*>(
296 dispatcher()->GetInterfaceProxy(API_ID_PPB_FILE_REF));
297
298 // Convert the returned files to the serialized info.
299 for (size_t i = 0; i < output->output().size(); i++) {
300 PPB_FileRef_CreateInfo cur_create_info;
301 file_ref_proxy->SerializeFileRef(output->output()[i], &cur_create_info);
302 files.push_back(cur_create_info);
303 }
304 }
305
306 dispatcher()->Send(new PpapiMsg_PPBFileChooser_ChooseComplete(
307 API_ID_PPB_FILE_CHOOSER, chooser, result, files));
308 }
309
310 } // namespace proxy
311 } // namespace ppapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698