tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gfxVars.cpp (5125B)


      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 #include "gfxVars.h"
      8 #include "gfxVarReceiver.h"
      9 #include "mozilla/dom/ContentChild.h"
     10 
     11 namespace mozilla {
     12 namespace gfx {
     13 
     14 StaticAutoPtr<gfxVars> gfxVars::sInstance;
     15 StaticAutoPtr<nsTArray<gfxVars::VarBase*>> gfxVars::sVarList;
     16 
     17 // Used only during initialization to store pending updates if received prior to
     18 // gfxVars::Initialize.
     19 StaticAutoPtr<nsTArray<GfxVarUpdate>> gGfxVarInitUpdates;
     20 
     21 // Used only after initialization to store pending updates for
     22 // gfxVarsCollectUpdates that will be dispatched once it goes out of scope. This
     23 // is useful when we are changing multiple gfxVars and wish to only update the
     24 // child processes once.
     25 StaticAutoPtr<nsTArray<GfxVarUpdate>> gGfxVarPendingUpdates;
     26 
     27 void gfxVars::SetValuesForInitialize(
     28    const nsTArray<GfxVarUpdate>& aInitUpdates) {
     29  // This should only be called once
     30  MOZ_RELEASE_ASSERT(!gGfxVarInitUpdates);
     31 
     32  // We expect aInitUpdates to be provided before any other gfxVars operation,
     33  // and for sInstance to be null here, but handle the alternative.
     34  if (sInstance) {
     35    // Apply the updates, the object has been created already
     36    ApplyUpdate(aInitUpdates);
     37  } else {
     38    // Save the values for Initialize call
     39    gGfxVarInitUpdates = new nsTArray<GfxVarUpdate>(aInitUpdates.Clone());
     40  }
     41 }
     42 
     43 void gfxVars::StartCollectingUpdates() {
     44  MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
     45  MOZ_RELEASE_ASSERT(sInstance);
     46  MOZ_RELEASE_ASSERT(!gGfxVarPendingUpdates);
     47  gGfxVarPendingUpdates = new nsTArray<GfxVarUpdate>();
     48 }
     49 
     50 void gfxVars::StopCollectingUpdates() {
     51  MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
     52  MOZ_RELEASE_ASSERT(sInstance);
     53  MOZ_RELEASE_ASSERT(gGfxVarPendingUpdates);
     54  if (!gGfxVarPendingUpdates->IsEmpty()) {
     55    for (auto& receiver : sInstance->mReceivers) {
     56      receiver->OnVarChanged(*gGfxVarPendingUpdates);
     57    }
     58  }
     59  gGfxVarPendingUpdates = nullptr;
     60 }
     61 
     62 void gfxVars::Initialize() {
     63  if (sInstance) {
     64    MOZ_RELEASE_ASSERT(
     65        !gGfxVarInitUpdates,
     66        "Initial updates should not be present after any gfxVars operation");
     67    return;
     68  }
     69 
     70  // sVarList must be initialized first since it's used in the constructor for
     71  // sInstance.
     72  sVarList = new nsTArray<gfxVars::VarBase*>();
     73  sInstance = new gfxVars;
     74 
     75  // Content processes should have gotten a call to SetValuesForInitialize,
     76  // which will have set gGfxVarInitUpdates.
     77  MOZ_ASSERT_IF(XRE_IsContentProcess(), gGfxVarInitUpdates);
     78 
     79  if (gGfxVarInitUpdates) {
     80    // Apply any updates from gGfxVarInitUpdates.
     81    ApplyUpdate(*gGfxVarInitUpdates);
     82    gGfxVarInitUpdates = nullptr;
     83  }
     84 }
     85 
     86 gfxVars::gfxVars() = default;
     87 
     88 void gfxVars::Shutdown() {
     89  sInstance = nullptr;
     90  sVarList = nullptr;
     91  gGfxVarInitUpdates = nullptr;
     92 }
     93 
     94 /* static */
     95 void gfxVars::ApplyUpdate(const nsTArray<GfxVarUpdate>& aUpdate) {
     96  // Only subprocesses receive updates and apply them locally.
     97  MOZ_ASSERT(!XRE_IsParentProcess());
     98  MOZ_DIAGNOSTIC_ASSERT(sVarList || gGfxVarInitUpdates);
     99  if (sVarList) {
    100    for (auto& i : aUpdate) {
    101      sVarList->ElementAt(i.index())->SetValue(i.value());
    102    }
    103  } else if (gGfxVarInitUpdates) {
    104    // Too early, we haven't been initialized, so just add to
    105    // the array waiting for the initialization...
    106    gGfxVarInitUpdates->AppendElements(aUpdate);
    107  }
    108 }
    109 
    110 /* static */
    111 void gfxVars::AddReceiver(gfxVarReceiver* aReceiver) {
    112  MOZ_ASSERT(NS_IsMainThread());
    113 
    114  // Don't double-add receivers, in case a broken content process sends two
    115  // init messages.
    116  if (!sInstance->mReceivers.Contains(aReceiver)) {
    117    sInstance->mReceivers.AppendElement(aReceiver);
    118  }
    119 }
    120 
    121 /* static */
    122 void gfxVars::RemoveReceiver(gfxVarReceiver* aReceiver) {
    123  MOZ_ASSERT(NS_IsMainThread());
    124 
    125  if (sInstance) {
    126    sInstance->mReceivers.RemoveElement(aReceiver);
    127  }
    128 }
    129 
    130 /* static */
    131 nsTArray<GfxVarUpdate> gfxVars::FetchNonDefaultVars() {
    132  MOZ_ASSERT(NS_IsMainThread());
    133  MOZ_ASSERT(sVarList);
    134 
    135  nsTArray<GfxVarUpdate> updates;
    136  for (size_t i = 0; i < sVarList->Length(); i++) {
    137    VarBase* var = sVarList->ElementAt(i);
    138    if (var->HasDefaultValue()) {
    139      continue;
    140    }
    141 
    142    GfxVarValue value;
    143    var->GetValue(&value);
    144 
    145    updates.AppendElement(GfxVarUpdate(i, value));
    146  }
    147 
    148  return updates;
    149 }
    150 
    151 gfxVars::VarBase::VarBase() {
    152  mIndex = gfxVars::sVarList->Length();
    153  gfxVars::sVarList->AppendElement(this);
    154 }
    155 
    156 void gfxVars::NotifyReceivers(VarBase* aVar) {
    157  MOZ_ASSERT(NS_IsMainThread());
    158 
    159  GfxVarValue value;
    160  aVar->GetValue(&value);
    161 
    162  if (XRE_IsParentProcess() && gGfxVarPendingUpdates) {
    163    gGfxVarPendingUpdates->AppendElement(GfxVarUpdate(aVar->Index(), value));
    164    return;
    165  }
    166 
    167  AutoTArray<GfxVarUpdate, 1> vars;
    168  vars.AppendElement(GfxVarUpdate(aVar->Index(), value));
    169 
    170  for (auto& receiver : mReceivers) {
    171    receiver->OnVarChanged(vars);
    172  }
    173 }
    174 
    175 }  // namespace gfx
    176 }  // namespace mozilla