Bug 966467 - Proxy clipboard service in content process (r=vlad)
authorBill McCloskey <wmccloskey@mozilla.com>
Sun, 09 Feb 2014 16:13:10 -0800
changeset 167802 2925006239ec146ad645e5113d7887feab70d54c
parent 167801 a43fb54ca20e800eca250e2f68bded7730bdb55e
child 167803 9e5d07c8c87b157212d968756333edddbf61c591
push id26186
push usercbook@mozilla.com
push dateMon, 10 Feb 2014 11:48:02 +0000
treeherdermozilla-central@063a9e3da435 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvlad
bugs966467
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 966467 - Proxy clipboard service in content process (r=vlad)
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
widget/android/nsClipboard.cpp
widget/xpwidgets/moz.build
widget/xpwidgets/nsClipboardProxy.cpp
widget/xpwidgets/nsClipboardProxy.h
widget/xpwidgets/nsContentProcessWidgetFactory.cpp
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1594,86 +1594,87 @@ ContentParent::RecvSetClipboardText(cons
 {
     nsresult rv;
     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
     NS_ENSURE_SUCCESS(rv, true);
 
     nsCOMPtr<nsISupportsString> dataWrapper =
         do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, true);
-    
+
     rv = dataWrapper->SetData(text);
     NS_ENSURE_SUCCESS(rv, true);
-    
+
     nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
     NS_ENSURE_SUCCESS(rv, true);
     trans->Init(nullptr);
-    
+
     // If our data flavor has already been added, this will fail. But we don't care
     trans->AddDataFlavor(kUnicodeMime);
     trans->SetIsPrivateData(isPrivateData);
-    
+
     nsCOMPtr<nsISupports> nsisupportsDataWrapper =
         do_QueryInterface(dataWrapper);
-    
+
     rv = trans->SetTransferData(kUnicodeMime, nsisupportsDataWrapper,
                                 text.Length() * sizeof(char16_t));
     NS_ENSURE_SUCCESS(rv, true);
-    
+
     clipboard->SetData(trans, nullptr, whichClipboard);
     return true;
 }
 
 bool
 ContentParent::RecvGetClipboardText(const int32_t& whichClipboard, nsString* text)
 {
     nsresult rv;
     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
     NS_ENSURE_SUCCESS(rv, true);
 
     nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
     NS_ENSURE_SUCCESS(rv, true);
     trans->Init(nullptr);
-    
+    trans->AddDataFlavor(kUnicodeMime);
+
     clipboard->GetData(trans, whichClipboard);
     nsCOMPtr<nsISupports> tmp;
     uint32_t len;
     rv = trans->GetTransferData(kUnicodeMime, getter_AddRefs(tmp), &len);
     if (NS_FAILED(rv))
-        return false;
+        return true;
 
     nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(tmp);
     // No support for non-text data
     if (!supportsString)
-        return false;
+        return true;
     supportsString->GetData(*text);
     return true;
 }
 
 bool
-ContentParent::RecvEmptyClipboard()
+ContentParent::RecvEmptyClipboard(const int32_t& whichClipboard)
 {
     nsresult rv;
     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
     NS_ENSURE_SUCCESS(rv, true);
 
-    clipboard->EmptyClipboard(nsIClipboard::kGlobalClipboard);
+    clipboard->EmptyClipboard(whichClipboard);
 
     return true;
 }
 
 bool
-ContentParent::RecvClipboardHasText(bool* hasText)
+ContentParent::RecvClipboardHasText(const int32_t& whichClipboard, bool* hasText)
 {
     nsresult rv;
     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
     NS_ENSURE_SUCCESS(rv, true);
 
-    clipboard->HasDataMatchingFlavors(sClipboardTextFlavors, 1, 
-                                      nsIClipboard::kGlobalClipboard, hasText);
+    clipboard->HasDataMatchingFlavors(sClipboardTextFlavors, 1,
+                                      whichClipboard, hasText);
     return true;
 }
 
 bool
 ContentParent::RecvGetSystemColors(const uint32_t& colorsCount, InfallibleTArray<uint32_t>* colors)
 {
 #ifdef MOZ_WIDGET_ANDROID
     NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -403,18 +403,18 @@ private:
     virtual bool RecvReadFontList(InfallibleTArray<FontListEntry>* retValue) MOZ_OVERRIDE;
 
     virtual bool RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions) MOZ_OVERRIDE;
 
     virtual bool RecvSetClipboardText(const nsString& text,
                                       const bool& isPrivateData,
                                       const int32_t& whichClipboard) MOZ_OVERRIDE;
     virtual bool RecvGetClipboardText(const int32_t& whichClipboard, nsString* text) MOZ_OVERRIDE;
