summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-12 21:58:18 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-12 21:58:18 +0000
commit8c3dc79bc13ba84f418d3c135e1bf296a3e29722 (patch)
tree32eb9688d500a90eb74a7c4f8cb5a97e507dd0fc /app
parentabaccb2cb8cff8138e5ea9daf420645e5852c9eb (diff)
downloadchromium_src-8c3dc79bc13ba84f418d3c135e1bf296a3e29722.zip
chromium_src-8c3dc79bc13ba84f418d3c135e1bf296a3e29722.tar.gz
chromium_src-8c3dc79bc13ba84f418d3c135e1bf296a3e29722.tar.bz2
Refactors OSExchangeData for easier portability.
BUG=none TEST=none Review URL: http://codereview.chromium.org/164401 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23230 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app')
-rw-r--r--app/app.gyp18
-rw-r--r--app/os_exchange_data.cc125
-rw-r--r--app/os_exchange_data.h164
-rw-r--r--app/os_exchange_data_provider_gtk.cc170
-rw-r--r--app/os_exchange_data_provider_gtk.h106
-rw-r--r--app/os_exchange_data_provider_win.cc (renamed from app/os_exchange_data_win.cc)183
-rw-r--r--app/os_exchange_data_provider_win.h128
-rw-r--r--app/os_exchange_data_win_unittest.cc127
8 files changed, 813 insertions, 208 deletions
diff --git a/app/app.gyp b/app/app.gyp
index 77e3a3d..0a36bd5 100644
--- a/app/app.gyp
+++ b/app/app.gyp
@@ -95,8 +95,11 @@
'l10n_util_win.cc',
'l10n_util_win.h',
'message_box_flags.h',
- 'os_exchange_data_win.cc',
- 'os_exchange_data_gtk.cc',
+ 'os_exchange_data_provider_gtk.cc',
+ 'os_exchange_data_provider_gtk.h',
+ 'os_exchange_data_provider_win.cc',
+ 'os_exchange_data_provider_win.h',
+ 'os_exchange_data.cc',
'os_exchange_data.h',
'resource_bundle.cc',
'resource_bundle.h',
@@ -131,11 +134,20 @@
# Note: because of gyp predence rules this has to be defined as
# 'sources/' rather than 'sources!'.
'sources/': [
- ['exclude', '^os_exchange_data_gtk.cc'],
+ ['exclude', '^os_exchange_data.cc'],
['exclude', '^os_exchange_data.h'],
+ ['exclude', '^os_exchange_data_provider_gtk.cc'],
+ ['exclude', '^os_exchange_data_provider_gtk.h'],
['exclude', '^drag_drop_types_gtk.cc'],
],
}],
+ ['toolkit_views==1 or chromeos==1', {
+ # Note: because of gyp predence rules this has to be defined as
+ # 'sources/' rather than 'sources!'.
+ 'sources/': [
+ ['include', '^os_exchange_data.cc'],
+ ],
+ }],
],
}],
['OS=="win"', {
diff --git a/app/os_exchange_data.cc b/app/os_exchange_data.cc
new file mode 100644
index 0000000..9361466
--- /dev/null
+++ b/app/os_exchange_data.cc
@@ -0,0 +1,125 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "app/os_exchange_data.h"
+
+#include "base/pickle.h"
+#include "googleurl/src/gurl.h"
+
+OSExchangeData::OSExchangeData() : provider_(CreateProvider()) {
+}
+
+OSExchangeData::OSExchangeData(Provider* provider) : provider_(provider) {
+}
+
+OSExchangeData::~OSExchangeData() {
+}
+
+void OSExchangeData::SetString(const std::wstring& data) {
+ provider_->SetString(data);
+}
+
+void OSExchangeData::SetURL(const GURL& url, const std::wstring& title) {
+ provider_->SetURL(url, title);
+}
+
+void OSExchangeData::SetFilename(const std::wstring& full_path) {
+ provider_->SetFilename(full_path);
+}
+
+void OSExchangeData::SetPickledData(CustomFormat format, const Pickle& data) {
+ provider_->SetPickledData(format, data);
+}
+
+void OSExchangeData::SetFileContents(const std::wstring& filename,
+ const std::string& file_contents) {
+ provider_->SetFileContents(filename, file_contents);
+}
+
+void OSExchangeData::SetHtml(const std::wstring& html, const GURL& base_url) {
+ provider_->SetHtml(html, base_url);
+}
+
+bool OSExchangeData::GetString(std::wstring* data) const {
+ return provider_->GetString(data);
+}
+
+bool OSExchangeData::GetURLAndTitle(GURL* url, std::wstring* title) const {
+ return provider_->GetURLAndTitle(url, title);
+}
+
+bool OSExchangeData::GetFilename(std::wstring* full_path) const {
+ return provider_->GetFilename(full_path);
+}
+
+bool OSExchangeData::GetPickledData(CustomFormat format, Pickle* data) const {
+ return provider_->GetPickledData(format, data);
+}
+
+bool OSExchangeData::GetFileContents(std::wstring* filename,
+ std::string* file_contents) const {
+ return provider_->GetFileContents(filename, file_contents);
+}
+
+bool OSExchangeData::GetHtml(std::wstring* html, GURL* base_url) const {
+ return provider_->GetHtml(html, base_url);
+}
+
+bool OSExchangeData::HasString() const {
+ return provider_->HasString();
+}
+
+bool OSExchangeData::HasURL() const {
+ return provider_->HasURL();
+}
+
+bool OSExchangeData::HasFile() const {
+ return provider_->HasFile();
+}
+
+bool OSExchangeData::HasCustomFormat(CustomFormat format) const {
+ return provider_->HasCustomFormat(format);
+}
+
+bool OSExchangeData::HasAllFormats(
+ int formats,
+ const std::set<CustomFormat>& custom_formats) const {
+ if ((formats & STRING) != 0 && !HasString())
+ return false;
+ if ((formats & URL) != 0 && !HasURL())
+ return false;
+ if ((formats & FILE_CONTENTS) != 0 && !provider_->HasFileContents())
+ return false;
+ if ((formats & FILE_NAME) != 0 && !provider_->HasFile())
+ return false;
+ if ((formats & HTML) != 0 && !provider_->HasHtml())
+ return false;
+ for (std::set<CustomFormat>::const_iterator i = custom_formats.begin();
+ i != custom_formats.end(); ++i) {
+ if (!HasCustomFormat(*i))
+ return false;
+ }
+ return true;
+}
+
+bool OSExchangeData::HasAnyFormat(
+ int formats,
+ const std::set<CustomFormat>& custom_formats) const {
+ if ((formats & STRING) != 0 && HasString())
+ return true;
+ if ((formats & URL) != 0 && HasURL())
+ return true;
+ if ((formats & FILE_CONTENTS) != 0 && provider_->HasFileContents())
+ return true;
+ if ((formats & FILE_NAME) != 0 && provider_->HasFile())
+ return true;
+ if ((formats & HTML) != 0 && provider_->HasHtml())
+ return true;
+ for (std::set<CustomFormat>::const_iterator i = custom_formats.begin();
+ i != custom_formats.end(); ++i) {
+ if (HasCustomFormat(*i))
+ return true;
+ }
+ return false;
+}
diff --git a/app/os_exchange_data.h b/app/os_exchange_data.h
index 2400266..a956b80 100644
--- a/app/os_exchange_data.h
+++ b/app/os_exchange_data.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -7,15 +7,18 @@
#include "build/build_config.h"
+#include <set>
+#include <string>
+#include <vector>
+
#if defined(OS_WIN)
#include <objidl.h>
-#include "base/scoped_comptr_win.h"
+#elif defined(OS_LINUX)
+#include <gtk/gtk.h>
#endif
-#include <string>
-#include <vector>
-
#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
class GURL;
class Pickle;
@@ -29,25 +32,71 @@ class Pickle;
// translating that into something the OS can understand.
//
///////////////////////////////////////////////////////////////////////////////
-#if defined(OS_WIN)
-class OSExchangeData : public IDataObject {
-#else
class OSExchangeData {
-#endif
public:
+ // CustomFormats are used for non-standard data types. For example, bookmark
+ // nodes are written using a CustomFormat.
#if defined(OS_WIN)
- // Returns true if source has plain text that is a valid url.
- static bool HasPlainTextURL(IDataObject* source);
+ typedef CLIPFORMAT CustomFormat;
+#elif defined(OS_LINUX)
+ typedef GdkAtom CustomFormat;
+#endif
- // Returns true if source has plain text that is a valid URL and sets url to
- // that url.
- static bool GetPlainTextURL(IDataObject* source, GURL* url);
+ // Enumeration of the known formats.
+ enum Format {
+ STRING = 1 << 0,
+ URL = 1 << 1,
+ FILE_CONTENTS = 1 << 2,
+ FILE_NAME = 1 << 3,
+ PICKLED_DATA = 1 << 4,
+ HTML = 1 << 5
+ };
- explicit OSExchangeData(IDataObject* source);
-#endif
+ // Provider defines the platform specific part of OSExchangeData that
+ // interacts with the native system.
+ class Provider {
+ public:
+ Provider() {}
+ virtual ~Provider() {}
+
+ virtual void SetString(const std::wstring& data) = 0;
+ virtual void SetURL(const GURL& url, const std::wstring& title) = 0;
+ virtual void SetFilename(const std::wstring& full_path) = 0;
+ virtual void SetPickledData(CustomFormat format, const Pickle& data) = 0;
+ virtual void SetFileContents(const std::wstring& filename,
+ const std::string& file_contents) = 0;
+ virtual void SetHtml(const std::wstring& html, const GURL& base_url) = 0;
+
+ virtual bool GetString(std::wstring* data) const = 0;
+ virtual bool GetURLAndTitle(GURL* url, std::wstring* title) const = 0;
+ virtual bool GetFilename(std::wstring* full_path) const = 0;
+ virtual bool GetPickledData(CustomFormat format, Pickle* data) const = 0;
+ virtual bool GetFileContents(std::wstring* filename,
+ std::string* file_contents) const = 0;
+ virtual bool GetHtml(std::wstring* html, GURL* base_url) const = 0;
+
+ virtual bool HasString() const = 0;
+ virtual bool HasURL() const = 0;
+ virtual bool HasFile() const = 0;
+ virtual bool HasFileContents() const = 0;
+ virtual bool HasHtml() const = 0;
+ virtual bool HasCustomFormat(
+ OSExchangeData::CustomFormat format) const = 0;
+ };
OSExchangeData();
- virtual ~OSExchangeData();
+ // Creates an OSExchangeData with the specified provider. OSExchangeData
+ // takes ownership of the supplied provider.
+ explicit OSExchangeData(Provider* provider);
+
+ ~OSExchangeData();
+
+ // Registers the specific string as a possible format for data.
+ static CustomFormat RegisterCustomFormat(const std::string& type);
+
+ // Returns the Provider, which actually stores and manages the data.
+ const Provider& provider() const { return *provider_; }
+ Provider& provider() { return *provider_; }
// These functions add data to the OSExchangeData object of various Chrome
// types. The OSExchangeData object takes care of translating the data into
@@ -64,10 +113,8 @@ class OSExchangeData {
void SetURL(const GURL& url, const std::wstring& title);
// A full path to a file
void SetFilename(const std::wstring& full_path);
-#if defined(OS_WIN)
// Adds pickled data of the specified format.
- void SetPickledData(CLIPFORMAT format, const Pickle& data);
-#endif
+ void SetPickledData(CustomFormat format, const Pickle& data);
// Adds the bytes of a file (CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR).
void SetFileContents(const std::wstring& filename,
const std::string& file_contents);
@@ -83,9 +130,7 @@ class OSExchangeData {
bool GetURLAndTitle(GURL* url, std::wstring* title) const;
// Return the path of a file, if available.
bool GetFilename(std::wstring* full_path) const;
-#if defined(OS_WIN)
- bool GetPickledData(CLIPFORMAT format, Pickle* data) const;
-#endif
+ bool GetPickledData(CustomFormat format, Pickle* data) const;
bool GetFileContents(std::wstring* filename,
std::string* file_contents) const;
bool GetHtml(std::wstring* html, GURL* base_url) const;
@@ -94,70 +139,25 @@ class OSExchangeData {
// returning anything.
bool HasString() const;
bool HasURL() const;
- bool HasURLTitle() const;
bool HasFile() const;
-#if defined(OS_WIN)
- bool HasFormat(CLIPFORMAT format) const;
-
- // IDataObject implementation:
- HRESULT __stdcall GetData(FORMATETC* format_etc, STGMEDIUM* medium);
- HRESULT __stdcall GetDataHere(FORMATETC* format_etc, STGMEDIUM* medium);
- HRESULT __stdcall QueryGetData(FORMATETC* format_etc);
- HRESULT __stdcall GetCanonicalFormatEtc(
- FORMATETC* format_etc, FORMATETC* result);
- HRESULT __stdcall SetData(
- FORMATETC* format_etc, STGMEDIUM* medium, BOOL should_release);
- HRESULT __stdcall EnumFormatEtc(
- DWORD direction, IEnumFORMATETC** enumerator);
- HRESULT __stdcall DAdvise(
- FORMATETC* format_etc, DWORD advf, IAdviseSink* sink, DWORD* connection);
- HRESULT __stdcall DUnadvise(DWORD connection);
- HRESULT __stdcall EnumDAdvise(IEnumSTATDATA** enumerator);
-
- // IUnknown implementation:
- HRESULT __stdcall QueryInterface(const IID& iid, void** object);
- ULONG __stdcall AddRef();
- ULONG __stdcall Release();
-#endif
+ bool HasCustomFormat(CustomFormat format) const;
- private:
-#if defined(OS_WIN)
- // FormatEtcEnumerator only likes us for our StoredDataMap typedef.
- friend class FormatEtcEnumerator;
-
- // Our internal representation of stored data & type info.
- struct StoredDataInfo {
- FORMATETC format_etc;
- STGMEDIUM* medium;
- bool owns_medium;
-
- StoredDataInfo(CLIPFORMAT cf, STGMEDIUM* a_medium) {
- format_etc.cfFormat = cf;
- format_etc.dwAspect = DVASPECT_CONTENT;
- format_etc.lindex = -1;
- format_etc.ptd = NULL;
- format_etc.tymed = a_medium->tymed;
-
- owns_medium = true;
-
- medium = a_medium;
- }
-
- ~StoredDataInfo() {
- if (owns_medium) {
- ReleaseStgMedium(medium);
- delete medium;
- }
- }
- };
+ // Returns true if this OSExchangeData has data for ALL the formats in
+ // |formats| and ALL the custom formats in |custom_formats|.
+ bool HasAllFormats(int formats,
+ const std::set<CustomFormat>& custom_formats) const;
- typedef std::vector<StoredDataInfo*> StoredData;
- StoredData contents_;
+ // Returns true if this OSExchangeData has data in any of the formats in
+ // |formats| or any custom format in |custom_formats|.
+ bool HasAnyFormat(int formats,
+ const std::set<CustomFormat>& custom_formats) const;
- ScopedComPtr<IDataObject> source_object_;
+ private:
+ // Creates the platform specific Provider.
+ static Provider* CreateProvider();
- LONG ref_count_;
-#endif
+ // Provides the actual data.
+ scoped_ptr<Provider> provider_;
DISALLOW_COPY_AND_ASSIGN(OSExchangeData);
};
diff --git a/app/os_exchange_data_provider_gtk.cc b/app/os_exchange_data_provider_gtk.cc
new file mode 100644
index 0000000..5aaa414
--- /dev/null
+++ b/app/os_exchange_data_provider_gtk.cc
@@ -0,0 +1,170 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "app/os_exchange_data_provider_gtk.h"
+
+#include <algorithm>
+
+#include "base/string_util.h"
+
+OSExchangeDataProviderGtk::OSExchangeDataProviderGtk(
+ int known_formats,
+ const std::set<GdkAtom>& known_custom_formats)
+ : known_formats_(known_formats),
+ known_custom_formats_(known_custom_formats),
+ formats_(0) {
+}
+
+OSExchangeDataProviderGtk::OSExchangeDataProviderGtk()
+ : known_formats_(0),
+ formats_(0) {
+}
+
+OSExchangeDataProviderGtk::~OSExchangeDataProviderGtk() {
+}
+
+bool OSExchangeDataProviderGtk::HasDataForAllFormats(
+ int formats,
+ const std::set<GdkAtom>& custom_formats) const {
+ if ((formats_ & formats) != formats)
+ return false;
+ return std::includes(custom_formats_.begin(),
+ custom_formats_.end(),
+ custom_formats.begin(), custom_formats.end());
+}
+
+void OSExchangeDataProviderGtk::SetString(const std::wstring& data) {
+ string_ = WideToUTF16Hack(data);
+ formats_ |= OSExchangeData::STRING;
+}
+
+void OSExchangeDataProviderGtk::SetURL(const GURL& url,
+ const std::wstring& title) {
+ url_ = url;
+ title_ = WideToUTF16Hack(title);
+ formats_ |= OSExchangeData::URL;
+}
+
+void OSExchangeDataProviderGtk::SetFilename(const std::wstring& full_path) {
+ filename_ = WideToUTF16Hack(full_path);
+ formats_ |= OSExchangeData::FILE_NAME;
+}
+
+void OSExchangeDataProviderGtk::SetPickledData(GdkAtom format,
+ const Pickle& data) {
+ pickle_data_[format] = data;
+ formats_ |= OSExchangeData::PICKLED_DATA;
+}
+
+void OSExchangeDataProviderGtk::SetFileContents(
+ const std::wstring& filename,
+ const std::string& file_contents) {
+ filename_ = WideToUTF16Hack(filename);
+ file_contents_ = file_contents;
+ formats_ |= OSExchangeData::FILE_CONTENTS;
+}
+
+void OSExchangeDataProviderGtk::SetHtml(const std::wstring& html,
+ const GURL& base_url) {
+ html_ = WideToUTF16Hack(html);
+ base_url_ = base_url;
+ formats_ |= OSExchangeData::HTML;
+}
+
+bool OSExchangeDataProviderGtk::GetString(std::wstring* data) const {
+ if (formats_ & OSExchangeData::STRING == 0)
+ return false;
+ *data = UTF16ToWideHack(string_);
+ return true;
+}
+
+bool OSExchangeDataProviderGtk::GetURLAndTitle(GURL* url,
+ std::wstring* title) const {
+ if (formats_ & OSExchangeData::URL == 0)
+ return false;
+ if (!url_.is_valid())
+ return false;
+
+ *url = url_;
+ *title = UTF16ToWideHack(title_);
+ return true;
+}
+
+bool OSExchangeDataProviderGtk::GetFilename(std::wstring* full_path) const {
+ if (formats_ & OSExchangeData::FILE_NAME == 0)
+ return false;
+ *full_path = UTF16ToWideHack(filename_);
+ return true;
+}
+
+bool OSExchangeDataProviderGtk::GetPickledData(GdkAtom format,
+ Pickle* data) const {
+ PickleData::const_iterator i = pickle_data_.find(format);
+ if (i == pickle_data_.end())
+ return false;
+
+ *data = i->second;
+ return true;
+}
+
+bool OSExchangeDataProviderGtk::GetFileContents(
+ std::wstring* filename,
+ std::string* file_contents) const {
+ if (formats_ & OSExchangeData::FILE_CONTENTS == 0)
+ return false;
+ *filename = UTF16ToWideHack(filename_);
+ *file_contents = file_contents_;
+ return true;
+}
+
+bool OSExchangeDataProviderGtk::GetHtml(std::wstring* html,
+ GURL* base_url) const {
+ if (formats_ & OSExchangeData::HTML == 0)
+ return false;
+ *html = UTF16ToWideHack(filename_);
+ *base_url = base_url_;
+ return true;
+}
+
+bool OSExchangeDataProviderGtk::HasString() const {
+ return (known_formats_ & OSExchangeData::STRING) != 0 ||
+ (formats_ & OSExchangeData::STRING) != 0;
+}
+
+bool OSExchangeDataProviderGtk::HasURL() const {
+ return (known_formats_ & OSExchangeData::URL) != 0 ||
+ (formats_ & OSExchangeData::URL) != 0;
+}
+
+bool OSExchangeDataProviderGtk::HasFile() const {
+ return (known_formats_ & OSExchangeData::FILE_NAME) != 0 ||
+ (formats_ & OSExchangeData::FILE_NAME) != 0;
+ }
+
+bool OSExchangeDataProviderGtk::HasFileContents() const {
+ return (known_formats_ & OSExchangeData::FILE_CONTENTS) != 0 ||
+ (formats_ & OSExchangeData::FILE_CONTENTS) != 0;
+}
+
+bool OSExchangeDataProviderGtk::HasHtml() const {
+ return (known_formats_ & OSExchangeData::HTML) != 0 ||
+ (formats_ & OSExchangeData::HTML) != 0;
+}
+
+bool OSExchangeDataProviderGtk::HasCustomFormat(GdkAtom format) const {
+ return known_custom_formats_.find(format) != known_custom_formats_.end() ||
+ custom_formats_.find(format) != custom_formats_.end();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// OSExchangeData, public:
+
+// static
+OSExchangeData::Provider* OSExchangeData::CreateProvider() {
+ return new OSExchangeDataProviderGtk();
+}
+
+GdkAtom OSExchangeData::RegisterCustomFormat(const std::string& type) {
+ return gdk_atom_intern(type.c_str(), false);
+}
diff --git a/app/os_exchange_data_provider_gtk.h b/app/os_exchange_data_provider_gtk.h
new file mode 100644
index 0000000..dd9c009
--- /dev/null
+++ b/app/os_exchange_data_provider_gtk.h
@@ -0,0 +1,106 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef APP_OS_EXCHANGE_DATA_PROVIDER_GTK_H_
+#define APP_OS_EXCHANGE_DATA_PROVIDER_GTK_H_
+
+#include <gtk/gtk.h>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "app/os_exchange_data.h"
+#include "base/pickle.h"
+#include "base/string16.h"
+#include "googleurl/src/gurl.h"
+
+// OSExchangeData::Provider implementation for Gtk. OSExchangeDataProviderGtk
+// is created with a set of known data types. In addition specific data
+// types can be set on OSExchangeDataProviderGtk by way of the various setters.
+// The various has methods return true if the format was supplied to the
+// constructor, or explicitly set.
+class OSExchangeDataProviderGtk : public OSExchangeData::Provider {
+ public:
+ OSExchangeDataProviderGtk(int known_formats,
+ const std::set<GdkAtom>& known_custom_formats_);
+ OSExchangeDataProviderGtk();
+
+ virtual ~OSExchangeDataProviderGtk();
+
+ int known_formats() const { return known_formats_; }
+ const std::set<GdkAtom>& known_custom_formats() const {
+ return known_custom_formats_;
+ }
+
+ // Returns true if all the formats and custom formats identified by |formats|
+ // and |custom_formats| have been set in this provider.
+ //
+ // NOTE: this is NOT the same as whether a format may be provided (as is
+ // returned by the various HasXXX methods), but rather if the data for the
+ // formats has been set on this provider by way of the various Setter
+ // methods.
+ bool HasDataForAllFormats(int formats,
+ const std::set<GdkAtom>& custom_formats) const;
+
+ // Provider methods.
+ virtual void SetString(const std::wstring& data);
+ virtual void SetURL(const GURL& url, const std::wstring& title);
+ virtual void SetFilename(const std::wstring& full_path);
+ virtual void SetPickledData(OSExchangeData::CustomFormat format,
+ const Pickle& data);
+ virtual void SetFileContents(const std::wstring& filename,
+ const std::string& file_contents);
+ virtual void SetHtml(const std::wstring& html, const GURL& base_url);
+ virtual bool GetString(std::wstring* data) const;
+ virtual bool GetURLAndTitle(GURL* url, std::wstring* title) const;
+ virtual bool GetFilename(std::wstring* full_path) const;
+ virtual bool GetPickledData(OSExchangeData::CustomFormat format,
+ Pickle* data) const;
+ virtual bool GetFileContents(std::wstring* filename,
+ std::string* file_contents) const;
+ virtual bool GetHtml(std::wstring* html, GURL* base_url) const;
+ virtual bool HasString() const;
+ virtual bool HasURL() const;
+ virtual bool HasFile() const;
+ virtual bool HasFileContents() const;
+ virtual bool HasHtml() const;
+ virtual bool HasCustomFormat(OSExchangeData::CustomFormat format) const;
+
+ private:
+ typedef std::map<OSExchangeData::CustomFormat, Pickle> PickleData;
+
+ // These are the possible formats the OSExchangeData may contain. Don't
+ // confuse this with the actual formats that have been set, which are
+ // |formats_| and |custom_formats_|.
+ const int known_formats_;
+ const std::set<GdkAtom> known_custom_formats_;
+
+ // Actual formats that have been set. See comment above |known_formats_|
+ // for details.
+ int formats_;
+ std::set<GdkAtom> custom_formats_;
+
+ // String contents.
+ string16 string_;
+
+ // URL contents.
+ GURL url_;
+ string16 title_;
+
+ // File contents.
+ string16 filename_;
+ std::string file_contents_;
+
+ // HTML contents.
+ string16 html_;
+ GURL base_url_;
+
+ // PICKLED_DATA contents.
+ PickleData pickle_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(OSExchangeDataProviderGtk);
+};
+
+#endif // APP_OS_EXCHANGE_DATA_PROVIDER_GTK_H_
diff --git a/app/os_exchange_data_win.cc b/app/os_exchange_data_provider_win.cc
index c7bd18b..1d8bdd8 100644
--- a/app/os_exchange_data_win.cc
+++ b/app/os_exchange_data_provider_win.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "app/os_exchange_data.h"
+#include "app/os_exchange_data_provider_win.h"
#include "app/l10n_util.h"
#include "base/clipboard_util.h"
@@ -48,8 +48,8 @@ static STGMEDIUM* GetStorageForFileDescriptor(
//
class FormatEtcEnumerator : public IEnumFORMATETC {
public:
- FormatEtcEnumerator(OSExchangeData::StoredData::const_iterator begin,
- OSExchangeData::StoredData::const_iterator end);
+ FormatEtcEnumerator(DataObjectImpl::StoredData::const_iterator begin,
+ DataObjectImpl::StoredData::const_iterator end);
~FormatEtcEnumerator();
// IEnumFORMATETC implementation:
@@ -99,8 +99,8 @@ static void CloneFormatEtc(FORMATETC* source, FORMATETC* clone) {
}
FormatEtcEnumerator::FormatEtcEnumerator(
- OSExchangeData::StoredData::const_iterator start,
- OSExchangeData::StoredData::const_iterator end)
+ DataObjectImpl::StoredData::const_iterator start,
+ DataObjectImpl::StoredData::const_iterator end)
: ref_count_(0), cursor_(0) {
// Copy FORMATETC data from our source into ourselves.
while (start != end) {
@@ -200,17 +200,18 @@ FormatEtcEnumerator* FormatEtcEnumerator::CloneFromOther(
}
///////////////////////////////////////////////////////////////////////////////
-// OSExchangeData, public:
+// OSExchangeDataProviderWin, public:
// static
-bool OSExchangeData::HasPlainTextURL(IDataObject* source) {
+bool OSExchangeDataProviderWin::HasPlainTextURL(IDataObject* source) {
std::wstring plain_text;
return (ClipboardUtil::GetPlainText(source, &plain_text) &&
!plain_text.empty() && GURL(plain_text).is_valid());
}
// static
-bool OSExchangeData::GetPlainTextURL(IDataObject* source, GURL* url) {
+bool OSExchangeDataProviderWin::GetPlainTextURL(IDataObject* source,
+ GURL* url) {
std::wstring plain_text;
if (ClipboardUtil::GetPlainText(source, &plain_text) &&
!plain_text.empty()) {
@@ -223,29 +224,39 @@ bool OSExchangeData::GetPlainTextURL(IDataObject* source, GURL* url) {
return false;
}
-OSExchangeData::OSExchangeData()
- : ref_count_(0) {
+// static
+IDataObject* OSExchangeDataProviderWin::GetIDataObject(
+ const OSExchangeData& data) {
+ return static_cast<const OSExchangeDataProviderWin&>(data.provider()).
+ data_object();
}
-OSExchangeData::OSExchangeData(IDataObject* source)
- : ref_count_(0) {
- source_object_ = source;
+OSExchangeDataProviderWin::OSExchangeDataProviderWin(IDataObject* source)
+ : data_(new DataObjectImpl()),
+ source_object_(source) {
}
-OSExchangeData::~OSExchangeData() {
- STLDeleteContainerPointers(contents_.begin(), contents_.end());
+OSExchangeDataProviderWin::OSExchangeDataProviderWin()
+ : data_(new DataObjectImpl()),
+ source_object_(data_.get()) {
}
-void OSExchangeData::SetString(const std::wstring& data) {
+OSExchangeDataProviderWin::~OSExchangeDataProviderWin() {
+}
+
+void OSExchangeDataProviderWin::SetString(const std::wstring& data) {
STGMEDIUM* storage = GetStorageForWString(data);
- contents_.push_back(new StoredDataInfo(CF_UNICODETEXT, storage));
+ data_->contents_.push_back(
+ new DataObjectImpl::StoredDataInfo(CF_UNICODETEXT, storage));
// Also add plain text.
storage = GetStorageForString(WideToUTF8(data));
- contents_.push_back(new StoredDataInfo(CF_TEXT, storage));
+ data_->contents_.push_back(
+ new DataObjectImpl::StoredDataInfo(CF_TEXT, storage));
}
-void OSExchangeData::SetURL(const GURL& url, const std::wstring& title) {
+void OSExchangeDataProviderWin::SetURL(const GURL& url,
+ const std::wstring& title) {
// NOTE WELL:
// Every time you change the order of the first two CLIPFORMATS that get
// added here, you need to update the EnumerationViaCOM test case in
@@ -257,7 +268,7 @@ void OSExchangeData::SetURL(const GURL& url, const std::wstring& title) {
x_moz_url_str += '\n';
x_moz_url_str += title;
STGMEDIUM* storage = GetStorageForWString(x_moz_url_str);
- contents_.push_back(new StoredDataInfo(
+ data_->contents_.push_back(new DataObjectImpl::StoredDataInfo(
ClipboardUtil::GetMozUrlFormat()->cfFormat, storage));
// Add a .URL shortcut file for dragging to Explorer.
@@ -269,10 +280,10 @@ void OSExchangeData::SetURL(const GURL& url, const std::wstring& title) {
// Add a UniformResourceLocator link for apps like IE and Word.
storage = GetStorageForWString(UTF8ToWide(url.spec()));
- contents_.push_back(new StoredDataInfo(
+ data_->contents_.push_back(new DataObjectImpl::StoredDataInfo(
ClipboardUtil::GetUrlWFormat()->cfFormat, storage));
storage = GetStorageForString(url.spec());
- contents_.push_back(new StoredDataInfo(
+ data_->contents_.push_back(new DataObjectImpl::StoredDataInfo(
ClipboardUtil::GetUrlFormat()->cfFormat, storage));
// TODO(beng): (http://b/1085501) add CF_HTML...
@@ -280,12 +291,14 @@ void OSExchangeData::SetURL(const GURL& url, const std::wstring& title) {
// Also add text representations (these should be last since they're the
// least preferable).
storage = GetStorageForWString(UTF8ToWide(url.spec()));
- contents_.push_back(new StoredDataInfo(CF_UNICODETEXT, storage));
+ data_->contents_.push_back(
+ new DataObjectImpl::StoredDataInfo(CF_UNICODETEXT, storage));
storage = GetStorageForString(url.spec());
- contents_.push_back(new StoredDataInfo(CF_TEXT, storage));
+ data_->contents_.push_back(
+ new DataObjectImpl::StoredDataInfo(CF_TEXT, storage));
}
-void OSExchangeData::SetFilename(const std::wstring& full_path) {
+void OSExchangeDataProviderWin::SetFilename(const std::wstring& full_path) {
const size_t drop_size = sizeof(DROPFILES);
const size_t bytes = drop_size + (full_path.length() + 2) * sizeof(wchar_t);
HANDLE hdata = ::GlobalAlloc(GMEM_MOVEABLE, bytes);
@@ -308,51 +321,57 @@ void OSExchangeData::SetFilename(const std::wstring& full_path) {
storage->pUnkForRelease = NULL;
// Set up the StoredDataInfo
- StoredDataInfo* info = new StoredDataInfo(CF_HDROP, storage);
- contents_.push_back(info);
+ DataObjectImpl::StoredDataInfo* info =
+ new DataObjectImpl::StoredDataInfo(CF_HDROP, storage);
+ data_->contents_.push_back(info);
}
-void OSExchangeData::SetPickledData(CLIPFORMAT format, const Pickle& data) {
+void OSExchangeDataProviderWin::SetPickledData(CLIPFORMAT format,
+ const Pickle& data) {
STGMEDIUM* storage = GetStorageForString(
std::string(static_cast<const char *>(data.data()),
static_cast<size_t>(data.size())));
- contents_.push_back(new StoredDataInfo(format, storage));
+ data_->contents_.push_back(
+ new DataObjectImpl::StoredDataInfo(format, storage));
}
-void OSExchangeData::SetFileContents(const std::wstring& filename,
- const std::string& file_contents) {
+void OSExchangeDataProviderWin::SetFileContents(
+ const std::wstring& filename,
+ const std::string& file_contents) {
// Add CFSTR_FILEDESCRIPTOR
STGMEDIUM* storage = GetStorageForFileDescriptor(filename);
- contents_.push_back(new StoredDataInfo(
+ data_->contents_.push_back(new DataObjectImpl::StoredDataInfo(
ClipboardUtil::GetFileDescriptorFormat()->cfFormat, storage));
// Add CFSTR_FILECONTENTS
storage = GetStorageForBytes(file_contents.data(), file_contents.length());
- contents_.push_back(new StoredDataInfo(
+ data_->contents_.push_back(new DataObjectImpl::StoredDataInfo(
ClipboardUtil::GetFileContentFormatZero()->cfFormat, storage));
}
-void OSExchangeData::SetHtml(const std::wstring& html, const GURL& base_url) {
+void OSExchangeDataProviderWin::SetHtml(const std::wstring& html,
+ const GURL& base_url) {
// Add both MS CF_HTML and text/html format. CF_HTML should be in utf-8.
std::string utf8_html = WideToUTF8(html);
std::string url = base_url.is_valid() ? base_url.spec() : std::string();
std::string cf_html = ClipboardUtil::HtmlToCFHtml(utf8_html, url);
STGMEDIUM* storage = GetStorageForBytes(cf_html.c_str(), cf_html.size());
- contents_.push_back(new StoredDataInfo(
+ data_->contents_.push_back(new DataObjectImpl::StoredDataInfo(
ClipboardUtil::GetHtmlFormat()->cfFormat, storage));
STGMEDIUM* storage_plain = GetStorageForBytes(utf8_html.c_str(),
utf8_html.size());
- contents_.push_back(new StoredDataInfo(
+ data_->contents_.push_back(new DataObjectImpl::StoredDataInfo(
ClipboardUtil::GetTextHtmlFormat()->cfFormat, storage_plain));
}
-bool OSExchangeData::GetString(std::wstring* data) const {
+bool OSExchangeDataProviderWin::GetString(std::wstring* data) const {
return ClipboardUtil::GetPlainText(source_object_, data);
}
-bool OSExchangeData::GetURLAndTitle(GURL* url, std::wstring* title) const {
+bool OSExchangeDataProviderWin::GetURLAndTitle(GURL* url,
+ std::wstring* title) const {
std::wstring url_str;
bool success = ClipboardUtil::GetUrl(source_object_, &url_str, title);
if (success) {
@@ -368,7 +387,7 @@ bool OSExchangeData::GetURLAndTitle(GURL* url, std::wstring* title) const {
return false;
}
-bool OSExchangeData::GetFilename(std::wstring* full_path) const {
+bool OSExchangeDataProviderWin::GetFilename(std::wstring* full_path) const {
std::vector<std::wstring> filenames;
bool success = ClipboardUtil::GetFilenames(source_object_, &filenames);
if (success)
@@ -376,7 +395,8 @@ bool OSExchangeData::GetFilename(std::wstring* full_path) const {
return success;
}
-bool OSExchangeData::GetPickledData(CLIPFORMAT format, Pickle* data) const {
+bool OSExchangeDataProviderWin::GetPickledData(CLIPFORMAT format,
+ Pickle* data) const {
DCHECK(data);
FORMATETC format_etc =
{ format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
@@ -395,13 +415,15 @@ bool OSExchangeData::GetPickledData(CLIPFORMAT format, Pickle* data) const {
return success;
}
-bool OSExchangeData::GetFileContents(std::wstring* filename,
- std::string* file_contents) const {
+bool OSExchangeDataProviderWin::GetFileContents(
+ std::wstring* filename,
+ std::string* file_contents) const {
return ClipboardUtil::GetFileContents(source_object_, filename,
file_contents);
}
-bool OSExchangeData::GetHtml(std::wstring* html, GURL* base_url) const {
+bool OSExchangeDataProviderWin::GetHtml(std::wstring* html,
+ GURL* base_url) const {
std::string url;
bool success = ClipboardUtil::GetHtml(source_object_, html, &url);
if (success)
@@ -409,27 +431,35 @@ bool OSExchangeData::GetHtml(std::wstring* html, GURL* base_url) const {
return success;
}
-bool OSExchangeData::HasString() const {
+bool OSExchangeDataProviderWin::HasString() const {
return ClipboardUtil::HasPlainText(source_object_);
}
-bool OSExchangeData::HasURL() const {
+bool OSExchangeDataProviderWin::HasURL() const {
return (ClipboardUtil::HasUrl(source_object_) ||
HasPlainTextURL(source_object_));
}
-bool OSExchangeData::HasFile() const {
+bool OSExchangeDataProviderWin::HasFile() const {
return ClipboardUtil::HasFilenames(source_object_);
}
-bool OSExchangeData::HasFormat(CLIPFORMAT format) const {
+bool OSExchangeDataProviderWin::HasFileContents() const {
+ return ClipboardUtil::HasFileContents(source_object_);
+}
+
+bool OSExchangeDataProviderWin::HasHtml() const {
+ return ClipboardUtil::HasHtml(source_object_);
+}
+
+bool OSExchangeDataProviderWin::HasCustomFormat(CLIPFORMAT format) const {
FORMATETC format_etc =
{ format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
return (source_object_->QueryGetData(&format_etc) == S_OK);
}
///////////////////////////////////////////////////////////////////////////////
-// OSExchangeData, IDataObject implementation:
+// DataObjectImpl, IDataObject implementation:
// The following function, DuplicateMedium, is derived from WCDataObject.cpp
// in the WebKit source code. This is the license information for the file:
@@ -502,7 +532,15 @@ static void DuplicateMedium(CLIPFORMAT source_clipformat,
destination->pUnkForRelease->AddRef();
}
-HRESULT OSExchangeData::GetData(FORMATETC* format_etc, STGMEDIUM* medium) {
+DataObjectImpl::DataObjectImpl() : ref_count_(0) {
+ STLDeleteContainerPointers(contents_.begin(), contents_.end());
+}
+
+DataObjectImpl::~DataObjectImpl() {
+ STLDeleteContainerPointers(contents_.begin(), contents_.end());
+}
+
+HRESULT DataObjectImpl::GetData(FORMATETC* format_etc, STGMEDIUM* medium) {
StoredData::const_iterator iter = contents_.begin();
while (iter != contents_.end()) {
if ((*iter)->format_etc.cfFormat == format_etc->cfFormat) {
@@ -515,11 +553,12 @@ HRESULT OSExchangeData::GetData(FORMATETC* format_etc, STGMEDIUM* medium) {
return DV_E_FORMATETC;
}
-HRESULT OSExchangeData::GetDataHere(FORMATETC* format_etc, STGMEDIUM* medium) {
+HRESULT DataObjectImpl::GetDataHere(FORMATETC* format_etc,
+ STGMEDIUM* medium) {
return DATA_E_FORMATETC;
}
-HRESULT OSExchangeData::QueryGetData(FORMATETC* format_etc) {
+HRESULT DataObjectImpl::QueryGetData(FORMATETC* format_etc) {
StoredData::const_iterator iter = contents_.begin();
while (iter != contents_.end()) {
if ((*iter)->format_etc.cfFormat == format_etc->cfFormat)
@@ -529,13 +568,13 @@ HRESULT OSExchangeData::QueryGetData(FORMATETC* format_etc) {
return DV_E_FORMATETC;
}
-HRESULT OSExchangeData::GetCanonicalFormatEtc(
+HRESULT DataObjectImpl::GetCanonicalFormatEtc(
FORMATETC* format_etc, FORMATETC* result) {
format_etc->ptd = NULL;
return E_NOTIMPL;
}
-HRESULT OSExchangeData::SetData(
+HRESULT DataObjectImpl::SetData(
FORMATETC* format_etc, STGMEDIUM* medium, BOOL should_release) {
STGMEDIUM* local_medium = new STGMEDIUM;
if (should_release) {
@@ -544,8 +583,8 @@ HRESULT OSExchangeData::SetData(
DuplicateMedium(format_etc->cfFormat, medium, local_medium);
}
- StoredDataInfo* info =
- new StoredDataInfo(format_etc->cfFormat, local_medium);
+ DataObjectImpl::StoredDataInfo* info =
+ new DataObjectImpl::StoredDataInfo(format_etc->cfFormat, local_medium);
info->medium->tymed = format_etc->tymed;
info->owns_medium = !!should_release;
contents_.push_back(info);
@@ -553,7 +592,7 @@ HRESULT OSExchangeData::SetData(
return S_OK;
}
-HRESULT OSExchangeData::EnumFormatEtc(
+HRESULT DataObjectImpl::EnumFormatEtc(
DWORD direction, IEnumFORMATETC** enumerator) {
if (direction == DATADIR_GET) {
FormatEtcEnumerator* e =
@@ -565,23 +604,23 @@ HRESULT OSExchangeData::EnumFormatEtc(
return E_NOTIMPL;
}
-HRESULT OSExchangeData::DAdvise(
+HRESULT DataObjectImpl::DAdvise(
FORMATETC* format_etc, DWORD advf, IAdviseSink* sink, DWORD* connection) {
return OLE_E_ADVISENOTSUPPORTED;
}
-HRESULT OSExchangeData::DUnadvise(DWORD connection) {
+HRESULT DataObjectImpl::DUnadvise(DWORD connection) {
return OLE_E_ADVISENOTSUPPORTED;
}
-HRESULT OSExchangeData::EnumDAdvise(IEnumSTATDATA** enumerator) {
+HRESULT DataObjectImpl::EnumDAdvise(IEnumSTATDATA** enumerator) {
return OLE_E_ADVISENOTSUPPORTED;
}
///////////////////////////////////////////////////////////////////////////////
-// OSExchangeData, IUnknown implementation:
+// DataObjectImpl, IUnknown implementation:
-HRESULT OSExchangeData::QueryInterface(const IID& iid, void** object) {
+HRESULT DataObjectImpl::QueryInterface(const IID& iid, void** object) {
*object = NULL;
if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IDataObject)) {
*object = this;
@@ -592,11 +631,11 @@ HRESULT OSExchangeData::QueryInterface(const IID& iid, void** object) {
return S_OK;
}
-ULONG OSExchangeData::AddRef() {
+ULONG DataObjectImpl::AddRef() {
return InterlockedIncrement(&ref_count_);
}
-ULONG OSExchangeData::Release() {
+ULONG DataObjectImpl::Release() {
if (InterlockedDecrement(&ref_count_) == 0) {
ULONG copied_refcnt = ref_count_;
delete this;
@@ -606,7 +645,7 @@ ULONG OSExchangeData::Release() {
}
///////////////////////////////////////////////////////////////////////////////
-// OSExchangeData, private:
+// DataObjectImpl, private:
static STGMEDIUM* GetStorageForBytes(const char* data, size_t bytes) {
HANDLE handle = GlobalAlloc(GPTR, static_cast<int>(bytes));
@@ -702,3 +741,17 @@ static STGMEDIUM* GetStorageForFileDescriptor(
storage->pUnkForRelease = NULL;
return storage;
}
+
+///////////////////////////////////////////////////////////////////////////////
+// OSExchangeData, public:
+
+// static
+OSExchangeData::Provider* OSExchangeData::CreateProvider() {
+ return new OSExchangeDataProviderWin();
+}
+
+// static
+OSExchangeData::CustomFormat OSExchangeData::RegisterCustomFormat(
+ const std::string& type) {
+ return RegisterClipboardFormat(ASCIIToWide(type).c_str());
+}
diff --git a/app/os_exchange_data_provider_win.h b/app/os_exchange_data_provider_win.h
new file mode 100644
index 0000000..42b11e2
--- /dev/null
+++ b/app/os_exchange_data_provider_win.h
@@ -0,0 +1,128 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef APP_OS_EXCHANGE_DATA_PROVIDER_WIN_H_
+#define APP_OS_EXCHANGE_DATA_PROVIDER_WIN_H_
+
+#include <objidl.h>
+#include <string>
+
+#include "app/os_exchange_data.h"
+#include "base/scoped_comptr_win.h"
+
+class DataObjectImpl : public IDataObject {
+ public:
+ DataObjectImpl();
+ ~DataObjectImpl();
+
+ // IDataObject implementation:
+ HRESULT __stdcall GetData(FORMATETC* format_etc, STGMEDIUM* medium);
+ HRESULT __stdcall GetDataHere(FORMATETC* format_etc, STGMEDIUM* medium);
+ HRESULT __stdcall QueryGetData(FORMATETC* format_etc);
+ HRESULT __stdcall GetCanonicalFormatEtc(
+ FORMATETC* format_etc, FORMATETC* result);
+ HRESULT __stdcall SetData(
+ FORMATETC* format_etc, STGMEDIUM* medium, BOOL should_release);
+ HRESULT __stdcall EnumFormatEtc(
+ DWORD direction, IEnumFORMATETC** enumerator);
+ HRESULT __stdcall DAdvise(FORMATETC* format_etc, DWORD advf,
+ IAdviseSink* sink, DWORD* connection);
+ HRESULT __stdcall DUnadvise(DWORD connection);
+ HRESULT __stdcall EnumDAdvise(IEnumSTATDATA** enumerator);
+
+ // IUnknown implementation:
+ HRESULT __stdcall QueryInterface(const IID& iid, void** object);
+ ULONG __stdcall AddRef();
+ ULONG __stdcall Release();
+
+ private:
+ // FormatEtcEnumerator only likes us for our StoredDataMap typedef.
+ friend class FormatEtcEnumerator;
+ friend class OSExchangeDataProviderWin;
+
+ // Our internal representation of stored data & type info.
+ struct StoredDataInfo {
+ FORMATETC format_etc;
+ STGMEDIUM* medium;
+ bool owns_medium;
+
+ StoredDataInfo(CLIPFORMAT cf, STGMEDIUM* a_medium) {
+ format_etc.cfFormat = cf;
+ format_etc.dwAspect = DVASPECT_CONTENT;
+ format_etc.lindex = -1;
+ format_etc.ptd = NULL;
+ format_etc.tymed = a_medium->tymed;
+
+ owns_medium = true;
+
+ medium = a_medium;
+ }
+
+ ~StoredDataInfo() {
+ if (owns_medium) {
+ ReleaseStgMedium(medium);
+ delete medium;
+ }
+ }
+ };
+
+ typedef std::vector<StoredDataInfo*> StoredData;
+ StoredData contents_;
+
+ ScopedComPtr<IDataObject> source_object_;
+
+ LONG ref_count_;
+};
+
+class OSExchangeDataProviderWin : public OSExchangeData::Provider {
+ public:
+ // Returns true if source has plain text that is a valid url.
+ static bool HasPlainTextURL(IDataObject* source);
+
+ // Returns true if source has plain text that is a valid URL and sets url to
+ // that url.
+ static bool GetPlainTextURL(IDataObject* source, GURL* url);
+
+ static IDataObject* GetIDataObject(const OSExchangeData& data);
+
+ explicit OSExchangeDataProviderWin(IDataObject* source);
+ OSExchangeDataProviderWin();
+
+ virtual ~OSExchangeDataProviderWin();
+
+ IDataObject* data_object() const { return data_.get(); }
+
+ // OSExchangeData::Provider methods.
+ virtual void SetString(const std::wstring& data);
+ virtual void SetURL(const GURL& url, const std::wstring& title);
+ virtual void SetFilename(const std::wstring& full_path);
+ virtual void SetPickledData(OSExchangeData::CustomFormat format,
+ const Pickle& data);
+ virtual void SetFileContents(const std::wstring& filename,
+ const std::string& file_contents);
+ virtual void SetHtml(const std::wstring& html, const GURL& base_url);
+
+ virtual bool GetString(std::wstring* data) const;
+ virtual bool GetURLAndTitle(GURL* url, std::wstring* title) const;
+ virtual bool GetFilename(std::wstring* full_path) const;
+ virtual bool GetPickledData(OSExchangeData::CustomFormat format,
+ Pickle* data) const;
+ virtual bool GetFileContents(std::wstring* filename,
+ std::string* file_contents) const;
+ virtual bool GetHtml(std::wstring* html, GURL* base_url) const;
+ virtual bool HasString() const;
+ virtual bool HasURL() const;
+ virtual bool HasFile() const;
+ virtual bool HasFileContents() const;
+ virtual bool HasHtml() const;
+ virtual bool HasCustomFormat(OSExchangeData::CustomFormat format) const;
+
+ private:
+ scoped_refptr<DataObjectImpl> data_;
+ ScopedComPtr<IDataObject> source_object_;
+
+ DISALLOW_COPY_AND_ASSIGN(OSExchangeDataProviderWin);
+};
+
+#endif // APP_OS_EXCHANGE_DATA_PROVIDER_WIN_H_
diff --git a/app/os_exchange_data_win_unittest.cc b/app/os_exchange_data_win_unittest.cc
index 981a8d1..88f33b0 100644
--- a/app/os_exchange_data_win_unittest.cc
+++ b/app/os_exchange_data_win_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "app/os_exchange_data.h"
+#include "app/os_exchange_data_provider_win.h"
#include "base/clipboard_util.h"
#include "base/pickle.h"
#include "base/ref_counted.h"
@@ -14,32 +15,40 @@
typedef testing::Test OSExchangeDataTest;
+namespace {
+
+OSExchangeData::Provider* CloneProvider(const OSExchangeData& data) {
+ return new OSExchangeDataProviderWin(
+ OSExchangeDataProviderWin::GetIDataObject(data));
+}
+
+} // namespace
+
// Test setting/getting using the OSExchangeData API
TEST(OSExchangeDataTest, StringDataGetAndSet) {
- OSExchangeData* data = new OSExchangeData;
+ OSExchangeData data;
std::wstring input = L"I can has cheezburger?";
- data->SetString(input);
+ data.SetString(input);
- OSExchangeData* data2 = new OSExchangeData(data);
+ OSExchangeData data2(CloneProvider(data));
std::wstring output;
- EXPECT_TRUE(data2->GetString(&output));
+ EXPECT_TRUE(data2.GetString(&output));
EXPECT_EQ(input, output);
std::string url_spec = "http://www.goats.com/";
GURL url(url_spec);
std::wstring title;
- EXPECT_FALSE(data2->GetURLAndTitle(&url, &title));
+ EXPECT_FALSE(data2.GetURLAndTitle(&url, &title));
// No URLs in |data|, so url should be untouched.
EXPECT_EQ(url_spec, url.spec());
- // data gets freed when data2 releases the ref on it
- delete data2;
}
// Test getting using the IDataObject COM API
TEST(OSExchangeDataTest, StringDataAccessViaCOM) {
- OSExchangeData* data = new OSExchangeData;
+ OSExchangeData data;
std::wstring input = L"O hai googlz.";
- data->SetString(input);
- ScopedComPtr<IDataObject> com_data(data);
+ data.SetString(input);
+ ScopedComPtr<IDataObject> com_data(
+ OSExchangeDataProviderWin::GetIDataObject(data));
FORMATETC format_etc =
{ CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
@@ -55,10 +64,11 @@ TEST(OSExchangeDataTest, StringDataAccessViaCOM) {
// Test setting using the IDataObject COM API
TEST(OSExchangeDataTest, StringDataWritingViaCOM) {
- OSExchangeData* data = new OSExchangeData;
+ OSExchangeData data;
std::wstring input = L"http://www.google.com/";
- ScopedComPtr<IDataObject> com_data(data);
+ ScopedComPtr<IDataObject> com_data(
+ OSExchangeDataProviderWin::GetIDataObject(data));
// Store data in the object using the COM SetData API.
CLIPFORMAT cfstr_ineturl = RegisterClipboardFormat(CFSTR_INETURL);
@@ -78,22 +88,21 @@ TEST(OSExchangeDataTest, StringDataWritingViaCOM) {
// Construct a new object with the old object so that we can use our access
// APIs.
- OSExchangeData* data2 = new OSExchangeData(com_data);
- EXPECT_TRUE(data2->HasURL());
+ OSExchangeData data2(CloneProvider(data));
+ EXPECT_TRUE(data2.HasURL());
GURL url_from_data;
std::wstring title;
- EXPECT_TRUE(data2->GetURLAndTitle(&url_from_data, &title));
+ EXPECT_TRUE(data2.GetURLAndTitle(&url_from_data, &title));
GURL reference_url(input);
EXPECT_EQ(reference_url.spec(), url_from_data.spec());
- // deleting data2 will free data because it holds a ref to it.
- delete data2;
}
TEST(OSExchangeDataTest, URLDataAccessViaCOM) {
- OSExchangeData* data = new OSExchangeData;
+ OSExchangeData data;
GURL url("http://www.google.com/");
- data->SetURL(url, L"");
- ScopedComPtr<IDataObject> com_data(data);
+ data.SetURL(url, L"");
+ ScopedComPtr<IDataObject> com_data(
+ OSExchangeDataProviderWin::GetIDataObject(data));
CLIPFORMAT cfstr_ineturl = RegisterClipboardFormat(CFSTR_INETURL);
FORMATETC format_etc =
@@ -109,14 +118,15 @@ TEST(OSExchangeDataTest, URLDataAccessViaCOM) {
}
TEST(OSExchangeDataTest, MultipleFormatsViaCOM) {
- OSExchangeData* data = new OSExchangeData;
+ OSExchangeData data;
std::string url_spec = "http://www.google.com/";
GURL url(url_spec);
std::wstring text = L"O hai googlz.";
- data->SetURL(url, L"Google");
- data->SetString(text);
+ data.SetURL(url, L"Google");
+ data.SetString(text);
- ScopedComPtr<IDataObject> com_data(data);
+ ScopedComPtr<IDataObject> com_data(
+ OSExchangeDataProviderWin::GetIDataObject(data));
CLIPFORMAT cfstr_ineturl = RegisterClipboardFormat(CFSTR_INETURL);
FORMATETC url_format_etc =
@@ -143,15 +153,16 @@ TEST(OSExchangeDataTest, MultipleFormatsViaCOM) {
}
TEST(OSExchangeDataTest, EnumerationViaCOM) {
- OSExchangeData* data = new OSExchangeData;
- data->SetURL(GURL("http://www.google.com/"), L"");
- data->SetString(L"O hai googlz.");
+ OSExchangeData data;
+ data.SetURL(GURL("http://www.google.com/"), L"");
+ data.SetString(L"O hai googlz.");
CLIPFORMAT cfstr_file_group_descriptor =
RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
CLIPFORMAT text_x_moz_url = RegisterClipboardFormat(L"text/x-moz-url");
- ScopedComPtr<IDataObject> com_data(data);
+ ScopedComPtr<IDataObject> com_data(
+ OSExchangeDataProviderWin::GetIDataObject(data));
ScopedComPtr<IEnumFORMATETC> enumerator;
EXPECT_EQ(S_OK, com_data.get()->EnumFormatEtc(DATADIR_GET,
enumerator.Receive()));
@@ -231,29 +242,30 @@ TEST(OSExchangeDataTest, EnumerationViaCOM) {
}
TEST(OSExchangeDataTest, TestURLExchangeFormats) {
- OSExchangeData* data = new OSExchangeData;
+ OSExchangeData data;
std::string url_spec = "http://www.google.com/";
GURL url(url_spec);
std::wstring url_title = L"Google";
- data->SetURL(url, url_title);
+ data.SetURL(url, url_title);
std::wstring output;
- OSExchangeData* data2 = new OSExchangeData(data);
+ OSExchangeData data2(CloneProvider(data));
// URL spec and title should match
GURL output_url;
std::wstring output_title;
- EXPECT_TRUE(data2->GetURLAndTitle(&output_url, &output_title));
+ EXPECT_TRUE(data2.GetURLAndTitle(&output_url, &output_title));
EXPECT_EQ(url_spec, output_url.spec());
EXPECT_EQ(url_title, output_title);
std::wstring output_string;
// URL should be the raw text response
- EXPECT_TRUE(data2->GetString(&output_string));
+ EXPECT_TRUE(data2.GetString(&output_string));
EXPECT_EQ(url_spec, WideToUTF8(output_string));
// File contents access via COM
- ScopedComPtr<IDataObject> com_data(data);
+ ScopedComPtr<IDataObject> com_data(
+ OSExchangeDataProviderWin::GetIDataObject(data));
{
CLIPFORMAT cfstr_file_contents =
RegisterClipboardFormat(CFSTR_FILECONTENTS);
@@ -271,9 +283,6 @@ TEST(OSExchangeDataTest, TestURLExchangeFormats) {
EXPECT_EQ(file_contents, output);
ReleaseStgMedium(&medium);
}
-
- // Need to manually free data2 since we never stuff it into a COMPtr.
- delete data2;
}
TEST(OSExchangeDataTest, TestPickledData) {
@@ -282,14 +291,14 @@ TEST(OSExchangeDataTest, TestPickledData) {
Pickle saved_pickle;
saved_pickle.WriteInt(1);
saved_pickle.WriteInt(2);
- scoped_refptr<OSExchangeData> data(new OSExchangeData());
- data->SetPickledData(test_cf, saved_pickle);
+ OSExchangeData data;
+ data.SetPickledData(test_cf, saved_pickle);
- scoped_refptr<OSExchangeData> copy(new OSExchangeData(data.get()));
- EXPECT_TRUE(copy->HasFormat(test_cf));
+ OSExchangeData copy(CloneProvider(data));
+ EXPECT_TRUE(copy.HasCustomFormat(test_cf));
Pickle restored_pickle;
- EXPECT_TRUE(copy->GetPickledData(test_cf, &restored_pickle));
+ EXPECT_TRUE(copy.GetPickledData(test_cf, &restored_pickle));
void* p_iterator = NULL;
int value;
EXPECT_TRUE(restored_pickle.ReadInt(&p_iterator, &value));
@@ -299,30 +308,30 @@ TEST(OSExchangeDataTest, TestPickledData) {
}
TEST(OSExchangeDataTest, FileContents) {
- scoped_refptr<OSExchangeData> data(new OSExchangeData);
+ OSExchangeData data;
std::string file_contents("data\0with\0nulls", 15);
- data->SetFileContents(L"filename.txt", file_contents);
+ data.SetFileContents(L"filename.txt", file_contents);
- scoped_refptr<OSExchangeData> copy(new OSExchangeData(data.get()));
+ OSExchangeData copy(CloneProvider(data));
std::wstring filename;
std::string read_contents;
- EXPECT_TRUE(copy->GetFileContents(&filename, &read_contents));
+ EXPECT_TRUE(copy.GetFileContents(&filename, &read_contents));
EXPECT_EQ(L"filename.txt", filename);
EXPECT_EQ(file_contents, read_contents);
}
TEST(OSExchangeDataTest, Html) {
- scoped_refptr<OSExchangeData> data(new OSExchangeData);
+ OSExchangeData data;
GURL url("http://www.google.com/");
std::wstring html(
L"<HTML>\n<BODY>\n"
L"<b>bold.</b> <i><b>This is bold italic.</b></i>\n"
L"</BODY>\n</HTML>");
- data->SetHtml(html, url);
+ data.SetHtml(html, url);
- scoped_refptr<OSExchangeData> copy(new OSExchangeData(data.get()));
+ OSExchangeData copy(CloneProvider(data));
std::wstring read_html;
- EXPECT_TRUE(copy->GetHtml(&read_html, &url));
+ EXPECT_TRUE(copy.GetHtml(&read_html, &url));
EXPECT_EQ(html, read_html);
// Check the CF_HTML too.
@@ -335,7 +344,9 @@ TEST(OSExchangeDataTest, Html) {
expected_cf_html.append("\r\n<!--EndFragment-->\r\n</body>\r\n</html>");
STGMEDIUM medium;
- EXPECT_EQ(S_OK, data->GetData(ClipboardUtil::GetHtmlFormat(), &medium));
+ IDataObject* data_object = OSExchangeDataProviderWin::GetIDataObject(data);
+ EXPECT_EQ(S_OK,
+ data_object->GetData(ClipboardUtil::GetHtmlFormat(), &medium));
ScopedHGlobal<char> glob(medium.hGlobal);
std::string output(glob.get(), glob.Size());
EXPECT_EQ(expected_cf_html, output);
@@ -343,19 +354,19 @@ TEST(OSExchangeDataTest, Html) {
}
TEST(OSExchangeDataTest, SetURLWithMaxPath) {
- scoped_refptr<OSExchangeData> data(new OSExchangeData);
+ OSExchangeData data;
std::wstring long_title(L'a', MAX_PATH + 1);
- data->SetURL(GURL("http://google.com"), long_title);
+ data.SetURL(GURL("http://google.com"), long_title);
}
TEST(OSExchangeDataTest, ProvideURLForPlainTextURL) {
- scoped_refptr<OSExchangeData> data(new OSExchangeData);
- data->SetString(L"http://google.com");
+ OSExchangeData data;
+ data.SetString(L"http://google.com");
- scoped_ptr<OSExchangeData> data2(new OSExchangeData(data.get()));
- ASSERT_TRUE(data2->HasURL());
+ OSExchangeData data2(CloneProvider(data));
+ ASSERT_TRUE(data2.HasURL());
GURL read_url;
std::wstring title;
- EXPECT_TRUE(data2->GetURLAndTitle(&read_url, &title));
+ EXPECT_TRUE(data2.GetURLAndTitle(&read_url, &title));
EXPECT_EQ(GURL("http://google.com"), read_url);
}