Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/editor/libeditor/InsertNodeTransaction.cpp
Line
Count
Source (jump to first uncovered line)
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 "InsertNodeTransaction.h"
7
8
#include "mozilla/EditorBase.h"         // for EditorBase
9
#include "mozilla/EditorDOMPoint.h"     // for EditorDOMPoint
10
11
#include "mozilla/dom/Selection.h"      // for Selection
12
13
#include "nsAString.h"
14
#include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc.
15
#include "nsError.h"                    // for NS_ERROR_NULL_POINTER, etc.
16
#include "nsIContent.h"                 // for nsIContent
17
#include "nsMemory.h"                   // for nsMemory
18
#include "nsReadableUtils.h"            // for ToNewCString
19
#include "nsString.h"                   // for nsString
20
21
namespace mozilla {
22
23
using namespace dom;
24
25
template already_AddRefed<InsertNodeTransaction>
26
InsertNodeTransaction::Create(EditorBase& aEditorBase,
27
                              nsIContent& aContentToInsert,
28
                              const EditorDOMPoint& aPointToInsert);
29
template already_AddRefed<InsertNodeTransaction>
30
InsertNodeTransaction::Create(EditorBase& aEditorBase,
31
                              nsIContent& aContentToInsert,
32
                              const EditorRawDOMPoint& aPointToInsert);
33
34
// static
35
template<typename PT, typename CT>
36
already_AddRefed<InsertNodeTransaction>
37
InsertNodeTransaction::Create(EditorBase& aEditorBase,
38
                              nsIContent& aContentToInsert,
39
                              const EditorDOMPointBase<PT, CT>& aPointToInsert)
40
0
{
41
0
  RefPtr<InsertNodeTransaction> transaction =
42
0
    new InsertNodeTransaction(aEditorBase, aContentToInsert, aPointToInsert);
43
0
  return transaction.forget();
44
0
}
Unexecuted instantiation: already_AddRefed<mozilla::InsertNodeTransaction> mozilla::InsertNodeTransaction::Create<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> >(mozilla::EditorBase&, nsIContent&, mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&)
Unexecuted instantiation: already_AddRefed<mozilla::InsertNodeTransaction> mozilla::InsertNodeTransaction::Create<nsINode*, nsIContent*>(mozilla::EditorBase&, nsIContent&, mozilla::EditorDOMPointBase<nsINode*, nsIContent*> const&)
45
46
template<typename PT, typename CT>
47
InsertNodeTransaction::InsertNodeTransaction(
48
                         EditorBase& aEditorBase,
49
                         nsIContent& aContentToInsert,
50
                         const EditorDOMPointBase<PT, CT>& aPointToInsert)
51
  : mContentToInsert(&aContentToInsert)
52
  , mPointToInsert(aPointToInsert)
53
  , mEditorBase(&aEditorBase)
54
0
{
55
0
  MOZ_ASSERT(mPointToInsert.IsSetAndValid());
56
0
  // Ensure mPointToInsert stores child at offset.
57
0
  Unused << mPointToInsert.GetChild();
58
0
}
Unexecuted instantiation: mozilla::InsertNodeTransaction::InsertNodeTransaction<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> >(mozilla::EditorBase&, nsIContent&, mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&)
Unexecuted instantiation: mozilla::InsertNodeTransaction::InsertNodeTransaction<nsINode*, nsIContent*>(mozilla::EditorBase&, nsIContent&, mozilla::EditorDOMPointBase<nsINode*, nsIContent*> const&)
59
60
InsertNodeTransaction::~InsertNodeTransaction()
61
0
{
62
0
}
63
64
NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertNodeTransaction, EditTransactionBase,
65
                                   mEditorBase,
66
                                   mContentToInsert,
67
                                   mPointToInsert)
