editor/libeditor/base/DeleteRangeTxn.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "DeleteNodeTxn.h"
     7 #include "DeleteRangeTxn.h"
     8 #include "DeleteTextTxn.h"
     9 #include "mozilla/Assertions.h"
    10 #include "mozilla/dom/Selection.h"
    11 #include "mozilla/mozalloc.h"
    12 #include "nsCOMPtr.h"
    13 #include "nsDebug.h"
    14 #include "nsEditor.h"
    15 #include "nsError.h"
    16 #include "nsIContent.h"
    17 #include "nsIContentIterator.h"
    18 #include "nsIDOMCharacterData.h"
    19 #include "nsINode.h"
    20 #include "nsAString.h"
    22 class nsIDOMRange;
    24 using namespace mozilla;
    25 using namespace mozilla::dom;
    27 // note that aEditor is not refcounted
    28 DeleteRangeTxn::DeleteRangeTxn()
    29   : EditAggregateTxn(),
    30     mRange(),
    31     mEditor(nullptr),
    32     mRangeUpdater(nullptr)
    33 {
    34 }
    36 NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteRangeTxn, EditAggregateTxn,
    37                                    mRange)
    39 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteRangeTxn)
    40 NS_INTERFACE_MAP_END_INHERITING(EditAggregateTxn)
    42 nsresult
    43 DeleteRangeTxn::Init(nsEditor* aEditor,
    44                      nsRange* aRange,
    45                      nsRangeUpdater* aRangeUpdater)
    46 {
    47   MOZ_ASSERT(aEditor && aRange);
    49   mEditor = aEditor;
    50   mRange = aRange->CloneRange();
    51   mRangeUpdater = aRangeUpdater;
    53   NS_ENSURE_TRUE(mEditor->IsModifiableNode(mRange->GetStartParent()),
    54                  NS_ERROR_FAILURE);
    55   NS_ENSURE_TRUE(mEditor->IsModifiableNode(mRange->GetEndParent()),
    56                  NS_ERROR_FAILURE);
    57   NS_ENSURE_TRUE(mEditor->IsModifiableNode(mRange->GetCommonAncestor()),
    58                  NS_ERROR_FAILURE);
    60   return NS_OK;
    61 }
    63 NS_IMETHODIMP
    64 DeleteRangeTxn::DoTransaction()
    65 {
    66   MOZ_ASSERT(mRange && mEditor);
    67   nsresult res;
    69   // build the child transactions
    70   nsCOMPtr<nsINode> startParent = mRange->GetStartParent();
    71   int32_t startOffset = mRange->StartOffset();
    72   nsCOMPtr<nsINode> endParent = mRange->GetEndParent();
    73   int32_t endOffset = mRange->EndOffset();
    74   MOZ_ASSERT(startParent && endParent);
    76   if (startParent == endParent) {
    77     // the selection begins and ends in the same node
    78     res = CreateTxnsToDeleteBetween(startParent, startOffset, endOffset);
    79     NS_ENSURE_SUCCESS(res, res);
    80   } else {
    81     // the selection ends in a different node from where it started.  delete
    82     // the relevant content in the start node
    83     res = CreateTxnsToDeleteContent(startParent, startOffset, nsIEditor::eNext);
    84     NS_ENSURE_SUCCESS(res, res);
    85     // delete the intervening nodes
    86     res = CreateTxnsToDeleteNodesBetween();
    87     NS_ENSURE_SUCCESS(res, res);
    88     // delete the relevant content in the end node
    89     res = CreateTxnsToDeleteContent(endParent, endOffset, nsIEditor::ePrevious);
    90     NS_ENSURE_SUCCESS(res, res);
    91   }
    93   // if we've successfully built this aggregate transaction, then do it.
    94   res = EditAggregateTxn::DoTransaction();
    95   NS_ENSURE_SUCCESS(res, res);
    97   // only set selection to deletion point if editor gives permission
    98   bool bAdjustSelection;
    99   mEditor->ShouldTxnSetSelection(&bAdjustSelection);
   100   if (bAdjustSelection) {
   101     nsRefPtr<Selection> selection = mEditor->GetSelection();
   102     NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
   103     res = selection->Collapse(startParent, startOffset);
   104     NS_ENSURE_SUCCESS(res, res);
   105   }
   106   // else do nothing - dom range gravity will adjust selection
   108   return NS_OK;
   109 }
   111 NS_IMETHODIMP
   112 DeleteRangeTxn::UndoTransaction()
   113 {
   114   MOZ_ASSERT(mRange && mEditor);
   116   return EditAggregateTxn::UndoTransaction();
   117 }
   119 NS_IMETHODIMP
   120 DeleteRangeTxn::RedoTransaction()
   121 {
   122   MOZ_ASSERT(mRange && mEditor);
   124   return EditAggregateTxn::RedoTransaction();
   125 }
   127 NS_IMETHODIMP
   128 DeleteRangeTxn::GetTxnDescription(nsAString& aString)
   129 {
   130   aString.AssignLiteral("DeleteRangeTxn");
   131   return NS_OK;
   132 }
   134 nsresult
   135 DeleteRangeTxn::CreateTxnsToDeleteBetween(nsINode* aNode,
   136                                           int32_t aStartOffset,
   137                                           int32_t aEndOffset)
   138 {
   139   // see what kind of node we have
   140   if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) {
   141     // if the node is a chardata node, then delete chardata content
   142     nsRefPtr<DeleteTextTxn> txn = new DeleteTextTxn();
   144     int32_t numToDel;
   145     if (aStartOffset == aEndOffset) {
   146       numToDel = 1;
   147     } else {
   148       numToDel = aEndOffset - aStartOffset;
   149     }
   151     nsCOMPtr<nsIDOMCharacterData> charDataNode = do_QueryInterface(aNode);
   152     nsresult res = txn->Init(mEditor, charDataNode, aStartOffset, numToDel,
   153                              mRangeUpdater);
   154     NS_ENSURE_SUCCESS(res, res);
   156     AppendChild(txn);
   157     return NS_OK;
   158   }
   160   nsCOMPtr<nsIContent> child = aNode->GetChildAt(aStartOffset);
   161   NS_ENSURE_STATE(child);
   163   nsresult res = NS_OK;
   164   for (int32_t i = aStartOffset; i < aEndOffset; ++i) {
   165     nsRefPtr<DeleteNodeTxn> txn = new DeleteNodeTxn();
   166     res = txn->Init(mEditor, child, mRangeUpdater);
   167     if (NS_SUCCEEDED(res)) {
   168       AppendChild(txn);
   169     }
   171     child = child->GetNextSibling();
   172   }
   174   NS_ENSURE_SUCCESS(res, res);
   175   return NS_OK;
   176 }
   178 nsresult
   179 DeleteRangeTxn::CreateTxnsToDeleteContent(nsINode* aNode,
   180                                           int32_t aOffset,
   181                                           nsIEditor::EDirection aAction)
   182 {
   183   // see what kind of node we have
   184   if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) {
   185     // if the node is a chardata node, then delete chardata content
   186     uint32_t start, numToDelete;
   187     if (nsIEditor::eNext == aAction) {
   188       start = aOffset;
   189       numToDelete = aNode->Length() - aOffset;
   190     } else {
   191       start = 0;
   192       numToDelete = aOffset;
   193     }
   195     if (numToDelete) {
   196       nsRefPtr<DeleteTextTxn> txn = new DeleteTextTxn();
   198       nsCOMPtr<nsIDOMCharacterData> charDataNode = do_QueryInterface(aNode);
   199       nsresult res = txn->Init(mEditor, charDataNode, start, numToDelete,
   200                                mRangeUpdater);
   201       NS_ENSURE_SUCCESS(res, res);
   203       AppendChild(txn);
   204     }
   205   }
   207   return NS_OK;
   208 }
   210 nsresult
   211 DeleteRangeTxn::CreateTxnsToDeleteNodesBetween()
   212 {
   213   nsCOMPtr<nsIContentIterator> iter = NS_NewContentSubtreeIterator();
   215   nsresult res = iter->Init(mRange);
   216   NS_ENSURE_SUCCESS(res, res);
   218   while (!iter->IsDone()) {
   219     nsCOMPtr<nsINode> node = iter->GetCurrentNode();
   220     NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
   222     nsRefPtr<DeleteNodeTxn> txn = new DeleteNodeTxn();
   224     res = txn->Init(mEditor, node, mRangeUpdater);
   225     NS_ENSURE_SUCCESS(res, res);
   226     AppendChild(txn);
   228     iter->Next();
   229   }
   230   return NS_OK;
   231 }

mercurial