diff options
Diffstat (limited to 'base')
-rw-r--r-- | base/clipboard.h | 8 | ||||
-rw-r--r-- | base/clipboard_unittest.cc | 15 | ||||
-rw-r--r-- | base/clipboard_win.cc | 68 | ||||
-rw-r--r-- | base/file_util_unittest.cc | 4 |
4 files changed, 77 insertions, 18 deletions
diff --git a/base/clipboard.h b/base/clipboard.h index 64f9e3a..abaaa1b 100644 --- a/base/clipboard.h +++ b/base/clipboard.h @@ -130,6 +130,11 @@ class Clipboard { static FormatType GetCFHDropFormatType(); static FormatType GetFileDescriptorFormatType(); static FormatType GetFileContentFormatZeroType(); + + // Duplicates any remote shared memory handle embedded inside |objects| that + // was created by |process| so that it can be used by this process. + static void DuplicateRemoteHandles(base::ProcessHandle process, + ObjectMap* objects); #endif private: @@ -181,6 +186,9 @@ class Clipboard { // Mark this as mutable so const methods can still do lazy initialization. mutable HWND clipboard_owner_; + + // True if we can create a window. + bool create_window_; #elif defined(OS_LINUX) // Data is stored in the |clipboard_data_| map until it is saved to the system // clipboard. The Store* functions save data to the |clipboard_data_| map. The diff --git a/base/clipboard_unittest.cc b/base/clipboard_unittest.cc index c752b4c..18f5fbc 100644 --- a/base/clipboard_unittest.cc +++ b/base/clipboard_unittest.cc @@ -6,12 +6,27 @@ #include "base/basictypes.h" #include "base/clipboard.h" +#include "base/message_loop.h" #include "base/scoped_clipboard_writer.h" #include "base/string_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +#if defined(OS_WIN) +class ClipboardTest : public PlatformTest { + protected: + virtual void SetUp() { + message_loop_.reset(new MessageLoopForUI()); + } + virtual void TearDown() { + } + + private: + scoped_ptr<MessageLoop> message_loop_; +}; +#elif defined(OS_POSIX) typedef PlatformTest ClipboardTest; +#endif // defined(OS_WIN) TEST_F(ClipboardTest, ClearTest) { Clipboard clipboard; diff --git a/base/clipboard_win.cc b/base/clipboard_win.cc index 907a402..865a1307 100644 --- a/base/clipboard_win.cc +++ b/base/clipboard_win.cc @@ -12,6 +12,7 @@ #include "base/clipboard_util.h" #include "base/logging.h" +#include "base/message_loop.h" #include "base/string_util.h" namespace { @@ -82,7 +83,7 @@ LRESULT CALLBACK ClipboardOwnerWndProc(HWND hwnd, LPARAM lparam) { LRESULT lresult = 0; - switch(message) { + switch (message) { case WM_RENDERFORMAT: // This message comes when SetClipboardData was sent a null data handle // and now it's come time to put the data on the clipboard. @@ -122,14 +123,17 @@ HGLOBAL CreateGlobalData(const std::basic_string<charT>& str) { } // namespace -Clipboard::Clipboard() { - // make a dummy HWND to be the clipboard's owner - WNDCLASSEX wcex = {0}; - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.lpfnWndProc = ClipboardOwnerWndProc; - wcex.hInstance = GetModuleHandle(NULL); - wcex.lpszClassName = L"ClipboardOwnerWindowClass"; - ::RegisterClassEx(&wcex); +Clipboard::Clipboard() : create_window_(false) { + if (MessageLoop::current()->type() == MessageLoop::TYPE_UI) { + // Make a dummy HWND to be the clipboard's owner. + WNDCLASSEX wcex = {0}; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.lpfnWndProc = ClipboardOwnerWndProc; + wcex.hInstance = GetModuleHandle(NULL); + wcex.lpszClassName = L"ClipboardOwnerWindowClass"; + ::RegisterClassEx(&wcex); + create_window_ = true; + } clipboard_owner_ = NULL; } @@ -158,7 +162,7 @@ void Clipboard::WriteObjects(const ObjectMap& objects, WriteBitmapFromSharedMemory(&(iter->second[0].front()), &(iter->second[1].front()), process); - else + else DispatchObject(static_cast<ObjectType>(iter->first), iter->second); } } @@ -223,6 +227,7 @@ void Clipboard::WriteHyperlink(const char* title_data, } void Clipboard::WriteWebSmartPaste() { + DCHECK(clipboard_owner_); ::SetClipboardData(GetWebKitSmartPasteFormatType(), NULL); } @@ -265,13 +270,15 @@ void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) { void Clipboard::WriteBitmapFromSharedMemory(const char* bitmap_data, const char* size_data, base::ProcessHandle process) { - const base::SharedMemoryHandle* remote_bitmap_handle = - reinterpret_cast<const base::SharedMemoryHandle*>(bitmap_data); const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data); - base::SharedMemory bitmap(*remote_bitmap_handle, false, process); + // bitmap_data has an encoded shared memory object. See + // DuplicateRemoteHandles(). + char* ptr = const_cast<char*>(bitmap_data); + scoped_ptr<const base::SharedMemory> bitmap(* + reinterpret_cast<const base::SharedMemory**>(ptr)); - // TODO(darin): share data in gfx/bitmap_header.cc somehow + // TODO(darin): share data in gfx/bitmap_header.cc somehow. BITMAPINFO bm_info = {0}; bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bm_info.bmiHeader.biWidth = size->width(); @@ -286,7 +293,7 @@ void Clipboard::WriteBitmapFromSharedMemory(const char* bitmap_data, // a memcpy. HBITMAP source_hbitmap = ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, NULL, - bitmap.handle(), 0); + bitmap->handle(), 0); if (source_hbitmap) { // Now we can write the HBITMAP to the clipboard @@ -364,8 +371,11 @@ void Clipboard::WriteFiles(const char* file_data, size_t file_len) { } void Clipboard::WriteToClipboard(FormatType format, HANDLE handle) { - if (handle && !::SetClipboardData(format, handle)) + DCHECK(clipboard_owner_); + if (handle && !::SetClipboardData(format, handle)) { + DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError()); FreeData(format, handle); + } } bool Clipboard::IsFormatAvailable(unsigned int format) const { @@ -591,6 +601,30 @@ Clipboard::FormatType Clipboard::GetFileContentFormatZeroType() { } // static +void Clipboard::DuplicateRemoteHandles(base::ProcessHandle process, + ObjectMap* objects) { + for (ObjectMap::iterator iter = objects->begin(); iter != objects->end(); + ++iter) { + if (iter->first == CBF_SMBITMAP) { + // There is a shared memory handle encoded on the first ObjectMapParam. + // Use it to open a local handle to the memory. + char* bitmap_data = &(iter->second[0].front()); + base::SharedMemoryHandle* remote_bitmap_handle = + reinterpret_cast<base::SharedMemoryHandle*>(bitmap_data); + + base::SharedMemory* bitmap = new base::SharedMemory(*remote_bitmap_handle, + false, process); + + // We store the object where the remote handle was located so it can + // be retrieved by the UI thread (see WriteBitmapFromSharedMemory()). + iter->second[0].clear(); + for (size_t i = 0; i < sizeof(bitmap); i++) + iter->second[0].push_back(reinterpret_cast<char*>(&bitmap)[i]); + } + } +} + +// static Clipboard::FormatType Clipboard::GetWebKitSmartPasteFormatType() { return ClipboardUtil::GetWebKitSmartPasteFormat()->cfFormat; } @@ -604,7 +638,7 @@ void Clipboard::FreeData(FormatType format, HANDLE data) { } HWND Clipboard::GetClipboardWindow() const { - if (!clipboard_owner_) { + if (!clipboard_owner_ && create_window_) { clipboard_owner_ = ::CreateWindow(L"ClipboardOwnerWindowClass", L"ClipboardOwnerWindow", 0, 0, 0, 0, 0, diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc index 8f5ce19..98c2032 100644 --- a/base/file_util_unittest.cc +++ b/base/file_util_unittest.cc @@ -984,7 +984,9 @@ TEST_F(FileUtilTest, Contains) { data_dir = data_dir.Append(FILE_PATH_LITERAL("FilePathTest")); // Create a fresh, empty copy of this directory. - ASSERT_TRUE(file_util::Delete(data_dir, true)); + if (file_util::PathExists(data_dir)) { + ASSERT_TRUE(file_util::Delete(data_dir, true)); + } ASSERT_TRUE(file_util::CreateDirectory(data_dir)); FilePath foo(data_dir.Append(FILE_PATH_LITERAL("foo"))); |