Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: chrome/browser/importer/edge_importer_browsertest_win.cc

Issue 1465853002: Implement support for importing favorites from Edge on Windows 10. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix another CLANG warning Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698