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 "ui/base/clipboard/clipboard.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtk/gtk.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/Xfixes.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xatom.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/clipboard/custom_data_helper.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gtk/gtk_signal.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/x11_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/gtk_util.h"
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/scoped_gobject.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SelectionChangeObserver {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SelectionChangeObserver* GetInstance();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 clipboard_sequence_number() const {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return clipboard_sequence_number_;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 primary_sequence_number() const { return primary_sequence_number_; }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct DefaultSingletonTraits<SelectionChangeObserver>;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectionChangeObserver();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~SelectionChangeObserver();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHROMEG_CALLBACK_1(SelectionChangeObserver, GdkFilterReturn, OnXEvent,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     GdkXEvent*, GdkEvent*);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int event_base_;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atom clipboard_atom_;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 clipboard_sequence_number_;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 primary_sequence_number_;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SelectionChangeObserver);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectionChangeObserver::SelectionChangeObserver()
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : event_base_(-1),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clipboard_atom_(None),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clipboard_sequence_number_(0),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      primary_sequence_number_(0) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ignored;
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (XFixesQueryExtension(gfx::GetXDisplay(), &event_base_, &ignored)) {
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    clipboard_atom_ = XInternAtom(gfx::GetXDisplay(), "CLIPBOARD", false);
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               clipboard_atom_,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               XFixesSetSelectionOwnerNotifyMask |
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               XFixesSelectionWindowDestroyNotifyMask |
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               XFixesSelectionClientCloseNotifyMask);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This seems to be semi-optional. For some reason, registering for any
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // selection notify events seems to subscribe us to events for both the
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // primary and the clipboard buffers. Register anyway just to be safe.
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               XA_PRIMARY,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               XFixesSetSelectionOwnerNotifyMask |
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               XFixesSelectionWindowDestroyNotifyMask |
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               XFixesSelectionClientCloseNotifyMask);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gdk_window_add_filter(NULL, &SelectionChangeObserver::OnXEventThunk, this);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectionChangeObserver::~SelectionChangeObserver() {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectionChangeObserver* SelectionChangeObserver::GetInstance() {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<SelectionChangeObserver>::get();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GdkFilterReturn SelectionChangeObserver::OnXEvent(GdkXEvent* xevent,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  GdkEvent* event) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XEvent* xev = static_cast<XEvent*>(xevent);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (xev->type == event_base_ + XFixesSelectionNotify) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFixesSelectionNotifyEvent* ev =
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<XFixesSelectionNotifyEvent*>(xev);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ev->selection == clipboard_atom_) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clipboard_sequence_number_++;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (ev->selection == XA_PRIMARY) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      primary_sequence_number_++;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(ERROR) << "Unexpected selection atom: " << ev->selection;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GDK_FILTER_CONTINUE;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMimeTypeBitmap[] = "image/bmp";
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMimeTypeMozillaURL[] = "text/x-moz-url";
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data";
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste";
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GdkAtomToString(const GdkAtom& atom) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gchar* name = gdk_atom_name(atom);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string rv(name);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_free(name);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GdkAtom StringToGdkAtom(const std::string& str) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gdk_atom_intern(str.c_str(), FALSE);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GtkClipboardGetFunc callback.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GTK will call this when an application wants data we copied to the clipboard.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetData(GtkClipboard* clipboard,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             GtkSelectionData* selection_data,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             guint info,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             gpointer user_data) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Clipboard::TargetMap* data_map =
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<Clipboard::TargetMap*>(user_data);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string target_string = GdkAtomToString(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gtk_selection_data_get_target(selection_data));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Clipboard::TargetMap::iterator iter = data_map->find(target_string);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == data_map->end())
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (target_string == kMimeTypeBitmap) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gtk_selection_data_set_pixbuf(selection_data,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<GdkPixbuf*>(iter->second.first));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gtk_selection_data_set(selection_data,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           gtk_selection_data_get_target(selection_data), 8,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           reinterpret_cast<guchar*>(iter->second.first),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           iter->second.second);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GtkClipboardClearFunc callback.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We are guaranteed this will be called exactly once for each call to
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gtk_clipboard_set_with_data.
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClearData(GtkClipboard* /*clipboard*/,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               gpointer user_data) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Clipboard::TargetMap* map =
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<Clipboard::TargetMap*>(user_data);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The same data may be inserted under multiple keys, so use a set to
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // uniq them.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<char*> ptrs;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Clipboard::TargetMap::iterator iter = map->begin();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != map->end(); ++iter) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (iter->first == kMimeTypeBitmap)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_object_unref(reinterpret_cast<GdkPixbuf*>(iter->second.first));
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ptrs.insert(iter->second.first);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<char*>::iterator iter = ptrs.begin();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != ptrs.end(); ++iter) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete[] *iter;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete map;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Clipboard::FormatType::FormatType() : data_(GDK_NONE) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Clipboard::FormatType::FormatType(const std::string& format_string)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : data_(StringToGdkAtom(format_string)) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Clipboard::FormatType::FormatType(const GdkAtom& native_format)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : data_(native_format) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Clipboard::FormatType::~FormatType() {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Clipboard::FormatType::Serialize() const {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GdkAtomToString(data_);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Clipboard::FormatType Clipboard::FormatType::Deserialize(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& serialization) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FormatType(serialization);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Clipboard::FormatType::Equals(const FormatType& other) const {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data_ == other.data_;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Clipboard::Clipboard() : clipboard_data_(NULL) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  primary_selection_ = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Clipboard::~Clipboard() {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_clipboard_store(clipboard_);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Clipboard::WriteObjects(ClipboardType type, const ObjectMap& objects) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clipboard_data_ = new TargetMap();
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ObjectMap::const_iterator iter = objects.begin();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != objects.end(); ++iter) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SetGtkClipboard(type);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (type == CLIPBOARD_TYPE_COPY_PASTE) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ObjectMap::const_iterator text_iter = objects.find(CBF_TEXT);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (text_iter != objects.end()) {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Copy text and SourceTag to the selection clipboard.
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ObjectMap::const_iterator next_iter = text_iter;
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      WriteObjects(CLIPBOARD_TYPE_SELECTION, ObjectMap(text_iter, ++next_iter));
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Take ownership of the GTK clipboard and inform it of the targets we support.
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Clipboard::SetGtkClipboard(ClipboardType type) {
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<GtkTargetEntry[]> targets(
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new GtkTargetEntry[clipboard_data_->size()]);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i = 0;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Clipboard::TargetMap::iterator iter = clipboard_data_->begin();
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != clipboard_data_->end(); ++iter, ++i) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    targets[i].target = const_cast<char*>(iter->first.c_str());
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    targets[i].flags = 0;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    targets[i].info = 0;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GtkClipboard *clipboard = LookupBackingClipboard(type);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (gtk_clipboard_set_with_data(clipboard, targets.get(),
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  clipboard_data_->size(),
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  GetData, ClearData,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  clipboard_data_)) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gtk_clipboard_set_can_store(clipboard,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                targets.get(),
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                clipboard_data_->size());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // clipboard_data_ now owned by the GtkClipboard.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clipboard_data_ = NULL;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Clipboard::WriteText(const char* text_data, size_t text_len) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* data = new char[text_len];
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(data, text_data, text_len);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertMapping(kMimeTypeText, data, text_len);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertMapping("TEXT", data, text_len);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertMapping("STRING", data, text_len);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertMapping("UTF8_STRING", data, text_len);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertMapping("COMPOUND_TEXT", data, text_len);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Clipboard::WriteHTML(const char* markup_data,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          size_t markup_len,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char* url_data,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          size_t url_len) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(estade): We need to expand relative links with |url_data|.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* html_prefix = "<meta http-equiv=\"content-type\" "
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   "content=\"text/html; charset=utf-8\">";
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t html_prefix_len = strlen(html_prefix);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t total_len = html_prefix_len + markup_len + 1;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* data = new char[total_len];
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snprintf(data, total_len, "%s", html_prefix);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(data + html_prefix_len, markup_data, markup_len);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some programs expect NULL-terminated data. See http://crbug.com/42624
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data[total_len - 1] = '\0';
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertMapping(kMimeTypeHTML, data, total_len);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteData(GetRtfFormatType(), rtf_data, data_len);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Write an extra flavor that signifies WebKit was the last to modify the
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pasteboard. This flavor has no data.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Clipboard::WriteWebSmartPaste() {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertMapping(kMimeTypeWebkitSmartPaste, NULL, 0);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Clipboard::WriteBitmap(const SkBitmap& bitmap) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(bitmap);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We store the GdkPixbuf*, and the size_t half of the pair is meaningless.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that this contrasts with the vast majority of entries in our target
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // map, which directly store the data and its length.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertMapping(kMimeTypeBitmap, reinterpret_cast<char*>(pixbuf), 0);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Clipboard::WriteBookmark(const char* title_data, size_t title_len,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const char* url_data, size_t url_len) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write as a mozilla url (UTF16: URL, newline, title).
320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 url = UTF8ToUTF16(std::string(url_data, url_len) + "\n");
321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 title = UTF8ToUTF16(std::string(title_data, title_len));
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (title.length() >= std::numeric_limits<size_t>::max() / 4 ||
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url.length() >= std::numeric_limits<size_t>::max() / 4)
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t data_len = 2 * (title.length() + url.length());
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* data = new char[data_len];
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(data, url.data(), 2 * url.length());
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(data + 2 * url.length(), title.data(), 2 * title.length());
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertMapping(kMimeTypeMozillaURL, data, data_len);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Clipboard::WriteData(const FormatType& format,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char* data_data,
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          size_t data_len) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume that certain mapping types are only written by trusted code.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Therefore we must upkeep their integrity.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (format.Equals(GetBitmapFormatType()))
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* data = new char[data_len];
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(data, data_data, data_len);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(dcheng): Maybe this map should use GdkAtoms...
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertMapping(GdkAtomToString(format.ToGdkAtom()).c_str(), data, data_len);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We do not use gtk_clipboard_wait_is_target_available because of
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a bug with the gtk clipboard. It caches the available targets
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and does not always refresh the cache when it is appropriate.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format,
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                  ClipboardType type) const {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GtkClipboard* clipboard = LookupBackingClipboard(type);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (clipboard == NULL)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool retval = false;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GtkSelectionData* data = gtk_clipboard_wait_for_contents(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clipboard, gdk_atom_intern_static_string("TARGETS"));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool format_is_plain_text = GetPlainTextFormatType().Equals(format);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (format_is_plain_text) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This tries a number of common text targets.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      retval = gtk_selection_data_targets_include_text(data);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Some programs like Java decide to set an empty TARGETS list, so even if
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // data is not NULL, we still have to fall back.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!retval) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Some programs post data to the clipboard without any targets. If this
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // is the case we attempt to make sense of the contents as text. This is
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // pretty unfortunate since it means we have to actually copy the data to
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // see if it is available, but at least this path shouldn't be hit for
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // conforming programs.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gchar* text = gtk_clipboard_wait_for_text(clipboard);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (text) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g_free(text);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        retval = true;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (data) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GdkAtom* targets = NULL;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num = 0;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gtk_selection_data_get_targets(data, &targets, &num);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < num; i++) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (targets[i] == format.ToGdkAtom()) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        retval = true;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_free(targets);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gtk_selection_data_free(data);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return retval;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Clipboard::Clear(ClipboardType type) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GtkClipboard* clipboard = LookupBackingClipboard(type);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (clipboard == NULL)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_clipboard_clear(clipboard);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Clipboard::ReadAvailableTypes(ClipboardType type,
410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   std::vector<base::string16>* types,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   bool* contains_filenames) const {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!types || !contains_filenames) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  types->clear();
4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (IsFormatAvailable(GetPlainTextFormatType(), type))
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    types->push_back(UTF8ToUTF16(kMimeTypeText));
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (IsFormatAvailable(GetHtmlFormatType(), type))
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    types->push_back(UTF8ToUTF16(kMimeTypeHTML));
4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (IsFormatAvailable(GetRtfFormatType(), type))
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    types->push_back(UTF8ToUTF16(kMimeTypeRTF));
4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (IsFormatAvailable(GetBitmapFormatType(), type))
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    types->push_back(UTF8ToUTF16(kMimeTypePNG));
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *contains_filenames = false;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GtkClipboard* clipboard = LookupBackingClipboard(type);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!clipboard)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GtkSelectionData* data = gtk_clipboard_wait_for_contents(
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clipboard, GetWebCustomDataFormatType().ToGdkAtom());
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadCustomDataTypes(gtk_selection_data_get_data(data),
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      gtk_selection_data_get_length(data),
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      types);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_selection_data_free(data);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void Clipboard::ReadText(ClipboardType type, base::string16* result) const {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GtkClipboard* clipboard = LookupBackingClipboard(type);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (clipboard == NULL)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->clear();
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gchar* text = gtk_clipboard_wait_for_text(clipboard);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (text == NULL)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(estade): do we want to handle the possible error here?
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UTF8ToUTF16(text, strlen(text), result);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_free(text);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Clipboard::ReadAsciiText(ClipboardType type,
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              std::string* result) const {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GtkClipboard* clipboard = LookupBackingClipboard(type);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (clipboard == NULL)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->clear();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gchar* text = gtk_clipboard_wait_for_text(clipboard);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (text == NULL)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->assign(text);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_free(text);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(estade): handle different charsets.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(port): set *src_url.
4804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Clipboard::ReadHTML(ClipboardType type,
481a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         base::string16* markup,
4824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                         std::string* src_url,
4834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                         uint32* fragment_start,
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         uint32* fragment_end) const {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  markup->clear();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (src_url)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    src_url->clear();
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *fragment_start = 0;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *fragment_end = 0;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GtkClipboard* clipboard = LookupBackingClipboard(type);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (clipboard == NULL)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetHtmlFormatType().ToGdkAtom());
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UTF-16, otherwise assume UTF-8.
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gint data_length = gtk_selection_data_get_length(data);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const guchar* raw_data = gtk_selection_data_get_data(data);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data_length >= 2 &&
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const uint16_t*>(raw_data)[0] == 0xFEFF) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    markup->assign(reinterpret_cast<const uint16_t*>(raw_data) + 1,
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   (data_length / 2) - 1);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UTF8ToUTF16(reinterpret_cast<const char*>(raw_data), data_length, markup);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is a terminating NULL, drop it.
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!markup->empty() && markup->at(markup->length() - 1) == '\0')
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    markup->resize(markup->length() - 1);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *fragment_start = 0;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(markup->length() <= kuint32max);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *fragment_end = static_cast<uint32>(markup->length());
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_selection_data_free(data);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Clipboard::ReadRTF(ClipboardType type, std::string* result) const {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadData(GetRtfFormatType(), result);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)SkBitmap Clipboard::ReadImage(ClipboardType type) const {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedGObject<GdkPixbuf>::Type pixbuf(
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gtk_clipboard_wait_for_image(clipboard_));
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pixbuf.get())
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkBitmap();
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Canvas canvas(gfx::Size(gdk_pixbuf_get_width(pixbuf.get()),
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               gdk_pixbuf_get_height(pixbuf.get())),
53968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     1.0f, false);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_t* context = scoped_platform_paint.GetPlatformSurface();
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gdk_cairo_set_source_pixbuf(context, pixbuf.get(), 0.0, 0.0);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_paint(context);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return canvas.ExtractImageRep().sk_bitmap();
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Clipboard::ReadCustomData(ClipboardType clipboard_type,
550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               const base::string16& type,
551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               base::string16* result) const {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GtkClipboard* clipboard = LookupBackingClipboard(clipboard_type);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!clipboard)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GtkSelectionData* data = gtk_clipboard_wait_for_contents(
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clipboard, GetWebCustomDataFormatType().ToGdkAtom());
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadCustomDataForType(gtk_selection_data_get_data(data),
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        gtk_selection_data_get_length(data),
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        type, result);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_selection_data_free(data);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
567a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void Clipboard::ReadBookmark(base::string16* title, std::string* url) const {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(estade): implement this.
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Clipboard::ReadData(const FormatType& format, std::string* result) const {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->clear();
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GtkSelectionData* data =
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      gtk_clipboard_wait_for_contents(clipboard_, format.ToGdkAtom());
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->assign(reinterpret_cast<const char*>(
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     gtk_selection_data_get_data(data)),
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 gtk_selection_data_get_length(data));
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_selection_data_free(data);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)uint64 Clipboard::GetSequenceNumber(ClipboardType type) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (type == CLIPBOARD_TYPE_COPY_PASTE)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SelectionChangeObserver::GetInstance()->clipboard_sequence_number();
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SelectionChangeObserver::GetInstance()->primary_sequence_number();
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//static
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Clipboard::FormatType Clipboard::GetFormatType(
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& format_string) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FormatType::Deserialize(format_string);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FormatType, type, (GDK_TARGET_STRING));
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return type;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetPlainTextFormatType();
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetPlainTextFormatType();
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetPlainTextWFormatType();
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeHTML));
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return type;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeRTF));
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return type;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeBitmap));
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return type;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebkitSmartPaste));
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return type;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData));
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return type;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData));
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return type;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Clipboard::InsertMapping(const char* key,
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              char* data,
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              size_t data_len) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(clipboard_data_->find(key) == clipboard_data_->end());
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*clipboard_data_)[key] = std::make_pair(data, data_len);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)GtkClipboard* Clipboard::LookupBackingClipboard(ClipboardType type) const {
6654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  switch (type) {
6664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case CLIPBOARD_TYPE_COPY_PASTE:
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return clipboard_;
6684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case CLIPBOARD_TYPE_SELECTION:
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return primary_selection_;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
677