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
);
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 // Note the GPU process is not handled here - it cannot send sync
51 // messages, so instead the initial data is pushed down.
52 if (XRE_IsContentProcess()) {
53 MOZ_ASSERT(gGfxVarInitUpdates
,
54 "Initial updates should be provided in content process");
55 if (!gGfxVarInitUpdates
) {
56 // No provided initial updates, sync-request them from parent.
57 nsTArray
<GfxVarUpdate
> initUpdates
;
58 dom::ContentChild::GetSingleton()->SendGetGfxVars(&initUpdates
);
59 gGfxVarInitUpdates
= new nsTArray
<GfxVarUpdate
>(std::move(initUpdates
));
61 for (const auto& varUpdate
: *gGfxVarInitUpdates
) {
62 ApplyUpdate(varUpdate
);
64 gGfxVarInitUpdates
= nullptr;
70 void gfxVars::Shutdown() {
73 gGfxVarInitUpdates
= nullptr;
77 void gfxVars::ApplyUpdate(const GfxVarUpdate
& aUpdate
) {
78 // Only subprocesses receive updates and apply them locally.
79 MOZ_ASSERT(!XRE_IsParentProcess());
80 MOZ_DIAGNOSTIC_ASSERT(sVarList
|| gGfxVarInitUpdates
);
82 sVarList
->ElementAt(aUpdate
.index())->SetValue(aUpdate
.value());
83 } else if (gGfxVarInitUpdates
) {
84 // Too early, we haven't been initialized, so just add to
85 // the array waiting for the initialization...
86 gGfxVarInitUpdates
->AppendElement(aUpdate
);
91 void gfxVars::AddReceiver(gfxVarReceiver
* aReceiver
) {
92 MOZ_ASSERT(NS_IsMainThread());
94 // Don't double-add receivers, in case a broken content process sends two
96 if (!sInstance
->mReceivers
.Contains(aReceiver
)) {
97 sInstance
->mReceivers
.AppendElement(aReceiver
);
102 void gfxVars::RemoveReceiver(gfxVarReceiver
* aReceiver
) {
103 MOZ_ASSERT(NS_IsMainThread());
106 sInstance
->mReceivers
.RemoveElement(aReceiver
);
111 nsTArray
<GfxVarUpdate
> gfxVars::FetchNonDefaultVars() {
112 MOZ_ASSERT(NS_IsMainThread());
113 MOZ_ASSERT(sVarList
);
115 nsTArray
<GfxVarUpdate
> updates
;
116 for (size_t i
= 0; i
< sVarList
->Length(); i
++) {
117 VarBase
* var
= sVarList
->ElementAt(i
);
118 if (var
->HasDefaultValue()) {
123 var
->GetValue(&value
);
125 updates
.AppendElement(GfxVarUpdate(i
, value
));
131 gfxVars::VarBase::VarBase() {
132 mIndex
= gfxVars::sVarList
->Length();
133 gfxVars::sVarList
->AppendElement(this);
136 void gfxVars::NotifyReceivers(VarBase
* aVar
) {
137 MOZ_ASSERT(NS_IsMainThread());
140 aVar
->GetValue(&value
);
142 GfxVarUpdate
update(aVar
->Index(), value
);
143 for (auto& receiver
: mReceivers
) {
144 receiver
->OnVarChanged(update
);
149 } // namespace mozilla