summaryrefslogtreecommitdiffstats
path: root/app/clipboard/clipboard.cc
diff options
context:
space:
mode:
authorjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-27 10:24:59 +0000
committerjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-27 10:24:59 +0000
commite344c910c5f4a1c88e3da37e074873a6360f3624 (patch)
tree4c3717fd77e4fcd62fbcb5da37cfe10ca25146fe /app/clipboard/clipboard.cc
parent98e053c3baec827f9177a429e46abe36cd4fb9f2 (diff)
downloadchromium_src-e344c910c5f4a1c88e3da37e074873a6360f3624.zip
chromium_src-e344c910c5f4a1c88e3da37e074873a6360f3624.tar.gz
chromium_src-e344c910c5f4a1c88e3da37e074873a6360f3624.tar.bz2
POSIX: Use Shared Mem transport to copy images.
Prior to this change images where copied inline in IPC messages on non-Windows platforms. Copying an oversized image would cause the IPC system to bork and crash the renderer. Changes in this CL: * All platforms use a unified mechanism to copy images using shared memory. * Introduced a new IPC message so the renderer can allocated a shared memory segment on OS X. * On OS X tried to keep as few copies of the image data in memory as possible. BUG=26822 TEST=1)On all platforms: navigate to a webpage, right click on an image and copy. Then try pasting into an image editor. 2)Repro steps in bug should no longer crash the Renderer on Mac/Linux Review URL: http://codereview.chromium.org/552129 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37247 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app/clipboard/clipboard.cc')
-rw-r--r--app/clipboard/clipboard.cc108
1 files changed, 104 insertions, 4 deletions
diff --git a/app/clipboard/clipboard.cc b/app/clipboard/clipboard.cc
index a2050a0..54a7d90 100644
--- a/app/clipboard/clipboard.cc
+++ b/app/clipboard/clipboard.cc
@@ -6,11 +6,22 @@
#include "base/gfx/size.h"
#include "base/logging.h"
+#include "base/scoped_ptr.h"
namespace {
// A compromised renderer could send us bad data, so validate it.
-bool IsBitmapSafe(const Clipboard::ObjectMapParams& params) {
+// This function only checks that the size parameter makes sense, the caller
+// is responsible for further validating the bitmap buffer against
+// |bitmap_bytes|.
+//
+// |params| - Clipboard bitmap contents to validate.
+// |bitmap_bytes| - On return contains the number of bytes needed to store
+// the bitmap data or -1 if the data is invalid.
+// returns: true if the bitmap size is valid, false otherwise.
+bool IsBitmapSafe(const Clipboard::ObjectMapParams& params,
+ size_t* bitmap_bytes) {
+ *bitmap_bytes = -1;
if (params[1].size() != sizeof(gfx::Size))
return false;
const gfx::Size* size =
@@ -23,7 +34,40 @@ bool IsBitmapSafe(const Clipboard::ObjectMapParams& params) {
if (INT_MAX / total_size <= 4)
return false;
total_size *= 4;
- return params[0].size() == total_size;
+ *bitmap_bytes = total_size;
+ return true;
+}
+
+// Validates a plain bitmap on the clipboard.
+// Returns true if the clipboard data makes sense and it's safe to access the
+// bitmap.
+bool ValidatePlainBitmap(const Clipboard::ObjectMapParams& params) {
+ size_t bitmap_bytes = -1;
+ if (!IsBitmapSafe(params, &bitmap_bytes))
+ return false;
+ if (bitmap_bytes != params[0].size())
+ return false;
+ return true;
+}
+
+// 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(const Clipboard::ObjectMapParams& params,
+ base::SharedMemory* bitmap_data) {
+ using base::SharedMemory;
+ size_t bitmap_bytes = -1;
+ if (!IsBitmapSafe(params, &bitmap_bytes))
+ return false;
+
+ 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
@@ -33,7 +77,8 @@ void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
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_BITMAP || type == CBF_DATA) &&
+ if ((type == CBF_BOOKMARK || type == CBF_BITMAP ||
+ type == CBF_SMBITMAP || type == CBF_DATA) &&
(params.size() != 2 || params[1].empty()))
return;
switch (type) {
@@ -62,11 +107,34 @@ void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
break;
case CBF_BITMAP:
- if (!IsBitmapSafe(params))
+ if (!ValidatePlainBitmap(params))
return;
+
WriteBitmap(&(params[0].front()), &(params[1].front()));
break;
+ case CBF_SMBITMAP: {
+ using base::SharedMemory;
+ using base::SharedMemoryHandle;
+
+ if (params[0].size() != sizeof(SharedMemory*))
+ 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*>(&(params[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(params, bitmap_data.get()))
+ return;
+ WriteBitmap(static_cast<const char*>(bitmap_data->memory()),
+ &(params[1].front()));
+ break;
+ }
+
#if !defined(OS_MACOSX)
case CBF_DATA:
WriteData(&(params[0].front()), params[0].size(),
@@ -78,3 +146,35 @@ void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
NOTREACHED();
}
}
+
+// static
+void 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 hard if we ever encounter more than one shared bitmap structure to
+ // fill.
+ CHECK(!has_shared_bitmap);
+
+#if defined(OS_WIN)
+ SharedMemory* bitmap = new SharedMemory(bitmap_handle, true, process);
+#else
+ SharedMemory* bitmap = new SharedMemory(bitmap_handle, true);
+#endif
+
+ // 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;
+ }
+ }
+}
+