Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/TextComposition.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_TextComposition_h
8
#define mozilla_TextComposition_h
9
10
#include "nsCOMPtr.h"
11
#include "nsINode.h"
12
#include "nsIWeakReference.h"
13
#include "nsIWidget.h"
14
#include "nsTArray.h"
15
#include "nsThreadUtils.h"
16
#include "nsPresContext.h"
17
#include "mozilla/Attributes.h"
18
#include "mozilla/EventForwards.h"
19
#include "mozilla/TextRange.h"
20
#include "mozilla/dom/TabParent.h"
21
#include "mozilla/dom/Text.h"
22
23
namespace mozilla {
24
25
class EditorBase;
26
class EventDispatchingCallback;
27
class IMEStateManager;
28
29
/**
30
 * TextComposition represents a text composition.  This class stores the
31
 * composition event target and its presContext.  At dispatching the event via
32
 * this class, the instances use the stored event target.
33
 */
34
35
class TextComposition final
36
{
37
  friend class IMEStateManager;
38
39
  NS_INLINE_DECL_REFCOUNTING(TextComposition)
40
41
public:
42
  typedef dom::TabParent TabParent;
43
  typedef dom::Text Text;
44
45
0
  static bool IsHandlingSelectionEvent() { return sHandlingSelectionEvent; }
46
47
  TextComposition(nsPresContext* aPresContext,
48
                  nsINode* aNode,
49
                  TabParent* aTabParent,
50
                  WidgetCompositionEvent* aCompositionEvent);
51
52
0
  bool Destroyed() const { return !mPresContext; }
53
0
  nsPresContext* GetPresContext() const { return mPresContext; }
54
0
  nsINode* GetEventTargetNode() const { return mNode; }
55
  // The text node which includes composition string.
56
0
  Text* GetContainerTextNode() const { return mContainerTextNode; }
57
  // The latest CompositionEvent.data value except compositionstart event.
58
  // This value is modified at dispatching compositionupdate.
59
0
  const nsString& LastData() const { return mLastData; }
60
  // The composition string which is already handled by the focused editor.
61
  // I.e., this value must be same as the composition string on the focused
62
  // editor.  This value is modified at a call of
63
  // EditorDidHandleCompositionChangeEvent().
64
  // Note that mString and mLastData are different between dispatcing
65
  // compositionupdate and compositionchange event handled by focused editor.
66
0
  const nsString& String() const { return mString; }
67
  // The latest clauses range of the composition string.
68
  // During compositionupdate event, GetRanges() returns old ranges.
69
  // So if getting on compositionupdate, Use GetLastRange instead of GetRange().
70
0
  TextRangeArray* GetLastRanges() const { return mLastRanges; }
71
  // Returns the clauses and/or caret range of the composition string.
72
  // This is modified at a call of EditorWillHandleCompositionChangeEvent().
73
  // This may return null if there is no clauses and caret.
74
  // XXX We should return |const TextRangeArray*| here, but it causes compile
75
  //     error due to inaccessible Release() method.
76
0
  TextRangeArray* GetRanges() const { return mRanges; }
77
  // Returns the widget which is proper to call NotifyIME().
78
  nsIWidget* GetWidget() const
79
0
  {
80
0
    return mPresContext ? mPresContext->GetRootWidget() : nullptr;
81
0
  }
82
  // Returns the tab parent which has this composition in its remote process.
83
  TabParent* GetTabParent() const
84
0
  {
85
0
    return mTabParent;
86
0
  }
87
  // Returns true if the composition is started with synthesized event which
88
  // came from nsDOMWindowUtils.
89
0
  bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
90
91
  const widget::NativeIMEContext& GetNativeIMEContext() const
92
0
  {
93
0
    return mNativeContext;
94
0
  }
95
96
  /**
97
   * This is called when IMEStateManager stops managing the instance.
98
   */
99
  void Destroy();
100
101
  /**
102
   * Request to commit (or cancel) the composition to IME.  This method should
103
   * be called only by IMEStateManager::NotifyIME().
104
   */
105
  nsresult RequestToCommit(nsIWidget* aWidget, bool aDiscard);
106
107
  /**
108
   * IsRequestingCommitOrCancelComposition() returns true if the instance is
109
   * requesting widget to commit or cancel composition.
110
   */
111
  bool IsRequestingCommitOrCancelComposition() const
112
0
  {
113
0
    return mIsRequestingCancel || mIsRequestingCommit;
114
0
  }
115
116
  /**
117
   * Send a notification to IME.  It depends on the IME or platform spec what
118
   * will occur (or not occur).
119
   */
120
  nsresult NotifyIME(widget::IMEMessage aMessage);
121
122
  /**
123
   * the offset of first composition string
124
   */
125
  uint32_t NativeOffsetOfStartComposition() const
126
0
  {
127
0
    return mCompositionStartOffset;
128
0
  }
129
130
  /**
131
   * the offset of first selected clause or start of composition
132
   */
133
  uint32_t NativeOffsetOfTargetClause() const
134
0
  {
135
0
    return mCompositionStartOffset + mTargetClauseOffsetInComposition;
136
0
  }
137
138
  /**
139
   * The offset of composition string in the text node.  If composition string
140
   * hasn't been inserted in any text node yet, this returns UINT32_MAX.
141
   */
142
  uint32_t XPOffsetInTextNode() const
143
0
  {
144
0
    return mCompositionStartOffsetInTextNode;
145
0
  }
146
147
  /**
148
   * The length of composition string in the text node.  If composition string
149
   * hasn't been inserted in any text node yet, this returns 0.
150
   */
151
  uint32_t XPLengthInTextNode() const
152
0
  {
153
0
    return mCompositionLengthInTextNode == UINT32_MAX ?
154
0
             0 : mCompositionLengthInTextNode;
155
0
  }
156
157
  /**
158
   * The end offset of composition string in the text node.  If composition
159
   * string hasn't been inserted in any text node yet, this returns UINT32_MAX.
160
   */
161
  uint32_t XPEndOffsetInTextNode() const
162
0
  {
163
0
    if (mCompositionStartOffsetInTextNode == UINT32_MAX ||
164
0
        mCompositionLengthInTextNode == UINT32_MAX) {
165
0
      return UINT32_MAX;
166
0
    }
167
0
    return mCompositionStartOffsetInTextNode + mCompositionLengthInTextNode;
168
0
  }
169
170
  /**
171
   * Returns true if there is non-empty composition string and it's not fixed.
172
   * Otherwise, false.
173
   */
174
0
  bool IsComposing() const { return mIsComposing; }
175
176
  /**
177
   * Returns true while editor is handling an event which is modifying the
178
   * composition string.
179
   */
180
  bool IsEditorHandlingEvent() const
181
0
  {
182
0
    return mIsEditorHandlingEvent;
183
0
  }
184
185
  /**
186
   * IsMovingToNewTextNode() returns true if editor detects the text node
187
   * has been removed and still not insert the composition string into
188
   * new text node.
189
   */
190
  bool IsMovingToNewTextNode() const
191
0
  {
192
0
    return !mContainerTextNode && mCompositionLengthInTextNode &&
193
0
           mCompositionLengthInTextNode != UINT32_MAX;
194
0
  }
195
196
  /**
197
   * StartHandlingComposition() and EndHandlingComposition() are called by
198
   * editor when it holds a TextComposition instance and release it.
199
   */
200
  void StartHandlingComposition(EditorBase* aEditorBase);
201
  void EndHandlingComposition(EditorBase* aEditorBase);
202
203
  /**
204
   * OnEditorDestroyed() is called when the editor is destroyed but there is
205
   * active composition.
206
   */
207
  void OnEditorDestroyed();
208
209
  /**
210
   * CompositionChangeEventHandlingMarker class should be created at starting
211
   * to handle text event in focused editor.  This calls
212
   * EditorWillHandleCompositionChangeEvent() and
213
   * EditorDidHandleCompositionChangeEvent() automatically.
214
   */
215
  class MOZ_STACK_CLASS CompositionChangeEventHandlingMarker
216
  {
217
  public:
218
    CompositionChangeEventHandlingMarker(
219
      TextComposition* aComposition,
220
      const WidgetCompositionEvent* aCompositionChangeEvent)
221
      : mComposition(aComposition)
222
0
    {
223
0
      mComposition->EditorWillHandleCompositionChangeEvent(
224
0
                      aCompositionChangeEvent);
225
0
    }
226
227
    ~CompositionChangeEventHandlingMarker()
228
0
    {
229
0
      mComposition->EditorDidHandleCompositionChangeEvent();
230
0
    }
231
232
  private:
233
    RefPtr<TextComposition> mComposition;
234
    CompositionChangeEventHandlingMarker();
235
    CompositionChangeEventHandlingMarker(
236
      const CompositionChangeEventHandlingMarker& aOther);
237
  };
238
239
  /**
240
   * OnCreateCompositionTransaction() is called by
241
   * CompositionTransaction::Create() immediately after creating
242
   * new CompositionTransaction instance.
243
   *
244
   * @param aStringToInsert     The string to insert the text node actually.
245
   *                            This may be different from the data of
246
   *                            dispatching composition event because it may
247
   *                            be replaced with different character for
248
   *                            passwords, or truncated due to maxlength.
249
   * @param aTextNode           The text node which includes composition string.
250
   * @param aOffset             The offset of composition string in aTextNode.
251
   */
252
  void OnCreateCompositionTransaction(const nsAString& aStringToInsert,
253
                                      Text* aTextNode,
254
                                      uint32_t aOffset)
255
0
  {
256
0
    if (!mContainerTextNode) {
257
0
      mContainerTextNode = aTextNode;
258
0
      mCompositionStartOffsetInTextNode = aOffset;
259
0
      NS_WARNING_ASSERTION(mCompositionStartOffsetInTextNode != UINT32_MAX,
260
0
        "The text node is really too long.");
261
0
    }
262
#ifdef DEBUG
263
    else {
264
      MOZ_ASSERT(aTextNode == mContainerTextNode);
265
      MOZ_ASSERT(aOffset == mCompositionStartOffsetInTextNode);
266
    }
267
#endif // #ifdef DEBUG
268
    mCompositionLengthInTextNode = aStringToInsert.Length();
269
0
    NS_WARNING_ASSERTION(mCompositionLengthInTextNode != UINT32_MAX,
270
0
      "The string to insert is really too long.");
271
0
  }
272
273
  /**
274
   * OnTextNodeRemoved() is called when focused editor is reframed and
275
   * mContainerTextNode may be (or have been) replaced with different text
276
   * node, or just removes the text node due to empty.
277
   */
278
  void OnTextNodeRemoved()
279
0
  {
280
0
    mContainerTextNode = nullptr;
281
0
    // Don't reset mCompositionStartOffsetInTextNode nor
282
0
    // mCompositionLengthInTextNode because editor needs them to restore
283
0
    // composition in new text node.
284
0
  }
285
286
private:
287
  // Private destructor, to discourage deletion outside of Release():
288
  ~TextComposition()
289
0
  {
290
0
    // WARNING: mPresContext may be destroying, so, be careful if you touch it.
291
0
  }
292
293
  // sHandlingSelectionEvent is true while TextComposition sends a selection
294
  // event to ContentEventHandler.
295
  static bool sHandlingSelectionEvent;
296
297
  // This class holds nsPresContext weak.  This instance shouldn't block
298
  // destroying it.  When the presContext is being destroyed, it's notified to
299
  // IMEStateManager::OnDestroyPresContext(), and then, it destroy
300
  // this instance.
301
  nsPresContext* mPresContext;
302
  nsCOMPtr<nsINode> mNode;
303
  RefPtr<TabParent> mTabParent;
304
305
  // The text node which includes the composition string.
306
  RefPtr<Text> mContainerTextNode;
307
308
  // This is the clause and caret range information which is managed by
309
  // the focused editor.  This may be null if there is no clauses or caret.
310
  RefPtr<TextRangeArray> mRanges;
311
  // Same as mRange, but mRange will have old data during compositionupdate.
312
  // So this will be valied during compositionupdate.
313
  RefPtr<TextRangeArray> mLastRanges;
314
315
  // mNativeContext stores a opaque pointer.  This works as the "ID" for this
316
  // composition.  Don't access the instance, it may not be available.
317
  widget::NativeIMEContext mNativeContext;
318
319
  // mEditorBaseWeak is a weak reference to the focused editor handling
320
  // composition.
321
  nsWeakPtr mEditorBaseWeak;
322
323
  // mLastData stores the data attribute of the latest composition event (except
324
  // the compositionstart event).
325
  nsString mLastData;
326
327
  // mString stores the composition text which has been handled by the focused
328
  // editor.
329
  nsString mString;
330
331
  // Offset of the composition string from start of the editor
332
  uint32_t mCompositionStartOffset;
333
  // Offset of the selected clause of the composition string from
334
  // mCompositionStartOffset
335
  uint32_t mTargetClauseOffsetInComposition;
336
  // Offset of the composition string in mContainerTextNode.
337
  // NOTE: This is NOT valid in the main process if focused editor is in a
338
  //       remote process.
339
  uint32_t mCompositionStartOffsetInTextNode;
340
  // Length of the composition string in mContainerTextNode.  If this instance
341
  // has already dispatched eCompositionCommit(AsIs) and
342
  // EditorDidHandleCompositionChangeEvent() has already been called,
343
  // this may be different from length of mString because committed string
344
  // may be truncated by maxlength attribute of <input> or <textarea>.
345
  // NOTE: This is NOT valid in the main process if focused editor is in a
346
  //       remote process.
347
  uint32_t mCompositionLengthInTextNode;
348
349
  // See the comment for IsSynthesizedForTests().
350
  bool mIsSynthesizedForTests;
351
352
  // See the comment for IsComposing().
353
  bool mIsComposing;
354
355
  // mIsEditorHandlingEvent is true while editor is modifying the composition
356
  // string.
357
  bool mIsEditorHandlingEvent;
358
359
  // mIsRequestingCommit or mIsRequestingCancel is true *only* while we're
360
  // requesting commit or canceling the composition.  In other words, while
361
  // one of these values is true, we're handling the request.
362
  bool mIsRequestingCommit;
363
  bool mIsRequestingCancel;
364
365
  // mRequestedToCommitOrCancel is true *after* we requested IME to commit or
366
  // cancel the composition.  In other words, we already requested of IME that
367
  // it commits or cancels current composition.
368
  // NOTE: Before this is set to true, both mIsRequestingCommit and
369
  //       mIsRequestingCancel are set to false.
370
  bool mRequestedToCommitOrCancel;
371
372
  // Set to true if the instance dispatches an eCompositionChange event.
373
  bool mHasDispatchedDOMTextEvent;
374
375
  // Before this dispatches commit event into the tree, this is set to true.
376
  // So, this means if native IME already commits the composition.
377
  bool mHasReceivedCommitEvent;
378
379
  // mWasNativeCompositionEndEventDiscarded is true if this composition was
380
  // requested commit or cancel itself but native compositionend event is
381
  // discarded by PresShell due to not safe to dispatch events.
382
  bool mWasNativeCompositionEndEventDiscarded;
383
384
  // Allow control characters appear in composition string.
385
  // When this is false, control characters except
386
  // CHARACTER TABULATION (horizontal tab) are removed from
387
  // both composition string and data attribute of compositionupdate
388
  // and compositionend events.
389
  bool mAllowControlCharacters;
390
391
  // mWasCompositionStringEmpty is true if the composition string was empty
392
  // when DispatchCompositionEvent() is called.
393
  bool mWasCompositionStringEmpty;
394
395
  // Hide the default constructor and copy constructor.
396
  TextComposition()
397
    : mPresContext(nullptr)
398
    , mNativeContext(nullptr)
399
    , mCompositionStartOffset(0)
400
    , mTargetClauseOffsetInComposition(0)
401
    , mCompositionStartOffsetInTextNode(UINT32_MAX)
402
    , mCompositionLengthInTextNode(UINT32_MAX)
403
    , mIsSynthesizedForTests(false)
404
    , mIsComposing(false)
405
    , mIsEditorHandlingEvent(false)
406
    , mIsRequestingCommit(false)
407
    , mIsRequestingCancel(false)
408
    , mRequestedToCommitOrCancel(false)
409
    , mHasReceivedCommitEvent(false)
410
    , mWasNativeCompositionEndEventDiscarded(false)
411
    , mAllowControlCharacters(false)
412
    , mWasCompositionStringEmpty(true)
413
0
  {}
414
  TextComposition(const TextComposition& aOther);
415
416
  /**
417
   * If we're requesting IME to commit or cancel composition, or we've already
418
   * requested it, or we've already known this composition has been ended in
419
   * IME, we don't need to request commit nor cancel composition anymore and
420
   * shouldn't do so if we're in content process for not committing/canceling
421
   * "current" composition in native IME.  So, when this returns true,
422
   * RequestIMEToCommit() does nothing.
423
   */
424
  bool CanRequsetIMEToCommitOrCancelComposition() const
425
0
  {
426
0
    return !mIsRequestingCommit && !mIsRequestingCancel &&
427
0
           !mRequestedToCommitOrCancel && !mHasReceivedCommitEvent;
428
0
  }
429
430
  /**
431
   * GetEditorBase() returns EditorBase pointer of mEditorBaseWeak.
432
   */
433
  already_AddRefed<EditorBase> GetEditorBase() const;
434
435
  /**
436
   * HasEditor() returns true if mEditorBaseWeak holds EditorBase instance
437
   * which is alive.  Otherwise, false.
438
   */
439
  bool HasEditor() const;
440
441
  /**
442
   * EditorWillHandleCompositionChangeEvent() must be called before the focused
443
   * editor handles the compositionchange event.
444
   */
445
  void EditorWillHandleCompositionChangeEvent(
446
         const WidgetCompositionEvent* aCompositionChangeEvent);
447
448
  /**
449
   * EditorDidHandleCompositionChangeEvent() must be called after the focused
450
   * editor handles a compositionchange event.
451
   */
452
  void EditorDidHandleCompositionChangeEvent();
453
454
  /**
455
   * IsValidStateForComposition() returns true if it's safe to dispatch an event
456
   * to the DOM tree.  Otherwise, false.
457
   * WARNING: This doesn't check script blocker state.  It should be checked
458
   *          before dispatching the first event.
459
   */
460
  bool IsValidStateForComposition(nsIWidget* aWidget) const;
461
462
  /**
463
   * DispatchCompositionEvent() dispatches the aCompositionEvent to the mContent
464
   * synchronously. The caller must ensure that it's safe to dispatch the event.
465
   */
466
  void DispatchCompositionEvent(WidgetCompositionEvent* aCompositionEvent,
467
                                nsEventStatus* aStatus,
468
                                EventDispatchingCallback* aCallBack,
469
                                bool aIsSynthesized);
470
471
  /**
472
   * Simply calling EventDispatcher::Dispatch() with plugin event.
473
   * If dispatching event has no orginal clone, aOriginalEvent can be null.
474
   */
475
  void DispatchEvent(WidgetCompositionEvent* aDispatchEvent,
476
                     nsEventStatus* aStatus,
477
                     EventDispatchingCallback* aCallback,
478
                     const WidgetCompositionEvent *aOriginalEvent = nullptr);
479
480
  /**
481
   * HandleSelectionEvent() sends the selection event to ContentEventHandler
482
   * or dispatches it to the focused child process.
483
   */
484
  void HandleSelectionEvent(WidgetSelectionEvent* aSelectionEvent)
485
0
  {
486
0
    HandleSelectionEvent(mPresContext, mTabParent, aSelectionEvent);
487
0
  }
488
  static void HandleSelectionEvent(nsPresContext* aPresContext,
489
                                   TabParent* aTabParent,
490
                                   WidgetSelectionEvent* aSelectionEvent);
491
492
  /**
493
   * MaybeDispatchCompositionUpdate() may dispatch a compositionupdate event
494
   * if aCompositionEvent changes composition string.
495
   * @return Returns false if dispatching the compositionupdate event caused
496
   *         destroying this composition.
497
   */
498
  bool MaybeDispatchCompositionUpdate(
499
         const WidgetCompositionEvent* aCompositionEvent);
500
501
  /**
502
   * CloneAndDispatchAs() dispatches a composition event which is
503
   * duplicateed from aCompositionEvent and set the aMessage.
504
   *
505
   * @return Returns BaseEventFlags which is the result of dispatched event.
506
   */
507
  BaseEventFlags CloneAndDispatchAs(
508
                   const WidgetCompositionEvent* aCompositionEvent,
509
                   EventMessage aMessage,
510
                   nsEventStatus* aStatus = nullptr,
511
                   EventDispatchingCallback* aCallBack = nullptr);
512
513
  /**
514
   * If IME has already dispatched compositionend event but it was discarded
515
   * by PresShell due to not safe to dispatch, this returns true.
516
   */
517
  bool WasNativeCompositionEndEventDiscarded() const
518
0
  {
519
0
    return mWasNativeCompositionEndEventDiscarded;
520
0
  }
521
522
  /**
523
   * OnCompositionEventDiscarded() is called when PresShell discards
524
   * compositionupdate, compositionend or compositionchange event due to not
525
   * safe to dispatch event.
526
   */
527
  void OnCompositionEventDiscarded(WidgetCompositionEvent* aCompositionEvent);
528
529
  /**
530
   * OnCompositionEventDispatched() is called after a composition event is
531
   * dispatched.
532
   */
533
  void OnCompositionEventDispatched(
534
         const WidgetCompositionEvent* aDispatchEvent);
535
536
  /**
537
   * MaybeNotifyIMEOfCompositionEventHandled() notifies IME of composition
538
   * event handled.  This should be called after dispatching a composition
539
   * event which came from widget.
540
   */
541
  void MaybeNotifyIMEOfCompositionEventHandled(
542
         const WidgetCompositionEvent* aCompositionEvent);
543
544
  /**
545
   * GetSelectionStartOffset() returns normal selection start offset in the
546
   * editor which has this composition.
547
   * If it failed or lost focus, this would return 0.
548
   */
549
  uint32_t GetSelectionStartOffset();
550
551
  /**
552
   * OnStartOffsetUpdatedInChild() is called when composition start offset
553
   * is updated in the child process.  I.e., this is called and never called
554
   * if the composition is in this process.
555
   * @param aStartOffset        New composition start offset with native
556
   *                            linebreaks.
557
   */
558
  void OnStartOffsetUpdatedInChild(uint32_t aStartOffset);
559
560
  /**
561
   * CompositionEventDispatcher dispatches the specified composition (or text)
562
   * event.
563
   */
564
  class CompositionEventDispatcher : public Runnable
565
  {
566
  public:
567
    CompositionEventDispatcher(TextComposition* aTextComposition,
568
                               nsINode* aEventTarget,
569
                               EventMessage aEventMessage,
570
                               const nsAString& aData,
571
                               bool aIsSynthesizedEvent = false);
572
    NS_IMETHOD Run() override;
573
574
  private:
575
    RefPtr<TextComposition> mTextComposition;
576
    nsCOMPtr<nsINode> mEventTarget;
577
    nsString mData;
578
    EventMessage mEventMessage;
579
    bool mIsSynthesizedEvent;
580
581
    CompositionEventDispatcher()
582
      : Runnable("TextComposition::CompositionEventDispatcher")
583
      , mEventMessage(eVoidEvent)
584
0
      , mIsSynthesizedEvent(false){};
585
  };
586
587
  /**
588
   * DispatchCompositionEventRunnable() dispatches a composition event to the
589
   * content.  Be aware, if you use this method, nsPresShellEventCB isn't used.
590
   * That means that nsIFrame::HandleEvent() is never called.
591
   * WARNING: The instance which is managed by IMEStateManager may be
592
   *          destroyed by this method call.
593
   *
594
   * @param aEventMessage       Must be one of composition events.
595
   * @param aData               Used for mData value.
596
   * @param aIsSynthesizingCommit   true if this is called for synthesizing
597
   *                                commit or cancel composition.  Otherwise,
598
   *                                false.
599
   */
600
  void DispatchCompositionEventRunnable(EventMessage aEventMessage,
601
                                        const nsAString& aData,
602
                                        bool aIsSynthesizingCommit = false);
603
};
604
605
/**
606
 * TextCompositionArray manages the instances of TextComposition class.
607
 * Managing with array is enough because only one composition is typically
608
 * there.  Even if user switches native IME context, it's very rare that
609
 * second or more composition is started.
610
 * It's assumed that this is used by IMEStateManager for storing all active
611
 * compositions in the process.  If the instance is it, each TextComposition
612
 * in the array can be destroyed by calling some methods of itself.
613
 */
614
615
class TextCompositionArray final :
616
  public AutoTArray<RefPtr<TextComposition>, 2>
617
{
618
public:
619
  // Looking for per native IME context.
620
  index_type IndexOf(const widget::NativeIMEContext& aNativeIMEContext);
621
  index_type IndexOf(nsIWidget* aWidget);
622
623
  TextComposition* GetCompositionFor(nsIWidget* aWidget);
624
  TextComposition* GetCompositionFor(
625
                     const WidgetCompositionEvent* aCompositionEvent);
626
627
  // Looking for per nsPresContext
628
  index_type IndexOf(nsPresContext* aPresContext);
629
  index_type IndexOf(nsPresContext* aPresContext, nsINode* aNode);
630
631
  TextComposition* GetCompositionFor(nsPresContext* aPresContext);
632
  TextComposition* GetCompositionFor(nsPresContext* aPresContext,
633
                                     nsINode* aNode);
634
  TextComposition* GetCompositionInContent(nsPresContext* aPresContext,
635
                                           nsIContent* aContent);
636
};
637
638
} // namespace mozilla
639
640
#endif // #ifndef mozilla_TextComposition_h