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