// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ppapi/cpp/dev/file_chooser_dev.h" #include #include "ppapi/c/dev/ppb_file_chooser_dev.h" #include "ppapi/c/pp_errors.h" #include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/file_ref.h" #include "ppapi/cpp/instance_handle.h" #include "ppapi/cpp/module.h" #include "ppapi/cpp/module_impl.h" namespace pp { namespace { template <> const char* interface_name() { return PPB_FILECHOOSER_DEV_INTERFACE_0_5; } template <> const char* interface_name() { return PPB_FILECHOOSER_DEV_INTERFACE_0_6; } } // namespace FileChooser_Dev::FileChooser_Dev(const InstanceHandle& instance, PP_FileChooserMode_Dev mode, const Var& accept_types) { if (has_interface()) { PassRefFromConstructor(get_interface()->Create( instance.pp_instance(), mode, accept_types.pp_var())); } else if (has_interface()) { PassRefFromConstructor(get_interface()->Create( instance.pp_instance(), mode, accept_types.pp_var())); } } FileChooser_Dev::FileChooser_Dev(const FileChooser_Dev& other) : Resource(other) { } int32_t FileChooser_Dev::Show( const CompletionCallbackWithOutput< std::vector >& callback) { if (has_interface()) { return get_interface()->Show( pp_resource(), callback.output(), callback.pp_completion_callback()); } if (has_interface()) { // Data for our callback wrapper. The callback handler will delete it. ChooseCallbackData0_5* data = new ChooseCallbackData0_5; data->file_chooser = pp_resource(); data->output = callback.output(); data->original_callback = callback.pp_completion_callback(); return get_interface()->Show( pp_resource(), PP_MakeCompletionCallback(&CallbackConverter, data)); } return callback.MayForce(PP_ERROR_NOINTERFACE); } // static void FileChooser_Dev::CallbackConverter(void* user_data, int32_t result) { ChooseCallbackData0_5* data = static_cast(user_data); // Get all of the selected file resources using the iterator API. std::vector selected_files; if (result == PP_OK) { const PPB_FileChooser_Dev_0_5* chooser = get_interface(); while (PP_Resource cur = chooser->GetNextChosenFile(data->file_chooser)) selected_files.push_back(cur); } // Need to issue the "GetDataBuffer" even for error cases & when the // number of items is 0. void* output_buf = data->output.GetDataBuffer( data->output.user_data, selected_files.size(), sizeof(PP_Resource)); if (output_buf) { if (!selected_files.empty()) { memcpy(output_buf, &selected_files[0], sizeof(PP_Resource) * selected_files.size()); } } else { // Error allocating, need to free the resource IDs. for (size_t i = 0; i < selected_files.size(); i++) Module::Get()->core()->ReleaseResource(selected_files[i]); } // Now execute the original callback. PP_RunCompletionCallback(&data->original_callback, result); delete data; } } // namespace pp