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

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: Document Created 6 years, 1 month 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_test_template.h » ('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/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "third_party/skia/include/core/SkBitmap.h" 12 #include "third_party/skia/include/core/SkBitmap.h"
13 #include "ui/gfx/size.h" 13 #include "ui/gfx/size.h"
14 14
15 namespace ui { 15 namespace ui {
16 16
17 namespace {
18
19 // Valides a shared bitmap on the clipboard.
20 // Returns true if the clipboard data makes sense and it's safe to access the
21 // bitmap.
22 bool ValidateAndMapSharedBitmap(size_t bitmap_bytes,
23 base::SharedMemory* bitmap_data) {
24 using base::SharedMemory;
25
26 if (!bitmap_data || !SharedMemory::IsHandleValid(bitmap_data->handle()))
27 return false;
28
29 if (!bitmap_data->Map(bitmap_bytes)) {
30 PLOG(ERROR) << "Failed to map bitmap memory";
31 return false;
32 }
33 return true;
34 }
35
36 } // namespace
37
38 base::LazyInstance<Clipboard::AllowedThreadsVector> 17 base::LazyInstance<Clipboard::AllowedThreadsVector>
39 Clipboard::allowed_threads_ = LAZY_INSTANCE_INITIALIZER; 18 Clipboard::allowed_threads_ = LAZY_INSTANCE_INITIALIZER;
40 base::LazyInstance<Clipboard::ClipboardMap> Clipboard::clipboard_map_ = 19 base::LazyInstance<Clipboard::ClipboardMap> Clipboard::clipboard_map_ =
41 LAZY_INSTANCE_INITIALIZER; 20 LAZY_INSTANCE_INITIALIZER;
42 base::LazyInstance<base::Lock>::Leaky Clipboard::clipboard_map_lock_ = 21 base::LazyInstance<base::Lock>::Leaky Clipboard::clipboard_map_lock_ =
43 LAZY_INSTANCE_INITIALIZER; 22 LAZY_INSTANCE_INITIALIZER;
44 23
45 // static 24 // static
46 void Clipboard::SetAllowedThreads( 25 void Clipboard::SetAllowedThreads(
47 const std::vector<base::PlatformThreadId>& allowed_threads) { 26 const std::vector<base::PlatformThreadId>& allowed_threads) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 ClipboardMap* clipboard_map = clipboard_map_.Pointer(); 67 ClipboardMap* clipboard_map = clipboard_map_.Pointer();
89 base::PlatformThreadId id = base::PlatformThread::CurrentId(); 68 base::PlatformThreadId id = base::PlatformThread::CurrentId();
90 ClipboardMap::iterator it = clipboard_map->find(id); 69 ClipboardMap::iterator it = clipboard_map->find(id);
91 if (it != clipboard_map->end()) { 70 if (it != clipboard_map->end()) {
92 delete it->second; 71 delete it->second;
93 clipboard_map->erase(it); 72 clipboard_map->erase(it);
94 } 73 }
95 } 74 }
96 75
97 void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) { 76 void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
98 // All types apart from CBF_WEBKIT need at least 1 non-empty param.
99 if (type != CBF_WEBKIT && (params.empty() || params[0].empty()))
100 return;
101 // Some other types need a non-empty 2nd param.
102 if ((type == CBF_BOOKMARK || type == CBF_SMBITMAP || type == CBF_DATA) &&
103 (params.size() != 2 || params[1].empty()))
104 return;
105 switch (type) { 77 switch (type) {
106 case CBF_TEXT: 78 case CBF_TEXT:
107 WriteText(&(params[0].front()), params[0].size()); 79 WriteText(&(params[0].front()), params[0].size());
108 break; 80 break;
109 81
110 case CBF_HTML: 82 case CBF_HTML:
111 if (params.size() == 2) { 83 if (params.size() == 2) {
112 if (params[1].empty()) 84 if (params[1].empty())
113 return; 85 return;
114 WriteHTML(&(params[0].front()), params[0].size(), 86 WriteHTML(&(params[0].front()), params[0].size(),
(...skipping 10 matching lines...) Expand all
125 case CBF_BOOKMARK: 97 case CBF_BOOKMARK:
126 WriteBookmark(&(params[0].front()), params[0].size(), 98 WriteBookmark(&(params[0].front()), params[0].size(),
127 &(params[1].front()), params[1].size()); 99 &(params[1].front()), params[1].size());
128 break; 100 break;
129 101
130 case CBF_WEBKIT: 102 case CBF_WEBKIT:
131 WriteWebSmartPaste(); 103 WriteWebSmartPaste();
132 break; 104 break;
133 105
134 case CBF_SMBITMAP: { 106 case CBF_SMBITMAP: {
135 using base::SharedMemory; 107 // Usually, the params are just UTF-8 strings. However, for images,
136 using base::SharedMemoryHandle; 108 // ScopedClipboardWriter actually sizes the buffer to sizeof(SkBitmap*),
137 109 // aliases the contents of the vector to a SkBitmap**, and writes the
138 if (params[0].size() != sizeof(SharedMemory*) || 110 // pointer to the actual SkBitmap in the clipboard object param.
139 params[1].size() != sizeof(gfx::Size)) { 111 const char* packed_pointer_buffer = &params[0].front();
140 return; 112 WriteBitmap(
141 } 113 **reinterpret_cast<SkBitmap* const*>(packed_pointer_buffer));
142
143 SkBitmap bitmap;
144 const gfx::Size* unvalidated_size =
145 reinterpret_cast<const gfx::Size*>(&params[1].front());
146 // Let Skia do some sanity checking for us (no negative widths/heights, no
147 // overflows while calculating bytes per row, etc).
148 if (!bitmap.setInfo(SkImageInfo::MakeN32Premul(
149 unvalidated_size->width(), unvalidated_size->height()))) {
150 return;
151 }
152 // Make sure the size is representable as a signed 32-bit int, so
153 // SkBitmap::getSize() won't be truncated.
154 if (!sk_64_isS32(bitmap.computeSize64()))
155 return;
156
157 // It's OK to cast away constness here since we map the handle as
158 // read-only.
159 const char* raw_bitmap_data_const =
160 reinterpret_cast<const char*>(&params[0].front());
161 char* raw_bitmap_data = const_cast<char*>(raw_bitmap_data_const);
162 scoped_ptr<SharedMemory> bitmap_data(
163 *reinterpret_cast<SharedMemory**>(raw_bitmap_data));
164
165 if (!ValidateAndMapSharedBitmap(bitmap.getSize(), bitmap_data.get()))
166 return;
167 bitmap.setPixels(bitmap_data->memory());
168
169 WriteBitmap(bitmap);
170 break; 114 break;
171 } 115 }
172 116
173 case CBF_DATA: 117 case CBF_DATA:
174 WriteData( 118 WriteData(
175 FormatType::Deserialize( 119 FormatType::Deserialize(
176 std::string(&(params[0].front()), params[0].size())), 120 std::string(&(params[0].front()), params[0].size())),
177 &(params[1].front()), 121 &(params[1].front()),
178 params[1].size()); 122 params[1].size());
179 break; 123 break;
180 124
181 default: 125 default:
182 NOTREACHED(); 126 NOTREACHED();
183 } 127 }
184 } 128 }
185 129
186 // static
187 bool Clipboard::ReplaceSharedMemHandle(ObjectMap* objects,
188 base::SharedMemoryHandle bitmap_handle,
189 base::ProcessHandle process) {
190 using base::SharedMemory;
191 bool has_shared_bitmap = false;
192
193 for (ObjectMap::iterator iter = objects->begin(); iter != objects->end();
194 ++iter) {
195 if (iter->first == CBF_SMBITMAP) {
196 // The code currently only accepts sending a single bitmap over this way.
197 // Fail if we ever encounter more than one shmem bitmap structure to fill.
198 if (has_shared_bitmap)
199 return false;
200
201 #if defined(OS_WIN)
202 SharedMemory* bitmap = new SharedMemory(bitmap_handle, true, process);
203 #else
204 SharedMemory* bitmap = new SharedMemory(bitmap_handle, true);
205 #endif
206
207 // There must always be two parameters associated with each shmem bitmap.
208 if (iter->second.size() != 2)
209 return false;
210
211 // We store the shared memory object pointer so it can be retrieved by the
212 // UI thread (see DispatchObject()).
213 iter->second[0].clear();
214 for (size_t i = 0; i < sizeof(SharedMemory*); ++i)
215 iter->second[0].push_back(reinterpret_cast<char*>(&bitmap)[i]);
216 has_shared_bitmap = true;
217 }
218 }
219 return true;
220 }
221
222 } // namespace ui 130 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/clipboard/clipboard.h ('k') | ui/base/clipboard/clipboard_test_template.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698