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

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

Issue 6519057: Implement proxying for FileRef and FileChooser.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 9 years, 10 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // 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/proxy/ppb_file_chooser_proxy.h"
6
7 #include <queue>
8
9 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
10 #include "ppapi/c/pp_errors.h"
11 #include "ppapi/c/private/ppb_proxy_private.h"
12 #include "ppapi/proxy/host_dispatcher.h"
13 #include "ppapi/proxy/plugin_dispatcher.h"
14 #include "ppapi/proxy/plugin_resource.h"
15 #include "ppapi/proxy/ppapi_messages.h"
16 #include "ppapi/proxy/ppb_file_ref_proxy.h"
17 #include "ppapi/proxy/serialized_var.h"
18
19 namespace pp {
20 namespace proxy {
21
22 class FileChooser : public PluginResource {
23 public:
24 FileChooser(const HostResource& resource);
25 virtual ~FileChooser();
26
27 virtual FileChooser* AsFileChooser();
28
29 PP_CompletionCallback current_show_callback_;
30
31 // All files returned by the current show callback that haven't yet been
32 // given to the plugin. The plugin will repeatedly call us to get the next
33 // file, and we'll vend those out of this queue, removing them when ownership
34 // has transferred to the plugin.
35 std::queue<PP_Resource> file_queue_;
36
37 private:
38 DISALLOW_COPY_AND_ASSIGN(FileChooser);
39 };
40
41 FileChooser::FileChooser(const HostResource& resource)
42 : PluginResource(resource),
43 current_show_callback_(PP_MakeCompletionCallback(NULL, NULL)) {
44 }
45
46 FileChooser::~FileChooser() {
47 // Always need to fire completion callbacks to prevent a leak in the plugin.
48 if (current_show_callback_.func)
49 PP_RunCompletionCallback(&current_show_callback_, PP_ERROR_ABORTED);
50
51 // Any existing files we haven't transferred ownership to the plugin need
52 // to be freed.
53 PluginResourceTracker* tracker = PluginResourceTracker::GetInstance();
54 while (!file_queue_.empty()) {
55 tracker->ReleaseResource(file_queue_.front());
56 file_queue_.pop();
57 }
58 }
59
60 FileChooser* FileChooser::AsFileChooser() {
61 return this;
62 }
63
64 namespace {
65
66 PP_Resource Create(PP_Instance instance,
67 const PP_FileChooserOptions_Dev* options) {
68 Dispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
69 if (!dispatcher)
70 return 0;
71
72 HostResource result;
73 dispatcher->Send(new PpapiHostMsg_PPBFileChooser_Create(
74 INTERFACE_ID_PPB_FILE_CHOOSER, instance,
75 static_cast<int>(options->mode), options->accept_mime_types, &result));
piman 2011/02/17 21:25:07 Is the static_cast necessary ? I'd assume the cast
76
77 if (result.is_null())
78 return 0;
79 linked_ptr<FileChooser> object(new FileChooser(result));
80 return PluginResourceTracker::GetInstance()->AddResource(object);
81 }
82
83 PP_Bool IsFileChooser(PP_Resource resource) {
84 FileChooser* object = PluginResource::GetAs<FileChooser>(resource);
85 return BoolToPPBool(!!object);
86 }
87
88 int32_t Show(PP_Resource chooser, struct PP_CompletionCallback callback) {
89 FileChooser* object = PluginResource::GetAs<FileChooser>(chooser);
90 if (!object)
91 return PP_ERROR_BADRESOURCE;
92 Dispatcher* dispatcher = PluginDispatcher::GetForInstance(object->instance());
93 if (!dispatcher)
94 return PP_ERROR_BADARGUMENT;
95
96 if (object->current_show_callback_.func)
97 return PP_ERROR_INPROGRESS; // Can't show more than once.
98
99 object->current_show_callback_ = callback;
100 dispatcher->Send(new PpapiHostMsg_PPBFileChooser_Show(
101 INTERFACE_ID_PPB_FILE_CHOOSER,
102 object->host_resource()));
103 return PP_ERROR_WOULDBLOCK;
104 }
105
106 PP_Resource GetNextChosenFile(PP_Resource chooser) {
107 FileChooser* object = PluginResource::GetAs<FileChooser>(chooser);
108 if (!object || object->file_queue_.empty())
109 return 0;
110
111 // Return the next resource in the queue. These resource have already been
112 // addrefed (they're currently owned by the FileChooser) and returning them
113 // transfers ownership of that reference to the plugin.
114 PP_Resource next = object->file_queue_.front();
115 object->file_queue_.pop();
116 return next;
117 }
118
119 const PPB_FileChooser_Dev file_chooser_interface = {
120 &Create,
121 &IsFileChooser,
122 &Show,
123 &GetNextChosenFile
124 };
125
126 InterfaceProxy* CreateFileChooserProxy(Dispatcher* dispatcher,
127 const void* target_interface) {
128 return new PPB_FileChooser_Proxy(dispatcher, target_interface);
129 }
130
131 } // namespace
132
133 PPB_FileChooser_Proxy::PPB_FileChooser_Proxy(Dispatcher* dispatcher,
134 const void* target_interface)
135 : InterfaceProxy(dispatcher, target_interface),
136 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
137 }
138
139 PPB_FileChooser_Proxy::~PPB_FileChooser_Proxy() {
140 }
141
142 const InterfaceProxy::Info* PPB_FileChooser_Proxy::GetInfo() {
143 static const Info info = {
144 &file_chooser_interface,
145 PPB_FILECHOOSER_DEV_INTERFACE,
146 INTERFACE_ID_PPB_FILE_CHOOSER,
147 false,
148 &CreateFileChooserProxy,
149 };
150 return &info;
151 }
152
153 bool PPB_FileChooser_Proxy::OnMessageReceived(const IPC::Message& msg) {
154 bool handled = true;
155 IPC_BEGIN_MESSAGE_MAP(PPB_FileChooser_Proxy, msg)
156 // Plugin -> host messages.
157 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileChooser_Create, OnMsgCreate)
158 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileChooser_Show, OnMsgShow)
159
160 // Host -> plugin messages.
161 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileChooser_ChooseComplete,
162 OnMsgChooseComplete)
163 IPC_MESSAGE_UNHANDLED(handled = false)
164 IPC_END_MESSAGE_MAP()
165 return handled;
166 }
167
168 void PPB_FileChooser_Proxy::OnMsgCreate(PP_Instance instance,
169 int mode,
170 const std::string& accept_mime_types,
171 HostResource* result) {
172 PP_FileChooserOptions_Dev options;
173 options.mode = static_cast<PP_FileChooserMode_Dev>(mode);
174 options.accept_mime_types = accept_mime_types.c_str();
175 result->SetHostResource(
176 instance, ppb_file_chooser_target()->Create(instance, &options));
177 }
178
179 void PPB_FileChooser_Proxy::OnMsgShow(const HostResource& chooser) {
180 CompletionCallback callback = callback_factory_.NewCallback(
181 &PPB_FileChooser_Proxy::OnShowCallback, chooser);
182
183 int32_t result = ppb_file_chooser_target()->Show(
184 chooser.host_resource(), callback.pp_completion_callback());
185 if (result != PP_ERROR_WOULDBLOCK)
186 callback.Run(result);
187 }
188
189 void PPB_FileChooser_Proxy::OnMsgChooseComplete(
190 const HostResource& chooser,
191 int32_t result_code,
192 const std::vector<PPBFileRef_CreateInfo>& chosen_files) {
193 PP_Resource plugin_resource =
194 PluginResourceTracker::GetInstance()->PluginResourceForHostResource(
195 chooser);
196 if (!plugin_resource)
197 return;
198 FileChooser* object = PluginResource::GetAs<FileChooser>(plugin_resource);
199 if (!object)
200 return;
201
202 // Convert each of the passed in file infos to resources. These will be owned
203 // by the FileChooser object until they're passed to the plugin.
204 DCHECK(object->file_queue_.empty());
205 for (size_t i = 0; i < chosen_files.size(); i++) {
206 object->file_queue_.push(
207 PPB_FileRef_Proxy::DeserializeFileRef(chosen_files[i]));
208 }
209
210 // Notify the plugin of the new data. We have to swap out the callback
211 // because the plugin may trigger deleting the object from the callback, and
212 // the FileChooser object will attempt to call the callback in its destructor
213 // with the ABORTED status.
214 PP_CompletionCallback callback = object->current_show_callback_;
215 object->current_show_callback_ = PP_MakeCompletionCallback(NULL, NULL);
216 PP_RunCompletionCallback(&callback, result_code);
217 // DANGER: May delete |object|!
218 }
219
220 void PPB_FileChooser_Proxy::OnShowCallback(int32_t result,
221 const HostResource& chooser) {
222 std::vector<PPBFileRef_CreateInfo> files;
223 if (result == PP_OK) {
224 // Jump through some hoops to get the FileRef proxy. Since we know we're
225 // in the host at this point, we can ask the host dispatcher for it.
226 DCHECK(!dispatcher()->IsPlugin());
227 HostDispatcher* host_disp = static_cast<HostDispatcher*>(dispatcher());
228 PPB_FileRef_Proxy* file_ref_proxy = static_cast<PPB_FileRef_Proxy*>(
229 host_disp->GetOrCreatePPBInterfaceProxy(INTERFACE_ID_PPB_FILE_REF));
230
231 // Convert the returned files to the serialized info.
232 while (PP_Resource cur_file_resource =
233 ppb_file_chooser_target()->GetNextChosenFile(
234 chooser.host_resource())) {
235 PPBFileRef_CreateInfo cur_create_info;
236 file_ref_proxy->SerializeFileRef(cur_file_resource, &cur_create_info);
237 files.push_back(cur_create_info);
238 }
239 }
240
241 dispatcher()->Send(new PpapiMsg_PPBFileChooser_ChooseComplete(
242 INTERFACE_ID_PPB_FILE_CHOOSER, chooser, result, files));
243 }
244
245 } // namespace proxy
246 } // namespace pp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698