Bug 1327798 - Part 1. PasteNoFormatting shouldn't set text/html to clipboard event on paste. r=enndeakin
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Wed, 22 Feb 2017 18:34:45 +0900
changeset 488151 ac3511a433966bd9ed0a1065b362e8a9fe70b1cf
parent 488150 acdb8e6dc477e1e4c01b7dd53e94bb4e0823b62b
child 488152 bbd4c0e017c80cf09a578a723d23b94f38cbda57
push id46446
push userna-g@nostrum.com
push dateWed, 22 Feb 2017 18:16:33 +0000
reviewersenndeakin
bugs1327798
milestone54.0a1
Bug 1327798 - Part 1. PasteNoFormatting shouldn't set text/html to clipboard event on paste. r=enndeakin MozReview-Commit-ID: 8VMudiPiXcK
dom/base/nsCopySupport.cpp
dom/events/DataTransfer.cpp
dom/events/DataTransfer.h
editor/libeditor/HTMLEditorDataTransfer.cpp
widget/EventMessageList.h
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -750,18 +750,23 @@ nsCopySupport::FireClipboardEvent(EventM
                                   nsIPresShell* aPresShell,
                                   nsISelection* aSelection,
                                   bool* aActionTaken)
 {
   if (aActionTaken) {
     *aActionTaken = false;
   }
 
-  NS_ASSERTION(aEventMessage == eCut || aEventMessage == eCopy ||
-               aEventMessage == ePaste,
+  EventMessage originalEventMessage = aEventMessage;
+  if (originalEventMessage == ePasteNoFormatting) {
+    originalEventMessage = ePaste;
+  }
+
+  NS_ASSERTION(originalEventMessage == eCut || originalEventMessage == eCopy ||
+               originalEventMessage == ePaste,
                "Invalid clipboard event type");
 
   nsCOMPtr<nsIPresShell> presShell = aPresShell;
   if (!presShell)
     return false;
 
   nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
   if (!doc)
@@ -808,31 +813,31 @@ nsCopySupport::FireClipboardEvent(EventM
     docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome;
 
   // next, fire the cut, copy or paste event
   bool doDefault = true;
   RefPtr<DataTransfer> clipboardData;
   if (chromeShell || Preferences::GetBool("dom.event.clipboardevents.enabled", true)) {
     clipboardData =
       new DataTransfer(doc->GetScopeObject(), aEventMessage,
-                       aEventMessage == ePaste, aClipboardType);
+                       originalEventMessage == ePaste, aClipboardType);
 
     nsEventStatus status = nsEventStatus_eIgnore;
-    InternalClipboardEvent evt(true, aEventMessage);
+    InternalClipboardEvent evt(true, originalEventMessage);
     evt.mClipboardData = clipboardData;
     EventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt,
                               nullptr, &status);
     // If the event was cancelled, don't do the clipboard operation
     doDefault = (status != nsEventStatus_eConsumeNoDefault);
   }
 
   // No need to do anything special during a paste. Either an event listener
   // took care of it and cancelled the event, or the caller will handle it.
   // Return true to indicate that the event wasn't cancelled.
-  if (aEventMessage == ePaste) {
+  if (originalEventMessage == ePaste) {
     // Clear and mark the clipboardData as readonly. This prevents someone
     // from reading the clipboard contents after the paste event has fired.
     if (clipboardData) {
       clipboardData->ClearAll();
       clipboardData->SetReadOnly();
     }
 
     if (aActionTaken) {
@@ -862,17 +867,17 @@ nsCopySupport::FireClipboardEvent(EventM
     if (formControl) {
       if (formControl->GetType() == NS_FORM_INPUT_PASSWORD) {
         return false;
       }
     }
 
     // when cutting non-editable content, do nothing
     // XXX this is probably the wrong editable flag to check
-    if (aEventMessage != eCut || content->IsEditable()) {
+    if (originalEventMessage != eCut || content->IsEditable()) {
       // get the data from the selection if any
       bool isCollapsed;
       sel->GetIsCollapsed(&isCollapsed);
       if (isCollapsed) {
         if (aActionTaken) {
           *aActionTaken = true;
         }
         return false;
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -100,18 +100,21 @@ DataTransfer::DataTransfer(nsISupports* 
   // For these events, we want to be able to add data to the data transfer, so
   // clear the readonly state. Otherwise, the data is already present. For
   // external usage, cache the data from the native clipboard or drag.
   if (aEventMessage == eCut ||
       aEventMessage == eCopy ||
       aEventMessage == eDragStart) {
     mReadOnly = false;
   } else if (mIsExternal) {
-    if (aEventMessage == ePaste) {
-      CacheExternalClipboardFormats();
+    if (aEventMessage == ePasteNoFormatting) {
+      mEventMessage = ePaste;
+      CacheExternalClipboardFormats(true);
+    } else if (aEventMessage == ePaste) {
+      CacheExternalClipboardFormats(false);
     } else if (aEventMessage >= eDragDropEventFirst &&
                aEventMessage <= eDragDropEventLast) {
       CacheExternalDragFormats();
     }
   }
 }
 
 DataTransfer::DataTransfer(nsISupports* aParent,
@@ -1351,17 +1354,17 @@ DataTransfer::CacheExternalDragFormats()
       if (supported) {
         CacheExternalData(formats[f], c, sysPrincipal, /* hidden = */ f && hasFileData);
       }
     }
   }
 }
 
 void
-DataTransfer::CacheExternalClipboardFormats()
+DataTransfer::CacheExternalClipboardFormats(bool aPlainTextOnly)
 {
   NS_ASSERTION(mEventMessage == ePaste,
                "caching clipboard data for invalid event");
 
   // Called during the constructor for paste events to cache the formats
   // available on the clipboard. As with CacheExternalDragFormats, the
   // data will only be retrieved when needed.
 
@@ -1370,16 +1373,27 @@ DataTransfer::CacheExternalClipboardForm
   if (!clipboard || mClipboardType < 0) {
     return;
   }
 
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   nsCOMPtr<nsIPrincipal> sysPrincipal;
   ssm->GetSystemPrincipal(getter_AddRefs(sysPrincipal));
 
+  if (aPlainTextOnly) {
+    bool supported;
+    const char* unicodeMime[] = { kUnicodeMime };
+    clipboard->HasDataMatchingFlavors(unicodeMime, 1, mClipboardType,
+                                      &supported);
+    if (supported) {
+      CacheExternalData(kUnicodeMime, 0, sysPrincipal, false);
+    }
+    return;
+  }
+
   // Check if the clipboard has any files
   bool hasFileData = false;
   const char *fileMime[] = { kFileMime };
   clipboard->HasDataMatchingFlavors(fileMime, 1, mClipboardType, &hasFileData);
 
   // We will be ignoring any application/x-moz-file files found in the paste
   // datatransfer within e10s, as they will fail to be sent over IPC. Because of
   // that, we will unset hasFileData, whether or not it would have been set.
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -302,17 +302,17 @@ protected:
   nsresult CacheExternalData(const char* aFormat, uint32_t aIndex,
                              nsIPrincipal* aPrincipal, bool aHidden);
 
   // caches the formats that exist in the drag service that were added by an
   // external drag
   void CacheExternalDragFormats();
 
   // caches the formats that exist in the clipboard
-  void CacheExternalClipboardFormats();
+  void CacheExternalClipboardFormats(bool aPlainTextOnly);
 
   FileList* GetFilesInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal);
   nsresult GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex,
                              nsIPrincipal* aSubjectPrincipal,
                              nsIVariant** aData);
 
   nsresult SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
                              uint32_t aIndex, nsIPrincipal* aSubjectPrincipal);
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -1490,17 +1490,17 @@ HTMLEditor::PasteTransferable(nsITransfe
 }
 
 /**
  * HTML PasteNoFormatting. Ignore any HTML styles and formating in paste source.
  */
 NS_IMETHODIMP
 HTMLEditor::PasteNoFormatting(int32_t aSelectionType)
 {
-  if (!FireClipboardEvent(ePaste, aSelectionType)) {
+  if (!FireClipboardEvent(ePasteNoFormatting, aSelectionType)) {
     return NS_OK;
   }
 
   ForceCompositionEnd();
 
   // Get Clipboard Service
   nsresult rv;
   nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
--- a/widget/EventMessageList.h
+++ b/widget/EventMessageList.h
@@ -221,16 +221,17 @@ NS_EVENT_MESSAGE(eSVGZoom)
 
 // XUL command events
 NS_EVENT_MESSAGE(eXULCommand)
 
 // Cut, copy, paste events
 NS_EVENT_MESSAGE(eCopy)
 NS_EVENT_MESSAGE(eCut)
 NS_EVENT_MESSAGE(ePaste)
+NS_EVENT_MESSAGE(ePasteNoFormatting)
 
 // Query for the selected text information, it return the selection offset,
 // selection length and selected text.
 NS_EVENT_MESSAGE(eQuerySelectedText)
 // Query for the text content of specified range, it returns actual lengh (if
 // the specified range is too long) and the text of the specified range.
 // Returns the entire text if requested length > actual length.
 NS_EVENT_MESSAGE(eQueryTextContent)