• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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<string16, string16> and swap the deserialized values in.
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 
SkippablePickle(const void * data,size_t data_len)25 SkippablePickle::SkippablePickle(const void* data, size_t data_len)
26     : Pickle(reinterpret_cast<const char*>(data), data_len) {
27 }
28 
SkipString16(PickleIterator * iter)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 
ReadCustomDataTypes(const void * data,size_t data_length,std::vector<base::string16> * types)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 
ReadCustomDataForType(const void * data,size_t data_length,const base::string16 & type,base::string16 * result)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 
ReadCustomDataIntoMap(const void * data,size_t data_length,std::map<base::string16,base::string16> * result)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 
WriteCustomDataToPickle(const std::map<base::string16,base::string16> & data,Pickle * pickle)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