Bug 1261299 - Implement nsIClipboard methods in nsClipboard.mm with methods specific for osx. (EmptyClipboard, SetData) methods modified from nsBaseClipboard to also set the current selection cache. draft
authorJimmy Wang <jimmyw22@gmail.com>
Thu, 11 Aug 2016 16:43:32 -0400
changeset 401299 6d83ff4eb530843be75dfa9fc80a133939be2324
parent 401298 7b2c3e3d9b6cd5defec315fd67ee85f77c291d5a
child 528455 35d0d4edb404f062dcb8568b43b6581fd3a12d24
push id26424
push userjimmyw22@gmail.com
push dateTue, 16 Aug 2016 21:05:59 +0000
bugs1261299
milestone51.0a1
Bug 1261299 - Implement nsIClipboard methods in nsClipboard.mm with methods specific for osx. (EmptyClipboard, SetData) methods modified from nsBaseClipboard to also set the current selection cache. MozReview-Commit-ID: D8aRmK6FAai
widget/cocoa/nsClipboard.h
widget/cocoa/nsClipboard.mm
widget/nsBaseClipboard.cpp
widget/nsBaseClipboard.h
--- a/widget/cocoa/nsClipboard.h
+++ b/widget/cocoa/nsClipboard.h
@@ -1,35 +1,32 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 nsClipboard_h_
 #define nsClipboard_h_
 
-#include "nsBaseClipboard.h"
+#include "nsIClipboard.h"
 #include "nsXPIDLString.h"
 #include "mozilla/StaticPtr.h"
 
 #import <Cocoa/Cocoa.h>
 
 class nsITransferable;
 
-class nsClipboard : public nsBaseClipboard
+class nsClipboard : public nsIClipboard
 {
 
 public:
   nsClipboard();
-  virtual ~nsClipboard();
 
-  // nsIClipboard  
-  NS_IMETHOD HasDataMatchingFlavors(const char** aFlavorList, uint32_t aLength,
-                                    int32_t aWhichClipboard, bool *_retval);
-  NS_IMETHOD SupportsFindClipboard(bool *_retval);
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICLIPBOARD
 
   // On macOS, cache the transferable of the current selection (chrome/content)
   // in the parent process. This is needed for the services menu which
   // requires synchronous access to the current selection.
   static mozilla::StaticRefPtr<nsITransferable> sSelectionCache;
 
   // Helper methods, used also by nsDragService
   static NSDictionary* PasteboardDictFromTransferable(nsITransferable *aTransferable);
@@ -41,13 +38,18 @@ protected:
 
   // impelement the native clipboard behavior
   NS_IMETHOD SetNativeClipboardData(int32_t aWhichClipboard);
   NS_IMETHOD GetNativeClipboardData(nsITransferable * aTransferable, int32_t aWhichClipboard);
   void ClearSelectionCache();
   void SetSelectionCache(nsITransferable* aTransferable);
   
 private:
+  virtual ~nsClipboard();
   int32_t mCachedClipboard;
   int32_t mChangeCount; // Set to the native change count after any modification of the clipboard.
+
+  bool                        mIgnoreEmptyNotification;
+  nsCOMPtr<nsIClipboardOwner> mClipboardOwner;
+  nsCOMPtr<nsITransferable>   mTransferable;
 };
 
 #endif // nsClipboard_h_
--- a/widget/cocoa/nsClipboard.mm
+++ b/widget/cocoa/nsClipboard.mm
@@ -32,29 +32,33 @@ using mozilla::LogLevel;
 #define IMAGE_PASTEBOARD_TYPES NSTIFFPboardType, @"Apple PNG pasteboard type", nil
 
 extern PRLogModuleInfo* sCocoaLog;
 
 extern void EnsureLogInitialized();
 
 mozilla::StaticRefPtr<nsITransferable> nsClipboard::sSelectionCache;
 
-nsClipboard::nsClipboard() : nsBaseClipboard()
+nsClipboard::nsClipboard()
+  : mCachedClipboard(-1)
+  , mChangeCount(0)
+  , mIgnoreEmptyNotification(false)
 {
-  mCachedClipboard = -1;
-  mChangeCount = 0;
-
   EnsureLogInitialized();
 }
 
 nsClipboard::~nsClipboard()
 {
-  sSelectionCache = nullptr;
+  EmptyClipboard(kGlobalClipboard);
+  EmptyClipboard(kFindClipboard);
+  ClearSelectionCache();
 }
 
+NS_IMPL_ISUPPORTS(nsClipboard, nsIClipboard)
+
 // We separate this into its own function because after an @try, all local
 // variables within that function get marked as volatile, and our C++ type
 // system doesn't like volatile things.
 static NSData*
 GetDataFromPasteboard(NSPasteboard* aPasteboard, NSString* aType)
 {
   NSData *data = nil;
   @try {
@@ -341,17 +345,17 @@ nsClipboard::GetNativeClipboardData(nsIT
         rv = mTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize);
         if (NS_SUCCEEDED(rv)) {
           aTransferable->SetTransferData(flavorStr, dataSupports, dataSize);
           return NS_OK; // maybe try to fill in more types? Is there a point?
         }
       }
     }
   } else {
-    nsBaseClipboard::EmptyClipboard(aWhichClipboard);
+    EmptyClipboard(aWhichClipboard);
   }
 
   // at this point we can't satisfy the request from cache data so let's look
   // for things other people put on the system clipboard
 
   return nsClipboard::TransferableFromPasteboard(aTransferable, cocoaPasteboard);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
