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.
5 #include "ppapi/proxy/file_chooser_resource.h"
8 #include "base/strings/string_split.h"
9 #include "ipc/ipc_message.h"
10 #include "ppapi/c/pp_errors.h"
11 #include "ppapi/proxy/dispatch_reply_message.h"
12 #include "ppapi/proxy/file_ref_resource.h"
13 #include "ppapi/proxy/ppapi_messages.h"
14 #include "ppapi/shared_impl/var.h"
19 FileChooserResource::FileChooserResource(Connection connection
,
21 PP_FileChooserMode_Dev mode
,
22 const std::string
& accept_types
)
23 : PluginResource(connection
, instance
),
25 PopulateAcceptTypes(accept_types
, &accept_types_
);
28 FileChooserResource::~FileChooserResource() {
31 thunk::PPB_FileChooser_API
* FileChooserResource::AsPPB_FileChooser_API() {
35 int32_t FileChooserResource::Show(const PP_ArrayOutput
& output
,
36 scoped_refptr
<TrackedCallback
> callback
) {
37 return ShowWithoutUserGesture(PP_FALSE
, PP_MakeUndefined(), output
, callback
);
40 int32_t FileChooserResource::ShowWithoutUserGesture(
42 PP_Var suggested_file_name
,
43 const PP_ArrayOutput
& output
,
44 scoped_refptr
<TrackedCallback
> callback
) {
45 int32_t result
= ShowInternal(save_as
, suggested_file_name
, callback
);
46 if (result
== PP_OK_COMPLETIONPENDING
)
47 output_
.set_pp_array_output(output
);
51 int32_t FileChooserResource::Show0_5(scoped_refptr
<TrackedCallback
> callback
) {
52 return ShowInternal(PP_FALSE
, PP_MakeUndefined(), callback
);
55 PP_Resource
FileChooserResource::GetNextChosenFile() {
56 if (file_queue_
.empty())
59 // Return the next resource in the queue. It will already have been addrefed
60 // (they're currently owned by the FileChooser) and returning it transfers
61 // ownership of that reference to the plugin.
62 PP_Resource next
= file_queue_
.front();
67 int32_t FileChooserResource::ShowWithoutUserGesture0_5(
69 PP_Var suggested_file_name
,
70 scoped_refptr
<TrackedCallback
> callback
) {
71 return ShowInternal(save_as
, suggested_file_name
, callback
);
75 void FileChooserResource::PopulateAcceptTypes(
76 const std::string
& input
,
77 std::vector
<std::string
>* output
) {
81 std::vector
<std::string
> type_list
= base::SplitString(
82 input
, ",", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
83 output
->reserve(type_list
.size());
85 for (size_t i
= 0; i
< type_list
.size(); ++i
) {
86 std::string type
= type_list
[i
];
87 base::TrimWhitespaceASCII(type
, base::TRIM_ALL
, &type
);
89 // If the type is a single character, it definitely cannot be valid. In the
90 // case of a file extension it would be a single ".". In the case of a MIME
91 // type it would just be a "/".
92 if (type
.length() < 2)
94 if (type
.find_first_of('/') == std::string::npos
&& type
[0] != '.')
96 output
->push_back(base::ToLowerASCII(type
));
100 void FileChooserResource::OnPluginMsgShowReply(
101 const ResourceMessageReplyParams
& params
,
102 const std::vector
<FileRefCreateInfo
>& chosen_files
) {
103 if (output_
.is_valid()) {
104 // Using v0.6 of the API with the output array.
105 std::vector
<PP_Resource
> files
;
106 for (size_t i
= 0; i
< chosen_files
.size(); i
++) {
107 files
.push_back(FileRefResource::CreateFileRef(
112 output_
.StoreResourceVector(files
);
114 // Convert each of the passed in file infos to resources. These will be
115 // owned by the FileChooser object until they're passed to the plugin.
116 DCHECK(file_queue_
.empty());
117 for (size_t i
= 0; i
< chosen_files
.size(); i
++) {
118 file_queue_
.push(FileRefResource::CreateFileRef(
125 // Notify the plugin of the new data.
126 callback_
->Run(params
.result());
127 // DANGER: May delete |this|!
130 int32_t FileChooserResource::ShowInternal(
132 const PP_Var
& suggested_file_name
,
133 scoped_refptr
<TrackedCallback
> callback
) {
134 if (TrackedCallback::IsPending(callback_
))
135 return PP_ERROR_INPROGRESS
;
137 if (!sent_create_to_renderer())
138 SendCreate(RENDERER
, PpapiHostMsg_FileChooser_Create());
140 callback_
= callback
;
141 StringVar
* sugg_str
= StringVar::FromPPVar(suggested_file_name
);
143 PpapiHostMsg_FileChooser_Show
msg(
145 mode_
== PP_FILECHOOSERMODE_OPENMULTIPLE
,
146 sugg_str
? sugg_str
->value() : std::string(),
148 Call
<PpapiPluginMsg_FileChooser_ShowReply
>(RENDERER
, msg
,
149 base::Bind(&FileChooserResource::OnPluginMsgShowReply
, this));
150 return PP_OK_COMPLETIONPENDING
;