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