OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/public/browser/host_zoom_map.h" | 5 #include "content/public/browser/host_zoom_map.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
14 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
16 #include "base/path_service.h" | 16 #include "base/path_service.h" |
17 #include "base/prefs/pref_service.h" | 17 #include "base/prefs/pref_service.h" |
18 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
19 #include "base/values.h" | 19 #include "base/values.h" |
20 #include "chrome/browser/chrome_page_zoom.h" | 20 #include "chrome/browser/chrome_page_zoom.h" |
21 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
22 #include "chrome/browser/ui/browser.h" | 22 #include "chrome/browser/ui/browser.h" |
23 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 23 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 24 #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h" |
24 #include "chrome/common/chrome_constants.h" | 25 #include "chrome/common/chrome_constants.h" |
25 #include "chrome/common/chrome_paths.h" | 26 #include "chrome/common/chrome_paths.h" |
26 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
27 #include "chrome/test/base/in_process_browser_test.h" | 28 #include "chrome/test/base/in_process_browser_test.h" |
28 #include "chrome/test/base/testing_profile.h" | 29 #include "chrome/test/base/testing_profile.h" |
29 #include "chrome/test/base/ui_test_utils.h" | 30 #include "chrome/test/base/ui_test_utils.h" |
30 #include "content/public/test/test_utils.h" | 31 #include "content/public/test/test_utils.h" |
31 #include "net/dns/mock_host_resolver.h" | 32 #include "net/dns/mock_host_resolver.h" |
32 #include "net/test/embedded_test_server/embedded_test_server.h" | 33 #include "net/test/embedded_test_server/embedded_test_server.h" |
33 #include "net/test/embedded_test_server/http_response.h" | 34 #include "net/test/embedded_test_server/http_response.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 }; | 69 }; |
69 | 70 |
70 } // namespace | 71 } // namespace |
71 | 72 |
72 class HostZoomMapBrowserTest : public InProcessBrowserTest { | 73 class HostZoomMapBrowserTest : public InProcessBrowserTest { |
73 public: | 74 public: |
74 HostZoomMapBrowserTest() {} | 75 HostZoomMapBrowserTest() {} |
75 | 76 |
76 protected: | 77 protected: |
77 void SetDefaultZoomLevel(double level) { | 78 void SetDefaultZoomLevel(double level) { |
78 browser()->profile()->GetPrefs()->SetDouble( | 79 browser()->profile()->GetZoomLevelPrefs()->SetDefaultZoomLevelPref(level); |
79 prefs::kDefaultZoomLevel, level); | |
80 } | 80 } |
81 | 81 |
82 double GetZoomLevel(const GURL& url) { | 82 double GetZoomLevel(const GURL& url) { |
83 content::HostZoomMap* host_zoom_map = static_cast<content::HostZoomMap*>( | 83 content::HostZoomMap* host_zoom_map = static_cast<content::HostZoomMap*>( |
84 content::HostZoomMap::GetDefaultForBrowserContext( | 84 content::HostZoomMap::GetDefaultForBrowserContext( |
85 browser()->profile())); | 85 browser()->profile())); |
86 return host_zoom_map->GetZoomLevelForHostAndScheme(url.scheme(), | 86 return host_zoom_map->GetZoomLevelForHostAndScheme(url.scheme(), |
87 url.host()); | 87 url.host()); |
88 } | 88 } |
89 | 89 |
90 std::vector<std::string> GetHostsWithZoomLevels() { | 90 std::vector<std::string> GetHostsWithZoomLevels() { |
91 typedef content::HostZoomMap::ZoomLevelVector ZoomLevelVector; | 91 typedef content::HostZoomMap::ZoomLevelVector ZoomLevelVector; |
92 content::HostZoomMap* host_zoom_map = static_cast<content::HostZoomMap*>( | 92 content::HostZoomMap* host_zoom_map = static_cast<content::HostZoomMap*>( |
93 content::HostZoomMap::GetDefaultForBrowserContext( | 93 content::HostZoomMap::GetDefaultForBrowserContext( |
94 browser()->profile())); | 94 browser()->profile())); |
95 content::HostZoomMap::ZoomLevelVector zoom_levels = | 95 content::HostZoomMap::ZoomLevelVector zoom_levels = |
96 host_zoom_map->GetAllZoomLevels(); | 96 host_zoom_map->GetAllZoomLevels(); |
97 std::vector<std::string> results; | 97 std::vector<std::string> results; |
98 for (ZoomLevelVector::const_iterator it = zoom_levels.begin(); | 98 for (ZoomLevelVector::const_iterator it = zoom_levels.begin(); |
99 it != zoom_levels.end(); ++it) | 99 it != zoom_levels.end(); ++it) |
100 results.push_back(it->host); | 100 results.push_back(it->host); |
101 return results; | 101 return results; |
102 } | 102 } |
103 | 103 |
104 std::vector<std::string> GetHostsWithZoomLevelsFromPrefs() { | 104 std::vector<std::string> GetHostsWithZoomLevelsFromPrefs() { |
105 PrefService* prefs = browser()->profile()->GetPrefs(); | 105 PrefService* prefs = browser()->profile()->GetPrefs(); |
106 const base::DictionaryValue* values = | 106 const base::DictionaryValue* dictionaries = |
107 prefs->GetDictionary(prefs::kPerHostZoomLevels); | 107 prefs->GetDictionary(prefs::kPartitionPerHostZoomLevels); |
| 108 const base::DictionaryValue* values = NULL; |
| 109 std::string partition_key = |
| 110 chrome::ChromeZoomLevelPrefs::GetHashForTesting(base::FilePath()); |
| 111 dictionaries->GetDictionary(partition_key, &values); |
108 std::vector<std::string> results; | 112 std::vector<std::string> results; |
109 if (values) { | 113 if (values) { |
110 for (base::DictionaryValue::Iterator it(*values); | 114 for (base::DictionaryValue::Iterator it(*values); |
111 !it.IsAtEnd(); it.Advance()) | 115 !it.IsAtEnd(); it.Advance()) |
112 results.push_back(it.key()); | 116 results.push_back(it.key()); |
113 } | 117 } |
114 return results; | 118 return results; |
115 } | 119 } |
116 | 120 |
117 GURL ConstructTestServerURL(const char* url_template) { | 121 GURL ConstructTestServerURL(const char* url_template) { |
(...skipping 12 matching lines...) Expand all Loading... |
130 virtual void SetUpOnMainThread() override { | 134 virtual void SetUpOnMainThread() override { |
131 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); | 135 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
132 embedded_test_server()->RegisterRequestHandler(base::Bind( | 136 embedded_test_server()->RegisterRequestHandler(base::Bind( |
133 &HostZoomMapBrowserTest::HandleRequest, base::Unretained(this))); | 137 &HostZoomMapBrowserTest::HandleRequest, base::Unretained(this))); |
134 host_resolver()->AddRule("*", "127.0.0.1"); | 138 host_resolver()->AddRule("*", "127.0.0.1"); |
135 } | 139 } |
136 | 140 |
137 DISALLOW_COPY_AND_ASSIGN(HostZoomMapBrowserTest); | 141 DISALLOW_COPY_AND_ASSIGN(HostZoomMapBrowserTest); |
138 }; | 142 }; |
139 | 143 |
140 class HostZoomMapSanitizationBrowserTest : public HostZoomMapBrowserTest { | 144 #define PARTITION_KEY_PLACEHOLDER "NNN" |
| 145 |
| 146 class HostZoomMapBrowserTestWithPrefs : public HostZoomMapBrowserTest { |
141 public: | 147 public: |
142 HostZoomMapSanitizationBrowserTest() {} | 148 explicit HostZoomMapBrowserTestWithPrefs(const std::string& prefs_data) |
| 149 : prefs_data_(prefs_data) {} |
143 | 150 |
144 private: | 151 private: |
145 // InProcessBrowserTest: | 152 // InProcessBrowserTest: |
146 virtual bool SetUpUserDataDirectory() override { | 153 virtual bool SetUpUserDataDirectory() override { |
147 // Zoom-related preferences demonstrating the two problems that could be | 154 std::replace(prefs_data_.begin(), prefs_data_.end(), '\'', '\"'); |
148 // caused by the bug. They incorrectly contain a per-host zoom level for the | 155 // It seems the hash functions on different platforms can return different |
149 // empty host; and a value for 'host1' that only differs from the default by | 156 // values for the same input, so make sure we test with the hash appropriate |
150 // epsilon. Neither should have been persisted. | 157 // for the platform. |
151 const char kBrokenPrefs[] = | 158 std::string hash_string = |
152 "{'profile': {" | 159 chrome::ChromeZoomLevelPrefs::GetHashForTesting(base::FilePath()); |
153 " 'default_zoom_level': 1.2," | 160 std::string partition_key_placeholder(PARTITION_KEY_PLACEHOLDER); |
154 " 'per_host_zoom_levels': {'': 1.1, 'host1': 1.20001, 'host2': 1.3}" | 161 size_t start_index; |
155 "}}"; | 162 while ((start_index = prefs_data_.find(partition_key_placeholder)) != |
156 std::string broken_prefs(kBrokenPrefs); | 163 std::string::npos) { |
157 std::replace(broken_prefs.begin(), broken_prefs.end(), '\'', '\"'); | 164 prefs_data_.replace( |
| 165 start_index, partition_key_placeholder.size(), hash_string); |
| 166 } |
158 | 167 |
159 base::FilePath user_data_directory, path_to_prefs; | 168 base::FilePath user_data_directory, path_to_prefs; |
160 PathService::Get(chrome::DIR_USER_DATA, &user_data_directory); | 169 PathService::Get(chrome::DIR_USER_DATA, &user_data_directory); |
161 path_to_prefs = user_data_directory | 170 path_to_prefs = user_data_directory |
162 .AppendASCII(TestingProfile::kTestUserProfileDir) | 171 .AppendASCII(TestingProfile::kTestUserProfileDir) |
163 .Append(chrome::kPreferencesFilename); | 172 .Append(chrome::kPreferencesFilename); |
164 base::CreateDirectory(path_to_prefs.DirName()); | 173 base::CreateDirectory(path_to_prefs.DirName()); |
165 base::WriteFile(path_to_prefs, broken_prefs.c_str(), broken_prefs.size()); | 174 base::WriteFile( |
| 175 path_to_prefs, prefs_data_.c_str(), prefs_data_.size()); |
166 return true; | 176 return true; |
167 } | 177 } |
168 | 178 |
| 179 std::string prefs_data_; |
| 180 |
| 181 DISALLOW_COPY_AND_ASSIGN(HostZoomMapBrowserTestWithPrefs); |
| 182 }; |
| 183 |
| 184 // Zoom-related preferences demonstrating the two problems that |
| 185 // could be caused by the bug. They incorrectly contain a per-host |
| 186 // zoom level for the empty host; and a value for 'host1' that only |
| 187 // differs from the default by epsilon. Neither should have been |
| 188 // persisted. |
| 189 const char kSanitizationTestPrefs[] = |
| 190 "{'partition': {" |
| 191 " 'default_zoom_level': { '" PARTITION_KEY_PLACEHOLDER "': 1.2 }," |
| 192 " 'per_host_zoom_levels': {" |
| 193 " '" PARTITION_KEY_PLACEHOLDER "': {" |
| 194 " '': 1.1, 'host1': 1.20001, 'host2': 1.3 }" |
| 195 " }" |
| 196 "}}"; |
| 197 |
| 198 #undef PARTITION_KEY_PLACEHOLDER |
| 199 |
| 200 class HostZoomMapSanitizationBrowserTest |
| 201 : public HostZoomMapBrowserTestWithPrefs { |
| 202 public: |
| 203 HostZoomMapSanitizationBrowserTest() |
| 204 : HostZoomMapBrowserTestWithPrefs(kSanitizationTestPrefs) {} |
| 205 |
| 206 private: |
169 DISALLOW_COPY_AND_ASSIGN(HostZoomMapSanitizationBrowserTest); | 207 DISALLOW_COPY_AND_ASSIGN(HostZoomMapSanitizationBrowserTest); |
170 }; | 208 }; |
171 | 209 |
172 // Regression test for crbug.com/364399. | 210 // Regression test for crbug.com/364399. |
173 IN_PROC_BROWSER_TEST_F(HostZoomMapBrowserTest, ToggleDefaultZoomLevel) { | 211 IN_PROC_BROWSER_TEST_F(HostZoomMapBrowserTest, ToggleDefaultZoomLevel) { |
174 const double default_zoom_level = content::ZoomFactorToZoomLevel(1.5); | 212 const double default_zoom_level = content::ZoomFactorToZoomLevel(1.5); |
175 | 213 |
176 const char kTestURLTemplate1[] = "http://host1:%d/"; | 214 const char kTestURLTemplate1[] = "http://host1:%d/"; |
177 const char kTestURLTemplate2[] = "http://host2:%d/"; | 215 const char kTestURLTemplate2[] = "http://host2:%d/"; |
178 | 216 |
(...skipping 30 matching lines...) Expand all Loading... |
209 // any per-host values saved either to Pref, or internally in HostZoomMap. | 247 // any per-host values saved either to Pref, or internally in HostZoomMap. |
210 EXPECT_TRUE(GetHostsWithZoomLevels().empty()); | 248 EXPECT_TRUE(GetHostsWithZoomLevels().empty()); |
211 EXPECT_TRUE(GetHostsWithZoomLevelsFromPrefs().empty()); | 249 EXPECT_TRUE(GetHostsWithZoomLevelsFromPrefs().empty()); |
212 } | 250 } |
213 | 251 |
214 // Test that garbage data from crbug.com/364399 is cleared up on startup. | 252 // Test that garbage data from crbug.com/364399 is cleared up on startup. |
215 IN_PROC_BROWSER_TEST_F(HostZoomMapSanitizationBrowserTest, ClearOnStartup) { | 253 IN_PROC_BROWSER_TEST_F(HostZoomMapSanitizationBrowserTest, ClearOnStartup) { |
216 EXPECT_THAT(GetHostsWithZoomLevels(), testing::ElementsAre("host2")); | 254 EXPECT_THAT(GetHostsWithZoomLevels(), testing::ElementsAre("host2")); |
217 EXPECT_THAT(GetHostsWithZoomLevelsFromPrefs(), testing::ElementsAre("host2")); | 255 EXPECT_THAT(GetHostsWithZoomLevelsFromPrefs(), testing::ElementsAre("host2")); |
218 } | 256 } |
| 257 |
| 258 // In this case we migrate the zoom level data from the profile prefs. |
| 259 const char kMigrationTestPrefs[] = |
| 260 "{'profile': {" |
| 261 " 'default_zoom_level': 1.2," |
| 262 " 'per_host_zoom_levels': {'': 1.1, 'host1': 1.20001, 'host2': " |
| 263 "1.3}" |
| 264 "}}"; |
| 265 |
| 266 class HostZoomMapMigrationBrowserTest : public HostZoomMapBrowserTestWithPrefs { |
| 267 public: |
| 268 HostZoomMapMigrationBrowserTest() |
| 269 : HostZoomMapBrowserTestWithPrefs(kMigrationTestPrefs) {} |
| 270 |
| 271 static const double kOriginalDefaultZoomLevel; |
| 272 |
| 273 private: |
| 274 DISALLOW_COPY_AND_ASSIGN(HostZoomMapMigrationBrowserTest); |
| 275 }; |
| 276 |
| 277 const double HostZoomMapMigrationBrowserTest::kOriginalDefaultZoomLevel = 1.2; |
| 278 |
| 279 // This test is the same as HostZoomMapSanitizationBrowserTest, except that the |
| 280 // zoom level data is loaded from the profile prefs, transfered to the |
| 281 // zoom-level prefs, and we verify that the profile zoom level prefs are |
| 282 // erased in the process. We also test that changes to the host zoom map and the |
| 283 // default zoom level don't propagate back to the profile prefs. |
| 284 IN_PROC_BROWSER_TEST_F(HostZoomMapMigrationBrowserTest, |
| 285 MigrateProfileZoomPreferences) { |
| 286 EXPECT_THAT(GetHostsWithZoomLevels(), testing::ElementsAre("host2")); |
| 287 EXPECT_THAT(GetHostsWithZoomLevelsFromPrefs(), testing::ElementsAre("host2")); |
| 288 |
| 289 PrefService* profile_prefs = |
| 290 browser()->profile()->GetPrefs(); |
| 291 chrome::ChromeZoomLevelPrefs* zoom_level_prefs = |
| 292 browser()->profile()->GetZoomLevelPrefs(); |
| 293 // Make sure that the profile pref for default zoom level has been set to |
| 294 // its default value of 0.0. |
| 295 EXPECT_EQ(0.0, profile_prefs->GetDouble(prefs::kDefaultZoomLevelDeprecated)); |
| 296 EXPECT_EQ(kOriginalDefaultZoomLevel, |
| 297 zoom_level_prefs->GetDefaultZoomLevelPref()); |
| 298 |
| 299 // Make sure that the profile prefs for per-host zoom levels are erased. |
| 300 { |
| 301 const base::DictionaryValue* profile_host_zoom_dictionary = |
| 302 profile_prefs->GetDictionary(prefs::kPerHostZoomLevelsDeprecated); |
| 303 EXPECT_EQ(0UL, profile_host_zoom_dictionary->size()); |
| 304 } |
| 305 |
| 306 ZoomLevelChangeObserver observer(browser()->profile()); |
| 307 content::HostZoomMap* host_zoom_map = static_cast<content::HostZoomMap*>( |
| 308 content::HostZoomMap::GetDefaultForBrowserContext( |
| 309 browser()->profile())); |
| 310 |
| 311 // Make sure that a change to a host zoom level doesn't propagate to the |
| 312 // profile prefs. |
| 313 std::string host3("host3"); |
| 314 host_zoom_map->SetZoomLevelForHost(host3, 1.3); |
| 315 observer.BlockUntilZoomLevelForHostHasChanged(host3); |
| 316 EXPECT_THAT(GetHostsWithZoomLevelsFromPrefs(), |
| 317 testing::ElementsAre("host2", host3)); |
| 318 { |
| 319 const base::DictionaryValue* profile_host_zoom_dictionary = |
| 320 profile_prefs->GetDictionary(prefs::kPerHostZoomLevelsDeprecated); |
| 321 EXPECT_EQ(0UL, profile_host_zoom_dictionary->size()); |
| 322 } |
| 323 |
| 324 // Make sure a change to the default zoom level doesn't propagate to the |
| 325 // profile prefs. |
| 326 |
| 327 // First, we need a host at the default zoom level to respond when the |
| 328 // default zoom level changes. |
| 329 const double kNewDefaultZoomLevel = 1.5; |
| 330 GURL test_url = ConstructTestServerURL("http://host4:%d/"); |
| 331 ui_test_utils::NavigateToURL(browser(), test_url); |
| 332 EXPECT_TRUE(content::ZoomValuesEqual(kOriginalDefaultZoomLevel, |
| 333 GetZoomLevel(test_url))); |
| 334 |
| 335 // Change the default zoom level and observe. |
| 336 SetDefaultZoomLevel(kNewDefaultZoomLevel); |
| 337 observer.BlockUntilZoomLevelForHostHasChanged(test_url.host()); |
| 338 EXPECT_TRUE( |
| 339 content::ZoomValuesEqual(kNewDefaultZoomLevel, GetZoomLevel(test_url))); |
| 340 EXPECT_EQ(kNewDefaultZoomLevel, zoom_level_prefs->GetDefaultZoomLevelPref()); |
| 341 EXPECT_EQ(0.0, profile_prefs->GetDouble(prefs::kDefaultZoomLevelDeprecated)); |
| 342 } |
| 343 |
OLD | NEW |