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

Side by Side Diff: webkit/plugins/ppapi/ppb_file_chooser_impl.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 "webkit/plugins/ppapi/ppb_file_chooser_impl.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/logging.h"
11 #include "base/string_split.h"
12 #include "base/string_util.h"
13 #include "base/sys_string_conversions.h"
14 #include "ppapi/c/pp_completion_callback.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/shared_impl/tracked_callback.h"
17 #include "ppapi/shared_impl/var.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h "
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserComplet ion.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserParams. h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h"
23 #include "webkit/glue/webkit_glue.h"
24 #include "webkit/plugins/ppapi/common.h"
25 #include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
26 #include "webkit/plugins/ppapi/plugin_delegate.h"
27 #include "webkit/plugins/ppapi/plugin_module.h"
28 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
29 #include "webkit/plugins/ppapi/resource_helper.h"
30
31 using ppapi::StringVar;
32 using ppapi::thunk::PPB_FileChooser_API;
33 using ppapi::TrackedCallback;
34 using WebKit::WebCString;
35 using WebKit::WebFileChooserCompletion;
36 using WebKit::WebFileChooserParams;
37 using WebKit::WebString;
38 using WebKit::WebVector;
39
40 namespace webkit {
41 namespace ppapi {
42
43 namespace {
44
45 class FileChooserCompletionImpl : public WebFileChooserCompletion {
46 public:
47 FileChooserCompletionImpl(PPB_FileChooser_Impl* file_chooser)
48 : file_chooser_(file_chooser) {
49 DCHECK(file_chooser_);
50 }
51
52 virtual ~FileChooserCompletionImpl() {}
53
54 virtual void didChooseFile(const WebVector<WebString>& file_names) {
55 std::vector<PPB_FileChooser_Impl::ChosenFileInfo> files;
56 for (size_t i = 0; i < file_names.size(); i++) {
57 files.push_back(
58 PPB_FileChooser_Impl::ChosenFileInfo(file_names[i].utf8(),
59 std::string()));
60 }
61
62 file_chooser_->StoreChosenFiles(files);
63
64 // It is the responsibility of this method to delete the instance.
65 delete this;
66 }
67 virtual void didChooseFile(const WebVector<SelectedFileInfo>& file_names) {
68 std::vector<PPB_FileChooser_Impl::ChosenFileInfo> files;
69 for (size_t i = 0; i < file_names.size(); i++) {
70 files.push_back(
71 PPB_FileChooser_Impl::ChosenFileInfo(
72 file_names[i].path.utf8(),
73 file_names[i].displayName.utf8()));
74 }
75
76 file_chooser_->StoreChosenFiles(files);
77
78 // It is the responsibility of this method to delete the instance.
79 delete this;
80 }
81
82 private:
83 scoped_refptr<PPB_FileChooser_Impl> file_chooser_;
84 };
85
86 } // namespace
87
88 PPB_FileChooser_Impl::ChosenFileInfo::ChosenFileInfo(
89 const std::string& path,
90 const std::string& display_name)
91 : path(path),
92 display_name(display_name) {
93 }
94
95 PPB_FileChooser_Impl::PPB_FileChooser_Impl(
96 PP_Instance instance,
97 PP_FileChooserMode_Dev mode,
98 const char* accept_types)
99 : Resource(::ppapi::OBJECT_IS_IMPL, instance),
100 mode_(mode),
101 next_chosen_file_index_(0) {
102 if (accept_types)
103 accept_types_ = std::string(accept_types);
104 }
105
106 PPB_FileChooser_Impl::~PPB_FileChooser_Impl() {
107 }
108
109 // static
110 PP_Resource PPB_FileChooser_Impl::Create(
111 PP_Instance instance,
112 PP_FileChooserMode_Dev mode,
113 const char* accept_types) {
114 if (mode != PP_FILECHOOSERMODE_OPEN &&
115 mode != PP_FILECHOOSERMODE_OPENMULTIPLE)
116 return 0;
117 return (new PPB_FileChooser_Impl(instance, mode,
118 accept_types))->GetReference();
119 }
120
121 PPB_FileChooser_Impl* PPB_FileChooser_Impl::AsPPB_FileChooser_Impl() {
122 return this;
123 }
124
125 PPB_FileChooser_API* PPB_FileChooser_Impl::AsPPB_FileChooser_API() {
126 return this;
127 }
128
129 void PPB_FileChooser_Impl::StoreChosenFiles(
130 const std::vector<ChosenFileInfo>& files) {
131 next_chosen_file_index_ = 0;
132
133 // It is possible that |callback_| has been run: before the user takes action
134 // on the file chooser, the page navigates away and causes the plugin module
135 // (whose instance requested to show the file chooser) to be destroyed. In
136 // that case, |callback_| has been aborted when we get here.
137 if (!TrackedCallback::IsPending(callback_)) {
138 // To be cautious, reset our internal state.
139 output_.Reset();
140 chosen_files_.clear();
141 return;
142 }
143
144 std::vector< scoped_refptr<Resource> > chosen_files;
145 for (std::vector<ChosenFileInfo>::const_iterator it = files.begin();
146 it != files.end(); ++it) {
147 #if defined(OS_WIN)
148 FilePath file_path(base::SysUTF8ToWide(it->path));
149 #else
150 FilePath file_path(it->path);
151 #endif
152
153 chosen_files.push_back(scoped_refptr<Resource>(
154 PPB_FileRef_Impl::CreateExternal(pp_instance(),
155 file_path,
156 it->display_name)));
157 }
158
159 int32_t result_code = (chosen_files.size() > 0) ? PP_OK : PP_ERROR_USERCANCEL;
160 if (output_.is_valid())
161 output_.StoreResourceVector(chosen_files);
162 else // v0.5 API.
163 chosen_files_.swap(chosen_files);
164 RunCallback(result_code);
165 }
166
167 int32_t PPB_FileChooser_Impl::ValidateCallback(
168 scoped_refptr<TrackedCallback> callback) {
169 if (TrackedCallback::IsPending(callback_))
170 return PP_ERROR_INPROGRESS;
171
172 return PP_OK;
173 }
174
175 void PPB_FileChooser_Impl::RegisterCallback(
176 scoped_refptr<TrackedCallback> callback) {
177 DCHECK(!TrackedCallback::IsPending(callback_));
178
179 PluginModule* plugin_module = ResourceHelper::GetPluginModule(this);
180 if (!plugin_module)
181 return;
182
183 callback_ = callback;
184 }
185
186 void PPB_FileChooser_Impl::RunCallback(int32_t result) {
187 TrackedCallback::ClearAndRun(&callback_, result);
188 }
189
190 int32_t PPB_FileChooser_Impl::Show(const PP_ArrayOutput& output,
191 scoped_refptr<TrackedCallback> callback) {
192 int32_t result = Show0_5(callback);
193 if (result == PP_OK_COMPLETIONPENDING)
194 output_.set_pp_array_output(output);
195 return result;
196 }
197
198 int32_t PPB_FileChooser_Impl::ShowWithoutUserGesture(
199 PP_Bool save_as,
200 PP_Var suggested_file_name,
201 const PP_ArrayOutput& output,
202 scoped_refptr<TrackedCallback> callback) {
203 int32_t result = ShowWithoutUserGesture0_5(save_as, suggested_file_name,
204 callback);
205 if (result == PP_OK_COMPLETIONPENDING)
206 output_.set_pp_array_output(output);
207 return result;
208 }
209
210 int32_t PPB_FileChooser_Impl::Show0_5(scoped_refptr<TrackedCallback> callback) {
211 PluginInstance* plugin_instance = ResourceHelper::GetPluginInstance(this);
212 if (!plugin_instance)
213 return PP_ERROR_FAILED;
214 if (!plugin_instance->IsProcessingUserGesture())
215 return PP_ERROR_NO_USER_GESTURE;
216 return ShowWithoutUserGesture0_5(PP_FALSE, PP_MakeUndefined(), callback);
217 }
218
219 int32_t PPB_FileChooser_Impl::ShowWithoutUserGesture0_5(
220 PP_Bool save_as,
221 PP_Var suggested_file_name,
222 scoped_refptr<TrackedCallback> callback) {
223 int32_t rv = ValidateCallback(callback);
224 if (rv != PP_OK)
225 return rv;
226
227 DCHECK((mode_ == PP_FILECHOOSERMODE_OPEN) ||
228 (mode_ == PP_FILECHOOSERMODE_OPENMULTIPLE));
229
230 WebFileChooserParams params;
231 if (save_as) {
232 params.saveAs = true;
233 StringVar* str = StringVar::FromPPVar(suggested_file_name);
234 if (str)
235 params.initialValue = WebString::fromUTF8(str->value().c_str());
236 } else {
237 params.multiSelect = (mode_ == PP_FILECHOOSERMODE_OPENMULTIPLE);
238 }
239 params.acceptTypes = ParseAcceptValue(accept_types_);
240 params.directory = false;
241
242 PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(this);
243 if (!plugin_delegate)
244 return PP_ERROR_FAILED;
245
246 if (!plugin_delegate->RunFileChooser(params,
247 new FileChooserCompletionImpl(this)))
248 return PP_ERROR_FAILED;
249
250 RegisterCallback(callback);
251 return PP_OK_COMPLETIONPENDING;
252 }
253
254 PP_Resource PPB_FileChooser_Impl::GetNextChosenFile() {
255 if (next_chosen_file_index_ >= chosen_files_.size())
256 return 0;
257
258 return chosen_files_[next_chosen_file_index_++]->GetReference();
259 }
260
261 std::vector<WebString> PPB_FileChooser_Impl::ParseAcceptValue(
262 const std::string& accept_types) {
263 if (accept_types.empty())
264 return std::vector<WebString>();
265 std::vector<std::string> type_list;
266 base::SplitString(accept_types, ',', &type_list);
267 std::vector<WebString> normalized_type_list;
268 normalized_type_list.reserve(type_list.size());
269 for (size_t i = 0; i < type_list.size(); ++i) {
270 std::string type = type_list[i];
271 TrimWhitespaceASCII(type, TRIM_ALL, &type);
272
273 // If the type is a single character, it definitely cannot be valid. In the
274 // case of a file extension it would be a single ".". In the case of a MIME
275 // type it would just be a "/".
276 if (type.length() < 2)
277 continue;
278 if (type.find_first_of('/') == std::string::npos && type[0] != '.')
279 continue;
280 StringToLowerASCII(&type);
281 normalized_type_list.push_back(WebString::fromUTF8(type.data(),
282 type.size()));
283 }
284 return normalized_type_list;
285 }
286
287 } // namespace ppapi
288 } // namespace webkit
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698