// 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/proxy/flash_clipboard_resource.h" #include "base/numerics/safe_conversions.h" #include "ipc/ipc_message.h" #include "ppapi/c/pp_errors.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/var.h" #include "ppapi/shared_impl/var_tracker.h" namespace ppapi { namespace proxy { namespace { // Returns whether the given clipboard type is valid. bool IsValidClipboardType(PP_Flash_Clipboard_Type type) { return type == PP_FLASH_CLIPBOARD_TYPE_STANDARD || type == PP_FLASH_CLIPBOARD_TYPE_SELECTION; } // Convert a PP_Var to/from a string which is transmitted to the pepper host. // These functions assume the format is valid. bool PPVarToClipboardString(int32_t format, const PP_Var& var, std::string* string_out) { if (format == PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT || format == PP_FLASH_CLIPBOARD_FORMAT_HTML) { StringVar* string_var = StringVar::FromPPVar(var); if (!string_var) return false; *string_out = string_var->value(); return true; } else { // All other formats are expected to be array buffers. ArrayBufferVar* array_buffer_var = ArrayBufferVar::FromPPVar(var); if (!array_buffer_var) return false; *string_out = std::string(static_cast(array_buffer_var->Map()), array_buffer_var->ByteLength()); return true; } } PP_Var ClipboardStringToPPVar(int32_t format, const std::string& string) { if (format == PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT || format == PP_FLASH_CLIPBOARD_FORMAT_HTML) { return StringVar::StringToPPVar(string); } else { // All other formats are expected to be array buffers. return PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( base::checked_cast(string.size()), string.data()); } } } // namespace FlashClipboardResource::FlashClipboardResource( Connection connection, PP_Instance instance) : PluginResource(connection, instance) { SendCreate(BROWSER, PpapiHostMsg_FlashClipboard_Create()); } FlashClipboardResource::~FlashClipboardResource() { } thunk::PPB_Flash_Clipboard_API* FlashClipboardResource::AsPPB_Flash_Clipboard_API() { return this; } uint32_t FlashClipboardResource::RegisterCustomFormat( PP_Instance instance, const char* format_name) { // Check to see if the format has already been registered. uint32_t format = clipboard_formats_.GetFormatID(format_name); if (format != PP_FLASH_CLIPBOARD_FORMAT_INVALID) return format; int32_t result = SyncCall( BROWSER, PpapiHostMsg_FlashClipboard_RegisterCustomFormat(format_name), &format); if (result != PP_OK || format == PP_FLASH_CLIPBOARD_FORMAT_INVALID) return PP_FLASH_CLIPBOARD_FORMAT_INVALID; clipboard_formats_.SetRegisteredFormat(format_name, format); return format; } PP_Bool FlashClipboardResource::IsFormatAvailable( PP_Instance instance, PP_Flash_Clipboard_Type clipboard_type, uint32_t format) { if (IsValidClipboardType(clipboard_type) && (FlashClipboardFormatRegistry::IsValidPredefinedFormat(format) || clipboard_formats_.IsFormatRegistered(format))) { int32_t result = SyncCall(BROWSER, PpapiHostMsg_FlashClipboard_IsFormatAvailable(clipboard_type, format)); return result == PP_OK ? PP_TRUE : PP_FALSE; } return PP_FALSE; } PP_Var FlashClipboardResource::ReadData( PP_Instance instance, PP_Flash_Clipboard_Type clipboard_type, uint32_t format) { std::string value; int32_t result = SyncCall( BROWSER, PpapiHostMsg_FlashClipboard_ReadData(clipboard_type, format), &value); if (result != PP_OK) return PP_MakeUndefined(); return ClipboardStringToPPVar(format, value); } int32_t FlashClipboardResource::WriteData( PP_Instance instance, PP_Flash_Clipboard_Type clipboard_type, uint32_t data_item_count, const uint32_t formats[], const PP_Var data_items[]) { if (!IsValidClipboardType(clipboard_type)) return PP_ERROR_BADARGUMENT; std::vector formats_vector; std::vector data_items_vector; for (size_t i = 0; i < data_item_count; ++i) { if (!clipboard_formats_.IsFormatRegistered(formats[i]) && !FlashClipboardFormatRegistry::IsValidPredefinedFormat(formats[i])) { return PP_ERROR_BADARGUMENT; } formats_vector.push_back(formats[i]); std::string string; if (!PPVarToClipboardString(formats[i], data_items[i], &string)) return PP_ERROR_BADARGUMENT; data_items_vector.push_back(string); } Post(BROWSER, PpapiHostMsg_FlashClipboard_WriteData( static_cast(clipboard_type), formats_vector, data_items_vector)); // Assume success, since it allows us to avoid a sync IPC. return PP_OK; } PP_Bool FlashClipboardResource::GetSequenceNumber( PP_Instance instance, PP_Flash_Clipboard_Type clipboard_type, uint64_t* sequence_number) { int32_t result = SyncCall( BROWSER, PpapiHostMsg_FlashClipboard_GetSequenceNumber(clipboard_type), sequence_number); return PP_FromBool(result == PP_OK); } } // namespace proxy } // namespace ppapi