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 #ifndef mozilla_TransactionManager_h
7 #define mozilla_TransactionManager_h
8 
9 #include "mozilla/TransactionStack.h"
10 
11 #include "nsCOMArray.h"
12 #include "nsCOMPtr.h"
13 #include "nsCycleCollectionParticipant.h"
14 #include "nsISupportsImpl.h"
15 #include "nsITransactionManager.h"
16 #include "nsWeakReference.h"
17 #include "nscore.h"
18 
19 class nsITransaction;
20 class nsITransactionListener;
21 
22 namespace mozilla {
23 
24 class TransactionManager final : public nsITransactionManager,
25                                  public nsSupportsWeakReference {
26  public:
27   explicit TransactionManager(int32_t aMaxTransactionCount = -1);
28 
29   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
30   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(TransactionManager,
31                                            nsITransactionManager)
32 
33   NS_DECL_NSITRANSACTIONMANAGER
34 
35   already_AddRefed<nsITransaction> PeekUndoStack();
36   already_AddRefed<nsITransaction> PeekRedoStack();
37 
38   MOZ_CAN_RUN_SCRIPT nsresult Undo();
39   MOZ_CAN_RUN_SCRIPT nsresult Redo();
40 
NumberOfUndoItems()41   size_t NumberOfUndoItems() const { return mUndoStack.GetSize(); }
NumberOfRedoItems()42   size_t NumberOfRedoItems() const { return mRedoStack.GetSize(); }
43 
NumberOfMaximumTransactions()44   int32_t NumberOfMaximumTransactions() const { return mMaxTransactionCount; }
45 
46   bool EnableUndoRedo(int32_t aMaxTransactionCount = -1);
DisableUndoRedo()47   bool DisableUndoRedo() { return EnableUndoRedo(0); }
ClearUndoRedo()48   bool ClearUndoRedo() {
49     if (NS_WARN_IF(!mDoStack.IsEmpty())) {
50       return false;
51     }
52     mUndoStack.Clear();
53     mRedoStack.Clear();
54     return true;
55   }
56 
AddTransactionListener(nsITransactionListener & aListener)57   bool AddTransactionListener(nsITransactionListener& aListener) {
58     // XXX Shouldn't we check if aListener has already been in mListeners?
59     return mListeners.AppendObject(&aListener);
60   }
RemoveTransactionListener(nsITransactionListener & aListener)61   bool RemoveTransactionListener(nsITransactionListener& aListener) {
62     return mListeners.RemoveObject(&aListener);
63   }
64 
65   // FYI: We don't need to treat the following methods as `MOZ_CAN_RUN_SCRIPT`
66   //      for now because only ComposerCommandUpdater is the listener and it
67   //      does not do something dangerous synchronously.
68   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
69   WillDoNotify(nsITransaction* aTransaction, bool* aInterrupt);
70   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult DidDoNotify(nsITransaction* aTransaction,
71                                                    nsresult aExecuteResult);
72   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
73   WillUndoNotify(nsITransaction* aTransaction, bool* aInterrupt);
74   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
75   DidUndoNotify(nsITransaction* aTransaction, nsresult aUndoResult);
76   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
77   WillRedoNotify(nsITransaction* aTransaction, bool* aInterrupt);
78   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
79   DidRedoNotify(nsITransaction* aTransaction, nsresult aRedoResult);
80   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult WillBeginBatchNotify(bool* aInterrupt);
81   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult DidBeginBatchNotify(nsresult aResult);
82   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult WillEndBatchNotify(bool* aInterrupt);
83   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult DidEndBatchNotify(nsresult aResult);
84   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult WillMergeNotify(
85       nsITransaction* aTop, nsITransaction* aTransaction, bool* aInterrupt);
86   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
87   DidMergeNotify(nsITransaction* aTop, nsITransaction* aTransaction,
88                  bool aDidMerge, nsresult aMergeResult);
89 
90   /**
91    * Exposing non-virtual methods of nsITransactionManager methods.
92    */
93   MOZ_CAN_RUN_SCRIPT nsresult BeginBatchInternal(nsISupports* aData);
94   nsresult EndBatchInternal(bool aAllowEmpty);
95 
96  private:
97   virtual ~TransactionManager() = default;
98 
99   MOZ_CAN_RUN_SCRIPT nsresult BeginTransaction(nsITransaction* aTransaction,
100                                                nsISupports* aData);
101   nsresult EndTransaction(bool aAllowEmpty);
102 
103   int32_t mMaxTransactionCount;
104   TransactionStack mDoStack;
105   TransactionStack mUndoStack;
106   TransactionStack mRedoStack;
107   nsCOMArray<nsITransactionListener> mListeners;
108 };
109 
110 }  // namespace mozilla
111 
AsTransactionManager()112 mozilla::TransactionManager* nsITransactionManager::AsTransactionManager() {
113   return static_cast<mozilla::TransactionManager*>(this);
114 }
115 
116 #endif  // #ifndef mozilla_TransactionManager_h
117