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

Side by Side Diff: content/browser/renderer_host/clipboard_message_filter.cc

Issue 740003003: Revert of Rewrite clipboard write IPC handling to be easier to understand. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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
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 "content/browser/renderer_host/clipboard_message_filter.h" 5 #include "content/browser/renderer_host/clipboard_message_filter.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/macros.h"
11 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
12 #include "base/pickle.h"
13 #include "base/stl_util.h" 11 #include "base/stl_util.h"
14 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
15 #include "content/common/clipboard_messages.h" 13 #include "content/common/clipboard_messages.h"
16 #include "content/public/browser/browser_context.h" 14 #include "content/public/browser/browser_context.h"
17 #include "ipc/ipc_message_macros.h" 15 #include "ipc/ipc_message_macros.h"
18 #include "third_party/skia/include/core/SkBitmap.h" 16 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "ui/base/clipboard/custom_data_helper.h"
20 #include "ui/base/clipboard/scoped_clipboard_writer.h"
21 #include "ui/gfx/codec/png_codec.h" 17 #include "ui/gfx/codec/png_codec.h"
22 #include "ui/gfx/size.h" 18 #include "ui/gfx/size.h"
23 #include "url/gurl.h" 19 #include "url/gurl.h"
24 20
25 namespace content { 21 namespace content {
26 22
27 namespace { 23 namespace {
28 24
29 void ReleaseSharedMemoryPixels(void* addr, void* context) { 25 enum BitmapPolicy {
30 delete reinterpret_cast<base::SharedMemory*>(context); 26 kFilterBitmap,
27 kAllowBitmap,
28 };
29 void SanitizeObjectMap(ui::Clipboard::ObjectMap* objects,
30 BitmapPolicy bitmap_policy) {
31 if (bitmap_policy != kAllowBitmap)
32 objects->erase(ui::Clipboard::CBF_SMBITMAP);
33
34 ui::Clipboard::ObjectMap::iterator data_it =
35 objects->find(ui::Clipboard::CBF_DATA);
36 if (data_it != objects->end()) {
37 const ui::Clipboard::FormatType& web_custom_format =
38 ui::Clipboard::GetWebCustomDataFormatType();
39 if (data_it->second.size() != 2 ||
40 !web_custom_format.Equals(
41 ui::Clipboard::FormatType::Deserialize(std::string(
42 &data_it->second[0].front(),
43 data_it->second[0].size())))) {
44 // CBF_DATA should always have two parameters associated with it, and the
45 // associated FormatType should always be web custom data. If not, then
46 // data is malformed and we'll ignore it.
47 objects->erase(ui::Clipboard::CBF_DATA);
48 }
49 }
31 } 50 }
32 51
33 } // namespace 52 } // namespace
34 53
54
35 ClipboardMessageFilter::ClipboardMessageFilter() 55 ClipboardMessageFilter::ClipboardMessageFilter()
36 : BrowserMessageFilter(ClipboardMsgStart), 56 : BrowserMessageFilter(ClipboardMsgStart) {}
37 clipboard_writer_(
38 new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)) {
39 }
40 57
41 void ClipboardMessageFilter::OverrideThreadForMessage( 58 void ClipboardMessageFilter::OverrideThreadForMessage(
42 const IPC::Message& message, BrowserThread::ID* thread) { 59 const IPC::Message& message, BrowserThread::ID* thread) {
43 // Clipboard writes should always occur on the UI thread due the restrictions 60 // Clipboard writes should always occur on the UI thread due the restrictions
44 // of various platform APIs. In general, the clipboard is not thread-safe, so 61 // of various platform APIs. In general, the clipboard is not thread-safe, so
45 // all clipboard calls should be serviced from the UI thread. 62 // all clipboard calls should be serviced from the UI thread.
46 // 63 //
47 // Windows needs clipboard reads to be serviced from the IO thread because 64 // Windows needs clipboard reads to be serviced from the IO thread because
48 // these are sync IPCs which can result in deadlocks with NPAPI plugins if 65 // these are sync IPCs which can result in deadlocks with NPAPI plugins if
49 // serviced from the UI thread. Note that Windows clipboard calls ARE 66 // serviced from the UI thread. Note that Windows clipboard calls ARE
50 // thread-safe so it is ok for reads and writes to be serviced from different 67 // thread-safe so it is ok for reads and writes to be serviced from different
51 // threads. 68 // threads.
52 #if !defined(OS_WIN) 69 #if !defined(OS_WIN)
53 if (IPC_MESSAGE_CLASS(message) == ClipboardMsgStart) 70 if (IPC_MESSAGE_CLASS(message) == ClipboardMsgStart)
54 *thread = BrowserThread::UI; 71 *thread = BrowserThread::UI;
55 #endif 72 #endif
56 73
57 #if defined(OS_WIN) 74 #if defined(OS_WIN)
58 if (message.type() == ClipboardHostMsg_ReadImage::ID) 75 if (message.type() == ClipboardHostMsg_ReadImage::ID)
59 *thread = BrowserThread::FILE; 76 *thread = BrowserThread::FILE;
60 #endif 77 #endif
61 } 78 }
62 79
63 bool ClipboardMessageFilter::OnMessageReceived(const IPC::Message& message) { 80 bool ClipboardMessageFilter::OnMessageReceived(const IPC::Message& message) {
64 bool handled = true; 81 bool handled = true;
65 IPC_BEGIN_MESSAGE_MAP(ClipboardMessageFilter, message) 82 IPC_BEGIN_MESSAGE_MAP(ClipboardMessageFilter, message)
83 IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteObjectsAsync, OnWriteObjectsAsync)
84 IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteObjectsSync, OnWriteObjectsSync)
66 IPC_MESSAGE_HANDLER(ClipboardHostMsg_GetSequenceNumber, OnGetSequenceNumber) 85 IPC_MESSAGE_HANDLER(ClipboardHostMsg_GetSequenceNumber, OnGetSequenceNumber)
67 IPC_MESSAGE_HANDLER(ClipboardHostMsg_IsFormatAvailable, OnIsFormatAvailable) 86 IPC_MESSAGE_HANDLER(ClipboardHostMsg_IsFormatAvailable, OnIsFormatAvailable)
68 IPC_MESSAGE_HANDLER(ClipboardHostMsg_Clear, OnClear) 87 IPC_MESSAGE_HANDLER(ClipboardHostMsg_Clear, OnClear)
69 IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadAvailableTypes, 88 IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadAvailableTypes,
70 OnReadAvailableTypes) 89 OnReadAvailableTypes)
71 IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadText, OnReadText) 90 IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadText, OnReadText)
72 IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadHTML, OnReadHTML) 91 IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadHTML, OnReadHTML)
73 IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadRTF, OnReadRTF) 92 IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadRTF, OnReadRTF)
74 IPC_MESSAGE_HANDLER_DELAY_REPLY(ClipboardHostMsg_ReadImage, OnReadImage) 93 IPC_MESSAGE_HANDLER_DELAY_REPLY(ClipboardHostMsg_ReadImage, OnReadImage)
75 IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadCustomData, OnReadCustomData) 94 IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadCustomData, OnReadCustomData)
76 IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteText, OnWriteText)
77 IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteHTML, OnWriteHTML)
78 IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteSmartPasteMarker,
79 OnWriteSmartPasteMarker)
80 IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteCustomData, OnWriteCustomData)
81 IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteBookmark, OnWriteBookmark)
82 IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteImage, OnWriteImage)
83 IPC_MESSAGE_HANDLER(ClipboardHostMsg_CommitWrite, OnCommitWrite);
84 #if defined(OS_MACOSX) 95 #if defined(OS_MACOSX)
85 IPC_MESSAGE_HANDLER(ClipboardHostMsg_FindPboardWriteStringAsync, 96 IPC_MESSAGE_HANDLER(ClipboardHostMsg_FindPboardWriteStringAsync,
86 OnFindPboardWriteString) 97 OnFindPboardWriteString)
87 #endif 98 #endif
88 IPC_MESSAGE_UNHANDLED(handled = false) 99 IPC_MESSAGE_UNHANDLED(handled = false)
89 IPC_END_MESSAGE_MAP() 100 IPC_END_MESSAGE_MAP()
90 return handled; 101 return handled;
91 } 102 }
92 103
93 ClipboardMessageFilter::~ClipboardMessageFilter() { 104 ClipboardMessageFilter::~ClipboardMessageFilter() {
94 } 105 }
95 106
107 void ClipboardMessageFilter::OnWriteObjectsSync(
108 const ui::Clipboard::ObjectMap& objects,
109 base::SharedMemoryHandle bitmap_handle) {
110 DCHECK(base::SharedMemory::IsHandleValid(bitmap_handle))
111 << "Bad bitmap handle";
112
113 // On Windows, we can't write directly from the IO thread, so we copy the data
114 // into a heap allocated map and post a task to the UI thread. On other
115 // platforms, to lower the amount of time the renderer has to wait for the
116 // sync IPC to complete, we also take a copy and post a task to flush the data
117 // to the clipboard later.
118 scoped_ptr<ui::Clipboard::ObjectMap> long_living_objects(
119 new ui::Clipboard::ObjectMap(objects));
120 SanitizeObjectMap(long_living_objects.get(), kAllowBitmap);
121 // Splice the shared memory handle into the data. |long_living_objects| now
122 // contains a heap-allocated SharedMemory object that references
123 // |bitmap_handle|. This reference will keep the shared memory section alive
124 // when this IPC returns, and the SharedMemory object will eventually be
125 // freed by ui::Clipboard::WriteObjects().
126 if (!ui::Clipboard::ReplaceSharedMemHandle(
127 long_living_objects.get(), bitmap_handle, PeerHandle()))
128 return;
129
130 BrowserThread::PostTask(
131 BrowserThread::UI,
132 FROM_HERE,
133 base::Bind(&ClipboardMessageFilter::WriteObjectsOnUIThread,
134 base::Owned(long_living_objects.release())));
135 }
136
137 // On Windows, the write must be performed on the UI thread because the
138 // clipboard object from the IO thread cannot create windows so it cannot be
139 // the "owner" of the clipboard's contents. See http://crbug.com/5823.
140 // TODO(dcheng): Temporarily a member of ClipboardMessageFilter so it can access
141 // ui::Clipboard::WriteObjects().
142 void ClipboardMessageFilter::WriteObjectsOnUIThread(
143 const ui::Clipboard::ObjectMap* objects) {
144 DCHECK_CURRENTLY_ON(BrowserThread::UI);
145 static ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
146 clipboard->WriteObjects(ui::CLIPBOARD_TYPE_COPY_PASTE, *objects);
147 }
148
149 void ClipboardMessageFilter::OnWriteObjectsAsync(
150 const ui::Clipboard::ObjectMap& objects) {
151 // This async message doesn't support shared-memory based bitmaps; they must
152 // be removed otherwise we might dereference a rubbish pointer.
153 scoped_ptr<ui::Clipboard::ObjectMap> sanitized_objects(
154 new ui::Clipboard::ObjectMap(objects));
155 SanitizeObjectMap(sanitized_objects.get(), kFilterBitmap);
156
157 #if defined(OS_WIN)
158 // We cannot write directly from the IO thread, and cannot service the IPC
159 // on the UI thread. We'll copy the relevant data and post a task to preform
160 // the write on the UI thread.
161 BrowserThread::PostTask(
162 BrowserThread::UI,
163 FROM_HERE,
164 base::Bind(
165 &WriteObjectsOnUIThread, base::Owned(sanitized_objects.release())));
166 #else
167 GetClipboard()->WriteObjects(
168 ui::CLIPBOARD_TYPE_COPY_PASTE, *sanitized_objects.get());
169 #endif
170 }
171
96 void ClipboardMessageFilter::OnGetSequenceNumber(ui::ClipboardType type, 172 void ClipboardMessageFilter::OnGetSequenceNumber(ui::ClipboardType type,
97 uint64* sequence_number) { 173 uint64* sequence_number) {
98 *sequence_number = GetClipboard()->GetSequenceNumber(type); 174 *sequence_number = GetClipboard()->GetSequenceNumber(type);
99 } 175 }
100 176
101 void ClipboardMessageFilter::OnReadAvailableTypes( 177 void ClipboardMessageFilter::OnReadAvailableTypes(
102 ui::ClipboardType type, 178 ui::ClipboardType type,
103 std::vector<base::string16>* types, 179 std::vector<base::string16>* types,
104 bool* contains_filenames) { 180 bool* contains_filenames) {
105 GetClipboard()->ReadAvailableTypes(type, types, contains_filenames); 181 GetClipboard()->ReadAvailableTypes(type, types, contains_filenames);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 image_size); 279 image_size);
204 Send(reply_msg); 280 Send(reply_msg);
205 } 281 }
206 282
207 void ClipboardMessageFilter::OnReadCustomData(ui::ClipboardType clipboard_type, 283 void ClipboardMessageFilter::OnReadCustomData(ui::ClipboardType clipboard_type,
208 const base::string16& type, 284 const base::string16& type,
209 base::string16* result) { 285 base::string16* result) {
210 GetClipboard()->ReadCustomData(clipboard_type, type, result); 286 GetClipboard()->ReadCustomData(clipboard_type, type, result);
211 } 287 }
212 288
213 void ClipboardMessageFilter::OnWriteText(ui::ClipboardType clipboard_type,
214 const base::string16& text) {
215 clipboard_writer_->WriteText(text);
216 }
217
218 void ClipboardMessageFilter::OnWriteHTML(ui::ClipboardType clipboard_type,
219 const base::string16& markup,
220 const GURL& url) {
221 clipboard_writer_->WriteHTML(markup, url.spec());
222 }
223
224 void ClipboardMessageFilter::OnWriteSmartPasteMarker(
225 ui::ClipboardType clipboard_type) {
226 clipboard_writer_->WriteWebSmartPaste();
227 }
228
229 void ClipboardMessageFilter::OnWriteCustomData(
230 ui::ClipboardType clipboard_type,
231 const std::map<base::string16, base::string16>& data) {
232 Pickle pickle;
233 ui::WriteCustomDataToPickle(data, &pickle);
234 clipboard_writer_->WritePickledData(
235 pickle, ui::Clipboard::GetWebCustomDataFormatType());
236 }
237
238 void ClipboardMessageFilter::OnWriteBookmark(ui::ClipboardType clipboard_type,
239 const GURL& url,
240 const base::string16& title) {
241 clipboard_writer_->WriteBookmark(title, url.spec());
242 }
243
244 void ClipboardMessageFilter::OnWriteImage(ui::ClipboardType clipboard_type,
245 const gfx::Size& size,
246 base::SharedMemoryHandle handle) {
247 if (!base::SharedMemory::IsHandleValid(handle)) {
248 return;
249 }
250
251 scoped_ptr<base::SharedMemory> bitmap_buffer(
252 #if defined(OS_WIN)
253 new base::SharedMemory(handle, true, PeerHandle()));
254 #else
255 new base::SharedMemory(handle, true));
256 #endif
257
258 SkBitmap bitmap;
259 // Let Skia do some sanity checking for (no negative widths/heights, no
260 // overflows while calculating bytes per row, etc).
261 if (!bitmap.setInfo(SkImageInfo::MakeN32Premul(
262 size.width(), size.height()))) {
263 return;
264 }
265
266 // Make sure the size is representable as a signed 32-bit int, so
267 // SkBitmap::getSize() won't be truncated.
268 if (!sk_64_isS32(bitmap.computeSize64()))
269 return;
270
271 if (!bitmap_buffer->Map(bitmap.getSize()))
272 return;
273
274 if (!bitmap.installPixels(bitmap.info(),
275 bitmap_buffer->memory(),
276 bitmap.rowBytes(),
277 NULL,
278 &ReleaseSharedMemoryPixels,
279 bitmap_buffer.get()))
280 return;
281
282 // On success, SkBitmap now owns the SharedMemory.
283 ignore_result(bitmap_buffer.release());
284 clipboard_writer_->WriteImage(bitmap);
285 }
286
287 void ClipboardMessageFilter::OnCommitWrite(ui::ClipboardType clipboard_type) {
288 #if defined(OS_WIN)
289 // On non-Windows platforms, all clipboard IPCs are handled on the UI thread.
290 // However, Windows handles the clipboard IPCs on the IO thread to prevent
291 // deadlocks. Clipboard writes must still occur on the UI thread because the
292 // clipboard object from the IO thread cannot create windows so it cannot be
293 // the "owner" of the clipboard's contents. See http://crbug.com/5823.
294 BrowserThread::DeleteSoon(
295 BrowserThread::UI, FROM_HERE, clipboard_writer_.release());
296 #endif
297 clipboard_writer_.reset(
298 new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE));
299 }
300
301 // static 289 // static
302 ui::Clipboard* ClipboardMessageFilter::GetClipboard() { 290 ui::Clipboard* ClipboardMessageFilter::GetClipboard() {
303 // We have a static instance of the clipboard service for use by all message 291 // We have a static instance of the clipboard service for use by all message
304 // filters. This instance lives for the life of the browser processes. 292 // filters. This instance lives for the life of the browser processes.
305 static ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); 293 static ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
306 return clipboard; 294 return clipboard;
307 } 295 }
308 296
309 } // namespace content 297 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698