Home | History | Annotate | Download | only in dev
      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/cpp/dev/file_chooser_dev.h"
      6 
      7 #include <string.h>
      8 
      9 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
     10 #include "ppapi/c/pp_errors.h"
     11 #include "ppapi/cpp/completion_callback.h"
     12 #include "ppapi/cpp/file_ref.h"
     13 #include "ppapi/cpp/instance_handle.h"
     14 #include "ppapi/cpp/module.h"
     15 #include "ppapi/cpp/module_impl.h"
     16 
     17 namespace pp {
     18 
     19 namespace {
     20 
     21 template <> const char* interface_name<PPB_FileChooser_Dev_0_5>() {
     22   return PPB_FILECHOOSER_DEV_INTERFACE_0_5;
     23 }
     24 
     25 template <> const char* interface_name<PPB_FileChooser_Dev_0_6>() {
     26   return PPB_FILECHOOSER_DEV_INTERFACE_0_6;
     27 }
     28 
     29 }  // namespace
     30 
     31 FileChooser_Dev::FileChooser_Dev(const InstanceHandle& instance,
     32                                  PP_FileChooserMode_Dev mode,
     33                                  const Var& accept_types) {
     34   if (has_interface<PPB_FileChooser_Dev_0_6>()) {
     35     PassRefFromConstructor(get_interface<PPB_FileChooser_Dev_0_6>()->Create(
     36         instance.pp_instance(), mode, accept_types.pp_var()));
     37   } else if (has_interface<PPB_FileChooser_Dev_0_5>()) {
     38     PassRefFromConstructor(get_interface<PPB_FileChooser_Dev_0_5>()->Create(
     39         instance.pp_instance(), mode, accept_types.pp_var()));
     40   }
     41 }
     42 
     43 FileChooser_Dev::FileChooser_Dev(const FileChooser_Dev& other)
     44     : Resource(other) {
     45 }
     46 
     47 int32_t FileChooser_Dev::Show(
     48     const CompletionCallbackWithOutput< std::vector<FileRef> >& callback) {
     49   if (has_interface<PPB_FileChooser_Dev_0_6>()) {
     50     return get_interface<PPB_FileChooser_Dev_0_6>()->Show(
     51         pp_resource(),
     52         callback.output(),
     53         callback.pp_completion_callback());
     54   }
     55   if (has_interface<PPB_FileChooser_Dev_0_5>()) {
     56     // Data for our callback wrapper. The callback handler will delete it.
     57     ChooseCallbackData0_5* data = new ChooseCallbackData0_5;
     58     data->file_chooser = pp_resource();
     59     data->output = callback.output();
     60     data->original_callback = callback.pp_completion_callback();
     61 
     62     return get_interface<PPB_FileChooser_Dev_0_5>()->Show(
     63         pp_resource(), PP_MakeCompletionCallback(&CallbackConverter, data));
     64   }
     65   return callback.MayForce(PP_ERROR_NOINTERFACE);
     66 }
     67 
     68 // static
     69 void FileChooser_Dev::CallbackConverter(void* user_data, int32_t result) {
     70   ChooseCallbackData0_5* data = static_cast<ChooseCallbackData0_5*>(user_data);
     71 
     72   // Get all of the selected file resources using the iterator API.
     73   std::vector<PP_Resource> selected_files;
     74   if (result == PP_OK) {
     75     const PPB_FileChooser_Dev_0_5* chooser =
     76         get_interface<PPB_FileChooser_Dev_0_5>();
     77     while (PP_Resource cur = chooser->GetNextChosenFile(data->file_chooser))
     78       selected_files.push_back(cur);
     79   }
     80 
     81   // Need to issue the "GetDataBuffer" even for error cases & when the
     82   // number of items is 0.
     83   void* output_buf = data->output.GetDataBuffer(
     84       data->output.user_data,
     85       selected_files.size(), sizeof(PP_Resource));
     86   if (output_buf) {
     87     if (!selected_files.empty()) {
     88       memcpy(output_buf, &selected_files[0],
     89              sizeof(PP_Resource) * selected_files.size());
     90     }
     91   } else {
     92     // Error allocating, need to free the resource IDs.
     93     for (size_t i = 0; i < selected_files.size(); i++)
     94       Module::Get()->core()->ReleaseResource(selected_files[i]);
     95   }
     96 
     97   // Now execute the original callback.
     98   PP_RunCompletionCallback(&data->original_callback, result);
     99   delete data;
    100 }
    101 
    102 }  // namespace pp
    103