@@ -669,8 +673,109 @@ NSString* nsClipboard::WrapHtmlForSystem
            "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"
          "</head>"
          "<body>"
            "%@"
          "</body>"
        "</html>", aString];
   return wrapped;
 }
+
+/**
+  * Sets the transferable object
+  *
+  */
+NS_IMETHODIMP
+nsClipboard::SetData(nsITransferable* aTransferable, nsIClipboardOwner* anOwner,
+                     int32_t aWhichClipboard)
+{
+  NS_ASSERTION (aTransferable, "clipboard given a null transferable");
+
+  if (aWhichClipboard == kSelectionCache) {
+    if (aTransferable) {
+      SetSelectionCache(aTransferable);
+      return NS_OK;
+    }
+    return NS_ERROR_FAILURE;
+  }
+
+  if (aTransferable == mTransferable && anOwner == mClipboardOwner) {
+    return NS_OK;
+  }
+  bool selectClipPresent;
+  SupportsSelectionClipboard(&selectClipPresent);
+  bool findClipPresent;
+  SupportsFindClipboard(&findClipPresent);
+  if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard) {
+    return NS_ERROR_FAILURE;
+  }
+
+  EmptyClipboard(aWhichClipboard);
+
+  mClipboardOwner = anOwner;
+  mTransferable = aTransferable;
+
+  nsresult rv = NS_ERROR_FAILURE;
+  if (mTransferable) {
+    rv = SetNativeClipboardData(aWhichClipboard);
+  }
+
+  return rv;
+}
+
+/**
+  * Gets the transferable object
+  *
+  */
+NS_IMETHODIMP
+nsClipboard::GetData(nsITransferable* aTransferable, int32_t aWhichClipboard)
+{
+  NS_ASSERTION (aTransferable, "clipboard given a null transferable");
+
+  bool selectClipPresent;
+  SupportsSelectionClipboard(&selectClipPresent);
+  bool findClipPresent;
+  SupportsFindClipboard(&findClipPresent);
+  if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard)
+    return NS_ERROR_FAILURE;
+
+  if (aTransferable) {
+    return GetNativeClipboardData(aTransferable, aWhichClipboard);
+  }
+
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
+{
+  if (aWhichClipboard == kSelectionCache) {
+    ClearSelectionCache();
+    return NS_OK;
+  }
+
+  bool selectClipPresent;
+  SupportsSelectionClipboard(&selectClipPresent);
+  bool findClipPresent;
+  SupportsFindClipboard(&findClipPresent);
+  if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (mIgnoreEmptyNotification) {
+    return NS_OK;
+  }
+
+  if (mClipboardOwner) {
+    mClipboardOwner->LosingOwnership(mTransferable);
+    mClipboardOwner = nullptr;
+  }
+
+  mTransferable = nullptr;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsClipboard::SupportsSelectionClipboard(bool* _retval)
+{
+  *_retval = false;   // we don't support the selection clipboard by default.
+  return NS_OK;
+}
\ No newline at end of file
--- a/widget/nsBaseClipboard.cpp
+++ b/widget/nsBaseClipboard.cpp
@@ -29,24 +29,16 @@ NS_IMPL_ISUPPORTS(nsBaseClipboard, nsICl
   * Sets the transferable object
   *
   */
 NS_IMETHODIMP nsBaseClipboard::SetData(nsITransferable * aTransferable, nsIClipboardOwner * anOwner,
                                         int32_t aWhichClipboard)
 {
   NS_ASSERTION ( aTransferable, "clipboard given a null transferable" );
 
-  if (aWhichClipboard == kSelectionCache) {
-    if (aTransferable) {
-      SetSelectionCache(aTransferable);
-      return NS_OK;
-    }
-    return NS_ERROR_FAILURE;
-  }
-
   if (aTransferable == mTransferable && anOwner == mClipboardOwner)
     return NS_OK;
   bool selectClipPresent;
   SupportsSelectionClipboard(&selectClipPresent);
   bool findClipPresent;
   SupportsFindClipboard(&findClipPresent);
   if ( !selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard )
     return NS_ERROR_FAILURE;
@@ -84,21 +76,16 @@ NS_IMETHODIMP nsBaseClipboard::GetData(n
   if ( aTransferable )
     return GetNativeClipboardData(aTransferable, aWhichClipboard);
 
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP nsBaseClipboard::EmptyClipboard(int32_t aWhichClipboard)
 {
-  if (aWhichClipboard == kSelectionCache) {
-    ClearSelectionCache();
-    return NS_OK;
-  }
-
   bool selectClipPresent;
   SupportsSelectionClipboard(&selectClipPresent);
   bool findClipPresent;
   SupportsFindClipboard(&findClipPresent);
   if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard)
     return NS_ERROR_FAILURE;
 
   if (mIgnoreEmptyNotification)
--- a/widget/nsBaseClipboard.h
+++ b/widget/nsBaseClipboard.h
@@ -29,18 +29,16 @@ public:
   // nsIClipboard  
   NS_DECL_NSICLIPBOARD
   
 protected:
   virtual ~nsBaseClipboard();
 
   NS_IMETHOD SetNativeClipboardData ( int32_t aWhichClipboard ) = 0;
   NS_IMETHOD GetNativeClipboardData ( nsITransferable * aTransferable, int32_t aWhichClipboard ) = 0;
-  virtual void ClearSelectionCache () = 0;
-  virtual void SetSelectionCache (nsITransferable* aTransferable) = 0;
 
   bool                mEmptyingForSetData;
   bool                mIgnoreEmptyNotification;
   nsCOMPtr<nsIClipboardOwner> mClipboardOwner;
   nsCOMPtr<nsITransferable>   mTransferable;
 
 };