Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 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 <vector> | |
| 6 | |
| 7 #include "base/files/file_util.h" | |
| 8 #include "base/files/scoped_temp_dir.h" | |
| 9 #include "base/message_loop/message_loop.h" | |
| 10 #include "base/path_service.h" | |
| 11 #include "base/strings/string16.h" | |
| 12 #include "base/strings/string_util.h" | |
| 13 #include "base/strings/utf_string_conversions.h" | |
| 14 #include "base/win/registry.h" | |
| 15 #include "base/win/windows_version.h" | |
| 16 #include "chrome/browser/importer/external_process_importer_host.h" | |
| 17 #include "chrome/browser/importer/importer_progress_observer.h" | |
| 18 #include "chrome/browser/importer/importer_unittest_utils.h" | |
| 19 #include "chrome/browser/ui/browser.h" | |
| 20 #include "chrome/common/chrome_paths.h" | |
| 21 #include "chrome/common/importer/edge_importer_utils_win.h" | |
| 22 #include "chrome/common/importer/ie_importer_test_registry_overrider_win.h" | |
| 23 #include "chrome/common/importer/imported_bookmark_entry.h" | |
| 24 #include "chrome/common/importer/importer_bridge.h" | |
| 25 #include "chrome/common/importer/importer_data_types.h" | |
| 26 #include "chrome/test/base/in_process_browser_test.h" | |
| 27 #include "chrome/test/base/testing_profile.h" | |
| 28 #include "components/favicon_base/favicon_usage_data.h" | |
| 29 #include "testing/gtest/include/gtest/gtest.h" | |
| 30 #include "third_party/zlib/zlib.h" | |
| 31 | |
| 32 namespace { | |
| 33 | |
| 34 struct FaviconGroup { | |
| 35 const base::char16* favicon_url; | |
| 36 const base::char16* site_url; | |
| 37 }; | |
| 38 | |
| 39 class TestObserver : public ProfileWriter, | |
| 40 public importer::ImporterProgressObserver { | |
| 41 public: | |
| 42 explicit TestObserver(uint16 importer_items, | |
| 43 const std::vector<BookmarkInfo>& bookmark_entries, | |
| 44 const std::vector<FaviconGroup>& favicon_groups) | |
| 45 : ProfileWriter(NULL), | |
|
Ilya Sherman
2015/11/26 02:04:43
nit: nullptr
forshaw
2015/11/30 12:57:57
Acknowledged.
| |
| 46 bookmark_count_(0), | |
| 47 bookmark_entries_(bookmark_entries), | |
|
Ilya Sherman
2015/11/26 02:04:43
nit: Maybe prefix this with "expected_"?
forshaw
2015/11/30 12:57:57
Acknowledged.
| |
| 48 favicon_count_(0), | |
| 49 favicon_groups_(favicon_groups), | |
|
Ilya Sherman
2015/11/26 02:04:43
Ditto
forshaw
2015/11/30 12:57:57
Acknowledged.
| |
| 50 importer_items_(importer_items) {} | |
| 51 | |
| 52 // importer::ImporterProgressObserver: | |
| 53 void ImportStarted() override {} | |
| 54 void ImportItemStarted(importer::ImportItem item) override {} | |
| 55 void ImportItemEnded(importer::ImportItem item) override {} | |
| 56 void ImportEnded() override { | |
| 57 base::MessageLoop::current()->QuitWhenIdle(); | |
| 58 if (importer_items_ & importer::FAVORITES) { | |
| 59 EXPECT_EQ(bookmark_entries_.size(), bookmark_count_); | |
| 60 EXPECT_EQ(favicon_groups_.size(), favicon_count_); | |
| 61 } | |
| 62 } | |
| 63 | |
| 64 // ProfileWriter: | |
| 65 bool BookmarkModelIsLoaded() const override { | |
| 66 // Profile is ready for writing. | |
| 67 return true; | |
| 68 } | |
| 69 | |
| 70 bool TemplateURLServiceIsLoaded() const override { return true; } | |
| 71 | |
| 72 void AddBookmarks(const std::vector<ImportedBookmarkEntry>& bookmarks, | |
| 73 const base::string16& top_level_folder_name) override { | |
| 74 EXPECT_EQ(bookmark_entries_.size(), bookmarks.size()); | |
| 75 for (size_t i = 0; i < bookmarks.size(); ++i) { | |
| 76 EXPECT_NO_FATAL_FAILURE( | |
| 77 TestEqualBookmarkEntry(bookmarks[i], bookmark_entries_[i])) | |
| 78 << i; | |
| 79 ++bookmark_count_; | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 void AddFavicons(const favicon_base::FaviconUsageDataList& usage) override { | |
| 84 // Importer should group the favicon information for each favicon URL. | |
| 85 EXPECT_EQ(favicon_groups_.size(), usage.size()); | |
|
Ilya Sherman
2015/11/26 02:04:43
nit: This seems like it should be an ASSERT_EQ, si
| |
| 86 for (size_t i = 0; i < favicon_groups_.size(); ++i) { | |
| 87 EXPECT_EQ(usage[i].urls.size(), 1); | |
|
Ilya Sherman
2015/11/26 02:04:43
Actually, this expectation seems oddly placed -- i
Ilya Sherman
2015/11/26 02:04:43
nit: I think you might need to write "1U"
forshaw
2015/11/30 12:57:57
Acknowledged.
forshaw
2015/11/30 12:57:57
Acknowledged.
| |
| 88 GURL favicon_url(favicon_groups_[i].favicon_url); | |
| 89 std::set<GURL> urls; | |
| 90 urls.insert(GURL(favicon_groups_[i].site_url)); | |
| 91 | |
| 92 bool expected_favicon_url_found = false; | |
| 93 for (size_t j = 0; j < usage.size(); ++j) { | |
| 94 if (usage[j].favicon_url == favicon_url) { | |
| 95 EXPECT_EQ(urls, usage[j].urls); | |
| 96 expected_favicon_url_found = true; | |
| 97 break; | |
| 98 } | |
| 99 } | |
| 100 EXPECT_TRUE(expected_favicon_url_found); | |
| 101 } | |
| 102 favicon_count_ += usage.size(); | |
| 103 } | |
| 104 | |
| 105 private: | |
| 106 ~TestObserver() override {} | |
| 107 | |
| 108 size_t bookmark_count_; | |
| 109 std::vector<BookmarkInfo> bookmark_entries_; | |
| 110 size_t favicon_count_; | |
| 111 std::vector<FaviconGroup> favicon_groups_; | |
| 112 uint16 importer_items_; | |
|
Ilya Sherman
2015/11/26 02:04:43
nit: Please document these member vars.
| |
| 113 }; | |
| 114 | |
| 115 class ScopedGzFile { | |
|
Ilya Sherman
2015/11/26 02:04:43
nit: s/Gz/Gzip
| |
| 116 public: | |
| 117 explicit ScopedGzFile(const base::FilePath& gzip_file) { | |
| 118 gz_file_ = gzopen(base::UTF16ToUTF8(gzip_file.value()).c_str(), "rb"); | |
| 119 } | |
| 120 | |
| 121 ~ScopedGzFile() { | |
| 122 if (gz_file_) { | |
| 123 gzclose(gz_file_); | |
| 124 gz_file_ = nullptr; | |
|
Ilya Sherman
2015/11/26 02:04:43
nit: Why is this line needed?
| |
| 125 } | |
| 126 } | |
| 127 | |
| 128 bool IsEof() { return !!gzeof(gz_file_); } | |
| 129 | |
| 130 bool IsValid() { return gz_file_ != nullptr; } | |
| 131 | |
| 132 int Read(void* buffer, int size) { | |
| 133 if (!IsValid()) | |
| 134 return -1; | |
| 135 return gzread(gz_file_, buffer, size); | |
| 136 } | |
| 137 | |
| 138 private: | |
| 139 gzFile gz_file_; | |
| 140 | |
| 141 DISALLOW_COPY_AND_ASSIGN(ScopedGzFile); | |
| 142 }; | |
| 143 | |
| 144 bool DecompressGzipFile(const base::FilePath& gzip_file, | |
| 145 const base::FilePath& decompressed_file) { | |
| 146 const int kBufferLength = 0x1000; | |
| 147 ScopedGzFile input_file(gzip_file); | |
| 148 if (!input_file.IsValid()) { | |
| 149 LOG(ERROR) << "Error opening gzip file"; | |
| 150 return false; | |
| 151 } | |
| 152 base::File output_file(decompressed_file, | |
| 153 base::File::FLAG_CREATE | base::File::FLAG_WRITE); | |
| 154 if (!output_file.IsValid()) { | |
| 155 LOG(ERROR) << "Error opening output decompressed file"; | |
| 156 return false; | |
| 157 } | |
| 158 while (true) { | |
| 159 char buffer[kBufferLength]; | |
| 160 int bytes_read = input_file.Read(buffer, kBufferLength); | |
| 161 if (bytes_read > 0) { | |
| 162 if (output_file.WriteAtCurrentPos(buffer, bytes_read) != bytes_read) { | |
| 163 LOG(ERROR) << "Error writing to output file"; | |
| 164 return false; | |
| 165 } | |
| 166 } | |
| 167 if (bytes_read < kBufferLength) { | |
| 168 if (input_file.IsEof()) { | |
| 169 break; | |
| 170 } else { | |
| 171 DLOG(ERROR) << "Error decompressing gzip data"; | |
| 172 return false; | |
| 173 } | |
| 174 } | |
| 175 } | |
| 176 | |
| 177 return true; | |
| 178 } | |
|
Ilya Sherman
2015/11/26 02:04:43
Can you just slurp in the whole file and then call
forshaw
2015/11/30 12:57:57
Acknowledged.
| |
| 179 | |
| 180 bool DecompressDatabase(const base::FilePath& data_path) { | |
| 181 base::FilePath output_file = data_path.Append( | |
| 182 L"DataStore\\Data\\nouser1\\120712-0049\\DBStore\\spartan.edb"); | |
| 183 base::FilePath gzip_file = output_file.AddExtension(L".gz"); | |
| 184 | |
| 185 return DecompressGzipFile(gzip_file, output_file); | |
| 186 } | |
| 187 | |
| 188 const char kDummyFaviconImageData[] = | |
| 189 "\x42\x4D" // Magic signature 'BM' | |
| 190 "\x1E\x00\x00\x00" // File size | |
| 191 "\x00\x00\x00\x00" // Reserved | |
| 192 "\x1A\x00\x00\x00" // Offset of the pixel data | |
| 193 "\x0C\x00\x00\x00" // Header Size | |
| 194 "\x01\x00\x01\x00" // Size: 1x1 | |
| 195 "\x01\x00" // Reserved | |
| 196 "\x18\x00" // 24-bits | |
| 197 "\x00\xFF\x00\x00"; // The pixel | |
| 198 | |
| 199 } // namespace | |
| 200 | |
| 201 // These tests need to be browser tests in order to be able to run the OOP | |
| 202 // import (via ExternalProcessImporterHost) which launches a utility process. | |
| 203 class EdgeImporterBrowserTest : public InProcessBrowserTest { | |
| 204 protected: | |
| 205 void SetUp() override { | |
| 206 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
|
Ilya Sherman
2015/11/26 02:04:43
nit: Would it be appropriate to simply call this a
| |
| 207 | |
| 208 // This will launch the browser test and thus needs to happen last. | |
| 209 InProcessBrowserTest::SetUp(); | |
| 210 } | |
| 211 | |
| 212 base::ScopedTempDir temp_dir_; | |
| 213 | |
| 214 // Overrides the default registry key for IE registry keys like favorites, | |
| 215 // settings, password store, etc. | |
| 216 IEImporterTestRegistryOverrider test_registry_overrider_; | |
| 217 }; | |
| 218 | |
| 219 IN_PROC_BROWSER_TEST_F(EdgeImporterBrowserTest, EdgeImporter) { | |
| 220 // Only verified to work with ESE library on Windows 8.1 and above. | |
| 221 if (base::win::GetVersion() < base::win::VERSION_WIN8_1) | |
| 222 return; | |
| 223 | |
| 224 const BookmarkInfo kEdgeBookmarks[] = { | |
| 225 {true, | |
| 226 2, | |
| 227 {"Links", "SubFolderOfLinks"}, | |
| 228 L"SubLink", | |
| 229 "http://www.links-sublink.com/"}, | |
| 230 {true, 1, {"Links"}, L"TheLink", "http://www.links-thelink.com/"}, | |
| 231 {false, 0, {}, L"Google Home Page", "http://www.google.com/"}, | |
| 232 {false, 0, {}, L"TheLink", "http://www.links-thelink.com/"}, | |
| 233 {false, 1, {"SubFolder"}, L"Title", "http://www.link.com/"}, | |
| 234 {false, 0, {}, L"WithPortAndQuery", "http://host:8080/cgi?q=query"}, | |
| 235 {false, 1, {"a"}, L"\x4E2D\x6587", "http://chinese-title-favorite/"}, | |
| 236 {false, 0, {}, L"SubFolder", "http://www.subfolder.com/"}, | |
| 237 {false, 0, {}, L"InvalidFavicon", "http://www.invalid-favicon.com/"}, | |
| 238 }; | |
| 239 std::vector<BookmarkInfo> bookmark_entries( | |
| 240 kEdgeBookmarks, kEdgeBookmarks + arraysize(kEdgeBookmarks)); | |
| 241 | |
| 242 const FaviconGroup kEdgeFaviconGroup[] = { | |
| 243 {L"http://www.links-sublink.com/favicon.ico", | |
| 244 L"http://www.links-sublink.com"}, | |
| 245 {L"http://www.links-thelink.com/favicon.ico", | |
| 246 L"http://www.links-thelink.com"}, | |
| 247 {L"http://www.google.com/favicon.ico", L"http://www.google.com"}, | |
| 248 {L"http://www.links-thelink.com/favicon.ico", | |
| 249 L"http://www.links-thelink.com"}, | |
| 250 {L"http://www.link.com/favicon.ico", L"http://www.link.com"}, | |
| 251 {L"http://host:8080/favicon.ico", L"http://host:8080/cgi?q=query"}, | |
| 252 {L"http://chinese-title-favorite/favicon.ico", | |
| 253 L"http://chinese-title-favorite"}, | |
| 254 {L"http://www.subfolder.com/favicon.ico", L"http://www.subfolder.com"}, | |
| 255 }; | |
| 256 | |
| 257 std::vector<FaviconGroup> favicon_groups( | |
| 258 kEdgeFaviconGroup, kEdgeFaviconGroup + arraysize(kEdgeFaviconGroup)); | |
| 259 | |
| 260 base::FilePath data_path; | |
| 261 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path)); | |
| 262 data_path = data_path.AppendASCII("edge_profile"); | |
| 263 | |
| 264 base::FilePath temp_path = temp_dir_.path(); | |
| 265 ASSERT_TRUE(base::CopyDirectory(data_path, temp_path, true)); | |
| 266 ASSERT_TRUE(DecompressDatabase(temp_path.AppendASCII("edge_profile"))); | |
| 267 | |
| 268 base::string16 key_path(importer::GetEdgeSettingsKey()); | |
| 269 base::win::RegKey key; | |
| 270 ASSERT_EQ(ERROR_SUCCESS, | |
| 271 key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE)); | |
| 272 key.WriteValue(L"FavoritesESEEnabled", 1); | |
| 273 ASSERT_FALSE(importer::IsEdgeFavoritesLegacyMode()); | |
| 274 | |
| 275 // Starts to import the above settings. | |
| 276 // Deletes itself. | |
| 277 ExternalProcessImporterHost* host = new ExternalProcessImporterHost; | |
| 278 TestObserver* observer = | |
| 279 new TestObserver(importer::FAVORITES, bookmark_entries, favicon_groups); | |
| 280 host->set_observer(observer); | |
| 281 | |
| 282 importer::SourceProfile source_profile; | |
| 283 source_profile.importer_type = importer::TYPE_EDGE; | |
| 284 source_profile.source_path = temp_path.AppendASCII("edge_profile"); | |
| 285 | |
| 286 host->StartImportSettings(source_profile, browser()->profile(), | |
| 287 importer::FAVORITES, observer); | |
| 288 base::MessageLoop::current()->Run(); | |
| 289 } | |
| 290 | |
| 291 IN_PROC_BROWSER_TEST_F(EdgeImporterBrowserTest, EdgeImporterLegacyFallback) { | |
| 292 const BookmarkInfo kEdgeBookmarks[] = { | |
| 293 {false, 0, {}, L"Google", "http://www.google.com/"}}; | |
| 294 std::vector<BookmarkInfo> bookmark_entries( | |
| 295 kEdgeBookmarks, kEdgeBookmarks + arraysize(kEdgeBookmarks)); | |
| 296 const FaviconGroup kEdgeFaviconGroup[] = { | |
| 297 {L"http://www.google.com/favicon.ico", L"http://www.google.com/"}}; | |
| 298 std::vector<FaviconGroup> favicon_groups( | |
| 299 kEdgeFaviconGroup, kEdgeFaviconGroup + arraysize(kEdgeFaviconGroup)); | |
| 300 | |
| 301 base::FilePath data_path; | |
| 302 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path)); | |
| 303 data_path = data_path.AppendASCII("edge_profile"); | |
| 304 | |
| 305 ASSERT_TRUE(base::CopyDirectory(data_path, temp_dir_.path(), true)); | |
| 306 ASSERT_TRUE(importer::IsEdgeFavoritesLegacyMode()); | |
| 307 | |
| 308 // Starts to import the above settings. | |
| 309 // Deletes itself. | |
| 310 ExternalProcessImporterHost* host = new ExternalProcessImporterHost; | |
| 311 TestObserver* observer = | |
| 312 new TestObserver(importer::FAVORITES, bookmark_entries, favicon_groups); | |
| 313 host->set_observer(observer); | |
| 314 | |
| 315 importer::SourceProfile source_profile; | |
| 316 source_profile.importer_type = importer::TYPE_EDGE; | |
| 317 base::FilePath source_path = temp_dir_.path().AppendASCII("edge_profile"); | |
| 318 ASSERT_NE(base::WriteFile( | |
| 319 source_path.AppendASCII("Favorites\\Google.url:favicon:$DATA"), | |
| 320 kDummyFaviconImageData, sizeof(kDummyFaviconImageData)), | |
| 321 -1); | |
| 322 source_profile.source_path = source_path; | |
| 323 | |
| 324 host->StartImportSettings(source_profile, browser()->profile(), | |
| 325 importer::FAVORITES, observer); | |
| 326 base::MessageLoop::current()->Run(); | |
| 327 } | |
| 328 | |
| 329 IN_PROC_BROWSER_TEST_F(EdgeImporterBrowserTest, EdgeImporterNoDatabase) { | |
| 330 // Only verified to work with ESE library on Windows 8.1 and above. | |
| 331 if (base::win::GetVersion() < base::win::VERSION_WIN8_1) | |
| 332 return; | |
| 333 | |
| 334 std::vector<BookmarkInfo> bookmark_entries; | |
| 335 std::vector<FaviconGroup> favicon_groups; | |
| 336 | |
| 337 base::string16 key_path(importer::GetEdgeSettingsKey()); | |
| 338 base::win::RegKey key; | |
| 339 ASSERT_EQ(ERROR_SUCCESS, | |
| 340 key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE)); | |
| 341 key.WriteValue(L"FavoritesESEEnabled", 1); | |
| 342 ASSERT_FALSE(importer::IsEdgeFavoritesLegacyMode()); | |
| 343 | |
| 344 // Starts to import the above settings. | |
| 345 // Deletes itself. | |
| 346 ExternalProcessImporterHost* host = new ExternalProcessImporterHost; | |
| 347 TestObserver* observer = | |
| 348 new TestObserver(importer::FAVORITES, bookmark_entries, favicon_groups); | |
|
Ilya Sherman
2015/11/26 02:04:43
Who owns the memory for the observer?
forshaw
2015/11/30 12:57:57
Good question, this was basically taken from the I
| |
| 349 host->set_observer(observer); | |
| 350 | |
| 351 importer::SourceProfile source_profile; | |
| 352 source_profile.importer_type = importer::TYPE_EDGE; | |
| 353 source_profile.source_path = temp_dir_.path(); | |
| 354 | |
| 355 host->StartImportSettings(source_profile, browser()->profile(), | |
| 356 importer::FAVORITES, observer); | |
| 357 base::MessageLoop::current()->Run(); | |
| 358 } | |
| OLD | NEW |