Home | History | Annotate | Download | only in importer
      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 
    637