[M108 Aura Migration][NaCl][PPFwk] Add error logs + SVACE/DLOG/Static analysis fix
[platform/framework/web/chromium-efl.git] / ppapi / proxy / file_chooser_resource.cc
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.
4
5 #include "ppapi/proxy/file_chooser_resource.h"
6
7 #include <stddef.h>
8
9 #include "base/bind.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"
18
19 namespace ppapi {
20 namespace proxy {
21
22 FileChooserResource::FileChooserResource(Connection connection,
23                                          PP_Instance instance,
24                                          PP_FileChooserMode_Dev mode,
25                                          const std::string& accept_types)
26     : PluginResource(connection, instance),
27       mode_(mode) {
28   PopulateAcceptTypes(accept_types, &accept_types_);
29 }
30
31 FileChooserResource::~FileChooserResource() {
32 }
33
34 thunk::PPB_FileChooser_API* FileChooserResource::AsPPB_FileChooser_API() {
35   return this;
36 }
37
38 int32_t FileChooserResource::Show(const PP_ArrayOutput& output,
39                                   scoped_refptr<TrackedCallback> callback) {
40   return ShowWithoutUserGesture(PP_FALSE, PP_MakeUndefined(), output, callback);
41 }
42
43 int32_t FileChooserResource::ShowWithoutUserGesture(
44     PP_Bool save_as,
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);
51   return result;
52 }
53
54 int32_t FileChooserResource::Show0_5(scoped_refptr<TrackedCallback> callback) {
55   return ShowInternal(PP_FALSE, PP_MakeUndefined(), callback);
56 }
57
58 PP_Resource FileChooserResource::GetNextChosenFile() {
59  if (file_queue_.empty())
60     return 0;
61
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();
66   file_queue_.pop();
67   return next;
68 }
69
70 int32_t FileChooserResource::ShowWithoutUserGesture0_5(
71     PP_Bool save_as,
72     PP_Var suggested_file_name,
73     scoped_refptr<TrackedCallback> callback) {
74   return ShowInternal(save_as, suggested_file_name, callback);
75 }
76
77 // static
78 void FileChooserResource::PopulateAcceptTypes(
79     const std::string& input,
80     std::vector<std::string>* output) {
81   if (input.empty())
82     return;
83
84   std::vector<std::string> type_list = base::SplitString(
85       input, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
86   output->reserve(type_list.size());
87
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);
91
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)
96       continue;
97     if (type.find_first_of('/') == std::string::npos && type[0] != '.')
98       continue;
99     output->push_back(base::ToLowerASCII(type));
100   }
101 }
102
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(
111           connection(),
112           pp_instance(),
113           chosen_files[i]));
114     }
115     output_.StoreResourceVector(files);
116   } else {
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(
122           connection(),
123           pp_instance(),
124           chosen_files[i]));
125     }
126   }
127
128   // Notify the plugin of the new data.
129   callback_->Run(params.result());
130   // DANGER: May delete |this|!
131 }
132
133 int32_t FileChooserResource::ShowInternal(
134     PP_Bool save_as,
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;
140   }
141
142   if (!sent_create_to_renderer())
143     SendCreate(RENDERER, PpapiHostMsg_FileChooser_Create());
144
145   callback_ = callback;
146   StringVar* sugg_str = StringVar::FromPPVar(suggested_file_name);
147
148   PpapiHostMsg_FileChooser_Show msg(
149         PP_ToBool(save_as),
150         mode_ == PP_FILECHOOSERMODE_OPENMULTIPLE,
151         sugg_str ? sugg_str->value() : std::string(),
152         accept_types_);
153   Call<PpapiPluginMsg_FileChooser_ShowReply>(
154       RENDERER, msg,
155       base::BindOnce(&FileChooserResource::OnPluginMsgShowReply, this));
156   return PP_OK_COMPLETIONPENDING;
157 }
158
159 }  // namespace proxy
160 }  // namespace ppapi