Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: ui/base/clipboard/clipboard.cc

Issue 574273002: Rewrite clipboard write IPC handling to be easier to understand. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/base/clipboard/clipboard.h ('k') | ui/base/clipboard/clipboard_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/base/clipboard/clipboard.h" 5 #include "ui/base/clipboard/clipboard.h"
6 6
7 #include <iterator> 7 #include <iterator>
8 #include <limits> 8 #include <limits>
9 9
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/synchronization/lock.h" 13 #include "base/synchronization/lock.h"
14 #include "third_party/skia/include/core/SkBitmap.h" 14 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "ui/gfx/size.h" 15 #include "ui/gfx/size.h"
16 16
17 namespace ui { 17 namespace ui {
18 18
19 namespace { 19 namespace {
20 20
21 // Valides a shared bitmap on the clipboard.
22 // Returns true if the clipboard data makes sense and it's safe to access the
23 // bitmap.
24 bool ValidateAndMapSharedBitmap(size_t bitmap_bytes,
25 base::SharedMemory* bitmap_data) {
26 using base::SharedMemory;
27
28 if (!bitmap_data || !SharedMemory::IsHandleValid(bitmap_data->handle()))
29 return false;
30
31 if (!bitmap_data->Map(bitmap_bytes)) {
32 PLOG(ERROR) << "Failed to map bitmap memory";
33 return false;
34 }
35 return true;
36 }
37
38 // A list of allowed threads. By default, this is empty and no thread checking 21 // A list of allowed threads. By default, this is empty and no thread checking
39 // is done (in the unit test case), but a user (like content) can set which 22 // is done (in the unit test case), but a user (like content) can set which
40 // threads are allowed to call this method. 23 // threads are allowed to call this method.
41 typedef std::vector<base::PlatformThreadId> AllowedThreadsVector; 24 typedef std::vector<base::PlatformThreadId> AllowedThreadsVector;
42 static base::LazyInstance<AllowedThreadsVector> g_allowed_threads = 25 static base::LazyInstance<AllowedThreadsVector> g_allowed_threads =
43 LAZY_INSTANCE_INITIALIZER; 26 LAZY_INSTANCE_INITIALIZER;
44 27
45 // Mapping from threads to clipboard objects. 28 // Mapping from threads to clipboard objects.
46 typedef std::map<base::PlatformThreadId, Clipboard*> ClipboardMap; 29 typedef std::map<base::PlatformThreadId, Clipboard*> ClipboardMap;
47 static base::LazyInstance<ClipboardMap> g_clipboard_map = 30 static base::LazyInstance<ClipboardMap> g_clipboard_map =
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 ClipboardMap* clipboard_map = g_clipboard_map.Pointer(); 82 ClipboardMap* clipboard_map = g_clipboard_map.Pointer();
100 base::PlatformThreadId id = base::PlatformThread::CurrentId(); 83 base::PlatformThreadId id = base::PlatformThread::CurrentId();
101 ClipboardMap::iterator it = clipboard_map->find(id); 84 ClipboardMap::iterator it = clipboard_map->find(id);
102 if (it != clipboard_map->end()) { 85 if (it != clipboard_map->end()) {
103 delete it->second; 86 delete it->second;
104 clipboard_map->erase(it); 87 clipboard_map->erase(it);
105 } 88 }
106 } 89 }
107 90
108 void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) { 91 void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
109 // All types apart from CBF_WEBKIT need at least 1 non-empty param.
110 if (type != CBF_WEBKIT && (params.empty() || params[0].empty()))
111 return;
112 // Some other types need a non-empty 2nd param.
113 if ((type == CBF_BOOKMARK || type == CBF_SMBITMAP || type == CBF_DATA) &&
114 (params.size() != 2 || params[1].empty()))
115 return;
116 switch (type) { 92 switch (type) {
117 case CBF_TEXT: 93 case CBF_TEXT:
118 WriteText(&(params[0].front()), params[0].size()); 94 WriteText(&(params[0].front()), params[0].size());
119 break; 95 break;
120 96
121 case CBF_HTML: 97 case CBF_HTML:
122 if (params.size() == 2) { 98 if (params.size() == 2) {
123 if (params[1].empty()) 99 if (params[1].empty())
124 return; 100 return;
125 WriteHTML(&(params[0].front()), params[0].size(), 101 WriteHTML(&(params[0].front()), params[0].size(),
(...skipping 10 matching lines...) Expand all
136 case CBF_BOOKMARK: 112 case CBF_BOOKMARK:
137 WriteBookmark(&(params[0].front()), params[0].size(), 113 WriteBookmark(&(params[0].front()), params[0].size(),
138 &(params[1].front()), params[1].size()); 114 &(params[1].front()), params[1].size());
139 break; 115 break;
140 116
141 case CBF_WEBKIT: 117 case CBF_WEBKIT:
142 WriteWebSmartPaste(); 118 WriteWebSmartPaste();
143 break; 119 break;
144 120
145 case CBF_SMBITMAP: { 121 case CBF_SMBITMAP: {
146 using base::SharedMemory; 122 WriteBitmap(
147 using base::SharedMemoryHandle; 123 **reinterpret_cast<const SkBitmap* const*>(&(params[0].front())));
jamesr 2014/10/09 22:34:12 i can't follow this expression. what is the type o
dcheng 2014/10/09 22:39:17 Would you find this clearer if it used vector_as_a
jamesr 2014/10/09 22:41:28 I'd find it clearer if the intermediates of this e
dcheng 2014/10/13 05:52:21 Done. I've added some intermediate types in both S
148
149 if (params[0].size() != sizeof(SharedMemory*) ||
150 params[1].size() != sizeof(gfx::Size)) {
151 return;
152 }
153
154 SkBitmap bitmap;
155 const gfx::Size* unvalidated_size =
156 reinterpret_cast<const gfx::Size*>(&params[1].front());
157 // Let Skia do some sanity checking for us (no negative widths/heights, no
158 // overflows while calculating bytes per row, etc).
159 if (!bitmap.setInfo(SkImageInfo::MakeN32Premul(
160 unvalidated_size->width(), unvalidated_size->height()))) {
161 return;
162 }
163 // Make sure the size is representable as a signed 32-bit int, so
164 // SkBitmap::getSize() won't be truncated.
165 if (!sk_64_isS32(bitmap.computeSize64()))
166 return;
167
168 // It's OK to cast away constness here since we map the handle as
169 // read-only.
170 const char* raw_bitmap_data_const =
171 reinterpret_cast<const char*>(&params[0].front());
172 char* raw_bitmap_data = const_cast<char*>(raw_bitmap_data_const);
173 scoped_ptr<SharedMemory> bitmap_data(
174 *reinterpret_cast<SharedMemory**>(raw_bitmap_data));
175
176 if (!ValidateAndMapSharedBitmap(bitmap.getSize(), bitmap_data.get()))
177 return;
178 bitmap.setPixels(bitmap_data->memory());
179
180 WriteBitmap(bitmap);
181 break; 124 break;
182 } 125 }
183 126
184 case CBF_DATA: 127 case CBF_DATA:
185 WriteData( 128 WriteData(
186 FormatType::Deserialize( 129 FormatType::Deserialize(
187 std::string(&(params[0].front()), params[0].size())), 130 std::string(&(params[0].front()), params[0].size())),
188 &(params[1].front()), 131 &(params[1].front()),
189 params[1].size()); 132 params[1].size());
190 break; 133 break;
191 134
192 default: 135 default:
193 NOTREACHED(); 136 NOTREACHED();
194 } 137 }
195 } 138 }
196 139
197 // static
198 bool Clipboard::ReplaceSharedMemHandle(ObjectMap* objects,
199 base::SharedMemoryHandle bitmap_handle,
200 base::ProcessHandle process) {
201 using base::SharedMemory;
202 bool has_shared_bitmap = false;
203
204 for (ObjectMap::iterator iter = objects->begin(); iter != objects->end();
205 ++iter) {
206 if (iter->first == CBF_SMBITMAP) {
207 // The code currently only accepts sending a single bitmap over this way.
208 // Fail if we ever encounter more than one shmem bitmap structure to fill.
209 if (has_shared_bitmap)
210 return false;
211
212 #if defined(OS_WIN)
213 SharedMemory* bitmap = new SharedMemory(bitmap_handle, true, process);
214 #else
215 SharedMemory* bitmap = new SharedMemory(bitmap_handle, true);
216 #endif
217
218 // There must always be two parameters associated with each shmem bitmap.
219 if (iter->second.size() != 2)
220 return false;
221
222 // We store the shared memory object pointer so it can be retrieved by the
223 // UI thread (see DispatchObject()).
224 iter->second[0].clear();
225 for (size_t i = 0; i < sizeof(SharedMemory*); ++i)
226 iter->second[0].push_back(reinterpret_cast<char*>(&bitmap)[i]);
227 has_shared_bitmap = true;
228 }
229 }
230 return true;
231 }
232
233 } // namespace ui 140 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/clipboard/clipboard.h ('k') | ui/base/clipboard/clipboard_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698