Line data Source code
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/. */
5 :
6 : #include "mozilla/EditorUtils.h"
7 :
8 : #include "mozilla/OwningNonNull.h"
9 : #include "mozilla/dom/Selection.h"
10 : #include "nsComponentManagerUtils.h"
11 : #include "nsError.h"
12 : #include "nsIClipboardDragDropHookList.h"
13 : // hooks
14 : #include "nsIClipboardDragDropHooks.h"
15 : #include "nsIContent.h"
16 : #include "nsIContentIterator.h"
17 : #include "nsIDOMDocument.h"
18 : #include "nsIDocShell.h"
19 : #include "nsIDocument.h"
20 : #include "nsIInterfaceRequestorUtils.h"
21 : #include "nsINode.h"
22 : #include "nsISimpleEnumerator.h"
23 :
24 : class nsISupports;
25 : class nsRange;
26 :
27 : namespace mozilla {
28 :
29 : using namespace dom;
30 :
31 : /******************************************************************************
32 : * AutoSelectionRestorer
33 : *****************************************************************************/
34 :
35 0 : AutoSelectionRestorer::AutoSelectionRestorer(
36 : Selection* aSelection,
37 : EditorBase* aEditorBase
38 0 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
39 0 : : mEditorBase(nullptr)
40 : {
41 0 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
42 0 : if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aEditorBase)) {
43 0 : return;
44 : }
45 0 : if (aEditorBase->ArePreservingSelection()) {
46 : // We already have initialized mSavedSel, so this must be nested call.
47 0 : return;
48 : }
49 0 : mSelection = aSelection;
50 0 : mEditorBase = aEditorBase;
51 0 : mEditorBase->PreserveSelectionAcrossActions(mSelection);
52 : }
53 :
54 0 : AutoSelectionRestorer::~AutoSelectionRestorer()
55 : {
56 0 : NS_ASSERTION(!mSelection || mEditorBase,
57 : "mEditorBase should be non-null when mSelection is");
58 : // mSelection will be null if this was nested call.
59 0 : if (mSelection && mEditorBase->ArePreservingSelection()) {
60 0 : mEditorBase->RestorePreservedSelection(mSelection);
61 : }
62 0 : }
63 :
64 : void
65 0 : AutoSelectionRestorer::Abort()
66 : {
67 0 : NS_ASSERTION(!mSelection || mEditorBase,
68 : "mEditorBase should be non-null when mSelection is");
69 0 : if (mSelection) {
70 0 : mEditorBase->StopPreservingSelection();
71 : }
72 0 : }
73 :
74 : /******************************************************************************
75 : * some helper classes for iterating the dom tree
76 : *****************************************************************************/
77 :
78 0 : DOMIterator::DOMIterator(nsINode& aNode MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
79 : {
80 0 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
81 0 : mIter = NS_NewContentIterator();
82 0 : DebugOnly<nsresult> rv = mIter->Init(&aNode);
83 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
84 0 : }
85 :
86 : nsresult
87 0 : DOMIterator::Init(nsRange& aRange)
88 : {
89 0 : mIter = NS_NewContentIterator();
90 0 : return mIter->Init(&aRange);
91 : }
92 :
93 0 : DOMIterator::DOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
94 : {
95 0 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
96 0 : }
97 :
98 0 : DOMIterator::~DOMIterator()
99 : {
100 0 : }
101 :
102 : void
103 0 : DOMIterator::AppendList(const BoolDomIterFunctor& functor,
104 : nsTArray<OwningNonNull<nsINode>>& arrayOfNodes) const
105 : {
106 : // Iterate through dom and build list
107 0 : for (; !mIter->IsDone(); mIter->Next()) {
108 0 : nsCOMPtr<nsINode> node = mIter->GetCurrentNode();
109 :
110 0 : if (functor(node)) {
111 0 : arrayOfNodes.AppendElement(*node);
112 : }
113 : }
114 0 : }
115 :
116 0 : DOMSubtreeIterator::DOMSubtreeIterator(
117 0 : MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
118 0 : : DOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT)
119 : {
120 0 : }
121 :
122 : nsresult
123 0 : DOMSubtreeIterator::Init(nsRange& aRange)
124 : {
125 0 : mIter = NS_NewContentSubtreeIterator();
126 0 : return mIter->Init(&aRange);
127 : }
128 :
129 0 : DOMSubtreeIterator::~DOMSubtreeIterator()
130 : {
131 0 : }
132 :
133 : /******************************************************************************
134 : * some general purpose editor utils
135 : *****************************************************************************/
136 :
137 : bool
138 0 : EditorUtils::IsDescendantOf(nsINode* aNode,
139 : nsINode* aParent,
140 : int32_t* aOffset)
141 : {
142 0 : MOZ_ASSERT(aNode && aParent);
143 0 : if (aNode == aParent) {
144 0 : return false;
145 : }
146 :
147 0 : for (nsCOMPtr<nsINode> node = aNode; node; node = node->GetParentNode()) {
148 0 : if (node->GetParentNode() == aParent) {
149 0 : if (aOffset) {
150 0 : *aOffset = aParent->IndexOf(node);
151 : }
152 0 : return true;
153 : }
154 : }
155 :
156 0 : return false;
157 : }
158 :
159 : bool
160 0 : EditorUtils::IsDescendantOf(nsIDOMNode* aNode,
161 : nsIDOMNode* aParent,
162 : int32_t* aOffset)
163 : {
164 0 : nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
165 0 : nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
166 0 : NS_ENSURE_TRUE(node && parent, false);
167 0 : return IsDescendantOf(node, parent, aOffset);
168 : }
169 :
170 : bool
171 0 : EditorUtils::IsLeafNode(nsIDOMNode* aNode)
172 : {
173 0 : bool hasChildren = false;
174 0 : if (aNode)
175 0 : aNode->HasChildNodes(&hasChildren);
176 0 : return !hasChildren;
177 : }
178 :
179 : /******************************************************************************
180 : * utility methods for drag/drop/copy/paste hooks
181 : *****************************************************************************/
182 :
183 : nsresult
184 0 : EditorHookUtils::GetHookEnumeratorFromDocument(nsIDOMDocument* aDoc,
185 : nsISimpleEnumerator** aResult)
186 : {
187 0 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
188 0 : NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
189 :
190 0 : nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
191 0 : nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
192 0 : NS_ENSURE_TRUE(hookObj, NS_ERROR_FAILURE);
193 :
194 0 : return hookObj->GetHookEnumerator(aResult);
195 : }
196 :
197 : bool
198 0 : EditorHookUtils::DoInsertionHook(nsIDOMDocument* aDoc,
199 : nsIDOMEvent* aDropEvent,
200 : nsITransferable *aTrans)
201 : {
202 0 : nsCOMPtr<nsISimpleEnumerator> enumerator;
203 0 : GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator));
204 0 : NS_ENSURE_TRUE(enumerator, true);
205 :
206 0 : bool hasMoreHooks = false;
207 0 : while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) &&
208 : hasMoreHooks) {
209 0 : nsCOMPtr<nsISupports> isupp;
210 0 : if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp)))) {
211 0 : break;
212 : }
213 :
214 0 : nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
215 0 : if (override) {
216 0 : bool doInsert = true;
217 : DebugOnly<nsresult> hookResult =
218 0 : override->OnPasteOrDrop(aDropEvent, aTrans, &doInsert);
219 0 : NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnPasteOrDrop");
220 0 : NS_ENSURE_TRUE(doInsert, false);
221 : }
222 : }
223 :
224 0 : return true;
225 : }
226 :
227 : } // namespace mozilla
|