1 // Copyright 2012 The Chromium Authors
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/proxy/file_chooser_resource.h"
10 #include "base/logging.h"
11 #include "base/strings/string_split.h"
12 #include "ipc/ipc_message.h"
13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/proxy/dispatch_reply_message.h"
15 #include "ppapi/proxy/file_ref_resource.h"
16 #include "ppapi/proxy/ppapi_messages.h"
17 #include "ppapi/shared_impl/var.h"
22 FileChooserResource::FileChooserResource(Connection connection,
24 PP_FileChooserMode_Dev mode,
25 const std::string& accept_types)
26 : PluginResource(connection, instance),
28 PopulateAcceptTypes(accept_types, &accept_types_);
31 FileChooserResource::~FileChooserResource() {
34 thunk::PPB_FileChooser_API* FileChooserResource::AsPPB_FileChooser_API() {
38 int32_t FileChooserResource::Show(const PP_ArrayOutput& output,
39 scoped_refptr<TrackedCallback> callback) {
40 return ShowWithoutUserGesture(PP_FALSE, PP_MakeUndefined(), output, callback);
43 int32_t FileChooserResource::ShowWithoutUserGesture(
45 PP_Var suggested_file_name,
46 const PP_ArrayOutput& output,
47 scoped_refptr<TrackedCallback> callback) {
48 int32_t result = ShowInternal(save_as, suggested_file_name, callback);
49 if (result == PP_OK_COMPLETIONPENDING)
50 output_.set_pp_array_output(output);
54 int32_t FileChooserResource::Show0_5(scoped_refptr<TrackedCallback> callback) {
55 return ShowInternal(PP_FALSE, PP_MakeUndefined(), callback);
58 PP_Resource FileChooserResource::GetNextChosenFile() {
59 if (file_queue_.empty())
62 // Return the next resource in the queue. It will already have been addrefed
63 // (they're currently owned by the FileChooser) and returning it transfers
64 // ownership of that reference to the plugin.
65 PP_Resource next = file_queue_.front();
70 int32_t FileChooserResource::ShowWithoutUserGesture0_5(
72 PP_Var suggested_file_name,
73 scoped_refptr<TrackedCallback> callback) {
74 return ShowInternal(save_as, suggested_file_name, callback);
78 void FileChooserResource::PopulateAcceptTypes(
79 const std::string& input,
80 std::vector<std::string>* output) {
84 std::vector<std::string> type_list = base::SplitString(
85 input, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
86 output->reserve(type_list.size());
88 for (size_t i = 0; i < type_list.size(); ++i) {
89 std::string type = type_list[i];
90 base::TrimWhitespaceASCII(type, base::TRIM_ALL, &type);
92 // If the type is a single character, it definitely cannot be valid. In the
93 // case of a file extension it would be a single ".". In the case of a MIME
94 // type it would just be a "/".
95 if (type.length() < 2)
97 if (type.find_first_of('/') == std::string::npos && type[0] != '.')
99 output->push_back(base::ToLowerASCII(type));
103 void FileChooserResource::OnPluginMsgShowReply(
104 const ResourceMessageReplyParams& params,
105 const std::vector<FileRefCreateInfo>& chosen_files) {
106 if (output_.is_valid()) {
107 // Using v0.6 of the API with the output array.
108 std::vector<PP_Resource> files;
109 for (size_t i = 0; i < chosen_files.size(); i++) {
110 files.push_back(FileRefResource::CreateFileRef(
115 output_.StoreResourceVector(files);
117 // Convert each of the passed in file infos to resources. These will be
118 // owned by the FileChooser object until they're passed to the plugin.
119 DCHECK(file_queue_.empty());
120 for (size_t i = 0; i < chosen_files.size(); i++) {
121 file_queue_.push(FileRefResource::CreateFileRef(
128 // Notify the plugin of the new data.
129 callback_->Run(params.result());
130 // DANGER: May delete |this|!
133 int32_t FileChooserResource::ShowInternal(
135 const PP_Var& suggested_file_name,
136 scoped_refptr<TrackedCallback> callback) {
137 if (TrackedCallback::IsPending(callback_)) {
138 LOG(ERROR) << "ShowInternal is pending";
139 return PP_ERROR_INPROGRESS;
142 if (!sent_create_to_renderer())
143 SendCreate(RENDERER, PpapiHostMsg_FileChooser_Create());
145 callback_ = callback;
146 StringVar* sugg_str = StringVar::FromPPVar(suggested_file_name);
148 PpapiHostMsg_FileChooser_Show msg(
150 mode_ == PP_FILECHOOSERMODE_OPENMULTIPLE,
151 sugg_str ? sugg_str->value() : std::string(),
153 Call<PpapiPluginMsg_FileChooser_ShowReply>(
155 base::BindOnce(&FileChooserResource::OnPluginMsgShowReply, this));
156 return PP_OK_COMPLETIONPENDING;