68
69
NS_IMPL_ADDREF_INHERITED(InsertNodeTransaction, EditTransactionBase)
70
NS_IMPL_RELEASE_INHERITED(InsertNodeTransaction, EditTransactionBase)
71
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertNodeTransaction)
72
0
NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
73
74
NS_IMETHODIMP
75
InsertNodeTransaction::DoTransaction()
76
0
{
77
0
  if (NS_WARN_IF(!mEditorBase) ||
78
0
      NS_WARN_IF(!mContentToInsert) ||
79
0
      NS_WARN_IF(!mPointToInsert.IsSet())) {
80
0
    return NS_ERROR_NOT_INITIALIZED;
81
0
  }
82
0
83
0
  if (!mPointToInsert.IsSetAndValid()) {
84
0
    // It seems that DOM tree has been changed after first DoTransaction()
85
0
    // and current RedoTranaction() call.
86
0
    if (mPointToInsert.GetChild()) {
87
0
      EditorDOMPoint newPointToInsert(mPointToInsert.GetChild());
88
0
      if (!newPointToInsert.IsSet()) {
89
0
        // The insertion point has been removed from the DOM tree.
90
0
        // In this case, we should append the node to the container instead.
91
0
        newPointToInsert.SetToEndOf(mPointToInsert.GetContainer());
92
0
        if (NS_WARN_IF(!newPointToInsert.IsSet())) {
93
0
          return NS_ERROR_FAILURE;
94
0
        }
95
0
      }
96
0
      mPointToInsert = newPointToInsert;
97
0
    } else {
98
0
      mPointToInsert.SetToEndOf(mPointToInsert.GetContainer());
99
0
      if (NS_WARN_IF(!mPointToInsert.IsSet())) {
100
0
        return NS_ERROR_FAILURE;
101
0
      }
102
0
    }
103
0
  }
104
0
105
0
  mEditorBase->MarkNodeDirty(mContentToInsert);
106
0
107
0
  ErrorResult error;
108
0
  mPointToInsert.GetContainer()->InsertBefore(*mContentToInsert,
109
0
                                              mPointToInsert.GetChild(),
110
0
                                              error);
111
0
  error.WouldReportJSException();
112
0
  if (NS_WARN_IF(error.Failed())) {
113
0
    return error.StealNSResult();
114
0
  }
115
0
116
0
  if (!mEditorBase->AllowsTransactionsToChangeSelection()) {
117
0
    return NS_OK;
118
0
  }
119
0
120
0
  RefPtr<Selection> selection = mEditorBase->GetSelection();
121
0
  if (NS_WARN_IF(!selection)) {
122
0
    return NS_ERROR_FAILURE;
123
0
  }
124
0
125
0
  // Place the selection just after the inserted element.
126
0
  EditorRawDOMPoint afterInsertedNode(mContentToInsert);
127
0
  DebugOnly<bool> advanced = afterInsertedNode.AdvanceOffset();
128
0
  NS_WARNING_ASSERTION(advanced,
129
0
    "Failed to advance offset after the inserted node");
130
0
  selection->Collapse(afterInsertedNode, error);
131
0
  if (NS_WARN_IF(error.Failed())) {
132
0
    error.SuppressException();
133
0
  }
134
0
  return NS_OK;
135
0
}
136
137
NS_IMETHODIMP
138
InsertNodeTransaction::UndoTransaction()
139
0
{
140
0
  if (NS_WARN_IF(!mContentToInsert) ||
141
0
      NS_WARN_IF(!mPointToInsert.IsSet())) {
142
0
    return NS_ERROR_NOT_INITIALIZED;
143
0
  }
144
0
  // XXX If the inserted node has been moved to different container node or
145
0
  //     just removed from the DOM tree, this always fails.
146
0
  ErrorResult error;
147
0
  mPointToInsert.GetContainer()->RemoveChild(*mContentToInsert, error);
148
0
  if (NS_WARN_IF(error.Failed())) {
149
0
    return error.StealNSResult();
150
0
  }
151
0
  return NS_OK;
152
0
}
153
154
} // namespace mozilla