15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/clipboard_message_filter.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/location.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/clipboard_messages.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_context.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message_macros.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)enum BitmapPolicy {
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  kFilterBitmap,
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  kAllowBitmap,
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SanitizeObjectMap(ui::Clipboard::ObjectMap* objects,
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       BitmapPolicy bitmap_policy) {
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (bitmap_policy != kAllowBitmap)
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    objects->erase(ui::Clipboard::CBF_SMBITMAP);
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ui::Clipboard::ObjectMap::iterator data_it =
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      objects->find(ui::Clipboard::CBF_DATA);
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (data_it != objects->end()) {
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const ui::Clipboard::FormatType& web_custom_format =
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ui::Clipboard::GetWebCustomDataFormatType();
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (data_it->second.size() != 2 ||
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        !web_custom_format.Equals(
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            ui::Clipboard::FormatType::Deserialize(std::string(
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                &data_it->second[0].front(),
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                data_it->second[0].size())))) {
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // CBF_DATA should always have two parameters associated with it, and the
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // associated FormatType should always be web custom data. If not, then
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // data is malformed and we'll ignore it.
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      objects->erase(ui::Clipboard::CBF_DATA);
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ClipboardMessageFilter::ClipboardMessageFilter()
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : BrowserMessageFilter(ClipboardMsgStart) {}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClipboardMessageFilter::OverrideThreadForMessage(
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& message, BrowserThread::ID* thread) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clipboard writes should always occur on the UI thread due the restrictions
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of various platform APIs. In general, the clipboard is not thread-safe, so
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // all clipboard calls should be serviced from the UI thread.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Windows needs clipboard reads to be serviced from the IO thread because
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // these are sync IPCs which can result in deadlocks with NPAPI plugins if
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // serviced from the UI thread. Note that Windows clipboard calls ARE
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread-safe so it is ok for reads and writes to be serviced from different
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threads.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_WIN)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IPC_MESSAGE_CLASS(message) == ClipboardMsgStart)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *thread = BrowserThread::UI;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message.type() == ClipboardHostMsg_ReadImage::ID)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *thread = BrowserThread::FILE;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ClipboardMessageFilter::OnMessageReceived(const IPC::Message& message) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(ClipboardMessageFilter, message)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteObjectsAsync, OnWriteObjectsAsync)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteObjectsSync, OnWriteObjectsSync)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_GetSequenceNumber, OnGetSequenceNumber)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_IsFormatAvailable, OnIsFormatAvailable)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_Clear, OnClear)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadAvailableTypes,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnReadAvailableTypes)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadText, OnReadText)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadHTML, OnReadHTML)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadRTF, OnReadRTF)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER_DELAY_REPLY(ClipboardHostMsg_ReadImage, OnReadImage)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadCustomData, OnReadCustomData)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ClipboardHostMsg_FindPboardWriteStringAsync,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnFindPboardWriteString)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClipboardMessageFilter::~ClipboardMessageFilter() {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClipboardMessageFilter::OnWriteObjectsSync(
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const ui::Clipboard::ObjectMap& objects,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle bitmap_handle) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(base::SharedMemory::IsHandleValid(bitmap_handle))
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Bad bitmap handle";
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // On Windows, we can't write directly from the IO thread, so we copy the data
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // into a heap allocated map and post a task to the UI thread. On other
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // platforms, to lower the amount of time the renderer has to wait for the
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // sync IPC to complete, we also take a copy and post a task to flush the data
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // to the clipboard later.
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<ui::Clipboard::ObjectMap> long_living_objects(
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new ui::Clipboard::ObjectMap(objects));
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SanitizeObjectMap(long_living_objects.get(), kAllowBitmap);
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Splice the shared memory handle into the data. |long_living_objects| now
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // contains a heap-allocated SharedMemory object that references
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |bitmap_handle|. This reference will keep the shared memory section alive
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // when this IPC returns, and the SharedMemory object will eventually be
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // freed by ui::Clipboard::WriteObjects().
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!ui::Clipboard::ReplaceSharedMemHandle(
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           long_living_objects.get(), bitmap_handle, PeerHandle()))
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      base::Bind(&ClipboardMessageFilter::WriteObjectsOnUIThread,
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 base::Owned(long_living_objects.release())));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// On Windows, the write must be performed on the UI thread because the
13823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// clipboard object from the IO thread cannot create windows so it cannot be
13923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// the "owner" of the clipboard's contents. See http://crbug.com/5823.
14023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// TODO(dcheng): Temporarily a member of ClipboardMessageFilter so it can access
14123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// ui::Clipboard::WriteObjects().
14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ClipboardMessageFilter::WriteObjectsOnUIThread(
14323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const ui::Clipboard::ObjectMap* objects) {
144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  static ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
14623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  clipboard->WriteObjects(ui::CLIPBOARD_TYPE_COPY_PASTE, *objects);
14723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
14823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClipboardMessageFilter::OnWriteObjectsAsync(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ui::Clipboard::ObjectMap& objects) {
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This async message doesn't support shared-memory based bitmaps; they must
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // be removed otherwise we might dereference a rubbish pointer.
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<ui::Clipboard::ObjectMap> sanitized_objects(
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new ui::Clipboard::ObjectMap(objects));
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SanitizeObjectMap(sanitized_objects.get(), kFilterBitmap);
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We cannot write directly from the IO thread, and cannot service the IPC
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the UI thread. We'll copy the relevant data and post a task to preform
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the write on the UI thread.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          &WriteObjectsOnUIThread, base::Owned(sanitized_objects.release())));
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GetClipboard()->WriteObjects(
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ui::CLIPBOARD_TYPE_COPY_PASTE, *sanitized_objects.get());
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ClipboardMessageFilter::OnGetSequenceNumber(ui::ClipboardType type,
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                 uint64* sequence_number) {
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *sequence_number = GetClipboard()->GetSequenceNumber(type);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ClipboardMessageFilter::OnReadAvailableTypes(
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ui::ClipboardType type,
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::vector<base::string16>* types,
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool* contains_filenames) {
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GetClipboard()->ReadAvailableTypes(type, types, contains_filenames);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ClipboardMessageFilter::OnIsFormatAvailable(ClipboardFormat format,
18523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                 ui::ClipboardType type,
18623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                 bool* result) {
18723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  switch (format) {
18823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case CLIPBOARD_FORMAT_PLAINTEXT:
18923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *result = GetClipboard()->IsFormatAvailable(
19023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                    ui::Clipboard::GetPlainTextWFormatType(), type) ||
19123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                GetClipboard()->IsFormatAvailable(
19223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                    ui::Clipboard::GetPlainTextFormatType(), type);
19323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      break;
19423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case CLIPBOARD_FORMAT_HTML:
19523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *result = GetClipboard()->IsFormatAvailable(
19623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          ui::Clipboard::GetHtmlFormatType(), type);
197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      break;
19823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case CLIPBOARD_FORMAT_SMART_PASTE:
19923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *result = GetClipboard()->IsFormatAvailable(
20023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          ui::Clipboard::GetWebKitSmartPasteFormatType(), type);
201effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      break;
20223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case CLIPBOARD_FORMAT_BOOKMARK:
20323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX)
20423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *result = GetClipboard()->IsFormatAvailable(
20523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          ui::Clipboard::GetUrlWFormatType(), type);
20623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#else
20723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *result = false;
20823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#endif
209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      break;
21023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ClipboardMessageFilter::OnClear(ui::ClipboardType type) {
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GetClipboard()->Clear(type);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ClipboardMessageFilter::OnReadText(ui::ClipboardType type,
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                        base::string16* result) {
21923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (GetClipboard()->IsFormatAvailable(
22023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          ui::Clipboard::GetPlainTextWFormatType(), type)) {
22123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    GetClipboard()->ReadText(type, result);
22223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else if (GetClipboard()->IsFormatAvailable(
22323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 ui::Clipboard::GetPlainTextFormatType(), type)) {
22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    std::string ascii;
22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    GetClipboard()->ReadAsciiText(type, &ascii);
22623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    *result = base::ASCIIToUTF16(ascii);
22723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    result->clear();
22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ClipboardMessageFilter::OnReadHTML(ui::ClipboardType type,
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                        base::string16* markup,
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                        GURL* url,
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                        uint32* fragment_start,
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                        uint32* fragment_end) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string src_url_str;
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GetClipboard()->ReadHTML(type, markup, &src_url_str, fragment_start,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           fragment_end);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *url = GURL(src_url_str);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ClipboardMessageFilter::OnReadRTF(ui::ClipboardType type,
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                       std::string* result) {
2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GetClipboard()->ReadRTF(type, result);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ClipboardMessageFilter::OnReadImage(ui::ClipboardType type,
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         IPC::Message* reply_msg) {
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SkBitmap bitmap = GetClipboard()->ReadImage(type);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_X11)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &ClipboardMessageFilter::OnReadImageReply, this, bitmap, reply_msg));
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnReadImageReply(bitmap, reply_msg);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClipboardMessageFilter::OnReadImageReply(
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SkBitmap& bitmap, IPC::Message* reply_msg) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SharedMemoryHandle image_handle = base::SharedMemory::NULLHandle();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 image_size = 0;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bitmap.isNull()) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<unsigned char> png_data;
268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, &png_data)) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::SharedMemory buffer;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (buffer.CreateAndMapAnonymous(png_data.size())) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(buffer.memory(), vector_as_array(&png_data), png_data.size());
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (buffer.GiveToProcess(PeerHandle(), &image_handle)) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          image_size = png_data.size();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClipboardHostMsg_ReadImage::WriteReplyParams(reply_msg, image_handle,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               image_size);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(reply_msg);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ClipboardMessageFilter::OnReadCustomData(ui::ClipboardType clipboard_type,
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                              const base::string16& type,
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                              base::string16* result) {
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GetClipboard()->ReadCustomData(clipboard_type, type, result);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::Clipboard* ClipboardMessageFilter::GetClipboard() {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have a static instance of the clipboard service for use by all message
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // filters.  This instance lives for the life of the browser processes.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return clipboard;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
298