| Index: ui/base/clipboard/clipboard.cc
|
| diff --git a/ui/base/clipboard/clipboard.cc b/ui/base/clipboard/clipboard.cc
|
| index 953ebb4d7e6dcf909d515a65abb234fab827284f..0bd542d563a9a66cb3955b062ab7695380b63958 100644
|
| --- a/ui/base/clipboard/clipboard.cc
|
| +++ b/ui/base/clipboard/clipboard.cc
|
| @@ -13,6 +13,27 @@
|
| #include "ui/gfx/size.h"
|
|
|
| namespace ui {
|
| +
|
| +namespace {
|
| +
|
| +// Valides a shared bitmap on the clipboard.
|
| +// Returns true if the clipboard data makes sense and it's safe to access the
|
| +// bitmap.
|
| +bool ValidateAndMapSharedBitmap(size_t bitmap_bytes,
|
| + base::SharedMemory* bitmap_data) {
|
| + using base::SharedMemory;
|
| +
|
| + if (!bitmap_data || !SharedMemory::IsHandleValid(bitmap_data->handle()))
|
| + return false;
|
| +
|
| + if (!bitmap_data->Map(bitmap_bytes)) {
|
| + PLOG(ERROR) << "Failed to map bitmap memory";
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
|
|
| base::LazyInstance<Clipboard::AllowedThreadsVector>
|
| Clipboard::allowed_threads_ = LAZY_INSTANCE_INITIALIZER;
|
| @@ -74,6 +95,13 @@
|
| }
|
|
|
| void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
|
| + // All types apart from CBF_WEBKIT need at least 1 non-empty param.
|
| + if (type != CBF_WEBKIT && (params.empty() || params[0].empty()))
|
| + return;
|
| + // Some other types need a non-empty 2nd param.
|
| + if ((type == CBF_BOOKMARK || type == CBF_SMBITMAP || type == CBF_DATA) &&
|
| + (params.size() != 2 || params[1].empty()))
|
| + return;
|
| switch (type) {
|
| case CBF_TEXT:
|
| WriteText(&(params[0].front()), params[0].size());
|
| @@ -104,13 +132,41 @@
|
| break;
|
|
|
| case CBF_SMBITMAP: {
|
| - // Usually, the params are just UTF-8 strings. However, for images,
|
| - // ScopedClipboardWriter actually sizes the buffer to sizeof(SkBitmap*),
|
| - // aliases the contents of the vector to a SkBitmap**, and writes the
|
| - // pointer to the actual SkBitmap in the clipboard object param.
|
| - const char* packed_pointer_buffer = ¶ms[0].front();
|
| - WriteBitmap(
|
| - **reinterpret_cast<SkBitmap* const*>(packed_pointer_buffer));
|
| + using base::SharedMemory;
|
| + using base::SharedMemoryHandle;
|
| +
|
| + if (params[0].size() != sizeof(SharedMemory*) ||
|
| + params[1].size() != sizeof(gfx::Size)) {
|
| + return;
|
| + }
|
| +
|
| + SkBitmap bitmap;
|
| + const gfx::Size* unvalidated_size =
|
| + reinterpret_cast<const gfx::Size*>(¶ms[1].front());
|
| + // Let Skia do some sanity checking for us (no negative widths/heights, no
|
| + // overflows while calculating bytes per row, etc).
|
| + if (!bitmap.setInfo(SkImageInfo::MakeN32Premul(
|
| + unvalidated_size->width(), unvalidated_size->height()))) {
|
| + return;
|
| + }
|
| + // Make sure the size is representable as a signed 32-bit int, so
|
| + // SkBitmap::getSize() won't be truncated.
|
| + if (!sk_64_isS32(bitmap.computeSize64()))
|
| + return;
|
| +
|
| + // It's OK to cast away constness here since we map the handle as
|
| + // read-only.
|
| + const char* raw_bitmap_data_const =
|
| + reinterpret_cast<const char*>(¶ms[0].front());
|
| + char* raw_bitmap_data = const_cast<char*>(raw_bitmap_data_const);
|
| + scoped_ptr<SharedMemory> bitmap_data(
|
| + *reinterpret_cast<SharedMemory**>(raw_bitmap_data));
|
| +
|
| + if (!ValidateAndMapSharedBitmap(bitmap.getSize(), bitmap_data.get()))
|
| + return;
|
| + bitmap.setPixels(bitmap_data->memory());
|
| +
|
| + WriteBitmap(bitmap);
|
| break;
|
| }
|
|
|
| @@ -127,4 +183,40 @@
|
| }
|
| }
|
|
|
| +// static
|
| +bool Clipboard::ReplaceSharedMemHandle(ObjectMap* objects,
|
| + base::SharedMemoryHandle bitmap_handle,
|
| + base::ProcessHandle process) {
|
| + using base::SharedMemory;
|
| + bool has_shared_bitmap = false;
|
| +
|
| + for (ObjectMap::iterator iter = objects->begin(); iter != objects->end();
|
| + ++iter) {
|
| + if (iter->first == CBF_SMBITMAP) {
|
| + // The code currently only accepts sending a single bitmap over this way.
|
| + // Fail if we ever encounter more than one shmem bitmap structure to fill.
|
| + if (has_shared_bitmap)
|
| + return false;
|
| +
|
| +#if defined(OS_WIN)
|
| + SharedMemory* bitmap = new SharedMemory(bitmap_handle, true, process);
|
| +#else
|
| + SharedMemory* bitmap = new SharedMemory(bitmap_handle, true);
|
| +#endif
|
| +
|
| + // There must always be two parameters associated with each shmem bitmap.
|
| + if (iter->second.size() != 2)
|
| + return false;
|
| +
|
| + // We store the shared memory object pointer so it can be retrieved by the
|
| + // UI thread (see DispatchObject()).
|
| + iter->second[0].clear();
|
| + for (size_t i = 0; i < sizeof(SharedMemory*); ++i)
|
| + iter->second[0].push_back(reinterpret_cast<char*>(&bitmap)[i]);
|
| + has_shared_bitmap = true;
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| } // namespace ui
|
|
|