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/profiles/off_the_record_profile_impl.h" 6 7 #include "base/prefs/pref_registry_simple.h" 8 #include "base/prefs/pref_service.h" 9 #include "base/run_loop.h" 10 #include "chrome/browser/net/ssl_config_service_manager.h" 11 #include "chrome/browser/prefs/browser_prefs.h" 12 #include "chrome/browser/prefs/scoped_user_pref_update.h" 13 #include "chrome/common/pref_names.h" 14 #include "chrome/test/base/browser_with_test_window_test.h" 15 #include "chrome/test/base/testing_browser_process.h" 16 #include "chrome/test/base/testing_io_thread_state.h" 17 #include "chrome/test/base/testing_pref_service_syncable.h" 18 #include "chrome/test/base/testing_profile.h" 19 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h" 20 #include "content/public/browser/host_zoom_map.h" 21 #include "net/dns/mock_host_resolver.h" 22 23 using content::HostZoomMap; 24 25 namespace { 26 27 class TestingProfileWithHostZoomMap : public TestingProfile { 28 public: 29 TestingProfileWithHostZoomMap() 30 : zoom_callback_( 31 base::Bind(&TestingProfileWithHostZoomMap::OnZoomLevelChanged, 32 base::Unretained(this))) { 33 HostZoomMap::GetForBrowserContext(this)->AddZoomLevelChangedCallback( 34 zoom_callback_); 35 } 36 37 virtual ~TestingProfileWithHostZoomMap() { 38 HostZoomMap::GetForBrowserContext(this)->RemoveZoomLevelChangedCallback( 39 zoom_callback_); 40 } 41 42 virtual Profile* GetOffTheRecordProfile() OVERRIDE { 43 if (!off_the_record_profile_) 44 off_the_record_profile_.reset(CreateOffTheRecordProfile()); 45 return off_the_record_profile_.get(); 46 } 47 48 virtual PrefService* GetOffTheRecordPrefs() OVERRIDE { 49 return GetPrefs(); 50 } 51 52 private: 53 void OnZoomLevelChanged(const HostZoomMap::ZoomLevelChange& change) { 54 55 if (change.mode != HostZoomMap::ZOOM_CHANGED_FOR_HOST) 56 return; 57 58 HostZoomMap* host_zoom_map = HostZoomMap::GetForBrowserContext(this); 59 60 double level = change.zoom_level; 61 DictionaryPrefUpdate update(prefs_.get(), prefs::kPerHostZoomLevels); 62 DictionaryValue* host_zoom_dictionary = update.Get(); 63 if (level == host_zoom_map->GetDefaultZoomLevel()) { 64 host_zoom_dictionary->RemoveWithoutPathExpansion(change.host, NULL); 65 } else { 66 host_zoom_dictionary->SetWithoutPathExpansion( 67 change.host, Value::CreateDoubleValue(level)); 68 } 69 } 70 71 scoped_ptr<Profile> off_the_record_profile_; 72 scoped_ptr<SSLConfigServiceManager> ssl_config_service_manager_; 73 74 HostZoomMap::ZoomLevelChangedCallback zoom_callback_; 75 76 DISALLOW_COPY_AND_ASSIGN(TestingProfileWithHostZoomMap); 77 }; 78 79 } // namespace 80 81 // We need to have a BrowserProcess in g_browser_process variable, since 82 // OffTheRecordProfileImpl ctor uses it in 83 // ProfileIOData::InitializeProfileParams. 84 class OffTheRecordProfileImplTest : public BrowserWithTestWindowTest { 85 protected: 86 OffTheRecordProfileImplTest() {} 87 88 virtual ~OffTheRecordProfileImplTest() {} 89 90 virtual void SetUp() OVERRIDE { 91 prefs_.reset(new TestingPrefServiceSimple()); 92 chrome::RegisterLocalState(prefs_->registry()); 93 94 browser_process()->SetLocalState(prefs_.get()); 95 testing_io_thread_state_.reset(new chrome::TestingIOThreadState()); 96 testing_io_thread_state_->io_thread_state()->globals()->host_resolver.reset( 97 new net::MockHostResolver()); 98 BrowserWithTestWindowTest::SetUp(); 99 } 100 101 virtual void TearDown() OVERRIDE { 102 BrowserWithTestWindowTest::TearDown(); 103 testing_io_thread_state_.reset(); 104 browser_process()->SetLocalState(NULL); 105 DestroyBrowserAndProfile(); 106 } 107 108 private: 109 TestingBrowserProcess* browser_process() { 110 return TestingBrowserProcess::GetGlobal(); 111 } 112 113 scoped_ptr<TestingPrefServiceSimple> prefs_; 114 scoped_ptr<chrome::TestingIOThreadState> testing_io_thread_state_; 115 116 DISALLOW_COPY_AND_ASSIGN(OffTheRecordProfileImplTest); 117 }; 118 119 // Test four things: 120 // 1. Host zoom maps of parent profile and child profile are different. 121 // 2. Child host zoom map inherites zoom level at construction. 122 // 3. Change of zoom level doesn't propagate from child to parent. 123 // 4. Change of zoom level propagate from parent to child. 124 TEST_F(OffTheRecordProfileImplTest, GetHostZoomMap) { 125 // Constants for test case. 126 std::string const host("example.com"); 127 double const zoom_level_25 = 2.5; 128 double const zoom_level_30 = 3.0; 129 double const zoom_level_40 = 4.0; 130 131 // Prepare parent profile. 132 scoped_ptr<Profile> parent_profile(new TestingProfileWithHostZoomMap); 133 ASSERT_TRUE(parent_profile.get()); 134 ASSERT_TRUE(parent_profile->GetPrefs()); 135 ASSERT_TRUE(parent_profile->GetOffTheRecordPrefs()); 136 137 // Prepare parent host zoom map. 138 HostZoomMap* parent_zoom_map = 139 HostZoomMap::GetForBrowserContext(parent_profile.get()); 140 ASSERT_TRUE(parent_zoom_map); 141 142 parent_zoom_map->SetZoomLevelForHost(host, zoom_level_25); 143 ASSERT_EQ(parent_zoom_map->GetZoomLevelForHostAndScheme("http", host), 144 zoom_level_25); 145 146 // TODO(yosin) We need to wait ProfileImpl::Observe done for 147 // OnZoomLevelChanged. 148 149 // Prepare child profile as off the record profile. 150 scoped_ptr<OffTheRecordProfileImpl> child_profile( 151 new OffTheRecordProfileImpl(parent_profile.get())); 152 child_profile->InitHostZoomMap(); 153 154 BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices( 155 child_profile.get(), 156 true); // For testing. 157 158 // Prepare child host zoom map. 159 HostZoomMap* child_zoom_map = 160 HostZoomMap::GetForBrowserContext(child_profile.get()); 161 ASSERT_TRUE(child_zoom_map); 162 163 // Verity. 164 EXPECT_NE(parent_zoom_map, child_zoom_map); 165 166 EXPECT_EQ(parent_zoom_map->GetZoomLevelForHostAndScheme("http", host), 167 child_zoom_map->GetZoomLevelForHostAndScheme("http", host)) << 168 "Child must inherit from parent."; 169 170 child_zoom_map->SetZoomLevelForHost(host, zoom_level_30); 171 ASSERT_EQ( 172 child_zoom_map->GetZoomLevelForHostAndScheme("http", host), 173 zoom_level_30); 174 175 EXPECT_NE(parent_zoom_map->GetZoomLevelForHostAndScheme("http", host), 176 child_zoom_map->GetZoomLevelForHostAndScheme("http", host)) << 177 "Child change must not propagate to parent."; 178 179 parent_zoom_map->SetZoomLevelForHost(host, zoom_level_40); 180 ASSERT_EQ( 181 parent_zoom_map->GetZoomLevelForHostAndScheme("http", host), 182 zoom_level_40); 183 184 EXPECT_EQ(parent_zoom_map->GetZoomLevelForHostAndScheme("http", host), 185 child_zoom_map->GetZoomLevelForHostAndScheme("http", host)) << 186 "Parent change should propagate to child."; 187 base::RunLoop().RunUntilIdle(); 188 } 189