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/proxy/flash_clipboard_resource.h" 6 7 #include "ipc/ipc_message.h" 8 #include "ppapi/c/pp_errors.h" 9 #include "ppapi/proxy/ppapi_messages.h" 10 #include "ppapi/shared_impl/ppapi_globals.h" 11 #include "ppapi/shared_impl/var.h" 12 #include "ppapi/shared_impl/var_tracker.h" 13 14 namespace ppapi { 15 namespace proxy { 16 17 namespace { 18 19 // Returns whether the given clipboard type is valid. 20 bool IsValidClipboardType(PP_Flash_Clipboard_Type type) { 21 return type == PP_FLASH_CLIPBOARD_TYPE_STANDARD || 22 type == PP_FLASH_CLIPBOARD_TYPE_SELECTION; 23 } 24 25 // Convert a PP_Var to/from a string which is transmitted to the pepper host. 26 // These functions assume the format is valid. 27 bool PPVarToClipboardString(int32_t format, 28 const PP_Var& var, 29 std::string* string_out) { 30 if (format == PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT || 31 format == PP_FLASH_CLIPBOARD_FORMAT_HTML) { 32 StringVar* string_var = StringVar::FromPPVar(var); 33 if (!string_var) 34 return false; 35 *string_out = string_var->value(); 36 return true; 37 } else { 38 // All other formats are expected to be array buffers. 39 ArrayBufferVar* array_buffer_var = ArrayBufferVar::FromPPVar(var); 40 if (!array_buffer_var) 41 return false; 42 *string_out = std::string(static_cast<const char*>(array_buffer_var->Map()), 43 array_buffer_var->ByteLength()); 44 return true; 45 } 46 } 47 48 PP_Var ClipboardStringToPPVar(int32_t format, 49 const std::string& string) { 50 if (format == PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT || 51 format == PP_FLASH_CLIPBOARD_FORMAT_HTML) { 52 return StringVar::StringToPPVar(string); 53 } else { 54 // All other formats are expected to be array buffers. 55 return PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( 56 string.size(), string.data()); 57 } 58 } 59 } // namespace 60 61 FlashClipboardResource::FlashClipboardResource( 62 Connection connection, PP_Instance instance) 63 : PluginResource(connection, instance) { 64 SendCreate(BROWSER, PpapiHostMsg_FlashClipboard_Create()); 65 } 66 67 FlashClipboardResource::~FlashClipboardResource() { 68 } 69 70 thunk::PPB_Flash_Clipboard_API* 71 FlashClipboardResource::AsPPB_Flash_Clipboard_API() { 72 return this; 73 } 74 75 uint32_t FlashClipboardResource::RegisterCustomFormat( 76 PP_Instance instance, 77 const char* format_name) { 78 // Check to see if the format has already been registered. 79 uint32_t format = clipboard_formats_.GetFormatID(format_name); 80 if (format != PP_FLASH_CLIPBOARD_FORMAT_INVALID) 81 return format; 82 int32_t result = 83 SyncCall<PpapiPluginMsg_FlashClipboard_RegisterCustomFormatReply>( 84 BROWSER, 85 PpapiHostMsg_FlashClipboard_RegisterCustomFormat(format_name), 86 &format); 87 if (result != PP_OK || format == PP_FLASH_CLIPBOARD_FORMAT_INVALID) 88 return PP_FLASH_CLIPBOARD_FORMAT_INVALID; 89 clipboard_formats_.SetRegisteredFormat(format_name, format); 90 return format; 91 } 92 93 PP_Bool FlashClipboardResource::IsFormatAvailable( 94 PP_Instance instance, 95 PP_Flash_Clipboard_Type clipboard_type, 96 uint32_t format) { 97 if (IsValidClipboardType(clipboard_type) && 98 (FlashClipboardFormatRegistry::IsValidPredefinedFormat(format) || 99 clipboard_formats_.IsFormatRegistered(format))) { 100 int32_t result = SyncCall<IPC::Message>(BROWSER, 101 PpapiHostMsg_FlashClipboard_IsFormatAvailable(clipboard_type, format)); 102 return result == PP_OK ? PP_TRUE : PP_FALSE; 103 } 104 return PP_FALSE; 105 } 106 107 PP_Var FlashClipboardResource::ReadData( 108 PP_Instance instance, 109 PP_Flash_Clipboard_Type clipboard_type, 110 uint32_t format) { 111 std::string value; 112 int32_t result = 113 SyncCall<PpapiPluginMsg_FlashClipboard_ReadDataReply>( 114 BROWSER, 115 PpapiHostMsg_FlashClipboard_ReadData(clipboard_type, format), 116 &value); 117 if (result != PP_OK) 118 return PP_MakeUndefined(); 119 120 return ClipboardStringToPPVar(format, value); 121 } 122 123 int32_t FlashClipboardResource::WriteData( 124 PP_Instance instance, 125 PP_Flash_Clipboard_Type clipboard_type, 126 uint32_t data_item_count, 127 const uint32_t formats[], 128 const PP_Var data_items[]) { 129 if (!IsValidClipboardType(clipboard_type)) 130 return PP_ERROR_BADARGUMENT; 131 std::vector<uint32_t> formats_vector; 132 std::vector<std::string> data_items_vector; 133 for (size_t i = 0; i < data_item_count; ++i) { 134 if (!clipboard_formats_.IsFormatRegistered(formats[i]) && 135 !FlashClipboardFormatRegistry::IsValidPredefinedFormat(formats[i])) { 136 return PP_ERROR_BADARGUMENT; 137 } 138 formats_vector.push_back(formats[i]); 139 std::string string; 140 if (!PPVarToClipboardString(formats[i], data_items[i], &string)) 141 return PP_ERROR_BADARGUMENT; 142 data_items_vector.push_back(string); 143 } 144 145 Post(BROWSER, 146 PpapiHostMsg_FlashClipboard_WriteData( 147 static_cast<uint32_t>(clipboard_type), 148 formats_vector, 149 data_items_vector)); 150 151 // Assume success, since it allows us to avoid a sync IPC. 152 return PP_OK; 153 } 154 155 } // namespace proxy 156 } // namespace ppapi 157