-    virtual bool RecvEmptyClipboard() MOZ_OVERRIDE;
-    virtual bool RecvClipboardHasText(bool* hasText) MOZ_OVERRIDE;
+    virtual bool RecvEmptyClipboard(const int32_t& whichClipboard) MOZ_OVERRIDE;
+    virtual bool RecvClipboardHasText(const int32_t& whichClipboard, bool* hasText) MOZ_OVERRIDE;
 
     virtual bool RecvGetSystemColors(const uint32_t& colorsCount,
                                      InfallibleTArray<uint32_t>* colors) MOZ_OVERRIDE;
     virtual bool RecvGetIconForExtension(const nsCString& aFileExt,
                                          const uint32_t& aIconSize,
                                          InfallibleTArray<uint8_t>* bits) MOZ_OVERRIDE;
     virtual bool RecvGetShowPasswordSetting(bool* showPassword) MOZ_OVERRIDE;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -434,23 +434,21 @@ parent:
     ConsoleMessage(nsString message);
     ScriptError(nsString message, nsString sourceName, nsString sourceLine,
                 uint32_t lineNumber, uint32_t colNumber, uint32_t flags,
                 nsCString category); 
 
     // nsIPermissionManager messages
     sync ReadPermissions() returns (Permission[] permissions);
 
-    // These clipboard methods are only really used on Android since
-    // the clipboard is not available in the content process.
     SetClipboardText(nsString text, bool isPrivateData, int32_t whichClipboard);
     sync GetClipboardText(int32_t whichClipboard)
         returns (nsString text);
-    EmptyClipboard();
-    sync ClipboardHasText()
+    EmptyClipboard(int32_t whichClipboard);
+    sync ClipboardHasText(int32_t whichClipboard)
         returns (bool hasText);
 
     sync GetSystemColors(uint32_t colorsCount)
         returns (uint32_t[] colors);
 
     sync GetIconForExtension(nsCString aFileExt, uint32_t aIconSize)
         returns (uint8_t[] bits);
 
--- a/widget/android/nsClipboard.cpp
+++ b/widget/android/nsClipboard.cpp
@@ -38,43 +38,32 @@ nsClipboard::SetData(nsITransferable *aT
                                                 &len);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(tmp);
   // No support for non-text data
   NS_ENSURE_TRUE(supportsString, NS_ERROR_NOT_IMPLEMENTED);
   nsAutoString buffer;
   supportsString->GetData(buffer);
 
