• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ppapi/proxy/file_chooser_resource.h"
6 
7 #include "base/bind.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"
15 
16 namespace ppapi {
17 namespace proxy {
18 
FileChooserResource(Connection connection,PP_Instance instance,PP_FileChooserMode_Dev mode,const std::string & accept_types)19 FileChooserResource::FileChooserResource(Connection connection,
20                                          PP_Instance instance,
21                                          PP_FileChooserMode_Dev mode,
22                                          const std::string& accept_types)
23     : PluginResource(connection, instance),
24       mode_(mode) {
25   PopulateAcceptTypes(accept_types, &accept_types_);
26 }
27 
~FileChooserResource()28 FileChooserResource::~FileChooserResource() {
29 }
30 
AsPPB_FileChooser_API()31 thunk::PPB_FileChooser_API* FileChooserResource::AsPPB_FileChooser_API() {
32   return this;
33 }
34 
Show(const PP_ArrayOutput & output,scoped_refptr<TrackedCallback> callback)35 int32_t FileChooserResource::Show(const PP_ArrayOutput& output,
36                                   scoped_refptr<TrackedCallback> callback) {
37   return ShowWithoutUserGesture(PP_FALSE, PP_MakeUndefined(), output, callback);
38 }
39 
ShowWithoutUserGesture(PP_Bool save_as,PP_Var suggested_file_name,const PP_ArrayOutput & output,scoped_refptr<TrackedCallback> callback)40 int32_t FileChooserResource::ShowWithoutUserGesture(
41     PP_Bool save_as,
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);
48   return result;
49 }
50 
Show0_5(scoped_refptr<TrackedCallback> callback)51 int32_t FileChooserResource::Show0_5(scoped_refptr<TrackedCallback> callback) {
52   return ShowInternal(PP_FALSE, PP_MakeUndefined(), callback);
53 }
54 
GetNextChosenFile()55 PP_Resource FileChooserResource::GetNextChosenFile() {
56  if (file_queue_.empty())
57     return 0;
58 
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();
63   file_queue_.pop();
64   return next;
65 }
66 
ShowWithoutUserGesture0_5(PP_Bool save_as,PP_Var suggested_file_name,scoped_refptr<TrackedCallback> callback)67 int32_t FileChooserResource::ShowWithoutUserGesture0_5(
68     PP_Bool save_as,
69     PP_Var suggested_file_name,
70     scoped_refptr<TrackedCallback> callback) {
71   return ShowInternal(save_as, suggested_file_name, callback);
72 }
73 
74 // static
PopulateAcceptTypes(const std::string & input,std::vector<std::string> * output)75 void FileChooserResource::PopulateAcceptTypes(
76     const std::string& input,
77     std::vector<std::string>* output) {
78   if (input.empty())
79     return;
80 
81   std::vector<std::string> type_list;
82   base::SplitString(input, ',', &type_list);
83   output->reserve(type_list.size());
84 
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);
88 
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)
93       continue;
94     if (type.find_first_of('/') == std::string::npos && type[0] != '.')
95       continue;
96     base::StringToLowerASCII(&type);
97     output->push_back(type);
98   }
99 }
100 
OnPluginMsgShowReply(const ResourceMessageReplyParams & params,const std::vector<FileRefCreateInfo> & chosen_files)101 void FileChooserResource::OnPluginMsgShowReply(
102     const ResourceMessageReplyParams& params,
103     const std::vector<FileRefCreateInfo>& chosen_files) {
104   if (output_.is_valid()) {
105     // Using v0.6 of the API with the output array.
106     std::vector<PP_Resource> files;
107     for (size_t i = 0; i < chosen_files.size(); i++) {
108       files.push_back(FileRefResource::CreateFileRef(
109           connection(),
110           pp_instance(),
111           chosen_files[i]));
112     }
113     output_.StoreResourceVector(files);
114   } else {
115     // Convert each of the passed in file infos to resources. These will be
116     // owned by the FileChooser object until they're passed to the plugin.
117     DCHECK(file_queue_.empty());
118     for (size_t i = 0; i < chosen_files.size(); i++) {
119       file_queue_.push(FileRefResource::CreateFileRef(
120           connection(),
121           pp_instance(),
122           chosen_files[i]));
123     }
124   }
125 
126   // Notify the plugin of the new data.
127   callback_->Run(params.result());
128   // DANGER: May delete |this|!
129 }
130 
ShowInternal(PP_Bool save_as,const PP_Var & suggested_file_name,scoped_refptr<TrackedCallback> callback)131 int32_t FileChooserResource::ShowInternal(
132     PP_Bool save_as,
133     const PP_Var& suggested_file_name,
134     scoped_refptr<TrackedCallback> callback) {
135   if (TrackedCallback::IsPending(callback_))
136     return PP_ERROR_INPROGRESS;
137 
138   if (!sent_create_to_renderer())
139     SendCreate(RENDERER, PpapiHostMsg_FileChooser_Create());
140 
141   callback_ = callback;
142   StringVar* sugg_str = StringVar::FromPPVar(suggested_file_name);
143 
144   PpapiHostMsg_FileChooser_Show msg(
145         PP_ToBool(save_as),
146         mode_ == PP_FILECHOOSERMODE_OPENMULTIPLE,
147         sugg_str ? sugg_str->value() : std::string(),
148         accept_types_);
149   Call<PpapiPluginMsg_FileChooser_ShowReply>(RENDERER, msg,
150       base::Bind(&FileChooserResource::OnPluginMsgShowReply, this));
151   return PP_OK_COMPLETIONPENDING;
152 }
153 
154 }  // namespace proxy
155 }  // namespace ppapi
156