Home | History | Annotate | Download | only in clipboard
      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 // TODO(dcheng): For efficiency reasons, consider passing custom data around
      6 // as a vector instead. It allows us to append a
      7 // std::pair<base::string16, base::string16> and swap the deserialized values.
      8 
      9 #include "ui/base/clipboard/custom_data_helper.h"
     10 
     11 #include <utility>
     12 
     13 #include "base/pickle.h"
     14 
     15 namespace ui {
     16 
     17 namespace {
     18 
     19 class SkippablePickle : public Pickle {
     20  public:
     21   SkippablePickle(const void* data, size_t data_len);
     22   bool SkipString16(PickleIterator* iter);
     23 };
     24 
     25 SkippablePickle::SkippablePickle(const void* data, size_t data_len)
     26     : Pickle(reinterpret_cast<const char*>(data), data_len) {
     27 }
     28 
     29 bool SkippablePickle::SkipString16(PickleIterator* iter) {
     30   DCHECK(iter);
     31 
     32   int len;
     33   if (!ReadLength(iter, &len))
     34     return false;
     35   return iter->SkipBytes(len * sizeof(base::char16));
     36 }
     37 
     38 }  // namespace
     39 
     40 void ReadCustomDataTypes(const void* data,
     41                          size_t data_length,
     42                          std::vector<base::string16>* types) {
     43   SkippablePickle pickle(data, data_length);
     44   PickleIterator iter(pickle);
     45 
     46   uint64 size = 0;
     47   if (!pickle.ReadUInt64(&iter, &size))
     48     return;
     49 
     50   // Keep track of the original elements in the types vector. On failure, we
     51   // truncate the vector to the original size since we want to ignore corrupt
     52   // custom data pickles.
     53   uint64 original_size = types->size();
     54 
     55   for (uint64 i = 0; i < size; ++i) {
     56     types->push_back(base::string16());
     57     if (!pickle.ReadString16(&iter, &types->back()) ||
     58         !pickle.SkipString16(&iter)) {
     59       types->resize(original_size);
     60       return;
     61     }
     62   }
     63 }
     64 
     65 void ReadCustomDataForType(const void* data,
     66                            size_t data_length,
     67                            const base::string16& type,
     68                            base::string16* result) {
     69   SkippablePickle pickle(data, data_length);
     70   PickleIterator iter(pickle);
     71 
     72   uint64 size = 0;
     73   if (!pickle.ReadUInt64(&iter, &size))
     74     return;
     75 
     76   for (uint64 i = 0; i < size; ++i) {
     77     base::string16 deserialized_type;
     78     if (!pickle.ReadString16(&iter, &deserialized_type))
     79       return;
     80     if (deserialized_type == type) {
     81       ignore_result(pickle.ReadString16(&iter, result));
     82       return;
     83     }
     84     if (!pickle.SkipString16(&iter))
     85       return;
     86   }
     87 }
     88 
     89 void ReadCustomDataIntoMap(const void* data,
     90                            size_t data_length,
     91                            std::map<base::string16, base::string16>* result) {
     92   Pickle pickle(reinterpret_cast<const char*>(data), data_length);
     93   PickleIterator iter(pickle);
     94 
     95   uint64 size = 0;
     96   if (!pickle.ReadUInt64(&iter, &size))
     97     return;
     98 
     99   for (uint64 i = 0; i < size; ++i) {
    100     base::string16 type;
    101     if (!pickle.ReadString16(&iter, &type)) {
    102       // Data is corrupt, return an empty map.
    103       result->clear();
    104       return;
    105     }
    106     std::pair<std::map<base::string16, base::string16>::iterator, bool>
    107         insert_result = result->insert(std::make_pair(type, base::string16()));
    108     if (!pickle.ReadString16(&iter, &insert_result.first->second)) {
    109       // Data is corrupt, return an empty map.
    110       result->clear();
    111       return;
    112     }
    113   }
    114 }
    115 
    116 void WriteCustomDataToPickle(
    117     const std::map<base::string16, base::string16>& data,
    118     Pickle* pickle) {
    119   pickle->WriteUInt64(data.size());
    120   for (std::map<base::string16, base::string16>::const_iterator it =
    121            data.begin();
    122        it != data.end();
    123        ++it) {
    124     pickle->WriteString16(it->first);
    125     pickle->WriteString16(it->second);
    126   }
    127 }
    128 
    129 }  // namespace ui
    130