Home | History | Annotate | Download | only in pepper
      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/ppb_file_ref_impl.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 "ppapi/proxy/ppb_file_ref_proxy.h"
     17 #include "third_party/WebKit/public/platform/WebCString.h"
     18 #include "third_party/WebKit/public/platform/WebString.h"
     19 #include "third_party/WebKit/public/platform/WebVector.h"
     20 #include "third_party/WebKit/public/web/WebFileChooserCompletion.h"
     21 #include "third_party/WebKit/public/web/WebFileChooserParams.h"
     22 
     23 namespace content {
     24 
     25 class PepperFileChooserHost::CompletionHandler
     26     : public WebKit::WebFileChooserCompletion {
     27  public:
     28   CompletionHandler(const base::WeakPtr<PepperFileChooserHost>& host)
     29       : host_(host) {
     30   }
     31 
     32   virtual ~CompletionHandler() {}
     33 
     34   virtual void didChooseFile(
     35       const WebKit::WebVector<WebKit::WebString>& file_names) {
     36     if (host_.get()) {
     37       std::vector<PepperFileChooserHost::ChosenFileInfo> files;
     38       for (size_t i = 0; i < file_names.size(); i++) {
     39         files.push_back(PepperFileChooserHost::ChosenFileInfo(
     40             file_names[i].utf8(), std::string()));
     41       }
     42       host_->StoreChosenFiles(files);
     43     }
     44 
     45     // It is the responsibility of this method to delete the instance.
     46     delete this;
     47   }
     48   virtual void didChooseFile(
     49       const WebKit::WebVector<SelectedFileInfo>& file_names) {
     50     if (host_.get()) {
     51       std::vector<PepperFileChooserHost::ChosenFileInfo> files;
     52       for (size_t i = 0; i < file_names.size(); i++) {
     53         files.push_back(PepperFileChooserHost::ChosenFileInfo(
     54             file_names[i].path.utf8(),
     55             file_names[i].displayName.utf8()));
     56       }
     57       host_->StoreChosenFiles(files);
     58     }
     59 
     60     // It is the responsibility of this method to delete the instance.
     61     delete this;
     62   }
     63 
     64  private:
     65   base::WeakPtr<PepperFileChooserHost> host_;
     66 
     67   DISALLOW_COPY_AND_ASSIGN(CompletionHandler);
     68 };
     69 
     70 PepperFileChooserHost::ChosenFileInfo::ChosenFileInfo(
     71     const std::string& path,
     72     const std::string& display_name)
     73     : path(path),
     74       display_name(display_name) {
     75 }
     76 
     77 
     78 PepperFileChooserHost::PepperFileChooserHost(
     79     RendererPpapiHost* host,
     80     PP_Instance instance,
     81     PP_Resource resource)
     82     : ResourceHost(host->GetPpapiHost(), instance, resource),
     83       renderer_ppapi_host_(host),
     84       handler_(NULL) {
     85 }
     86 
     87 PepperFileChooserHost::~PepperFileChooserHost() {
     88 }
     89 
     90 int32_t PepperFileChooserHost::OnResourceMessageReceived(
     91     const IPC::Message& msg,
     92     ppapi::host::HostMessageContext* context) {
     93   IPC_BEGIN_MESSAGE_MAP(PepperFileChooserHost, msg)
     94     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileChooser_Show, OnShow)
     95   IPC_END_MESSAGE_MAP()
     96   return PP_ERROR_FAILED;
     97 }
     98 
     99 void PepperFileChooserHost::StoreChosenFiles(
    100     const std::vector<ChosenFileInfo>& files) {
    101   std::vector<ppapi::PPB_FileRef_CreateInfo> chosen_files;
    102   for (size_t i = 0; i < files.size(); i++) {
    103 #if defined(OS_WIN)
    104     base::FilePath file_path(UTF8ToWide(files[i].path));
    105 #else
    106     base::FilePath file_path(files[i].path);
    107 #endif
    108 
    109     PPB_FileRef_Impl* ref = PPB_FileRef_Impl::CreateExternal(
    110         pp_instance(), file_path, files[i].display_name);
    111     ppapi::PPB_FileRef_CreateInfo create_info;
    112     ppapi::proxy::PPB_FileRef_Proxy::SerializeFileRef(ref->GetReference(),
    113                                                       &create_info);
    114     chosen_files.push_back(create_info);
    115   }
    116 
    117   reply_context_.params.set_result(
    118       (chosen_files.size() > 0) ? PP_OK : PP_ERROR_USERCANCEL);
    119   host()->SendReply(reply_context_,
    120                     PpapiPluginMsg_FileChooser_ShowReply(chosen_files));
    121 
    122   reply_context_ = ppapi::host::ReplyMessageContext();
    123   handler_ = NULL;  // Handler deletes itself.
    124 }
    125 
    126 int32_t PepperFileChooserHost::OnShow(
    127     ppapi::host::HostMessageContext* context,
    128     bool save_as,
    129     bool open_multiple,
    130     const std::string& suggested_file_name,
    131     const std::vector<std::string>& accept_mime_types) {
    132   if (handler_)
    133     return PP_ERROR_INPROGRESS;  // Already pending.
    134 
    135   if (!host()->permissions().HasPermission(
    136           ppapi::PERMISSION_BYPASS_USER_GESTURE) &&
    137        !renderer_ppapi_host_->HasUserGesture(pp_instance())) {
    138     return PP_ERROR_NO_USER_GESTURE;
    139   }
    140 
    141   WebKit::WebFileChooserParams params;
    142   if (save_as) {
    143     params.saveAs = true;
    144     params.initialValue = WebKit::WebString::fromUTF8(
    145         suggested_file_name.data(), suggested_file_name.size());
    146   } else {
    147     params.multiSelect = open_multiple;
    148   }
    149   std::vector<WebKit::WebString> mine_types(accept_mime_types.size());
    150   for (size_t i = 0; i < accept_mime_types.size(); i++) {
    151     mine_types[i] = WebKit::WebString::fromUTF8(
    152         accept_mime_types[i].data(), accept_mime_types[i].size());
    153   }
    154   params.acceptTypes = mine_types;
    155   params.directory = false;
    156 
    157   handler_ = new CompletionHandler(AsWeakPtr());
    158   RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
    159       renderer_ppapi_host_->GetRenderViewForInstance(pp_instance()));
    160   if (!render_view || !render_view->runFileChooser(params, handler_)) {
    161     delete handler_;
    162     handler_ = NULL;
    163     return PP_ERROR_NOACCESS;
    164   }
    165 
    166   reply_context_ = context->MakeReplyMessageContext();
    167   return PP_OK_COMPLETIONPENDING;
    168 }
    169 
    170 }  // namespace content
    171 
    172