tor-browser

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

TestConfigHelpers.cpp (17602B)


      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "gtest/gtest.h"
      8 #include "gmock/gmock.h"
      9 
     10 #include <string>
     11 #include <windows.h>
     12 
     13 #include "nsLiteralString.h"
     14 #include "nsWindowsHelpers.h"
     15 #include "sandbox/win/src/sandbox.h"
     16 #include "sandbox/win/src/app_container.h"
     17 #include "sandbox/win/src/policy_engine_opcodes.h"
     18 #include "../src/sandboxbroker/ConfigHelpers.h"
     19 
     20 using namespace sandbox;
     21 using mozilla::sandboxing::UserFontConfigHelper;
     22 using ::testing::Eq;
     23 using ::testing::Expectation;
     24 using ::testing::StartsWith;
     25 using ::testing::StrEq;
     26 using ::testing::StrictMock;
     27 
     28 // Only allow 2 pages to test by default.
     29 constexpr int kDefaultNumberOfPagesForTesting = 2;
     30 static const nsLiteralString sWinUserProfile = uR"(C:\Users\Moz User)"_ns;
     31 static const nsLiteralString sLocalAppData =
     32    uR"(C:\Users\Moz User\AppData\Local)"_ns;
     33 static const nsLiteralString sRoamingAppData =
     34    uR"(C:\Users\Moz User\AppData\Roaming)"_ns;
     35 static const wchar_t* sWinUserFonts =
     36    LR"(C:\Users\Moz User\AppData\Local\Microsoft\Windows\Fonts\*)";
     37 static const wchar_t* sAdobeLiveTypeFonts =
     38    LR"(C:\Users\Moz User\AppData\Roaming\ADOBE\CORESYNC\PLUGINS\LIVETYPE\R\*)";
     39 static const wchar_t* sAdobeUserOwnedFonts =
     40    LR"(C:\Users\Moz User\AppData\Roaming\ADOBE\USER OWNED FONTS\*)";
     41 static const wchar_t* sTestRegKey = LR"(Software\MozFontsPathsTest)";
     42 static const wchar_t* sTestFailRegKey = LR"(Software\MozFontsPathsTestFail)";
     43 
     44 namespace mozilla {
     45 
     46 class MockConfig : public TargetConfig {
     47 public:
     48  MOCK_METHOD(ResultCode, AllowFileAccess,
     49              (FileSemantics semantics, const wchar_t* pattern), (override));
     50 
     51  // Remaining methods should not be called during tests.
     52  MOCK_METHOD(bool, IsConfigured, (), (const, override));
     53  MOCK_METHOD(ResultCode, SetTokenLevel,
     54              (TokenLevel initial, TokenLevel lockdown), (override));
     55  MOCK_METHOD(TokenLevel, GetInitialTokenLevel, (), (const, override));
     56  MOCK_METHOD(TokenLevel, GetLockdownTokenLevel, (), (const, override));
     57  MOCK_METHOD(void, SetDoNotUseRestrictingSIDs, (), (override));
     58  MOCK_METHOD(bool, GetUseRestrictingSIDs, (), (override));
     59  MOCK_METHOD(void, SetForceKnownDllLoadingFallback, (), (override));
     60  MOCK_METHOD(ResultCode, SetJobLevel,
     61              (JobLevel job_level, uint32_t ui_exceptions), (override));
     62  MOCK_METHOD(JobLevel, GetJobLevel, (), (const, override));
     63  MOCK_METHOD(void, SetJobMemoryLimit, (size_t memory_limit), (override));
     64  MOCK_METHOD(ResultCode, AllowNamedPipes, (const wchar_t* pattern),
     65              (override));
     66  MOCK_METHOD(ResultCode, AllowRegistryRead, (const wchar_t* pattern),
     67              (override));
     68  MOCK_METHOD(ResultCode, AllowExtraDlls, (const wchar_t* pattern), (override));
     69  MOCK_METHOD(ResultCode, SetFakeGdiInit, (), (override));
     70  MOCK_METHOD(ResultCode, AllowLineBreaking, (), (override));
     71  MOCK_METHOD(void, AddDllToUnload, (const wchar_t* dll_name), (override));
     72  MOCK_METHOD(ResultCode, SetIntegrityLevel, (IntegrityLevel level),
     73              (override));
     74  MOCK_METHOD(IntegrityLevel, GetIntegrityLevel, (), (const, override));
     75  MOCK_METHOD(void, SetDelayedIntegrityLevel, (IntegrityLevel level),
     76              (override));
     77  MOCK_METHOD(ResultCode, SetLowBox, (const wchar_t* sid), (override));
     78  MOCK_METHOD(ResultCode, SetProcessMitigations, (MitigationFlags flags),
     79              (override));
     80  MOCK_METHOD(MitigationFlags, GetProcessMitigations, (), (override));
     81  MOCK_METHOD(ResultCode, SetDelayedProcessMitigations, (MitigationFlags flags),
     82              (override));
     83  MOCK_METHOD(MitigationFlags, GetDelayedProcessMitigations, (),
     84              (const, override));
     85  MOCK_METHOD(void, AddRestrictingRandomSid, (), (override));
     86  MOCK_METHOD(void, SetLockdownDefaultDacl, (), (override));
     87  MOCK_METHOD(ResultCode, AddAppContainerProfile,
     88              (const wchar_t* package_name, bool create_profile), (override));
     89  MOCK_METHOD(scoped_refptr<AppContainer>, GetAppContainer, (), (override));
     90  MOCK_METHOD(ResultCode, AddKernelObjectToClose,
     91              (const wchar_t* handle_type, const wchar_t* handle_name),
     92              (override));
     93  MOCK_METHOD(ResultCode, SetDisconnectCsrss, (), (override));
     94  MOCK_METHOD(void, SetDesktop, (Desktop desktop), (override));
     95  MOCK_METHOD(void, SetFilterEnvironment, (bool filter), (override));
     96  MOCK_METHOD(bool, GetEnvironmentFiltered, (), (override));
     97  MOCK_METHOD(void, SetZeroAppShim, (), (override));
     98 };
     99 
    100 #define EXPECT_READONLY_EQ(aRulePath)                                     \
    101  EXPECT_CALL(mConfig, AllowFileAccess(Eq(FileSemantics::kAllowReadonly), \
    102                                       StrEq(aRulePath)))
    103 
    104 #define EXPECT_READONLY_STARTS(aRulePath)                                 \
    105  EXPECT_CALL(mConfig, AllowFileAccess(Eq(FileSemantics::kAllowReadonly), \
    106                                       StartsWith(aRulePath)))
    107 
    108 static void SetUpPathsInKey(HKEY aKey,
    109                            const std::vector<std::wstring_view>& aFontPaths) {
    110  for (size_t i = 0; i < aFontPaths.size(); ++i) {
    111    const auto* pathBytes = reinterpret_cast<const BYTE*>(aFontPaths[i].data());
    112    size_t sizeInBytes = (aFontPaths[i].length() + 1) * sizeof(wchar_t);
    113    ::RegSetValueExW(aKey, std::to_wstring(i).c_str(), 0, REG_SZ, pathBytes,
    114                     sizeInBytes);
    115  }
    116 }
    117 
    118 class UserFontConfigHelperTest : public testing::Test {
    119 protected:
    120  // We always expect the Windows User font dir rule to be added.
    121  UserFontConfigHelperTest()
    122      : mWinUserFontCall(EXPECT_READONLY_EQ(sWinUserFonts)) {
    123    EXPECT_READONLY_EQ(sAdobeLiveTypeFonts);
    124    EXPECT_READONLY_EQ(sAdobeUserOwnedFonts);
    125    ::RegCreateKeyExW(HKEY_CURRENT_USER, sTestRegKey, 0, nullptr,
    126                      REG_OPTION_VOLATILE, KEY_ALL_ACCESS, nullptr,
    127                      &mTestUserFontKey, nullptr);
    128  }
    129 
    130  ~UserFontConfigHelperTest() {
    131    if (mTestUserFontKey) {
    132      ::RegCloseKey(mTestUserFontKey);
    133    }
    134    ::RegDeleteTreeW(HKEY_CURRENT_USER, sTestRegKey);
    135  }
    136 
    137  void SetUpPaths(const std::vector<std::wstring_view>& aFontPaths) {
    138    SetUpPathsInKey(mTestUserFontKey, aFontPaths);
    139  }
    140 
    141  void CreateHelperAndCallAddRules() {
    142    UserFontConfigHelper policyHelper(sTestRegKey, sWinUserProfile,
    143                                      sLocalAppData, sRoamingAppData);
    144    sandboxing::SizeTrackingConfig trackingPolicy(&mConfig,
    145                                                  mNumberOfStoragePages);
    146    policyHelper.AddRules(trackingPolicy);
    147  }
    148 
    149  // StrictMock because we only expect AllowFileAccess to be called.
    150  StrictMock<MockConfig> mConfig;
    151  const Expectation mWinUserFontCall;
    152  HKEY mTestUserFontKey = nullptr;
    153  int32_t mNumberOfStoragePages = kDefaultNumberOfPagesForTesting;
    154 };
    155 
    156 TEST_F(UserFontConfigHelperTest, WindowsDirRuleAddedOnKeyFailure) {
    157  // Create helper with incorrect key name.
    158  UserFontConfigHelper policyHelper(sTestFailRegKey, sWinUserProfile,
    159                                    sLocalAppData, sRoamingAppData);
    160  sandboxing::SizeTrackingConfig trackingPolicy(&mConfig, 1);
    161  policyHelper.AddRules(trackingPolicy);
    162 }
    163 
    164 TEST_F(UserFontConfigHelperTest, PathsInsideUsersDirAdded) {
    165  SetUpPaths({LR"(C:\Users\Moz User\Fonts\FontFile1.ttf)"});
    166 
    167  // We expect the windows user font rule to be added first.
    168  EXPECT_READONLY_EQ(LR"(C:\Users\Moz User\Fonts\FontFile1.ttf)")
    169      .After(mWinUserFontCall);
    170 
    171  CreateHelperAndCallAddRules();
    172 }
    173 
    174 TEST_F(UserFontConfigHelperTest, PathsInsideUsersDirAddedIgnoringCase) {
    175  SetUpPaths({LR"(C:\users\moz uSER\Fonts\FontFile1.ttf)"});
    176 
    177  EXPECT_READONLY_EQ(LR"(C:\users\moz uSER\Fonts\FontFile1.ttf)")
    178      .After(mWinUserFontCall);
    179 
    180  CreateHelperAndCallAddRules();
    181 }
    182 
    183 TEST_F(UserFontConfigHelperTest, PathsOutsideUsersDirAdded) {
    184  SetUpPaths({LR"(C:\ProgramData\Fonts\FontFile1.ttf)",
    185              LR"(C:\programdata\Fonts\FontFile2.ttf)"});
    186 
    187  EXPECT_READONLY_EQ(LR"(C:\ProgramData\Fonts\FontFile1.ttf)")
    188      .After(mWinUserFontCall);
    189  EXPECT_READONLY_EQ(LR"(C:\programdata\Fonts\FontFile2.ttf)")
    190      .After(mWinUserFontCall);
    191 
    192  CreateHelperAndCallAddRules();
    193 }
    194 
    195 TEST_F(UserFontConfigHelperTest, SubKeyPathsInsideUsersDirAdded) {
    196  SetUpPaths({LR"(C:\Users\Moz User\Fonts\FontFile1.ttf)"});
    197  std::unique_ptr<HKEY, RegCloseKeyDeleter> subKey;
    198  auto lStatus = ::RegCreateKeyExW(mTestUserFontKey, L"SubKey", 0, nullptr,
    199                                   REG_OPTION_VOLATILE, KEY_ALL_ACCESS, nullptr,
    200                                   getter_Transfers(subKey), nullptr);
    201  ASSERT_EQ(lStatus, ERROR_SUCCESS);
    202  SetUpPathsInKey(subKey.get(), {LR"(C:\Users\Moz User\Fonts\FontFile2.ttf)"});
    203 
    204  // We expect the windows user font rule to be added first.
    205  auto& fontFile1 =
    206      EXPECT_READONLY_EQ(LR"(C:\Users\Moz User\Fonts\FontFile1.ttf)")
    207          .After(mWinUserFontCall);
    208  EXPECT_READONLY_EQ(LR"(C:\Users\Moz User\Fonts\FontFile2.ttf)")
    209      .After(fontFile1);
    210 
    211  CreateHelperAndCallAddRules();
    212 }
    213 
    214 TEST_F(UserFontConfigHelperTest, PathsOutsideUsersDirAddedAtEnd) {
    215  // We set up the paths in a particular order, but this doesn't guarantee the
    216  // order returned from registry calls. However the rule adding code should
    217  // guarantee that non-user dir fonts are added at the end.
    218  const auto* userFont1 = LR"(C:\Users\Moz User\Fonts\FontFile1.ttf)";
    219  const auto* userFont2 = LR"(C:\Users\Moz User\Fonts\FontFile2.ttf)";
    220  const auto* userFont3 = LR"(C:\Users\Moz User\Fonts\FontFile3.ttf)";
    221  const auto* pdFont1 = LR"(C:\ProgramData\Fonts\FontFile1.ttf)";
    222  const auto* pdFont2 = LR"(C:\ProgramData\Fonts\FontFile2.ttf)";
    223  SetUpPaths({pdFont1, userFont1, pdFont2, userFont2, userFont3});
    224 
    225  auto& userDirFont1 = EXPECT_READONLY_EQ(userFont1).After(mWinUserFontCall);
    226  auto& userDirFont2 = EXPECT_READONLY_EQ(userFont2).After(mWinUserFontCall);
    227  auto& userDirFont3 = EXPECT_READONLY_EQ(userFont3).After(mWinUserFontCall);
    228  EXPECT_READONLY_EQ(pdFont1).After(userDirFont1, userDirFont2, userDirFont3);
    229  EXPECT_READONLY_EQ(pdFont2).After(userDirFont1, userDirFont2, userDirFont3);
    230 
    231  CreateHelperAndCallAddRules();
    232 }
    233 
    234 TEST_F(UserFontConfigHelperTest, SubKeyPathsOutsideUsersDirAddedAtEnd) {
    235  // We set up the paths in a particular order, but this doesn't guarantee the
    236  // order returned from registry calls. However the rule adding code should
    237  // guarantee that non-user dir fonts are added at the end.
    238  const auto* userFont1 = LR"(C:\Users\Moz User\Fonts\FontFile1.ttf)";
    239  const auto* userFont2 = LR"(C:\Users\Moz User\Fonts\FontFile2.ttf)";
    240  const auto* userFont3 = LR"(C:\Users\Moz User\Fonts\FontFile3.ttf)";
    241  const auto* pdFont1 = LR"(C:\ProgramData\Fonts\FontFile1.ttf)";
    242  const auto* pdFont2 = LR"(C:\ProgramData\Fonts\FontFile2.ttf)";
    243  SetUpPaths({pdFont1, userFont1, userFont2});
    244  std::unique_ptr<HKEY, RegCloseKeyDeleter> subKey;
    245  auto lStatus = ::RegCreateKeyExW(mTestUserFontKey, L"SubKey", 0, nullptr,
    246                                   REG_OPTION_VOLATILE, KEY_ALL_ACCESS, nullptr,
    247                                   getter_Transfers(subKey), nullptr);
    248  ASSERT_EQ(lStatus, ERROR_SUCCESS);
    249  SetUpPathsInKey(subKey.get(), {pdFont2, userFont3});
    250 
    251  auto& userDirFont1 = EXPECT_READONLY_EQ(userFont1).After(mWinUserFontCall);
    252  auto& userDirFont2 = EXPECT_READONLY_EQ(userFont2).After(mWinUserFontCall);
    253  auto& userDirFont3 =
    254      EXPECT_READONLY_EQ(userFont3).After(userDirFont1, userDirFont2);
    255  EXPECT_READONLY_EQ(pdFont1).After(userDirFont3);
    256  EXPECT_READONLY_EQ(pdFont2).After(userDirFont3);
    257 
    258  CreateHelperAndCallAddRules();
    259 }
    260 
    261 TEST_F(UserFontConfigHelperTest, NonStringValueIsIgnored) {
    262  DWORD regValue = 42;
    263  ::RegSetValueExW(mTestUserFontKey, L"Liff", 0, REG_DWORD,
    264                   reinterpret_cast<const BYTE*>(&regValue), sizeof(regValue));
    265  wchar_t multiPath[] = LR"(C:\Users\Moz User\Fonts\FontFile1.ttf)";
    266  ::RegSetValueExW(mTestUserFontKey, L"MultiStr", 0, REG_MULTI_SZ,
    267                   reinterpret_cast<const BYTE*>(multiPath), sizeof(multiPath));
    268  ::RegSetValueExW(mTestUserFontKey, L"ExpandStr", 0, REG_EXPAND_SZ,
    269                   reinterpret_cast<const BYTE*>(multiPath), sizeof(multiPath));
    270 
    271  EXPECT_READONLY_EQ(LR"(C:\Users\Moz User\Fonts\FontFile1.ttf)").Times(0);
    272 
    273  CreateHelperAndCallAddRules();
    274 }
    275 
    276 TEST_F(UserFontConfigHelperTest, PathNotNullTerminated) {
    277  // If you just miss the null in the size it stills gets stored with it, so you
    278  // have to make the next character non-null.
    279  wchar_t fontPath[] = LR"(C:\Users\Moz User\Fonts\FontFile1.ttfx)";
    280  ::RegSetValueExW(mTestUserFontKey, L"NoNull", 0, REG_SZ,
    281                   reinterpret_cast<const BYTE*>(fontPath),
    282                   sizeof(fontPath) - (2 * sizeof(wchar_t)));
    283 
    284  EXPECT_READONLY_EQ(LR"(C:\Users\Moz User\Fonts\FontFile1.ttf)")
    285      .After(mWinUserFontCall);
    286 
    287  CreateHelperAndCallAddRules();
    288 }
    289 
    290 TEST_F(UserFontConfigHelperTest, PathEmpty) {
    291  wchar_t fontPath[] = L"";
    292  ::RegSetValueExW(mTestUserFontKey, L"EmptyNoNull", 0, REG_SZ,
    293                   reinterpret_cast<const BYTE*>(fontPath), sizeof(fontPath));
    294 
    295  EXPECT_READONLY_EQ(fontPath).Times(0);
    296 
    297  CreateHelperAndCallAddRules();
    298 }
    299 
    300 TEST_F(UserFontConfigHelperTest, PathEmptyNotNullTerminated) {
    301  // If you just miss the null in the size it stills gets stored with it, so you
    302  // have to make the next character non-null.
    303  wchar_t fontPath[] = L"F";
    304  ::RegSetValueExW(mTestUserFontKey, L"EmptyNoNull", 0, REG_SZ,
    305                   reinterpret_cast<const BYTE*>(fontPath), 0);
    306 
    307  EXPECT_READONLY_EQ(L"").Times(0);
    308 
    309  CreateHelperAndCallAddRules();
    310 }
    311 
    312 TEST_F(UserFontConfigHelperTest, DirsAreIgnored) {
    313  SetUpPaths({LR"(C:\Users\Moz User\Fonts\)"});
    314 
    315  EXPECT_READONLY_EQ(LR"(C:\Users\Moz Us]er\Fonts\)").Times(0);
    316 
    317  CreateHelperAndCallAddRules();
    318 }
    319 
    320 TEST_F(UserFontConfigHelperTest, PathsInWindowsUsersFontDirNotAdded) {
    321  SetUpPaths({
    322      LR"(C:\Users\Moz User\AppData\Local\Microsoft\Windows\Fonts\FontFile1.ttf)",
    323      LR"(C:\Users\Moz User\AppData\Local\Microsoft\Windows\Fonts\Sub\FontFile2.ttf)",
    324  });
    325 
    326  EXPECT_READONLY_EQ(
    327      LR"(C:\Users\Moz User\AppData\Local\Microsoft\Windows\Fonts\FontFile1.ttf)")
    328      .Times(0);
    329  EXPECT_READONLY_EQ(
    330      LR"(C:\Users\Moz User\AppData\Local\Microsoft\Windows\Fonts\Sub\FontFile2.ttf)")
    331      .Times(0);
    332 
    333  CreateHelperAndCallAddRules();
    334 }
    335 
    336 TEST_F(UserFontConfigHelperTest,
    337       PathsInWindowsUsersFontDirNotAddedIgnoringCase) {
    338  SetUpPaths({
    339      LR"(c:\Users\mOZ user\aPPdATA\Local\microsoft\wINDows\Fonts\FontFile1.ttf)",
    340      LR"(c:\uSERS\moz user\aPPdATA\lOCAL\MICRosoft\WindOWS\fONTS\Sub\FontFile2.ttf)",
    341  });
    342 
    343  EXPECT_READONLY_EQ(
    344      LR"(c:\Users\mOZ user\aPPdATA\Local\microsoft\wINDows\Fonts\FontFile1.ttf)")
    345      .Times(0);
    346  EXPECT_READONLY_EQ(
    347      LR"(c:\uSERS\moz user\aPPdATA\lOCAL\MICRosoft\WindOWS\fONTS\Sub\FontFile2.ttf)")
    348      .Times(0);
    349 
    350  CreateHelperAndCallAddRules();
    351 }
    352 
    353 auto RuleSize(const wchar_t* aRulePath) {
    354  return (12 * sizeof(sandbox::PolicyOpcode)) +
    355         ((wcslen(aRulePath) + 4) * sizeof(wchar_t) * 4);
    356 }
    357 
    358 std::wstring MakeLongFontPath(const wchar_t* aPrefix, const wchar_t* aSuffix) {
    359  static size_t sReqPathLen = []() {
    360    // Take the bytes required for the static rules from the starting memory
    361    // allowance for tests.
    362    size_t remainingSpace =
    363        (4096 * kDefaultNumberOfPagesForTesting) - RuleSize(sWinUserFonts) -
    364        RuleSize(sAdobeLiveTypeFonts) - RuleSize(sAdobeUserOwnedFonts);
    365 
    366    // We want 3 paths to be too big, so divide by 3 and reverse the formula.
    367    size_t spacePerFontPath = remainingSpace / 3;
    368    size_t reqFontLen =
    369        ((spacePerFontPath - (12 * sizeof(sandbox::PolicyOpcode))) /
    370         (4 * sizeof(wchar_t))) -
    371        4;
    372 
    373    // Add on 1 to make it too long for 3 paths.
    374    return reqFontLen + 1;
    375  }();
    376 
    377  std::wstring longFontPath(aPrefix);
    378  longFontPath.append(sReqPathLen - longFontPath.length() - wcslen(aSuffix),
    379                      'F');
    380  longFontPath.append(aSuffix);
    381  return longFontPath;
    382 }
    383 
    384 TEST_F(UserFontConfigHelperTest, PathsTooLongForStorage) {
    385  // These font paths take up enough storage such that, with the Windows user
    386  // font dir rule, only two will fit in the available 4K of storage. Note that
    387  // we can't guarantee the order they are returned from the registry.
    388  auto path1 = MakeLongFontPath(LR"(C:\Users\Moz User\)", L"1");
    389  auto path2 = MakeLongFontPath(LR"(C:\Users\Moz User\)", L"2");
    390  auto path3 = MakeLongFontPath(LR"(C:\Users\Moz User\)", L"3");
    391  SetUpPaths({
    392      path1,
    393      path2,
    394      path3,
    395  });
    396 
    397  path1.pop_back();
    398  EXPECT_READONLY_STARTS(path1).Times(2).After(mWinUserFontCall);
    399 
    400  CreateHelperAndCallAddRules();
    401 }
    402 
    403 TEST_F(UserFontConfigHelperTest, PathsTooLongOneOutsideUserProfile) {
    404  // These font paths take up enough storage such that, with the Windows user
    405  // font dir rule, only two will fit in the available 4K of storage.
    406  // However one is outside the user profile, so we can be certain about which
    407  // rules should be added.
    408  auto path1 = MakeLongFontPath(LR"(C:\ProgramData\)", L"1");
    409  auto path2 = MakeLongFontPath(LR"(C:\Users\Moz User\)", L"2");
    410  auto path3 = MakeLongFontPath(LR"(C:\Users\Moz User\)", L"3");
    411  SetUpPaths({
    412      path1,
    413      path2,
    414      path3,
    415  });
    416 
    417  EXPECT_READONLY_EQ(path1).Times(0);
    418  EXPECT_READONLY_EQ(path2).After(mWinUserFontCall);
    419  EXPECT_READONLY_EQ(path3).After(mWinUserFontCall);
    420 
    421  CreateHelperAndCallAddRules();
    422 }
    423 
    424 }  // namespace mozilla