This source file includes following definitions.
- ValidateAndMapSharedBitmap
- SetAllowedThreads
- GetForCurrentThread
- DestroyClipboardForCurrentThread
- DispatchObject
- ReplaceSharedMemHandle
#include "ui/base/clipboard/clipboard.h"
#include <iterator>
#include <limits>
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/size.h"
namespace ui {
namespace {
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;
}
typedef std::vector<base::PlatformThreadId> AllowedThreadsVector;
static base::LazyInstance<AllowedThreadsVector> g_allowed_threads =
LAZY_INSTANCE_INITIALIZER;
typedef std::map<base::PlatformThreadId, Clipboard*> ClipboardMap;
static base::LazyInstance<ClipboardMap> g_clipboard_map =
LAZY_INSTANCE_INITIALIZER;
static base::LazyInstance<base::Lock>::Leaky
g_clipboard_map_lock = LAZY_INSTANCE_INITIALIZER;
}
void Clipboard::SetAllowedThreads(
const std::vector<base::PlatformThreadId>& allowed_threads) {
base::AutoLock lock(g_clipboard_map_lock.Get());
g_allowed_threads.Get().clear();
std::copy(allowed_threads.begin(), allowed_threads.end(),
std::back_inserter(g_allowed_threads.Get()));
}
Clipboard* Clipboard::GetForCurrentThread() {
base::AutoLock lock(g_clipboard_map_lock.Get());
base::PlatformThreadId id = base::PlatformThread::CurrentId();
AllowedThreadsVector* allowed_threads = g_allowed_threads.Pointer();
if (!allowed_threads->empty()) {
bool found = false;
for (AllowedThreadsVector::const_iterator it = allowed_threads->begin();
it != allowed_threads->end(); ++it) {
if (*it == id) {
found = true;
break;
}
}
DCHECK(found);
}
ClipboardMap* clipboard_map = g_clipboard_map.Pointer();
ClipboardMap::iterator it = clipboard_map->find(id);
if (it != clipboard_map->end())
return it->second;
Clipboard* clipboard = new ui::Clipboard;
clipboard_map->insert(std::make_pair(id, clipboard));
return clipboard;
}
void Clipboard::DestroyClipboardForCurrentThread() {
base::AutoLock lock(g_clipboard_map_lock.Get());
ClipboardMap* clipboard_map = g_clipboard_map.Pointer();
base::PlatformThreadId id = base::PlatformThread::CurrentId();
ClipboardMap::iterator it = clipboard_map->find(id);
if (it != clipboard_map->end()) {
delete it->second;
clipboard_map->erase(it);
}
}
void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
if (type != CBF_WEBKIT && (params.empty() || params[0].empty()))
return;
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());
break;
case CBF_HTML:
if (params.size() == 2) {
if (params[1].empty())
return;
WriteHTML(&(params[0].front()), params[0].size(),
&(params[1].front()), params[1].size());
} else if (params.size() == 1) {
WriteHTML(&(params[0].front()), params[0].size(), NULL, 0);
}
break;
case CBF_RTF:
WriteRTF(&(params[0].front()), params[0].size());
break;
case CBF_BOOKMARK:
WriteBookmark(&(params[0].front()), params[0].size(),
&(params[1].front()), params[1].size());
break;
case CBF_WEBKIT:
WriteWebSmartPaste();
break;
case CBF_SMBITMAP: {
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());
if (!bitmap.setConfig(SkBitmap::kARGB_8888_Config,
unvalidated_size->width(),
unvalidated_size->height())) {
return;
}
if (!sk_64_isS32(bitmap.computeSize64()))
return;
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;
}
case CBF_DATA:
WriteData(
FormatType::Deserialize(
std::string(&(params[0].front()), params[0].size())),
&(params[1].front()),
params[1].size());
break;
default:
NOTREACHED();
}
}
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) {
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
if (iter->second.size() != 2)
return false;
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;
}
}