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/private/flash_clipboard.h"
6
7#include <vector>
8
9#include "ppapi/c/pp_bool.h"
10#include "ppapi/c/pp_errors.h"
11#include "ppapi/cpp/instance_handle.h"
12#include "ppapi/cpp/module_impl.h"
13#include "ppapi/cpp/var.h"
14
15namespace pp {
16
17namespace {
18
19template <> const char* interface_name<PPB_Flash_Clipboard_4_0>() {
20  return PPB_FLASH_CLIPBOARD_INTERFACE_4_0;
21}
22
23template <> const char* interface_name<PPB_Flash_Clipboard_5_0>() {
24  return PPB_FLASH_CLIPBOARD_INTERFACE_5_0;
25}
26
27template <> const char* interface_name<PPB_Flash_Clipboard_5_1>() {
28  return PPB_FLASH_CLIPBOARD_INTERFACE_5_1;
29}
30
31}  // namespace
32
33namespace flash {
34
35// static
36bool Clipboard::IsAvailable() {
37  return has_interface<PPB_Flash_Clipboard_5_1>() ||
38      has_interface<PPB_Flash_Clipboard_5_0>() ||
39      has_interface<PPB_Flash_Clipboard_4_0>() ;
40}
41
42// static
43uint32_t Clipboard::RegisterCustomFormat(const InstanceHandle& instance,
44                                         const std::string& format_name) {
45  uint32_t rv = PP_FLASH_CLIPBOARD_FORMAT_INVALID;
46  if (has_interface<PPB_Flash_Clipboard_5_1>()) {
47    rv = get_interface<PPB_Flash_Clipboard_5_1>()->RegisterCustomFormat(
48        instance.pp_instance(), format_name.c_str());
49  } else if (has_interface<PPB_Flash_Clipboard_5_0>()) {
50    rv = get_interface<PPB_Flash_Clipboard_5_0>()->RegisterCustomFormat(
51        instance.pp_instance(), format_name.c_str());
52  }
53  return rv;
54}
55
56// static
57bool Clipboard::IsFormatAvailable(const InstanceHandle& instance,
58                                  PP_Flash_Clipboard_Type clipboard_type,
59                                  uint32_t format) {
60  bool rv = false;
61  if (has_interface<PPB_Flash_Clipboard_5_1>()) {
62    rv = PP_ToBool(get_interface<PPB_Flash_Clipboard_5_1>()->IsFormatAvailable(
63        instance.pp_instance(), clipboard_type, format));
64  } else if (has_interface<PPB_Flash_Clipboard_5_0>()) {
65    rv = PP_ToBool(get_interface<PPB_Flash_Clipboard_5_0>()->IsFormatAvailable(
66        instance.pp_instance(), clipboard_type, format));
67  } else if (has_interface<PPB_Flash_Clipboard_4_0>()) {
68    rv = PP_ToBool(get_interface<PPB_Flash_Clipboard_4_0>()->IsFormatAvailable(
69        instance.pp_instance(), clipboard_type,
70        static_cast<PP_Flash_Clipboard_Format>(format)));
71  }
72  return rv;
73}
74
75// static
76bool Clipboard::ReadData(
77    const InstanceHandle& instance,
78    PP_Flash_Clipboard_Type clipboard_type,
79    uint32_t format,
80    Var* out) {
81  bool rv = false;
82  if (has_interface<PPB_Flash_Clipboard_5_1>()) {
83    PP_Var result = get_interface<PPB_Flash_Clipboard_5_1>()->ReadData(
84        instance.pp_instance(),
85        clipboard_type,
86        format);
87    *out = Var(PASS_REF, result);
88    rv = true;
89  } else if (has_interface<PPB_Flash_Clipboard_5_0>()) {
90    PP_Var result = get_interface<PPB_Flash_Clipboard_5_0>()->ReadData(
91        instance.pp_instance(),
92        clipboard_type,
93        format);
94    *out = Var(PASS_REF, result);
95    rv = true;
96  } else if (has_interface<PPB_Flash_Clipboard_4_0>()) {
97    PP_Var result = get_interface<PPB_Flash_Clipboard_4_0>()->ReadData(
98        instance.pp_instance(),
99        clipboard_type,
100        static_cast<PP_Flash_Clipboard_Format>(format));
101    *out = Var(PASS_REF, result);
102    rv = true;
103  }
104  return rv;
105}
106
107// static
108bool Clipboard::WriteData(
109    const InstanceHandle& instance,
110    PP_Flash_Clipboard_Type clipboard_type,
111    const std::vector<uint32_t>& formats,
112    const std::vector<Var>& data_items) {
113  if (formats.size() != data_items.size())
114    return false;
115
116  bool rv = false;
117  if (has_interface<PPB_Flash_Clipboard_5_1>()) {
118    // Convert vector of pp::Var into a vector of PP_Var.
119    std::vector<PP_Var> data_items_vector;
120    for (uint32_t i = 0; i < data_items.size(); ++i)
121      data_items_vector.push_back(data_items[i].pp_var());
122
123    // Ensure that we don't dereference the memory in empty vectors. We still
124    // want to call WriteData because it has the effect of clearing the
125    // clipboard.
126    const uint32_t* formats_ptr(NULL);
127    const PP_Var* data_items_ptr(NULL);
128    if (data_items.size() > 0) {
129      formats_ptr = &formats[0];
130      data_items_ptr = &data_items_vector[0];
131    }
132
133    rv = (get_interface<PPB_Flash_Clipboard_5_1>()->WriteData(
134        instance.pp_instance(),
135        clipboard_type,
136        data_items.size(),
137        formats_ptr,
138            data_items_ptr) == PP_OK);
139  } else if (has_interface<PPB_Flash_Clipboard_5_0>()) {
140    // Convert vector of pp::Var into a vector of PP_Var.
141    std::vector<PP_Var> data_items_vector;
142    for (uint32_t i = 0; i < data_items.size(); ++i)
143      data_items_vector.push_back(data_items[i].pp_var());
144
145    // Ensure that we don't dereference the memory in empty vectors. We still
146    // want to call WriteData because it has the effect of clearing the
147    // clipboard.
148    const uint32_t* formats_ptr(NULL);
149    const PP_Var* data_items_ptr(NULL);
150    if (data_items.size() > 0) {
151      formats_ptr = &formats[0];
152      data_items_ptr = &data_items_vector[0];
153    }
154
155    rv = (get_interface<PPB_Flash_Clipboard_5_0>()->WriteData(
156        instance.pp_instance(),
157        clipboard_type,
158        data_items.size(),
159        formats_ptr,
160        data_items_ptr) == PP_OK);
161  } else if (has_interface<PPB_Flash_Clipboard_4_0>()) {
162    // Convert vector of pp::Var into a vector of PP_Var.
163    std::vector<PP_Var> data_items_vector;
164    std::vector<PP_Flash_Clipboard_Format> old_formats;
165    for (uint32_t i = 0; i < data_items.size(); ++i) {
166      data_items_vector.push_back(data_items[i].pp_var());
167      old_formats.push_back(static_cast<PP_Flash_Clipboard_Format>(formats[i]));
168    }
169
170    // Ensure that we don't dereference the memory in empty vectors. We still
171    // want to call WriteData because it has the effect of clearing the
172    // clipboard.
173    const PP_Flash_Clipboard_Format* formats_ptr(NULL);
174    const PP_Var* data_items_ptr(NULL);
175    if (data_items.size() > 0) {
176      formats_ptr = &old_formats[0];
177      data_items_ptr = &data_items_vector[0];
178    }
179
180    rv = (get_interface<PPB_Flash_Clipboard_4_0>()->WriteData(
181        instance.pp_instance(),
182        clipboard_type,
183        data_items.size(),
184        formats_ptr,
185        data_items_ptr) == PP_OK);
186  }
187
188  return rv;
189}
190
191// static
192bool Clipboard::GetSequenceNumber(const InstanceHandle& instance,
193                                  PP_Flash_Clipboard_Type clipboard_type,
194                                  uint64_t* sequence_number) {
195  if (has_interface<PPB_Flash_Clipboard_5_1>()) {
196    return PP_ToBool(
197        get_interface<PPB_Flash_Clipboard_5_1>()->GetSequenceNumber(
198            instance.pp_instance(), clipboard_type, sequence_number));
199  }
200  return false;
201}
202
203}  // namespace flash
204}  // namespace pp
205