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/prefs/scoped_user_pref_update.h" 10 #include "base/run_loop.h" 11 #include "chrome/browser/net/ssl_config_service_manager.h" 12 #include "chrome/browser/prefs/browser_prefs.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 "chrome/test/base/testing_profile_manager.h" 20 #include "components/keyed_service/content/browser_context_dependency_manager.h" 21 #include "content/public/browser/host_zoom_map.h" 22 #include "content/public/common/page_zoom.h" 23 #include "net/dns/mock_host_resolver.h" 24 25 using content::HostZoomMap; 26 27 namespace { 28 29 class TestingProfileWithHostZoomMap : public TestingProfile { 30 public: 31 TestingProfileWithHostZoomMap() { 32 zoom_subscription_ = 33 HostZoomMap::GetForBrowserContext(this)->AddZoomLevelChangedCallback( 34 base::Bind(&TestingProfileWithHostZoomMap::OnZoomLevelChanged, 35 base::Unretained(this))); 36 } 37 38 virtual ~TestingProfileWithHostZoomMap() {} 39 40 virtual Profile* GetOffTheRecordProfile() OVERRIDE { 41 if (!off_the_record_profile_) 42 off_the_record_profile_.reset(CreateOffTheRecordProfile()); 43 return off_the_record_profile_.get(); 44 } 45 46 virtual PrefService* GetOffTheRecordPrefs() OVERRIDE { 47 return GetPrefs(); 48 } 49 50 private: 51 void OnZoomLevelChanged(const HostZoomMap::ZoomLevelChange& change) { 52 53 if (change.mode != HostZoomMap::ZOOM_CHANGED_FOR_HOST) 54 return; 55 56 HostZoomMap* host_zoom_map = HostZoomMap::GetForBrowserContext(this); 57 58 double level = change.zoom_level; 59 DictionaryPrefUpdate update(prefs_.get(), prefs::kPerHostZoomLevels); 60 base::DictionaryValue* host_zoom_dictionary = update.Get(); 61 if (content::ZoomValuesEqual(level, host_zoom_map->GetDefaultZoomLevel())) { 62 host_zoom_dictionary->RemoveWithoutPathExpansion(change.host, NULL); 63 } else { 64 host_zoom_dictionary->SetWithoutPathExpansion( 65 change.host, base::Value::CreateDoubleValue(level)); 66 } 67 } 68 69 scoped_ptr<Profile> off_the_record_profile_; 70 scoped_ptr<SSLConfigServiceManager> ssl_config_service_manager_; 71 72 scoped_ptr<HostZoomMap::Subscription> zoom_subscription_; 73 74 DISALLOW_COPY_AND_ASSIGN(TestingProfileWithHostZoomMap); 75 }; 76 77 } // namespace 78 79 // We need to have a BrowserProcess in g_browser_process variable, since 80 // OffTheRecordProfileImpl ctor uses it in 81 // ProfileIOData::InitializeProfileParams. 82 class OffTheRecordProfileImplTest : public BrowserWithTestWindowTest { 83 protected: 84 OffTheRecordProfileImplTest() {} 85 86 virtual ~OffTheRecordProfileImplTest() {} 87 88 virtual void SetUp() OVERRIDE { 89 profile_manager_.reset(new TestingProfileManager(browser_process())); 90 ASSERT_TRUE(profile_manager_->SetUp()); 91 92 testing_io_thread_state_.reset(new chrome::TestingIOThreadState()); 93 testing_io_thread_state_->io_thread_state()->globals()->host_resolver.reset( 94 new net::MockHostResolver()); 95 96 BrowserWithTestWindowTest::SetUp(); 97 } 98 99 virtual void TearDown() OVERRIDE { 100 DestroyBrowserAndProfile(); 101 BrowserWithTestWindowTest::TearDown(); 102 103 testing_io_thread_state_.reset(); 104 105 profile_manager_.reset(); 106 } 107 108 private: 109 TestingBrowserProcess* browser_process() { 110 return TestingBrowserProcess::GetGlobal(); 111 } 112 113 scoped_ptr<TestingProfileManager> profile_manager_; 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->InitIoData(); 153 child_profile->InitHostZoomMap(); 154 155 BrowserContextDependencyManager::GetInstance()-> 156 CreateBrowserContextServicesForTest(child_profile.get()); 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