- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / importer / ie_importer_browsertest_win.cc
1 // Copyright (c) 2013 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 // The order of these includes is important.
6 #include <windows.h>
7 #include <unknwn.h>
8 #include <intshcut.h>
9 #include <propvarutil.h>
10 #include <shlguid.h>
11 #include <shlobj.h>
12 #include <urlhist.h>
13
14 #include <algorithm>
15 #include <vector>
16
17 #include "base/bind.h"
18 #include "base/compiler_specific.h"
19 #include "base/file_util.h"
20 #include "base/files/scoped_temp_dir.h"
21 #include "base/message_loop/message_loop.h"
22 #include "base/path_service.h"
23 #include "base/stl_util.h"
24 #include "base/strings/string16.h"
25 #include "base/strings/string_util.h"
26 #include "base/strings/utf_string_conversions.h"
27 #include "base/win/registry.h"
28 #include "base/win/scoped_comptr.h"
29 #include "base/win/scoped_propvariant.h"
30 #include "base/win/windows_version.h"
31 #include "chrome/browser/importer/external_process_importer_host.h"
32 #include "chrome/browser/importer/importer_progress_observer.h"
33 #include "chrome/browser/importer/importer_unittest_utils.h"
34 #include "chrome/browser/search_engines/template_url.h"
35 #include "chrome/browser/ui/browser.h"
36 #include "chrome/common/chrome_paths.h"
37 #include "chrome/common/importer/ie_importer_test_registry_overrider_win.h"
38 #include "chrome/common/importer/ie_importer_utils_win.h"
39 #include "chrome/common/importer/imported_bookmark_entry.h"
40 #include "chrome/common/importer/imported_favicon_usage.h"
41 #include "chrome/common/importer/importer_bridge.h"
42 #include "chrome/common/importer/importer_data_types.h"
43 #include "chrome/common/importer/pstore_declarations.h"
44 #include "chrome/test/base/in_process_browser_test.h"
45 #include "chrome/test/base/testing_profile.h"
46 #include "components/autofill/core/common/password_form.h"
47 #include "components/webdata/encryptor/ie7_password_win.h"
48 #include "testing/gtest/include/gtest/gtest.h"
49
50 namespace {
51
52 const BookmarkInfo kIEBookmarks[] = {
53   {true, 2, {L"Links", L"SubFolderOfLinks"},
54    L"SubLink",
55    "http://www.links-sublink.com/"},
56   {true, 1, {L"Links"},
57    L"TheLink",
58    "http://www.links-thelink.com/"},
59   {false, 0, {},
60    L"Google Home Page",
61    "http://www.google.com/"},
62   {false, 0, {},
63    L"TheLink",
64    "http://www.links-thelink.com/"},
65   {false, 1, {L"SubFolder"},
66    L"Title",
67    "http://www.link.com/"},
68   {false, 0, {},
69    L"WithPortAndQuery",
70    "http://host:8080/cgi?q=query"},
71   {false, 1, {L"a"},
72    L"\x4E2D\x6587",
73    "http://chinese-title-favorite/"},
74   {false, 0, {},
75    L"SubFolder",
76    "http://www.subfolder.com/"},
77 };
78
79 const BookmarkInfo kIESortedBookmarks[] = {
80   {false, 0, {}, L"a", "http://www.google.com/0"},
81   {false, 1, {L"b"}, L"a", "http://www.google.com/1"},
82   {false, 1, {L"b"}, L"b", "http://www.google.com/2"},
83   {false, 0, {}, L"c", "http://www.google.com/3"},
84 };
85
86 const char16 kIEIdentifyUrl[] =
87     L"http://A79029D6-753E-4e27-B807-3D46AB1545DF.com:8080/path?key=value";
88 const char16 kIEIdentifyTitle[] =
89     L"Unittest GUID";
90
91 const char16 kFaviconStreamSuffix[] = L"url:favicon:$DATA";
92 const char kDummyFaviconImageData[] =
93     "\x42\x4D"          // Magic signature 'BM'
94     "\x1E\x00\x00\x00"  // File size
95     "\x00\x00\x00\x00"  // Reserved
96     "\x1A\x00\x00\x00"  // Offset of the pixel data
97     "\x0C\x00\x00\x00"  // Header Size
98     "\x01\x00\x01\x00"  // Size: 1x1
99     "\x01\x00"          // Reserved
100     "\x18\x00"          // 24-bits
101     "\x00\xFF\x00\x00"; // The pixel
102
103 struct FaviconGroup {
104   const char16* favicon_url;
105   const char16* site_url[2];
106 };
107
108 const FaviconGroup kIEFaviconGroup[2] = {
109   {L"http://www.google.com/favicon.ico",
110    {L"http://www.google.com/",
111     L"http://www.subfolder.com/"}},
112   {L"http://example.com/favicon.ico",
113    {L"http://host:8080/cgi?q=query",
114     L"http://chinese-title-favorite/"}},
115 };
116
117 bool CreateOrderBlob(const base::FilePath& favorites_folder,
118                      const string16& path,
119                      const std::vector<string16>& entries) {
120   if (entries.size() > 255)
121     return false;
122
123   // Create a binary sequence for setting a specific order of favorites.
124   // The format depends on the version of Shell32.dll, so we cannot embed
125   // a binary constant here.
126   std::vector<uint8> blob(20, 0);
127   blob[16] = static_cast<uint8>(entries.size());
128
129   for (size_t i = 0; i < entries.size(); ++i) {
130     PIDLIST_ABSOLUTE id_list_full = ILCreateFromPath(
131         favorites_folder.Append(path).Append(entries[i]).value().c_str());
132     PUITEMID_CHILD id_list = ILFindLastID(id_list_full);
133     // Include the trailing zero-length item id.  Don't include the single
134     // element array.
135     size_t id_list_size = id_list->mkid.cb + sizeof(id_list->mkid.cb);
136
137     blob.resize(blob.size() + 8);
138     uint32 total_size = id_list_size + 8;
139     memcpy(&blob[blob.size() - 8], &total_size, 4);
140     uint32 sort_index = i;
141     memcpy(&blob[blob.size() - 4], &sort_index, 4);
142     blob.resize(blob.size() + id_list_size);
143     memcpy(&blob[blob.size() - id_list_size], id_list, id_list_size);
144     ILFree(id_list_full);
145   }
146
147   base::string16 key_path(importer::GetIEFavoritesOrderKey());
148   if (!path.empty())
149     key_path += L"\\" + path;
150   base::win::RegKey key;
151   if (key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE) !=
152       ERROR_SUCCESS) {
153     return false;
154   }
155   if (key.WriteValue(L"Order", &blob[0], blob.size(), REG_BINARY) !=
156       ERROR_SUCCESS) {
157     return false;
158   }
159   return true;
160 }
161
162 bool CreateUrlFileWithFavicon(const base::FilePath& file,
163                               const string16& url,
164                               const string16& favicon_url) {
165   base::win::ScopedComPtr<IUniformResourceLocator> locator;
166   HRESULT result = locator.CreateInstance(CLSID_InternetShortcut, NULL,
167                                           CLSCTX_INPROC_SERVER);
168   if (FAILED(result))
169     return false;
170   base::win::ScopedComPtr<IPersistFile> persist_file;
171   result = persist_file.QueryFrom(locator);
172   if (FAILED(result))
173     return false;
174   result = locator->SetURL(url.c_str(), 0);
175   if (FAILED(result))
176     return false;
177
178   // Write favicon url if specified.
179   if (!favicon_url.empty()) {
180     base::win::ScopedComPtr<IPropertySetStorage> property_set_storage;
181     if (FAILED(property_set_storage.QueryFrom(locator)))
182       return false;
183     base::win::ScopedComPtr<IPropertyStorage> property_storage;
184     if (FAILED(property_set_storage->Open(FMTID_Intshcut,
185                                           STGM_WRITE,
186                                           property_storage.Receive()))) {
187       return false;
188     }
189     PROPSPEC properties[] = {{PRSPEC_PROPID, PID_IS_ICONFILE}};
190     // WriteMultiple takes an array of PROPVARIANTs, but since this code only
191     // needs an array of size 1: a pointer to |pv_icon| is equivalent.
192     base::win::ScopedPropVariant pv_icon;
193     if (FAILED(InitPropVariantFromString(favicon_url.c_str(),
194                                          pv_icon.Receive())) ||
195         FAILED(property_storage->WriteMultiple(1, properties, &pv_icon, 0))) {
196       return false;
197     }
198   }
199
200   // Save the .url file.
201   result = persist_file->Save(file.value().c_str(), TRUE);
202   if (FAILED(result))
203     return false;
204
205   // Write dummy favicon image data in NTFS alternate data stream.
206   return favicon_url.empty() || (file_util::WriteFile(
207       file.ReplaceExtension(kFaviconStreamSuffix), kDummyFaviconImageData,
208       sizeof kDummyFaviconImageData) != -1);
209 }
210
211 bool CreateUrlFile(const base::FilePath& file, const string16& url) {
212   return CreateUrlFileWithFavicon(file, url, string16());
213 }
214
215 void ClearPStoreType(IPStore* pstore, const GUID* type, const GUID* subtype) {
216   base::win::ScopedComPtr<IEnumPStoreItems, NULL> item;
217   HRESULT result = pstore->EnumItems(0, type, subtype, 0, item.Receive());
218   if (result == PST_E_OK) {
219     char16* item_name;
220     while (SUCCEEDED(item->Next(1, &item_name, 0))) {
221       pstore->DeleteItem(0, type, subtype, item_name, NULL, 0);
222       CoTaskMemFree(item_name);
223     }
224   }
225   pstore->DeleteSubtype(0, type, subtype, 0);
226   pstore->DeleteType(0, type, 0);
227 }
228
229 void WritePStore(IPStore* pstore, const GUID* type, const GUID* subtype) {
230   struct PStoreItem {
231     char16* name;
232     int data_size;
233     char* data;
234   } items[] = {
235     {L"http://localhost:8080/security/index.htm#ref:StringData", 8,
236      "\x31\x00\x00\x00\x32\x00\x00\x00"},
237     {L"http://localhost:8080/security/index.htm#ref:StringIndex", 20,
238      "\x57\x49\x43\x4b\x18\x00\x00\x00\x02\x00"
239      "\x00\x00\x2f\x00\x74\x00\x01\x00\x00\x00"},
240     {L"user:StringData", 4,
241      "\x31\x00\x00\x00"},
242     {L"user:StringIndex", 20,
243      "\x57\x49\x43\x4b\x18\x00\x00\x00\x01\x00"
244      "\x00\x00\x2f\x00\x74\x00\x00\x00\x00\x00"},
245   };
246
247   for (int i = 0; i < arraysize(items); ++i) {
248     HRESULT res = pstore->WriteItem(0, type, subtype, items[i].name,
249         items[i].data_size, reinterpret_cast<BYTE*>(items[i].data),
250         NULL, 0, 0);
251     ASSERT_TRUE(res == PST_E_OK);
252   }
253 }
254
255 class TestObserver : public ProfileWriter,
256                      public importer::ImporterProgressObserver {
257  public:
258   enum TestIEVersion {
259     IE6,
260     IE7,
261   };
262
263   explicit TestObserver(uint16 importer_items, TestIEVersion ie_version)
264       : ProfileWriter(NULL),
265         bookmark_count_(0),
266         history_count_(0),
267         password_count_(0),
268         favicon_count_(0),
269         homepage_count_(0),
270         ie7_password_count_(0),
271         importer_items_(importer_items),
272         ie_version_(ie_version) {
273   }
274
275   // importer::ImporterProgressObserver:
276   virtual void ImportStarted() OVERRIDE {}
277   virtual void ImportItemStarted(importer::ImportItem item) OVERRIDE {}
278   virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE {}
279   virtual void ImportEnded() OVERRIDE {
280     base::MessageLoop::current()->Quit();
281     if (importer_items_ & importer::FAVORITES) {
282       EXPECT_EQ(arraysize(kIEBookmarks), bookmark_count_);
283       EXPECT_EQ(arraysize(kIEFaviconGroup), favicon_count_);
284     }
285     if (importer_items_ & importer::HISTORY)
286       EXPECT_EQ(1, history_count_);
287     if (importer_items_ & importer::HOME_PAGE)
288       EXPECT_EQ(1, homepage_count_);
289     if ((importer_items_ & importer::PASSWORDS) && (ie_version_ == IE7))
290       EXPECT_EQ(1, ie7_password_count_);
291     // We need to test the IE6 password importer code.
292     // https://crbug.com/257100
293     // EXPECT_EQ(1, password_count_);
294   }
295
296   virtual bool BookmarkModelIsLoaded() const {
297     // Profile is ready for writing.
298     return true;
299   }
300
301   virtual bool TemplateURLServiceIsLoaded() const {
302     return true;
303   }
304
305   virtual void AddPasswordForm(const autofill::PasswordForm& form) {
306     // Importer should obtain this password form only.
307     EXPECT_EQ(GURL("http://localhost:8080/security/index.htm"), form.origin);
308     EXPECT_EQ("http://localhost:8080/", form.signon_realm);
309     EXPECT_EQ(L"user", form.username_element);
310     EXPECT_EQ(L"1", form.username_value);
311     EXPECT_EQ(L"", form.password_element);
312     EXPECT_EQ(L"2", form.password_value);
313     EXPECT_EQ("", form.action.spec());
314     ++password_count_;
315   }
316
317   virtual void AddHistoryPage(const history::URLRows& page,
318                               history::VisitSource visit_source) {
319     // Importer should read the specified URL.
320     for (size_t i = 0; i < page.size(); ++i) {
321       if (page[i].title() == kIEIdentifyTitle &&
322           page[i].url() == GURL(kIEIdentifyUrl))
323         ++history_count_;
324     }
325     EXPECT_EQ(history::SOURCE_IE_IMPORTED, visit_source);
326   }
327
328   virtual void AddBookmarks(const std::vector<ImportedBookmarkEntry>& bookmarks,
329                             const string16& top_level_folder_name) OVERRIDE {
330     ASSERT_LE(bookmark_count_ + bookmarks.size(), arraysize(kIEBookmarks));
331     // Importer should import the IE Favorites folder the same as the list,
332     // in the same order.
333     for (size_t i = 0; i < bookmarks.size(); ++i) {
334       EXPECT_NO_FATAL_FAILURE(
335           TestEqualBookmarkEntry(bookmarks[i],
336                                  kIEBookmarks[bookmark_count_])) << i;
337       ++bookmark_count_;
338     }
339   }
340
341   virtual void AddKeyword(std::vector<TemplateURL*> template_url,
342                           int default_keyword_index) {
343     // TODO(jcampan): bug 1169230: we should test keyword importing for IE.
344     // In order to do that we'll probably need to mock the Windows registry.
345     NOTREACHED();
346     STLDeleteContainerPointers(template_url.begin(), template_url.end());
347   }
348
349   virtual void AddFavicons(
350       const std::vector<ImportedFaviconUsage>& usage) OVERRIDE {
351     // Importer should group the favicon information for each favicon URL.
352     for (size_t i = 0; i < arraysize(kIEFaviconGroup); ++i) {
353       GURL favicon_url(kIEFaviconGroup[i].favicon_url);
354       std::set<GURL> urls;
355       for (size_t j = 0; j < arraysize(kIEFaviconGroup[i].site_url); ++j)
356         urls.insert(GURL(kIEFaviconGroup[i].site_url[j]));
357
358       SCOPED_TRACE(testing::Message() << "Expected Favicon: " << favicon_url);
359
360       bool expected_favicon_url_found = false;
361       for (size_t j = 0; j < usage.size(); ++j) {
362         if (usage[j].favicon_url == favicon_url) {
363           EXPECT_EQ(urls, usage[j].urls);
364           expected_favicon_url_found = true;
365           break;
366         }
367       }
368       EXPECT_TRUE(expected_favicon_url_found);
369     }
370
371     favicon_count_ += usage.size();
372   }
373
374   virtual void AddIE7PasswordInfo(const IE7PasswordInfo& info) {
375     // This function also gets called for the IEImporter test. Ignore.
376     if (ie_version_ == IE7) {
377       EXPECT_EQ(L"Test1", info.url_hash);
378       EXPECT_EQ(1, info.encrypted_data[0]);
379       EXPECT_EQ(4, info.encrypted_data.size());
380       ++ie7_password_count_;
381     }
382   }
383
384   virtual void AddHomepage(const GURL& homepage) {
385     EXPECT_EQ(homepage.spec(), "http://www.test.com/");
386     ++homepage_count_;
387   }
388
389  private:
390   ~TestObserver() {}
391
392   size_t bookmark_count_;
393   size_t history_count_;
394   size_t password_count_;
395   size_t favicon_count_;
396   size_t homepage_count_;
397   size_t ie7_password_count_;
398   uint16 importer_items_;
399   TestIEVersion ie_version_;
400 };
401
402 class MalformedFavoritesRegistryTestObserver
403     : public ProfileWriter,
404       public importer::ImporterProgressObserver {
405  public:
406   MalformedFavoritesRegistryTestObserver() : ProfileWriter(NULL) {
407     bookmark_count_ = 0;
408   }
409
410   // importer::ImporterProgressObserver:
411   virtual void ImportStarted() OVERRIDE {}
412   virtual void ImportItemStarted(importer::ImportItem item) OVERRIDE {}
413   virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE {}
414   virtual void ImportEnded() OVERRIDE {
415     base::MessageLoop::current()->Quit();
416     EXPECT_EQ(arraysize(kIESortedBookmarks), bookmark_count_);
417   }
418
419   virtual bool BookmarkModelIsLoaded() const { return true; }
420   virtual bool TemplateURLServiceIsLoaded() const { return true; }
421
422   virtual void AddPasswordForm(const autofill::PasswordForm& form) {}
423   virtual void AddHistoryPage(const history::URLRows& page,
424                               history::VisitSource visit_source) {}
425   virtual void AddKeyword(std::vector<TemplateURL*> template_url,
426                           int default_keyword_index) {}
427   virtual void AddBookmarks(const std::vector<ImportedBookmarkEntry>& bookmarks,
428                             const string16& top_level_folder_name) OVERRIDE {
429     ASSERT_LE(bookmark_count_ + bookmarks.size(),
430               arraysize(kIESortedBookmarks));
431     for (size_t i = 0; i < bookmarks.size(); ++i) {
432       EXPECT_NO_FATAL_FAILURE(
433           TestEqualBookmarkEntry(bookmarks[i],
434                                  kIESortedBookmarks[bookmark_count_])) << i;
435       ++bookmark_count_;
436     }
437   }
438
439  private:
440   ~MalformedFavoritesRegistryTestObserver() {}
441
442   size_t bookmark_count_;
443 };
444
445 }  // namespace
446
447 // These tests need to be browser tests in order to be able to run the OOP
448 // import (via ExternalProcessImporterHost) which launches a utility process.
449 class IEImporterBrowserTest : public InProcessBrowserTest {
450  protected:
451   virtual void SetUp() OVERRIDE {
452     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
453
454     // This will launch the browser test and thus needs to happen last.
455     InProcessBrowserTest::SetUp();
456   }
457
458   base::ScopedTempDir temp_dir_;
459
460   // Overrides the default registry key for IE registry keys like favorites,
461   // settings, password store, etc.
462   IEImporterTestRegistryOverrider test_registry_overrider_;
463 };
464
465 IN_PROC_BROWSER_TEST_F(IEImporterBrowserTest, IEImporter) {
466   // Sets up a favorites folder.
467   base::FilePath path = temp_dir_.path().AppendASCII("Favorites");
468   CreateDirectory(path.value().c_str(), NULL);
469   CreateDirectory(path.AppendASCII("SubFolder").value().c_str(), NULL);
470   base::FilePath links_path = path.AppendASCII("Links");
471   CreateDirectory(links_path.value().c_str(), NULL);
472   CreateDirectory(links_path.AppendASCII("SubFolderOfLinks").value().c_str(),
473                   NULL);
474   CreateDirectory(path.AppendASCII("\x0061").value().c_str(), NULL);
475   ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("Google Home Page.url"),
476                                        L"http://www.google.com/",
477                                        L"http://www.google.com/favicon.ico"));
478   ASSERT_TRUE(CreateUrlFile(path.AppendASCII("SubFolder\\Title.url"),
479                             L"http://www.link.com/"));
480   ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("SubFolder.url"),
481                                        L"http://www.subfolder.com/",
482                                        L"http://www.google.com/favicon.ico"));
483   ASSERT_TRUE(CreateUrlFile(path.AppendASCII("TheLink.url"),
484                             L"http://www.links-thelink.com/"));
485   ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("WithPortAndQuery.url"),
486                                        L"http://host:8080/cgi?q=query",
487                                        L"http://example.com/favicon.ico"));
488   ASSERT_TRUE(CreateUrlFileWithFavicon(
489       path.AppendASCII("\x0061").Append(L"\x4E2D\x6587.url"),
490       L"http://chinese-title-favorite/",
491       L"http://example.com/favicon.ico"));
492   ASSERT_TRUE(CreateUrlFile(links_path.AppendASCII("TheLink.url"),
493                             L"http://www.links-thelink.com/"));
494   ASSERT_TRUE(CreateUrlFile(
495       links_path.AppendASCII("SubFolderOfLinks").AppendASCII("SubLink.url"),
496       L"http://www.links-sublink.com/"));
497   ASSERT_TRUE(CreateUrlFile(path.AppendASCII("IEDefaultLink.url"),
498                             L"http://go.microsoft.com/fwlink/?linkid=140813"));
499   file_util::WriteFile(path.AppendASCII("InvalidUrlFile.url"), "x", 1);
500   file_util::WriteFile(path.AppendASCII("PlainTextFile.txt"), "x", 1);
501
502   const char16* root_links[] = {
503     L"Links",
504     L"Google Home Page.url",
505     L"TheLink.url",
506     L"SubFolder",
507     L"WithPortAndQuery.url",
508     L"a",
509     L"SubFolder.url",
510   };
511   ASSERT_TRUE(CreateOrderBlob(
512       base::FilePath(path), L"",
513       std::vector<string16>(root_links, root_links + arraysize(root_links))));
514
515   HRESULT res;
516
517   // Sets up a special history link.
518   base::win::ScopedComPtr<IUrlHistoryStg2> url_history_stg2;
519   res = url_history_stg2.CreateInstance(CLSID_CUrlHistory, NULL,
520                                         CLSCTX_INPROC_SERVER);
521   ASSERT_TRUE(res == S_OK);
522   res = url_history_stg2->AddUrl(kIEIdentifyUrl, kIEIdentifyTitle, 0);
523   ASSERT_TRUE(res == S_OK);
524
525   // Starts to import the above settings.
526   // Deletes itself.
527   ExternalProcessImporterHost* host = new ExternalProcessImporterHost;
528   TestObserver* observer = new TestObserver(
529       importer::HISTORY | importer::PASSWORDS | importer::FAVORITES,
530       TestObserver::IE6);
531   host->set_observer(observer);
532
533   importer::SourceProfile source_profile;
534   source_profile.importer_type = importer::TYPE_IE;
535   source_profile.source_path = temp_dir_.path();
536
537   host->StartImportSettings(
538       source_profile,
539       browser()->profile(),
540       importer::HISTORY | importer::PASSWORDS | importer::FAVORITES,
541       observer);
542   base::MessageLoop::current()->Run();
543
544   // Cleans up.
545   url_history_stg2->DeleteUrl(kIEIdentifyUrl, 0);
546   url_history_stg2.Release();
547 }
548
549 IN_PROC_BROWSER_TEST_F(IEImporterBrowserTest,
550                        IEImporterMalformedFavoritesRegistry) {
551   // Sets up a favorites folder.
552   base::FilePath path = temp_dir_.path().AppendASCII("Favorites");
553   CreateDirectory(path.value().c_str(), NULL);
554   CreateDirectory(path.AppendASCII("b").value().c_str(), NULL);
555   ASSERT_TRUE(CreateUrlFile(path.AppendASCII("a.url"),
556                             L"http://www.google.com/0"));
557   ASSERT_TRUE(CreateUrlFile(path.AppendASCII("b").AppendASCII("a.url"),
558                             L"http://www.google.com/1"));
559   ASSERT_TRUE(CreateUrlFile(path.AppendASCII("b").AppendASCII("b.url"),
560                             L"http://www.google.com/2"));
561   ASSERT_TRUE(CreateUrlFile(path.AppendASCII("c.url"),
562                             L"http://www.google.com/3"));
563
564   struct BadBinaryData {
565     const char* data;
566     int length;
567   };
568   static const BadBinaryData kBadBinary[] = {
569     // number_of_items field is truncated
570     {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
571      "\x00\xff\xff\xff", 17},
572     // number_of_items = 0xffff, but the byte sequence is too short.
573     {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
574      "\xff\xff\x00\x00", 20},
575     // number_of_items = 1, size_of_item is too big.
576     {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
577      "\x01\x00\x00\x00"
578      "\xff\xff\x00\x00\x00\x00\x00\x00"
579      "\x00\x00\x00\x00", 32},
580     // number_of_items = 1, size_of_item = 16, size_of_shid is too big.
581     {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
582      "\x01\x00\x00\x00"
583      "\x10\x00\x00\x00\x00\x00\x00\x00"
584      "\xff\x7f\x00\x00" "\x00\x00\x00\x00", 36},
585     // number_of_items = 1, size_of_item = 16, size_of_shid is too big.
586     {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
587      "\x01\x00\x00\x00"
588      "\x10\x00\x00\x00\x00\x00\x00\x00"
589      "\x06\x00\x00\x00" "\x00\x00\x00\x00", 36},
590   };
591
592   // Verify malformed registry data are safely ignored and alphabetical
593   // sort is performed.
594   for (size_t i = 0; i < arraysize(kBadBinary); ++i) {
595     base::string16 key_path(importer::GetIEFavoritesOrderKey());
596     base::win::RegKey key;
597     ASSERT_EQ(ERROR_SUCCESS,
598               key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE));
599     ASSERT_EQ(ERROR_SUCCESS,
600               key.WriteValue(L"Order", kBadBinary[i].data, kBadBinary[i].length,
601                              REG_BINARY));
602
603     // Starts to import the above settings.
604     // Deletes itself.
605     ExternalProcessImporterHost* host = new ExternalProcessImporterHost;
606     MalformedFavoritesRegistryTestObserver* observer =
607         new MalformedFavoritesRegistryTestObserver();
608     host->set_observer(observer);
609
610     importer::SourceProfile source_profile;
611     source_profile.importer_type = importer::TYPE_IE;
612     source_profile.source_path = temp_dir_.path();
613
614     host->StartImportSettings(
615         source_profile,
616         browser()->profile(),
617         importer::FAVORITES,
618         observer);
619     base::MessageLoop::current()->Run();
620   }
621 }
622
623 IN_PROC_BROWSER_TEST_F(IEImporterBrowserTest, IE7ImporterPasswordsTest) {
624   // Starts to import the IE7 passwords.
625   // Deletes itself.
626   ExternalProcessImporterHost* host = new ExternalProcessImporterHost;
627   TestObserver* observer = new TestObserver(importer::PASSWORDS,
628                                             TestObserver::IE7);
629   host->set_observer(observer);
630
631   base::string16 key_path(importer::GetIE7PasswordsKey());
632   base::win::RegKey key;
633   ASSERT_EQ(ERROR_SUCCESS,
634             key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE));
635   key.WriteValue(L"Test1", 1);
636
637   importer::SourceProfile source_profile;
638   source_profile.importer_type = importer::TYPE_IE;
639   source_profile.source_path = temp_dir_.path();
640
641   host->StartImportSettings(
642       source_profile,
643       browser()->profile(),
644       importer::PASSWORDS,
645       observer);
646   base::MessageLoop::current()->Run();
647 }
648
649 IN_PROC_BROWSER_TEST_F(IEImporterBrowserTest, IEImporterHomePageTest) {
650   // Starts to import the IE home page.
651   // Deletes itself.
652   ExternalProcessImporterHost* host = new ExternalProcessImporterHost;
653   TestObserver* observer = new TestObserver(importer::HOME_PAGE,
654                                             TestObserver::IE6);
655   host->set_observer(observer);
656
657   base::string16 key_path(importer::GetIESettingsKey());
658   base::win::RegKey key;
659   ASSERT_EQ(ERROR_SUCCESS,
660             key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE));
661   key.WriteValue(L"Start Page", L"http://www.test.com/");
662
663   importer::SourceProfile source_profile;
664   source_profile.importer_type = importer::TYPE_IE;
665   source_profile.source_path = temp_dir_.path();
666
667   host->StartImportSettings(
668       source_profile,
669       browser()->profile(),
670       importer::HOME_PAGE,
671       observer);
672   base::MessageLoop::current()->Run();
673 }
674