1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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/. */
8 #include "HighlightRegistry.h"
9 #include "mozilla/StaticAnalysisFunctions.h"
10 #include "mozilla/dom/HighlightBinding.h"
12 #include "mozilla/AlreadyAddRefed.h"
13 #include "mozilla/ErrorResult.h"
14 #include "mozilla/RefPtr.h"
16 #include "AbstractRange.h"
18 #include "PresShell.h"
19 #include "Selection.h"
21 #include "nsFrameSelection.h"
22 #include "nsPIDOMWindow.h"
24 namespace mozilla::dom
{
26 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Highlight
, mRanges
, mWindow
)
28 NS_IMPL_CYCLE_COLLECTING_ADDREF(Highlight
)
29 NS_IMPL_CYCLE_COLLECTING_RELEASE(Highlight
)
31 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Highlight
)
32 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
33 NS_INTERFACE_MAP_ENTRY(nsISupports
)
37 const Sequence
<OwningNonNull
<AbstractRange
>>& aInitialRanges
,
38 nsPIDOMWindowInner
* aWindow
, ErrorResult
& aRv
)
40 for (RefPtr
<AbstractRange
> range
: aInitialRanges
) {
48 already_AddRefed
<Highlight
> Highlight::Constructor(
49 const GlobalObject
& aGlobal
,
50 const Sequence
<OwningNonNull
<AbstractRange
>>& aInitialRanges
,
52 MOZ_ASSERT(NS_IsMainThread());
53 nsCOMPtr
<nsPIDOMWindowInner
> window
=
54 do_QueryInterface(aGlobal
.GetAsSupports());
56 aRv
.ThrowUnknownError(
57 "There is no window associated to "
58 "this highlight object!");
62 RefPtr
<Highlight
> highlight
= new Highlight(aInitialRanges
, window
, aRv
);
63 return aRv
.Failed() ? nullptr : highlight
.forget();
66 void Highlight::AddToHighlightRegistry(HighlightRegistry
& aHighlightRegistry
,
67 nsAtom
& aHighlightName
) {
68 mHighlightRegistries
.LookupOrInsert(&aHighlightRegistry
)
69 .Insert(&aHighlightName
);
72 void Highlight::RemoveFromHighlightRegistry(
73 HighlightRegistry
& aHighlightRegistry
, nsAtom
& aHighlightName
) {
74 if (auto entry
= mHighlightRegistries
.Lookup(&aHighlightRegistry
)) {
75 auto& highlightNames
= entry
.Data();
76 highlightNames
.Remove(&aHighlightName
);
77 if (highlightNames
.IsEmpty()) {
83 already_AddRefed
<Selection
> Highlight::CreateHighlightSelection(
84 nsAtom
* aHighlightName
, nsFrameSelection
* aFrameSelection
) {
85 MOZ_ASSERT(aFrameSelection
);
86 MOZ_ASSERT(aFrameSelection
->GetPresShell());
87 RefPtr
<Selection
> selection
=
88 MakeRefPtr
<Selection
>(SelectionType::eHighlight
, aFrameSelection
);
89 selection
->SetHighlightSelectionData({aHighlightName
, this});
90 AutoFrameSelectionBatcher
selectionBatcher(__FUNCTION__
);
91 for (const RefPtr
<AbstractRange
>& range
: mRanges
) {
92 if (range
->GetComposedDocOfContainers() ==
93 aFrameSelection
->GetPresShell()->GetDocument()) {
94 // since this is run in a context guarded by a selection batcher,
95 // no strong reference is needed to keep `range` alive.
96 selection
->AddHighlightRangeAndSelectFramesAndNotifyListeners(
97 MOZ_KnownLive(*range
));
100 return selection
.forget();
103 void Highlight::Add(AbstractRange
& aRange
, ErrorResult
& aRv
) {
104 Highlight_Binding::SetlikeHelpers::Add(this, aRange
, aRv
);
108 if (!mRanges
.Contains(&aRange
)) {
109 mRanges
.AppendElement(&aRange
);
110 AutoFrameSelectionBatcher
selectionBatcher(__FUNCTION__
,
111 mHighlightRegistries
.Count());
112 for (const RefPtr
<HighlightRegistry
>& registry
:
113 mHighlightRegistries
.Keys()) {
114 auto frameSelection
= registry
->GetFrameSelection();
115 selectionBatcher
.AddFrameSelection(frameSelection
);
116 // since this is run in a context guarded by a selection batcher,
117 // no strong reference is needed to keep `registry` alive.
118 MOZ_KnownLive(registry
)->MaybeAddRangeToHighlightSelection(aRange
, *this);
126 void Highlight::Clear(ErrorResult
& aRv
) {
127 Highlight_Binding::SetlikeHelpers::Clear(this, aRv
);
130 AutoFrameSelectionBatcher
selectionBatcher(__FUNCTION__
,
131 mHighlightRegistries
.Count());
133 for (const RefPtr
<HighlightRegistry
>& registry
:
134 mHighlightRegistries
.Keys()) {
135 auto frameSelection
= registry
->GetFrameSelection();
136 selectionBatcher
.AddFrameSelection(frameSelection
);
137 // since this is run in a context guarded by a selection batcher,
138 // no strong reference is needed to keep `registry` alive.
139 MOZ_KnownLive(registry
)->RemoveHighlightSelection(*this);
144 bool Highlight::Delete(AbstractRange
& aRange
, ErrorResult
& aRv
) {
145 if (Highlight_Binding::SetlikeHelpers::Delete(this, aRange
, aRv
)) {
146 mRanges
.RemoveElement(&aRange
);
147 AutoFrameSelectionBatcher
selectionBatcher(__FUNCTION__
,
148 mHighlightRegistries
.Count());
150 for (const RefPtr
<HighlightRegistry
>& registry
:
151 mHighlightRegistries
.Keys()) {
152 auto frameSelection
= registry
->GetFrameSelection();
153 selectionBatcher
.AddFrameSelection(frameSelection
);
154 // since this is run in a context guarded by a selection batcher,
155 // no strong reference is needed to keep `registry` alive.
156 MOZ_KnownLive(registry
)->MaybeRemoveRangeFromHighlightSelection(aRange
,
164 JSObject
* Highlight::WrapObject(JSContext
* aCx
,
165 JS::Handle
<JSObject
*> aGivenProto
) {
166 return Highlight_Binding::Wrap(aCx
, this, aGivenProto
);
169 } // namespace mozilla::dom