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/. */
8 #include "gfxVarReceiver.h"
9 #include "mozilla/dom/ContentChild.h"
14 StaticAutoPtr
<gfxVars
> gfxVars::sInstance
;
15 StaticAutoPtr
<nsTArray
<gfxVars::VarBase
*>> gfxVars::sVarList
;
17 StaticAutoPtr
<nsTArray
<GfxVarUpdate
>> gGfxVarInitUpdates
;
19 void gfxVars::SetValuesForInitialize(
20 const nsTArray
<GfxVarUpdate
>& aInitUpdates
) {
21 // This should only be called once
22 MOZ_RELEASE_ASSERT(!gGfxVarInitUpdates
);
24 // We expect aInitUpdates to be provided before any other gfxVars operation,
25 // and for sInstance to be null here, but handle the alternative.
27 // Apply the updates, the object has been created already
28 for (const auto& varUpdate
: aInitUpdates
) {
29 ApplyUpdate(varUpdate
);
32 // Save the values for Initialize call
33 gGfxVarInitUpdates
= new nsTArray
<GfxVarUpdate
>(aInitUpdates
.Clone());
37 void gfxVars::Initialize() {
41 "Initial updates should not be present after any gfxVars operation");
45 // sVarList must be initialized first since it's used in the constructor for
47 sVarList
= new nsTArray
<gfxVars::VarBase
*>();
48 sInstance
= new gfxVars
;
50 // Content processes should have gotten a call to SetValuesForInitialize,
51 // which will have set gGfxVarInitUpdates.
52 MOZ_ASSERT_IF(XRE_IsContentProcess(), gGfxVarInitUpdates
);
54 if (gGfxVarInitUpdates
) {
55 // Apply any updates from gGfxVarInitUpdates.
56 for (const auto& varUpdate
: *gGfxVarInitUpdates
) {
57 ApplyUpdate(varUpdate
);
59 gGfxVarInitUpdates
= nullptr;
63 gfxVars::gfxVars() = default;
65 void gfxVars::Shutdown() {
68 gGfxVarInitUpdates
= nullptr;
72 void gfxVars::ApplyUpdate(const GfxVarUpdate
& aUpdate
) {
73 // Only subprocesses receive updates and apply them locally.
74 MOZ_ASSERT(!XRE_IsParentProcess());
75 MOZ_DIAGNOSTIC_ASSERT(sVarList
|| gGfxVarInitUpdates
);
77 sVarList
->ElementAt(aUpdate
.index())->SetValue(aUpdate
.value());
78 } else if (gGfxVarInitUpdates
) {
79 // Too early, we haven't been initialized, so just add to
80 // the array waiting for the initialization...
81 gGfxVarInitUpdates
->AppendElement(aUpdate
);
86 void gfxVars::AddReceiver(gfxVarReceiver
* aReceiver
) {
87 MOZ_ASSERT(NS_IsMainThread());
89 // Don't double-add receivers, in case a broken content process sends two
91 if (!sInstance
->mReceivers
.Contains(aReceiver
)) {
92 sInstance
->mReceivers
.AppendElement(aReceiver
);
97 void gfxVars::RemoveReceiver(gfxVarReceiver
* aReceiver
) {
98 MOZ_ASSERT(NS_IsMainThread());
101 sInstance
->mReceivers
.RemoveElement(aReceiver
);
106 nsTArray
<GfxVarUpdate
> gfxVars::FetchNonDefaultVars() {
107 MOZ_ASSERT(NS_IsMainThread());
108 MOZ_ASSERT(sVarList
);
110 nsTArray
<GfxVarUpdate
> updates
;
111 for (size_t i
= 0; i
< sVarList
->Length(); i
++) {
112 VarBase
* var
= sVarList
->ElementAt(i
);
113 if (var
->HasDefaultValue()) {
118 var
->GetValue(&value
);
120 updates
.AppendElement(GfxVarUpdate(i
, value
));
126 gfxVars::VarBase::VarBase() {
127 mIndex
= gfxVars::sVarList
->Length();
128 gfxVars::sVarList
->AppendElement(this);
131 void gfxVars::NotifyReceivers(VarBase
* aVar
) {
132 MOZ_ASSERT(NS_IsMainThread());
135 aVar
->GetValue(&value
);
137 GfxVarUpdate
update(aVar
->Index(), value
);
138 for (auto& receiver
: mReceivers
) {
139 receiver
->OnVarChanged(update
);
144 } // namespace mozilla