tor-browser

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

TestPACMan.cpp (7380B)


      1 #include <utility>
      2 
      3 #include "gtest/gtest.h"
      4 #include "nsServiceManagerUtils.h"
      5 #include "../../../xpcom/threads/nsThreadManager.h"
      6 #include "nsIDHCPClient.h"
      7 #include "mozilla/Preferences.h"
      8 #include "nsComponentManager.h"
      9 #include "nsIPrefService.h"
     10 #include "nsNetCID.h"
     11 #include "mozilla/ModuleUtils.h"
     12 #include "mozilla/GenericFactory.h"
     13 #include "../../base/nsPACMan.h"
     14 #include "mozilla/StaticMutex.h"
     15 
     16 #define TEST_WPAD_DHCP_OPTION "http://pac/pac.dat"
     17 #define TEST_ASSIGNED_PAC_URL "http://assignedpac/pac.dat"
     18 #define WPAD_PREF 4
     19 #define NETWORK_PROXY_TYPE_PREF_NAME "network.proxy.type"
     20 #define GETTING_NETWORK_PROXY_TYPE_FAILED (-1)
     21 
     22 static mozilla::StaticMutex sMutex;
     23 constinit nsCString WPADOptionResult MOZ_GUARDED_BY(sMutex);
     24 
     25 namespace mozilla {
     26 namespace net {
     27 
     28 nsresult SetNetworkProxyType(int32_t pref) {
     29  return Preferences::SetInt(NETWORK_PROXY_TYPE_PREF_NAME, pref);
     30 }
     31 
     32 nsresult GetNetworkProxyType(int32_t* pref) {
     33  return Preferences::GetInt(NETWORK_PROXY_TYPE_PREF_NAME, pref);
     34 }
     35 
     36 class nsTestDHCPClient final : public nsIDHCPClient {
     37 public:
     38  NS_DECL_THREADSAFE_ISUPPORTS
     39  NS_DECL_NSIDHCPCLIENT
     40 
     41  nsTestDHCPClient() = default;
     42 
     43  nsresult Init() { return NS_OK; };
     44 
     45 private:
     46  ~nsTestDHCPClient() = default;
     47 };
     48 
     49 NS_IMETHODIMP
     50 nsTestDHCPClient::GetOption(uint8_t option, nsACString& _retval) {
     51  mozilla::StaticMutexAutoLock lock(sMutex);
     52  _retval.Assign(WPADOptionResult);
     53  return NS_OK;
     54 }
     55 
     56 NS_IMPL_ISUPPORTS(nsTestDHCPClient, nsIDHCPClient)
     57 
     58 #define NS_TESTDHCPCLIENTSERVICE_CID /* {FEBF1D69-4D7D-4891-9524-045AD18B5593} \
     59                                      */                                       \
     60  {0xFEBF1D69, 0x4D7D, 0x4891, {0x95, 0x24, 0x04, 0x5a, 0xd1, 0x8b, 0x55, 0x93}}
     61 
     62 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsTestDHCPClient, Init)
     63 NS_DEFINE_NAMED_CID(NS_TESTDHCPCLIENTSERVICE_CID);
     64 
     65 void SetOptionResult(const char* result) {
     66  mozilla::StaticMutexAutoLock lock(sMutex);
     67  WPADOptionResult.Assign(result);
     68 }
     69 
     70 class ProcessPendingEventsAction final : public Runnable {
     71 public:
     72  ProcessPendingEventsAction() : Runnable("net::ProcessPendingEventsAction") {}
     73 
     74  NS_IMETHOD
     75  Run() override {
     76    if (NS_HasPendingEvents(nullptr)) {
     77      NS_WARNING("Found pending requests on PAC thread");
     78      nsresult rv;
     79      rv = NS_ProcessPendingEvents(nullptr);
     80      EXPECT_EQ(NS_OK, rv);
     81    }
     82    NS_WARNING("No pending requests on PAC thread");
     83    return NS_OK;
     84  }
     85 };
     86 
     87 class TestPACMan : public ::testing::Test {
     88 protected:
     89  RefPtr<nsPACMan> mPACMan;
     90 
     91  void ProcessAllEvents() {
     92    ProcessPendingEventsOnPACThread();
     93    nsresult rv;
     94    while (NS_HasPendingEvents(nullptr)) {
     95      NS_WARNING("Pending events on main thread");
     96      rv = NS_ProcessPendingEvents(nullptr);
     97      ASSERT_EQ(NS_OK, rv);
     98      ProcessPendingEventsOnPACThread();
     99    }
    100    NS_WARNING("End of pending events on main thread");
    101  }
    102 
    103  // This method is used to ensure that all pending events on the main thread
    104  // and the Proxy thread are processsed.
    105  // It iterates over ProcessAllEvents because simply calling ProcessAllEvents
    106  // once did not reliably process the events on both threads on all platforms.
    107  void ProcessAllEventsTenTimes() {
    108    for (int i = 0; i < 10; i++) {
    109      ProcessAllEvents();
    110    }
    111  }
    112 
    113  virtual void SetUp() {
    114    Preferences::SetBool("network.proxy.dhcp_wpad_only_one_outstanding", false);
    115    Preferences::SetFloat("network.proxy.dhcp_wpad_timeout_sec", 30);
    116    ASSERT_EQ(NS_OK, GetNetworkProxyType(&originalNetworkProxyTypePref));
    117    nsCOMPtr<nsIFactory> factory;
    118    nsresult rv = nsComponentManagerImpl::gComponentManager->GetClassObject(
    119        kNS_TESTDHCPCLIENTSERVICE_CID, NS_GET_IID(nsIFactory),
    120        getter_AddRefs(factory));
    121    if (NS_SUCCEEDED(rv) && factory) {
    122      rv = nsComponentManagerImpl::gComponentManager->UnregisterFactory(
    123          kNS_TESTDHCPCLIENTSERVICE_CID, factory);
    124      ASSERT_EQ(NS_OK, rv);
    125    }
    126    factory = new mozilla::GenericFactory(nsTestDHCPClientConstructor);
    127    nsComponentManagerImpl::gComponentManager->RegisterFactory(
    128        kNS_TESTDHCPCLIENTSERVICE_CID, "nsTestDHCPClient",
    129        NS_DHCPCLIENT_CONTRACTID, factory);
    130 
    131    mPACMan = new nsPACMan(nullptr);
    132    mPACMan->SetWPADOverDHCPEnabled(true);
    133    mPACMan->Init(nullptr);
    134    ASSERT_EQ(NS_OK, SetNetworkProxyType(WPAD_PREF));
    135  }
    136 
    137  virtual void TearDown() {
    138    mPACMan->Shutdown();
    139    if (originalNetworkProxyTypePref != GETTING_NETWORK_PROXY_TYPE_FAILED) {
    140      ASSERT_EQ(NS_OK, SetNetworkProxyType(originalNetworkProxyTypePref));
    141    }
    142  }
    143 
    144  nsCOMPtr<nsIDHCPClient> GetPACManDHCPCient() { return mPACMan->mDHCPClient; }
    145 
    146  void SetPACManDHCPCient(nsCOMPtr<nsIDHCPClient> aValue) {
    147    mPACMan->mDHCPClient = std::move(aValue);
    148  }
    149 
    150  void AssertPACSpecEqualTo(const char* aExpected) {
    151    ASSERT_STREQ(aExpected, mPACMan->mPACURISpec.Data());
    152  }
    153 
    154 private:
    155  int32_t originalNetworkProxyTypePref = GETTING_NETWORK_PROXY_TYPE_FAILED;
    156 
    157  void ProcessPendingEventsOnPACThread() {
    158    RefPtr<ProcessPendingEventsAction> action =
    159        new ProcessPendingEventsAction();
    160 
    161    mPACMan->DispatchToPAC(action.forget(), /*aSync =*/true);
    162  }
    163 };
    164 
    165 TEST_F(TestPACMan, TestCreateDHCPClientAndGetOption) {
    166  SetOptionResult(TEST_WPAD_DHCP_OPTION);
    167  nsCString spec;
    168 
    169  GetPACManDHCPCient()->GetOption(252, spec);
    170 
    171  ASSERT_STREQ(TEST_WPAD_DHCP_OPTION, spec.Data());
    172 }
    173 
    174 TEST_F(TestPACMan, TestCreateDHCPClientAndGetEmptyOption) {
    175  SetOptionResult("");
    176  nsCString spec;
    177  spec.AssignLiteral(TEST_ASSIGNED_PAC_URL);
    178 
    179  GetPACManDHCPCient()->GetOption(252, spec);
    180 
    181  ASSERT_TRUE(spec.IsEmpty());
    182 }
    183 
    184 TEST_F(TestPACMan,
    185       WhenTheDHCPClientExistsAndDHCPIsNonEmptyDHCPOptionIsUsedAsPACUri) {
    186  SetOptionResult(TEST_WPAD_DHCP_OPTION);
    187 
    188  mPACMan->LoadPACFromURI(""_ns);
    189  ProcessAllEventsTenTimes();
    190 
    191  mozilla::StaticMutexAutoLock lock(sMutex);
    192  ASSERT_STREQ(TEST_WPAD_DHCP_OPTION, WPADOptionResult.Data());
    193  AssertPACSpecEqualTo(TEST_WPAD_DHCP_OPTION);
    194 }
    195 
    196 TEST_F(TestPACMan, WhenTheDHCPResponseIsEmptyWPADDefaultsToStandardURL) {
    197  SetOptionResult(""_ns.Data());
    198 
    199  mPACMan->LoadPACFromURI(""_ns);
    200  ASSERT_TRUE(NS_HasPendingEvents(nullptr));
    201  ProcessAllEventsTenTimes();
    202 
    203  mozilla::StaticMutexAutoLock lock(sMutex);
    204  ASSERT_STREQ("", WPADOptionResult.Data());
    205  AssertPACSpecEqualTo("http://wpad/wpad.dat");
    206 }
    207 
    208 TEST_F(TestPACMan, WhenThereIsNoDHCPClientWPADDefaultsToStandardURL) {
    209  SetOptionResult(TEST_WPAD_DHCP_OPTION);
    210  SetPACManDHCPCient(nullptr);
    211 
    212  mPACMan->LoadPACFromURI(""_ns);
    213  ProcessAllEventsTenTimes();
    214 
    215  mozilla::StaticMutexAutoLock lock(sMutex);
    216  ASSERT_STREQ(TEST_WPAD_DHCP_OPTION, WPADOptionResult.Data());
    217  AssertPACSpecEqualTo("http://wpad/wpad.dat");
    218 }
    219 
    220 TEST_F(TestPACMan, WhenWPADOverDHCPIsPreffedOffWPADDefaultsToStandardURL) {
    221  SetOptionResult(TEST_WPAD_DHCP_OPTION);
    222  mPACMan->SetWPADOverDHCPEnabled(false);
    223 
    224  mPACMan->LoadPACFromURI(""_ns);
    225  ProcessAllEventsTenTimes();
    226 
    227  mozilla::StaticMutexAutoLock lock(sMutex);
    228  ASSERT_STREQ(TEST_WPAD_DHCP_OPTION, WPADOptionResult.Data());
    229  AssertPACSpecEqualTo("http://wpad/wpad.dat");
    230 }
    231 
    232 TEST_F(TestPACMan, WhenPACUriIsSetDirectlyItIsUsedRatherThanWPAD) {
    233  SetOptionResult(TEST_WPAD_DHCP_OPTION);
    234  nsCString spec;
    235  spec.AssignLiteral(TEST_ASSIGNED_PAC_URL);
    236 
    237  mPACMan->LoadPACFromURI(spec);
    238  ProcessAllEventsTenTimes();
    239 
    240  AssertPACSpecEqualTo(TEST_ASSIGNED_PAC_URL);
    241 }
    242 
    243 }  // namespace net
    244 }  // namespace mozilla