Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / pepper_file_chooser_host.cc
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 "content/renderer/pepper/pepper_file_chooser_host.h"
6
7 #include "base/files/file_path.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "content/public/renderer/renderer_ppapi_host.h"
10 #include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
11 #include "content/renderer/render_view_impl.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/host/dispatch_host_message.h"
14 #include "ppapi/host/ppapi_host.h"
15 #include "ppapi/proxy/ppapi_messages.h"
16 #include "third_party/WebKit/public/platform/WebCString.h"
17 #include "third_party/WebKit/public/platform/WebString.h"
18 #include "third_party/WebKit/public/platform/WebVector.h"
19 #include "third_party/WebKit/public/web/WebFileChooserCompletion.h"
20 #include "third_party/WebKit/public/web/WebFileChooserParams.h"
21
22 namespace content {
23
24 class PepperFileChooserHost::CompletionHandler
25     : public blink::WebFileChooserCompletion {
26  public:
27   explicit CompletionHandler(const base::WeakPtr<PepperFileChooserHost>& host)
28       : host_(host) {}
29
30   virtual ~CompletionHandler() {}
31
32   virtual void didChooseFile(
33       const blink::WebVector<blink::WebString>& file_names) {
34     if (host_.get()) {
35       std::vector<PepperFileChooserHost::ChosenFileInfo> files;
36       for (size_t i = 0; i < file_names.size(); i++) {
37         files.push_back(PepperFileChooserHost::ChosenFileInfo(
38             file_names[i].utf8(), std::string()));
39       }
40       host_->StoreChosenFiles(files);
41     }
42
43     // It is the responsibility of this method to delete the instance.
44     delete this;
45   }
46   virtual void didChooseFile(
47       const blink::WebVector<SelectedFileInfo>& file_names) {
48     if (host_.get()) {
49       std::vector<PepperFileChooserHost::ChosenFileInfo> files;
50       for (size_t i = 0; i < file_names.size(); i++) {
51         files.push_back(PepperFileChooserHost::ChosenFileInfo(
52             file_names[i].path.utf8(), file_names[i].displayName.utf8()));
53       }
54       host_->StoreChosenFiles(files);
55     }
56
57     // It is the responsibility of this method to delete the instance.
58     delete this;
59   }
60
61  private:
62   base::WeakPtr<PepperFileChooserHost> host_;
63
64   DISALLOW_COPY_AND_ASSIGN(CompletionHandler);
65 };
66
67 PepperFileChooserHost::ChosenFileInfo::ChosenFileInfo(
68     const std::string& path,
69     const std::string& display_name)
70     : path(path), display_name(display_name) {}
71
72 PepperFileChooserHost::PepperFileChooserHost(RendererPpapiHost* host,
73                                              PP_Instance instance,
74                                              PP_Resource resource)
75     : ResourceHost(host->GetPpapiHost(), instance, resource),
76       renderer_ppapi_host_(host),
77       handler_(NULL),
78       weak_factory_(this) {}
79
80 PepperFileChooserHost::~PepperFileChooserHost() {}
81
82 int32_t PepperFileChooserHost::OnResourceMessageReceived(
83     const IPC::Message& msg,
84     ppapi::host::HostMessageContext* context) {
85   PPAPI_BEGIN_MESSAGE_MAP(PepperFileChooserHost, msg)
86     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileChooser_Show, OnShow)
87   PPAPI_END_MESSAGE_MAP()
88   return PP_ERROR_FAILED;
89 }
90
91 void PepperFileChooserHost::StoreChosenFiles(
92     const std::vector<ChosenFileInfo>& files) {
93   std::vector<IPC::Message> create_msgs;
94   std::vector<base::FilePath> file_paths;
95   std::vector<std::string> display_names;
96   for (size_t i = 0; i < files.size(); i++) {
97     base::FilePath file_path = base::FilePath::FromUTF8Unsafe(files[i].path);
98     file_paths.push_back(file_path);
99     create_msgs.push_back(PpapiHostMsg_FileRef_CreateForRawFS(file_path));
100     display_names.push_back(files[i].display_name);
101   }
102
103   if (!files.empty()) {
104     renderer_ppapi_host_->CreateBrowserResourceHosts(
105         pp_instance(),
106         create_msgs,
107         base::Bind(&PepperFileChooserHost::DidCreateResourceHosts,
108                    weak_factory_.GetWeakPtr(),
109                    file_paths,
110                    display_names));
111   } else {
112     reply_context_.params.set_result(PP_ERROR_USERCANCEL);
113     std::vector<ppapi::FileRefCreateInfo> chosen_files;
114     host()->SendReply(reply_context_,
115                       PpapiPluginMsg_FileChooser_ShowReply(chosen_files));
116     reply_context_ = ppapi::host::ReplyMessageContext();
117     handler_ = NULL;  // Handler deletes itself.
118   }
119 }
120
121 int32_t PepperFileChooserHost::OnShow(
122     ppapi::host::HostMessageContext* context,
123     bool save_as,
124     bool open_multiple,
125     const std::string& suggested_file_name,
126     const std::vector<std::string>& accept_mime_types) {
127   if (handler_)
128     return PP_ERROR_INPROGRESS;  // Already pending.
129
130   if (!host()->permissions().HasPermission(
131           ppapi::PERMISSION_BYPASS_USER_GESTURE) &&
132       !renderer_ppapi_host_->HasUserGesture(pp_instance())) {
133     return PP_ERROR_NO_USER_GESTURE;
134   }
135
136   blink::WebFileChooserParams params;
137   if (save_as) {
138     params.saveAs = true;
139     params.initialValue = blink::WebString::fromUTF8(
140         suggested_file_name.data(), suggested_file_name.size());
141   } else {
142     params.multiSelect = open_multiple;
143   }
144   std::vector<blink::WebString> mime_types(accept_mime_types.size());
145   for (size_t i = 0; i < accept_mime_types.size(); i++) {
146     mime_types[i] = blink::WebString::fromUTF8(accept_mime_types[i].data(),
147                                                accept_mime_types[i].size());
148   }
149   params.acceptTypes = mime_types;
150   params.directory = false;
151   params.needLocalPath = true;
152
153   handler_ = new CompletionHandler(AsWeakPtr());
154   RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
155       renderer_ppapi_host_->GetRenderViewForInstance(pp_instance()));
156   if (!render_view || !render_view->runFileChooser(params, handler_)) {
157     delete handler_;
158     handler_ = NULL;
159     return PP_ERROR_NOACCESS;
160   }
161
162   reply_context_ = context->MakeReplyMessageContext();
163   return PP_OK_COMPLETIONPENDING;
164 }
165
166 void PepperFileChooserHost::DidCreateResourceHosts(
167     const std::vector<base::FilePath>& file_paths,
168     const std::vector<std::string>& display_names,
169     const std::vector<int>& browser_ids) {
170   DCHECK(file_paths.size() == display_names.size());
171   DCHECK(file_paths.size() == browser_ids.size());
172
173   std::vector<ppapi::FileRefCreateInfo> chosen_files;
174   for (size_t i = 0; i < browser_ids.size(); ++i) {
175     PepperFileRefRendererHost* renderer_host = new PepperFileRefRendererHost(
176         renderer_ppapi_host_, pp_instance(), 0, file_paths[i]);
177     int renderer_id =
178         renderer_ppapi_host_->GetPpapiHost()->AddPendingResourceHost(
179             scoped_ptr<ppapi::host::ResourceHost>(renderer_host));
180     ppapi::FileRefCreateInfo info = ppapi::MakeExternalFileRefCreateInfo(
181         file_paths[i], display_names[i], browser_ids[i], renderer_id);
182     chosen_files.push_back(info);
183   }
184
185   reply_context_.params.set_result(PP_OK);
186   host()->SendReply(reply_context_,
187                     PpapiPluginMsg_FileChooser_ShowReply(chosen_files));
188   reply_context_ = ppapi::host::ReplyMessageContext();
189   handler_ = NULL;  // Handler deletes itself.
190 }
191
192 }  // namespace content