-  if (XRE_GetProcessType() == GeckoProcessType_Default) {
-   Clipboard::SetClipboardText(buffer);
-  } else {
-    bool isPrivateData = false;
-    aTransferable->GetIsPrivateData(&isPrivateData);
-    ContentChild::GetSingleton()->SendSetClipboardText(buffer, isPrivateData,
-                                                       aWhichClipboard);
-  }
+  Clipboard::SetClipboardText(buffer);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsClipboard::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard)
 {
   if (aWhichClipboard != kGlobalClipboard)
     return NS_ERROR_NOT_IMPLEMENTED;
 
   nsAutoString buffer;
-  if (XRE_GetProcessType() == GeckoProcessType_Default) {
-    if (!AndroidBridge::Bridge())
-      return NS_ERROR_NOT_IMPLEMENTED;
-    if (!AndroidBridge::Bridge()->GetClipboardText(buffer))
-      return NS_ERROR_UNEXPECTED;
-  } else {
-    ContentChild::GetSingleton()->SendGetClipboardText(aWhichClipboard, &buffer);
-  }
+  if (!AndroidBridge::Bridge())
+    return NS_ERROR_NOT_IMPLEMENTED;
+  if (!AndroidBridge::Bridge()->GetClipboardText(buffer))
+    return NS_ERROR_UNEXPECTED;
 
   nsresult rv;
   nsCOMPtr<nsISupportsString> dataWrapper =
     do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = dataWrapper->SetData(buffer);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -91,38 +80,30 @@ nsClipboard::GetData(nsITransferable *aT
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
 {
   if (aWhichClipboard != kGlobalClipboard)
     return NS_ERROR_NOT_IMPLEMENTED;
-  if (XRE_GetProcessType() == GeckoProcessType_Default) {
-    Clipboard::ClearText();
-  } else {
-    ContentChild::GetSingleton()->SendEmptyClipboard();
-  }
+  Clipboard::ClearText();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsClipboard::HasDataMatchingFlavors(const char **aFlavorList,
                                     uint32_t aLength, int32_t aWhichClipboard,
                                     bool *aHasText)
 {
   *aHasText = false;
   if (aWhichClipboard != kGlobalClipboard)
     return NS_ERROR_NOT_IMPLEMENTED;
-  if (XRE_GetProcessType() == GeckoProcessType_Default) {
-    *aHasText = Clipboard::HasText();
-  } else {
-    ContentChild::GetSingleton()->SendClipboardHasText(aHasText);
-  }
+  *aHasText = Clipboard::HasText();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsClipboard::SupportsSelectionClipboard(bool *aIsSupported)
 {
   *aIsSupported = false;
   return NS_OK;
--- a/widget/xpwidgets/moz.build
+++ b/widget/xpwidgets/moz.build
@@ -20,16 +20,17 @@ UNIFIED_SOURCES += [
     'GfxInfoCollector.cpp',
     'GfxInfoWebGL.cpp',
     'InputData.cpp',
     'nsBaseAppShell.cpp',
     'nsBaseDragService.cpp',
     'nsBaseScreen.cpp',
     'nsClipboardHelper.cpp',
     'nsClipboardPrivacyHandler.cpp',
+    'nsClipboardProxy.cpp',
     'nsContentProcessWidgetFactory.cpp',
     'nsFilePickerProxy.cpp',
     'nsHTMLFormatConverter.cpp',
     'nsIdleService.cpp',
     'nsIWidgetListener.cpp',
     'nsPrimitiveHelpers.cpp',
     'nsPrintOptionsImpl.cpp',
     'nsPrintSession.cpp',
new file mode 100644
--- /dev/null
+++ b/widget/xpwidgets/nsClipboardProxy.cpp
@@ -0,0 +1,93 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/ContentChild.h"
+#include "nsClipboardProxy.h"
+#include "nsISupportsPrimitives.h"
+#include "nsCOMPtr.h"
+#include "nsComponentManagerUtils.h"
+#include "nsXULAppAPI.h"
+
+using namespace mozilla;
+using mozilla::dom::ContentChild;
+
+NS_IMPL_ISUPPORTS1(nsClipboardProxy, nsIClipboard)
+
+nsClipboardProxy::nsClipboardProxy()
+{
+}
+
+NS_IMETHODIMP
+nsClipboardProxy::SetData(nsITransferable *aTransferable,
+			  nsIClipboardOwner *anOwner, int32_t aWhichClipboard)
+{
+  nsCOMPtr<nsISupports> tmp;
+  uint32_t len;
+  nsresult rv  = aTransferable->GetTransferData(kUnicodeMime, getter_AddRefs(tmp),
+                                                &len);
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(tmp);
+  // No support for non-text data
+  NS_ENSURE_TRUE(supportsString, NS_ERROR_NOT_IMPLEMENTED);
+  nsAutoString buffer;
+  supportsString->GetData(buffer);
+
+  bool isPrivateData = false;
+  aTransferable->GetIsPrivateData(&isPrivateData);
+  ContentChild::GetSingleton()->SendSetClipboardText(buffer, isPrivateData,
+						     aWhichClipboard);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsClipboardProxy::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard)
+{
+  nsAutoString buffer;
+  ContentChild::GetSingleton()->SendGetClipboardText(aWhichClipboard, &buffer);
+
+  nsresult rv;
+  nsCOMPtr<nsISupportsString> dataWrapper =
+    do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = dataWrapper->SetData(buffer);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // If our data flavor has already been added, this will fail. But we don't care
+  aTransferable->AddDataFlavor(kUnicodeMime);
+
+  nsCOMPtr<nsISupports> nsisupportsDataWrapper =
+    do_QueryInterface(dataWrapper);
+  rv = aTransferable->SetTransferData(kUnicodeMime, nsisupportsDataWrapper,
+                                      buffer.Length() * sizeof(char16_t));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsClipboardProxy::EmptyClipboard(int32_t aWhichClipboard)
+{
+  ContentChild::GetSingleton()->SendEmptyClipboard(aWhichClipboard);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsClipboardProxy::HasDataMatchingFlavors(const char **aFlavorList,
+                                    uint32_t aLength, int32_t aWhichClipboard,
+                                    bool *aHasText)
+{
+  *aHasText = false;
+  ContentChild::GetSingleton()->SendClipboardHasText(aWhichClipboard, aHasText);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsClipboardProxy::SupportsSelectionClipboard(bool *aIsSupported)
+{
+  *aIsSupported = false;
+  return NS_OK;
+}
+
new file mode 100644
--- /dev/null
+++ b/widget/xpwidgets/nsClipboardProxy.h
@@ -0,0 +1,20 @@
+/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef NS_CLIPBOARD_PROXY_H
+#define NS_CLIPBOARD_PROXY_H
+
+#include "nsIClipboard.h"
+
+class nsClipboardProxy MOZ_FINAL : public nsIClipboard
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICLIPBOARD
+
+  nsClipboardProxy();
+};
+
+#endif
--- a/widget/xpwidgets/nsContentProcessWidgetFactory.cpp
+++ b/widget/xpwidgets/nsContentProcessWidgetFactory.cpp
@@ -2,33 +2,39 @@
 /* vim:expandtab:shiftwidth=4:tabstop=4:
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ModuleUtils.h"
 #include "nsWidgetsCID.h"
+#include "nsClipboardProxy.h"
 #include "nsFilePickerProxy.h"
 
 using namespace mozilla;
 
 #ifndef MOZ_B2G
 
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardProxy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePickerProxy)
 
+NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
 NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
 
 static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
+    { &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardProxyConstructor,
+      Module::CONTENT_PROCESS_ONLY },
     { &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerProxyConstructor,
       Module::CONTENT_PROCESS_ONLY },
     { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
+    { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID, Module::CONTENT_PROCESS_ONLY },
     { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::CONTENT_PROCESS_ONLY },
     { nullptr }
 };
 
 static const mozilla::Module kWidgetModule = {
     mozilla::Module::kVersion,
     kWidgetCIDs,
     kWidgetContracts