Home | History | Annotate | Download | only in net
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/net/http_server_properties_manager.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/prefs/pref_registry_simple.h"
     10 #include "base/prefs/testing_pref_service.h"
     11 #include "base/values.h"
     12 #include "chrome/common/pref_names.h"
     13 #include "content/public/test/test_browser_thread.h"
     14 #include "testing/gmock/include/gmock/gmock.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 #include "url/gurl.h"
     17 
     18 namespace chrome_browser_net {
     19 
     20 namespace {
     21 
     22 using ::testing::_;
     23 using ::testing::Invoke;
     24 using ::testing::Mock;
     25 using ::testing::StrictMock;
     26 using content::BrowserThread;
     27 
     28 class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager {
     29  public:
     30   explicit TestingHttpServerPropertiesManager(PrefService* pref_service)
     31       : HttpServerPropertiesManager(pref_service) {
     32     InitializeOnIOThread();
     33   }
     34 
     35   virtual ~TestingHttpServerPropertiesManager() {
     36   }
     37 
     38   // Make these methods public for testing.
     39   using HttpServerPropertiesManager::ScheduleUpdateCacheOnUI;
     40   using HttpServerPropertiesManager::ScheduleUpdatePrefsOnIO;
     41 
     42   // Post tasks without a delay during tests.
     43   virtual void StartPrefsUpdateTimerOnIO(base::TimeDelta delay) OVERRIDE {
     44     HttpServerPropertiesManager::StartPrefsUpdateTimerOnIO(
     45         base::TimeDelta());
     46   }
     47 
     48   void UpdateCacheFromPrefsOnUIConcrete() {
     49     HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI();
     50   }
     51 
     52   // Post tasks without a delay during tests.
     53   virtual void StartCacheUpdateTimerOnUI(base::TimeDelta delay) OVERRIDE {
     54     HttpServerPropertiesManager::StartCacheUpdateTimerOnUI(
     55         base::TimeDelta());
     56   }
     57 
     58   void UpdatePrefsFromCacheOnIOConcrete(const base::Closure& callback) {
     59     HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO(callback);
     60   }
     61 
     62   MOCK_METHOD0(UpdateCacheFromPrefsOnUI, void());
     63   MOCK_METHOD1(UpdatePrefsFromCacheOnIO, void(const base::Closure&));
     64   MOCK_METHOD5(UpdateCacheFromPrefsOnIO,
     65                void(std::vector<std::string>* spdy_servers,
     66                     net::SpdySettingsMap* spdy_settings_map,
     67                     net::AlternateProtocolMap* alternate_protocol_map,
     68                     net::AlternateProtocolExperiment experiment,
     69                     bool detected_corrupted_prefs));
     70   MOCK_METHOD3(UpdatePrefsOnUI,
     71                void(base::ListValue* spdy_server_list,
     72                     net::SpdySettingsMap* spdy_settings_map,
     73                     net::AlternateProtocolMap* alternate_protocol_map));
     74 
     75  private:
     76   DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager);
     77 };
     78 
     79 class HttpServerPropertiesManagerTest : public testing::Test {
     80  protected:
     81   HttpServerPropertiesManagerTest()
     82       : ui_thread_(BrowserThread::UI, &loop_),
     83         io_thread_(BrowserThread::IO, &loop_) {
     84   }
     85 
     86   virtual void SetUp() OVERRIDE {
     87     pref_service_.registry()->RegisterDictionaryPref(
     88         prefs::kHttpServerProperties);
     89     http_server_props_manager_.reset(
     90         new StrictMock<TestingHttpServerPropertiesManager>(&pref_service_));
     91     ExpectCacheUpdate();
     92     loop_.RunUntilIdle();
     93   }
     94 
     95   virtual void TearDown() OVERRIDE {
     96     if (http_server_props_manager_.get())
     97       http_server_props_manager_->ShutdownOnUIThread();
     98     loop_.RunUntilIdle();
     99     // Delete |http_server_props_manager_| while |io_thread_| is mapping IO to
    100     // |loop_|.
    101     http_server_props_manager_.reset();
    102   }
    103 
    104   void ExpectCacheUpdate() {
    105     EXPECT_CALL(*http_server_props_manager_, UpdateCacheFromPrefsOnUI())
    106         .WillOnce(
    107             Invoke(http_server_props_manager_.get(),
    108                    &TestingHttpServerPropertiesManager::
    109                    UpdateCacheFromPrefsOnUIConcrete));
    110   }
    111 
    112   void ExpectPrefsUpdate() {
    113     EXPECT_CALL(*http_server_props_manager_, UpdatePrefsFromCacheOnIO(_))
    114         .WillOnce(
    115             Invoke(http_server_props_manager_.get(),
    116                    &TestingHttpServerPropertiesManager::
    117                    UpdatePrefsFromCacheOnIOConcrete));
    118   }
    119 
    120   void ExpectPrefsUpdateRepeatedly() {
    121     EXPECT_CALL(*http_server_props_manager_, UpdatePrefsFromCacheOnIO(_))
    122         .WillRepeatedly(
    123             Invoke(http_server_props_manager_.get(),
    124                    &TestingHttpServerPropertiesManager::
    125                    UpdatePrefsFromCacheOnIOConcrete));
    126   }
    127 
    128   base::MessageLoop loop_;
    129   TestingPrefServiceSimple pref_service_;
    130   scoped_ptr<TestingHttpServerPropertiesManager> http_server_props_manager_;
    131 
    132  private:
    133   content::TestBrowserThread ui_thread_;
    134   content::TestBrowserThread io_thread_;
    135 
    136   DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesManagerTest);
    137 };
    138 
    139 TEST_F(HttpServerPropertiesManagerTest,
    140        SingleUpdateForTwoSpdyServerPrefChanges) {
    141   ExpectCacheUpdate();
    142 
    143   // Set up the prefs for www.google.com:80 and mail.google.com:80 and then set
    144   // it twice. Only expect a single cache update.
    145 
    146   base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
    147 
    148   // Set supports_spdy for www.google.com:80.
    149   server_pref_dict->SetBoolean("supports_spdy", true);
    150 
    151   // Set up alternate_protocol for www.google.com:80.
    152   base::DictionaryValue* alternate_protocol = new base::DictionaryValue;
    153   alternate_protocol->SetInteger("port", 443);
    154   alternate_protocol->SetString("protocol_str", "npn-spdy/3");
    155   server_pref_dict->SetWithoutPathExpansion(
    156       "alternate_protocol", alternate_protocol);
    157 
    158   // Set the server preference for www.google.com:80.
    159   base::DictionaryValue* servers_dict = new base::DictionaryValue;
    160   servers_dict->SetWithoutPathExpansion(
    161       "www.google.com:80", server_pref_dict);
    162 
    163   // Set the preference for mail.google.com server.
    164   base::DictionaryValue* server_pref_dict1 = new base::DictionaryValue;
    165 
    166   // Set supports_spdy for mail.google.com:80
    167   server_pref_dict1->SetBoolean("supports_spdy", true);
    168 
    169   // Set up alternate_protocol for mail.google.com:80
    170   base::DictionaryValue* alternate_protocol1 = new base::DictionaryValue;
    171   alternate_protocol1->SetInteger("port", 444);
    172   alternate_protocol1->SetString("protocol_str", "npn-spdy/3.1");
    173 
    174   server_pref_dict1->SetWithoutPathExpansion(
    175       "alternate_protocol", alternate_protocol1);
    176 
    177   // Set the server preference for mail.google.com:80.
    178   servers_dict->SetWithoutPathExpansion(
    179       "mail.google.com:80", server_pref_dict1);
    180 
    181   base::DictionaryValue* http_server_properties_dict =
    182       new base::DictionaryValue;
    183   HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
    184   http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict);
    185 
    186   // Set the same value for kHttpServerProperties multiple times.
    187   pref_service_.SetManagedPref(prefs::kHttpServerProperties,
    188                                http_server_properties_dict);
    189   base::DictionaryValue* http_server_properties_dict2 =
    190       http_server_properties_dict->DeepCopy();
    191   pref_service_.SetManagedPref(prefs::kHttpServerProperties,
    192                                http_server_properties_dict2);
    193 
    194   loop_.RunUntilIdle();
    195   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    196 
    197   // Verify SupportsSpdy.
    198   EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(
    199       net::HostPortPair::FromString("www.google.com:80")));
    200   EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(
    201       net::HostPortPair::FromString("mail.google.com:80")));
    202   EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(
    203       net::HostPortPair::FromString("foo.google.com:1337")));
    204 
    205   // Verify AlternateProtocol.
    206   ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(
    207       net::HostPortPair::FromString("www.google.com:80")));
    208   ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(
    209       net::HostPortPair::FromString("mail.google.com:80")));
    210   net::PortAlternateProtocolPair port_alternate_protocol =
    211       http_server_props_manager_->GetAlternateProtocol(
    212           net::HostPortPair::FromString("www.google.com:80"));
    213   EXPECT_EQ(443, port_alternate_protocol.port);
    214   EXPECT_EQ(net::NPN_SPDY_3, port_alternate_protocol.protocol);
    215   port_alternate_protocol =
    216       http_server_props_manager_->GetAlternateProtocol(
    217           net::HostPortPair::FromString("mail.google.com:80"));
    218   EXPECT_EQ(444, port_alternate_protocol.port);
    219   EXPECT_EQ(net::NPN_SPDY_3_1, port_alternate_protocol.protocol);
    220 }
    221 
    222 TEST_F(HttpServerPropertiesManagerTest, SupportsSpdy) {
    223   ExpectPrefsUpdate();
    224 
    225   // Post an update task to the IO thread. SetSupportsSpdy calls
    226   // ScheduleUpdatePrefsOnIO.
    227 
    228   // Add mail.google.com:443 as a supporting spdy server.
    229   net::HostPortPair spdy_server_mail("mail.google.com", 443);
    230   EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
    231   http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
    232 
    233   // Run the task.
    234   loop_.RunUntilIdle();
    235 
    236   EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
    237   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    238 }
    239 
    240 TEST_F(HttpServerPropertiesManagerTest, SetSpdySetting) {
    241   ExpectPrefsUpdate();
    242 
    243   // Add SpdySetting for mail.google.com:443.
    244   net::HostPortPair spdy_server_mail("mail.google.com", 443);
    245   const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
    246   const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
    247   const uint32 value1 = 31337;
    248   http_server_props_manager_->SetSpdySetting(
    249       spdy_server_mail, id1, flags1, value1);
    250 
    251   // Run the task.
    252   loop_.RunUntilIdle();
    253 
    254   const net::SettingsMap& settings_map1_ret =
    255       http_server_props_manager_->GetSpdySettings(spdy_server_mail);
    256   ASSERT_EQ(1U, settings_map1_ret.size());
    257   net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
    258   EXPECT_TRUE(it1_ret != settings_map1_ret.end());
    259   net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
    260   EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
    261   EXPECT_EQ(value1, flags_and_value1_ret.second);
    262 
    263   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    264 }
    265 
    266 TEST_F(HttpServerPropertiesManagerTest, ClearSpdySetting) {
    267   ExpectPrefsUpdateRepeatedly();
    268 
    269   // Add SpdySetting for mail.google.com:443.
    270   net::HostPortPair spdy_server_mail("mail.google.com", 443);
    271   const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
    272   const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
    273   const uint32 value1 = 31337;
    274   http_server_props_manager_->SetSpdySetting(
    275       spdy_server_mail, id1, flags1, value1);
    276 
    277   // Run the task.
    278   loop_.RunUntilIdle();
    279 
    280   const net::SettingsMap& settings_map1_ret =
    281       http_server_props_manager_->GetSpdySettings(spdy_server_mail);
    282   ASSERT_EQ(1U, settings_map1_ret.size());
    283   net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
    284   EXPECT_TRUE(it1_ret != settings_map1_ret.end());
    285   net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
    286   EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
    287   EXPECT_EQ(value1, flags_and_value1_ret.second);
    288 
    289   // Clear SpdySetting for mail.google.com:443.
    290   http_server_props_manager_->ClearSpdySettings(spdy_server_mail);
    291 
    292   // Run the task.
    293   loop_.RunUntilIdle();
    294 
    295   // Verify that there are no entries in the settings map for
    296   // mail.google.com:443.
    297   const net::SettingsMap& settings_map2_ret =
    298       http_server_props_manager_->GetSpdySettings(spdy_server_mail);
    299   ASSERT_EQ(0U, settings_map2_ret.size());
    300 
    301   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    302 }
    303 
    304 TEST_F(HttpServerPropertiesManagerTest, ClearAllSpdySetting) {
    305   ExpectPrefsUpdateRepeatedly();
    306 
    307   // Add SpdySetting for mail.google.com:443.
    308   net::HostPortPair spdy_server_mail("mail.google.com", 443);
    309   const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
    310   const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
    311   const uint32 value1 = 31337;
    312   http_server_props_manager_->SetSpdySetting(
    313       spdy_server_mail, id1, flags1, value1);
    314 
    315   // Run the task.
    316   loop_.RunUntilIdle();
    317 
    318   const net::SettingsMap& settings_map1_ret =
    319       http_server_props_manager_->GetSpdySettings(spdy_server_mail);
    320   ASSERT_EQ(1U, settings_map1_ret.size());
    321   net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
    322   EXPECT_TRUE(it1_ret != settings_map1_ret.end());
    323   net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
    324   EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
    325   EXPECT_EQ(value1, flags_and_value1_ret.second);
    326 
    327   // Clear All SpdySettings.
    328   http_server_props_manager_->ClearAllSpdySettings();
    329 
    330   // Run the task.
    331   loop_.RunUntilIdle();
    332 
    333   // Verify that there are no entries in the settings map.
    334   const net::SpdySettingsMap& spdy_settings_map2_ret =
    335       http_server_props_manager_->spdy_settings_map();
    336   ASSERT_EQ(0U, spdy_settings_map2_ret.size());
    337 
    338   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    339 }
    340 
    341 TEST_F(HttpServerPropertiesManagerTest, HasAlternateProtocol) {
    342   ExpectPrefsUpdate();
    343 
    344   net::HostPortPair spdy_server_mail("mail.google.com", 80);
    345   EXPECT_FALSE(
    346       http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
    347   http_server_props_manager_->SetAlternateProtocol(
    348       spdy_server_mail, 443, net::NPN_SPDY_3);
    349 
    350   // Run the task.
    351   loop_.RunUntilIdle();
    352   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    353 
    354   ASSERT_TRUE(
    355       http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
    356   net::PortAlternateProtocolPair port_alternate_protocol =
    357       http_server_props_manager_->GetAlternateProtocol(spdy_server_mail);
    358   EXPECT_EQ(443, port_alternate_protocol.port);
    359   EXPECT_EQ(net::NPN_SPDY_3, port_alternate_protocol.protocol);
    360 }
    361 
    362 TEST_F(HttpServerPropertiesManagerTest, Clear) {
    363   ExpectPrefsUpdate();
    364 
    365   net::HostPortPair spdy_server_mail("mail.google.com", 443);
    366   http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
    367   http_server_props_manager_->SetAlternateProtocol(
    368       spdy_server_mail, 443, net::NPN_SPDY_3);
    369 
    370   const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
    371   const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
    372   const uint32 value1 = 31337;
    373   http_server_props_manager_->SetSpdySetting(
    374       spdy_server_mail, id1, flags1, value1);
    375 
    376   // Run the task.
    377   loop_.RunUntilIdle();
    378 
    379   EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
    380   EXPECT_TRUE(
    381       http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
    382 
    383   // Check SPDY settings values.
    384   const net::SettingsMap& settings_map1_ret =
    385       http_server_props_manager_->GetSpdySettings(spdy_server_mail);
    386   ASSERT_EQ(1U, settings_map1_ret.size());
    387   net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
    388   EXPECT_TRUE(it1_ret != settings_map1_ret.end());
    389   net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
    390   EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
    391   EXPECT_EQ(value1, flags_and_value1_ret.second);
    392 
    393   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    394 
    395   ExpectPrefsUpdate();
    396 
    397   // Clear http server data, time out if we do not get a completion callback.
    398   http_server_props_manager_->Clear(base::MessageLoop::QuitClosure());
    399   loop_.Run();
    400 
    401   EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
    402   EXPECT_FALSE(
    403       http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
    404 
    405   const net::SettingsMap& settings_map2_ret =
    406       http_server_props_manager_->GetSpdySettings(spdy_server_mail);
    407   EXPECT_EQ(0U, settings_map2_ret.size());
    408 
    409   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    410 }
    411 
    412 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache0) {
    413   // Post an update task to the UI thread.
    414   http_server_props_manager_->ScheduleUpdateCacheOnUI();
    415   // Shutdown comes before the task is executed.
    416   http_server_props_manager_->ShutdownOnUIThread();
    417   http_server_props_manager_.reset();
    418   // Run the task after shutdown and deletion.
    419   loop_.RunUntilIdle();
    420 }
    421 
    422 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache1) {
    423   // Post an update task.
    424   http_server_props_manager_->ScheduleUpdateCacheOnUI();
    425   // Shutdown comes before the task is executed.
    426   http_server_props_manager_->ShutdownOnUIThread();
    427   // Run the task after shutdown, but before deletion.
    428   loop_.RunUntilIdle();
    429   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    430   http_server_props_manager_.reset();
    431   loop_.RunUntilIdle();
    432 }
    433 
    434 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache2) {
    435   http_server_props_manager_->UpdateCacheFromPrefsOnUIConcrete();
    436   // Shutdown comes before the task is executed.
    437   http_server_props_manager_->ShutdownOnUIThread();
    438   // Run the task after shutdown, but before deletion.
    439   loop_.RunUntilIdle();
    440   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    441   http_server_props_manager_.reset();
    442   loop_.RunUntilIdle();
    443 }
    444 
    445 //
    446 // Tests for shutdown when updating prefs.
    447 //
    448 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs0) {
    449   // Post an update task to the IO thread.
    450   http_server_props_manager_->ScheduleUpdatePrefsOnIO();
    451   // Shutdown comes before the task is executed.
    452   http_server_props_manager_->ShutdownOnUIThread();
    453   http_server_props_manager_.reset();
    454   // Run the task after shutdown and deletion.
    455   loop_.RunUntilIdle();
    456 }
    457 
    458 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs1) {
    459   ExpectPrefsUpdate();
    460   // Post an update task.
    461   http_server_props_manager_->ScheduleUpdatePrefsOnIO();
    462   // Shutdown comes before the task is executed.
    463   http_server_props_manager_->ShutdownOnUIThread();
    464   // Run the task after shutdown, but before deletion.
    465   loop_.RunUntilIdle();
    466   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    467   http_server_props_manager_.reset();
    468   loop_.RunUntilIdle();
    469 }
    470 
    471 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs2) {
    472   // This posts a task to the UI thread.
    473   http_server_props_manager_->UpdatePrefsFromCacheOnIOConcrete(base::Closure());
    474   // Shutdown comes before the task is executed.
    475   http_server_props_manager_->ShutdownOnUIThread();
    476   // Run the task after shutdown, but before deletion.
    477   loop_.RunUntilIdle();
    478   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
    479   http_server_props_manager_.reset();
    480   loop_.RunUntilIdle();
    481 }
    482 
    483 }  // namespace
    484 
    485 }  // namespace chrome_browser_net
    486