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 50namespace { 51 52const 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 79const 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 86const char16 kIEIdentifyUrl[] = 87 L"http://A79029D6-753E-4e27-B807-3D46AB1545DF.com:8080/path?key=value"; 88const char16 kIEIdentifyTitle[] = 89 L"Unittest GUID"; 90 91const char16 kFaviconStreamSuffix[] = L"url:favicon:$DATA"; 92const 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 103struct FaviconGroup { 104 const char16* favicon_url; 105 const char16* site_url[2]; 106}; 107 108const 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 117bool CreateOrderBlob(const base::FilePath& favorites_folder, 118 const base::string16& path, 119 const std::vector<base::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 162bool CreateUrlFileWithFavicon(const base::FilePath& file, 163 const base::string16& url, 164 const base::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 211bool CreateUrlFile(const base::FilePath& file, const base::string16& url) { 212 return CreateUrlFileWithFavicon(file, url, base::string16()); 213} 214 215void 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 229void 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 255class 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( 329 const std::vector<ImportedBookmarkEntry>& bookmarks, 330 const base::string16& top_level_folder_name) OVERRIDE { 331 ASSERT_LE(bookmark_count_ + bookmarks.size(), arraysize(kIEBookmarks)); 332 // Importer should import the IE Favorites folder the same as the list, 333 // in the same order. 334 for (size_t i = 0; i < bookmarks.size(); ++i) { 335 EXPECT_NO_FATAL_FAILURE( 336 TestEqualBookmarkEntry(bookmarks[i], 337 kIEBookmarks[bookmark_count_])) << i; 338 ++bookmark_count_; 339 } 340 } 341 342 virtual void AddKeyword(std::vector<TemplateURL*> template_url, 343 int default_keyword_index) { 344 // TODO(jcampan): bug 1169230: we should test keyword importing for IE. 345 // In order to do that we'll probably need to mock the Windows registry. 346 NOTREACHED(); 347 STLDeleteContainerPointers(template_url.begin(), template_url.end()); 348 } 349 350 virtual void AddFavicons( 351 const std::vector<ImportedFaviconUsage>& usage) OVERRIDE { 352 // Importer should group the favicon information for each favicon URL. 353 for (size_t i = 0; i < arraysize(kIEFaviconGroup); ++i) { 354 GURL favicon_url(kIEFaviconGroup[i].favicon_url); 355 std::set<GURL> urls; 356 for (size_t j = 0; j < arraysize(kIEFaviconGroup[i].site_url); ++j) 357 urls.insert(GURL(kIEFaviconGroup[i].site_url[j])); 358 359 SCOPED_TRACE(testing::Message() << "Expected Favicon: " << favicon_url); 360 361 bool expected_favicon_url_found = false; 362 for (size_t j = 0; j < usage.size(); ++j) { 363 if (usage[j].favicon_url == favicon_url) { 364 EXPECT_EQ(urls, usage[j].urls); 365 expected_favicon_url_found = true; 366 break; 367 } 368 } 369 EXPECT_TRUE(expected_favicon_url_found); 370 } 371 372 favicon_count_ += usage.size(); 373 } 374 375 virtual void AddIE7PasswordInfo(const IE7PasswordInfo& info) { 376 // This function also gets called for the IEImporter test. Ignore. 377 if (ie_version_ == IE7) { 378 EXPECT_EQ(L"Test1", info.url_hash); 379 EXPECT_EQ(1, info.encrypted_data[0]); 380 EXPECT_EQ(4, info.encrypted_data.size()); 381 ++ie7_password_count_; 382 } 383 } 384 385 virtual void AddHomepage(const GURL& homepage) { 386 EXPECT_EQ(homepage.spec(), "http://www.test.com/"); 387 ++homepage_count_; 388 } 389 390 private: 391 ~TestObserver() {} 392 393 size_t bookmark_count_; 394 size_t history_count_; 395 size_t password_count_; 396 size_t favicon_count_; 397 size_t homepage_count_; 398 size_t ie7_password_count_; 399 uint16 importer_items_; 400 TestIEVersion ie_version_; 401}; 402 403class MalformedFavoritesRegistryTestObserver 404 : public ProfileWriter, 405 public importer::ImporterProgressObserver { 406 public: 407 MalformedFavoritesRegistryTestObserver() : ProfileWriter(NULL) { 408 bookmark_count_ = 0; 409 } 410 411 // importer::ImporterProgressObserver: 412 virtual void ImportStarted() OVERRIDE {} 413 virtual void ImportItemStarted(importer::ImportItem item) OVERRIDE {} 414 virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE {} 415 virtual void ImportEnded() OVERRIDE { 416 base::MessageLoop::current()->Quit(); 417 EXPECT_EQ(arraysize(kIESortedBookmarks), bookmark_count_); 418 } 419 420 virtual bool BookmarkModelIsLoaded() const { return true; } 421 virtual bool TemplateURLServiceIsLoaded() const { return true; } 422 423 virtual void AddPasswordForm(const autofill::PasswordForm& form) {} 424 virtual void AddHistoryPage(const history::URLRows& page, 425 history::VisitSource visit_source) {} 426 virtual void AddKeyword(std::vector<TemplateURL*> template_url, 427 int default_keyword_index) {} 428 virtual void AddBookmarks( 429 const std::vector<ImportedBookmarkEntry>& bookmarks, 430 const base::string16& top_level_folder_name) OVERRIDE { 431 ASSERT_LE(bookmark_count_ + bookmarks.size(), 432 arraysize(kIESortedBookmarks)); 433 for (size_t i = 0; i < bookmarks.size(); ++i) { 434 EXPECT_NO_FATAL_FAILURE( 435 TestEqualBookmarkEntry(bookmarks[i], 436 kIESortedBookmarks[bookmark_count_])) << i; 437 ++bookmark_count_; 438 } 439 } 440 441 private: 442 ~MalformedFavoritesRegistryTestObserver() {} 443 444 size_t bookmark_count_; 445}; 446 447} // namespace 448 449// These tests need to be browser tests in order to be able to run the OOP 450// import (via ExternalProcessImporterHost) which launches a utility process. 451class IEImporterBrowserTest : public InProcessBrowserTest { 452 protected: 453 virtual void SetUp() OVERRIDE { 454 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 455 456 // This will launch the browser test and thus needs to happen last. 457 InProcessBrowserTest::SetUp(); 458 } 459 460 base::ScopedTempDir temp_dir_; 461 462 // Overrides the default registry key for IE registry keys like favorites, 463 // settings, password store, etc. 464 IEImporterTestRegistryOverrider test_registry_overrider_; 465}; 466 467IN_PROC_BROWSER_TEST_F(IEImporterBrowserTest, IEImporter) { 468 // Sets up a favorites folder. 469 base::FilePath path = temp_dir_.path().AppendASCII("Favorites"); 470 CreateDirectory(path.value().c_str(), NULL); 471 CreateDirectory(path.AppendASCII("SubFolder").value().c_str(), NULL); 472 base::FilePath links_path = path.AppendASCII("Links"); 473 CreateDirectory(links_path.value().c_str(), NULL); 474 CreateDirectory(links_path.AppendASCII("SubFolderOfLinks").value().c_str(), 475 NULL); 476 CreateDirectory(path.AppendASCII("\x0061").value().c_str(), NULL); 477 ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("Google Home Page.url"), 478 L"http://www.google.com/", 479 L"http://www.google.com/favicon.ico")); 480 ASSERT_TRUE(CreateUrlFile(path.AppendASCII("SubFolder\\Title.url"), 481 L"http://www.link.com/")); 482 ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("SubFolder.url"), 483 L"http://www.subfolder.com/", 484 L"http://www.google.com/favicon.ico")); 485 ASSERT_TRUE(CreateUrlFile(path.AppendASCII("TheLink.url"), 486 L"http://www.links-thelink.com/")); 487 ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("WithPortAndQuery.url"), 488 L"http://host:8080/cgi?q=query", 489 L"http://example.com/favicon.ico")); 490 ASSERT_TRUE(CreateUrlFileWithFavicon( 491 path.AppendASCII("\x0061").Append(L"\x4E2D\x6587.url"), 492 L"http://chinese-title-favorite/", 493 L"http://example.com/favicon.ico")); 494 ASSERT_TRUE(CreateUrlFile(links_path.AppendASCII("TheLink.url"), 495 L"http://www.links-thelink.com/")); 496 ASSERT_TRUE(CreateUrlFile( 497 links_path.AppendASCII("SubFolderOfLinks").AppendASCII("SubLink.url"), 498 L"http://www.links-sublink.com/")); 499 ASSERT_TRUE(CreateUrlFile(path.AppendASCII("IEDefaultLink.url"), 500 L"http://go.microsoft.com/fwlink/?linkid=140813")); 501 file_util::WriteFile(path.AppendASCII("InvalidUrlFile.url"), "x", 1); 502 file_util::WriteFile(path.AppendASCII("PlainTextFile.txt"), "x", 1); 503 504 const char16* root_links[] = { 505 L"Links", 506 L"Google Home Page.url", 507 L"TheLink.url", 508 L"SubFolder", 509 L"WithPortAndQuery.url", 510 L"a", 511 L"SubFolder.url", 512 }; 513 ASSERT_TRUE(CreateOrderBlob( 514 base::FilePath(path), L"", 515 std::vector<base::string16>(root_links, 516 root_links + arraysize(root_links)))); 517 518 HRESULT res; 519 520 // Sets up a special history link. 521 base::win::ScopedComPtr<IUrlHistoryStg2> url_history_stg2; 522 res = url_history_stg2.CreateInstance(CLSID_CUrlHistory, NULL, 523 CLSCTX_INPROC_SERVER); 524 ASSERT_TRUE(res == S_OK); 525 res = url_history_stg2->AddUrl(kIEIdentifyUrl, kIEIdentifyTitle, 0); 526 ASSERT_TRUE(res == S_OK); 527 528 // Starts to import the above settings. 529 // Deletes itself. 530 ExternalProcessImporterHost* host = new ExternalProcessImporterHost; 531 TestObserver* observer = new TestObserver( 532 importer::HISTORY | importer::PASSWORDS | importer::FAVORITES, 533 TestObserver::IE6); 534 host->set_observer(observer); 535 536 importer::SourceProfile source_profile; 537 source_profile.importer_type = importer::TYPE_IE; 538 source_profile.source_path = temp_dir_.path(); 539 540 host->StartImportSettings( 541 source_profile, 542 browser()->profile(), 543 importer::HISTORY | importer::PASSWORDS | importer::FAVORITES, 544 observer); 545 base::MessageLoop::current()->Run(); 546 547 // Cleans up. 548 url_history_stg2->DeleteUrl(kIEIdentifyUrl, 0); 549 url_history_stg2.Release(); 550} 551 552IN_PROC_BROWSER_TEST_F(IEImporterBrowserTest, 553 IEImporterMalformedFavoritesRegistry) { 554 // Sets up a favorites folder. 555 base::FilePath path = temp_dir_.path().AppendASCII("Favorites"); 556 CreateDirectory(path.value().c_str(), NULL); 557 CreateDirectory(path.AppendASCII("b").value().c_str(), NULL); 558 ASSERT_TRUE(CreateUrlFile(path.AppendASCII("a.url"), 559 L"http://www.google.com/0")); 560 ASSERT_TRUE(CreateUrlFile(path.AppendASCII("b").AppendASCII("a.url"), 561 L"http://www.google.com/1")); 562 ASSERT_TRUE(CreateUrlFile(path.AppendASCII("b").AppendASCII("b.url"), 563 L"http://www.google.com/2")); 564 ASSERT_TRUE(CreateUrlFile(path.AppendASCII("c.url"), 565 L"http://www.google.com/3")); 566 567 struct BadBinaryData { 568 const char* data; 569 int length; 570 }; 571 static const BadBinaryData kBadBinary[] = { 572 // number_of_items field is truncated 573 {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 574 "\x00\xff\xff\xff", 17}, 575 // number_of_items = 0xffff, but the byte sequence is too short. 576 {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 577 "\xff\xff\x00\x00", 20}, 578 // number_of_items = 1, size_of_item is too big. 579 {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 580 "\x01\x00\x00\x00" 581 "\xff\xff\x00\x00\x00\x00\x00\x00" 582 "\x00\x00\x00\x00", 32}, 583 // number_of_items = 1, size_of_item = 16, size_of_shid is too big. 584 {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 585 "\x01\x00\x00\x00" 586 "\x10\x00\x00\x00\x00\x00\x00\x00" 587 "\xff\x7f\x00\x00" "\x00\x00\x00\x00", 36}, 588 // number_of_items = 1, size_of_item = 16, size_of_shid is too big. 589 {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 590 "\x01\x00\x00\x00" 591 "\x10\x00\x00\x00\x00\x00\x00\x00" 592 "\x06\x00\x00\x00" "\x00\x00\x00\x00", 36}, 593 }; 594 595 // Verify malformed registry data are safely ignored and alphabetical 596 // sort is performed. 597 for (size_t i = 0; i < arraysize(kBadBinary); ++i) { 598 base::string16 key_path(importer::GetIEFavoritesOrderKey()); 599 base::win::RegKey key; 600 ASSERT_EQ(ERROR_SUCCESS, 601 key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE)); 602 ASSERT_EQ(ERROR_SUCCESS, 603 key.WriteValue(L"Order", kBadBinary[i].data, kBadBinary[i].length, 604 REG_BINARY)); 605 606 // Starts to import the above settings. 607 // Deletes itself. 608 ExternalProcessImporterHost* host = new ExternalProcessImporterHost; 609 MalformedFavoritesRegistryTestObserver* observer = 610 new MalformedFavoritesRegistryTestObserver(); 611 host->set_observer(observer); 612 613 importer::SourceProfile source_profile; 614 source_profile.importer_type = importer::TYPE_IE; 615 source_profile.source_path = temp_dir_.path(); 616 617 host->StartImportSettings( 618 source_profile, 619 browser()->profile(), 620 importer::FAVORITES, 621 observer); 622 base::MessageLoop::current()->Run(); 623 } 624} 625 626IN_PROC_BROWSER_TEST_F(IEImporterBrowserTest, IE7ImporterPasswordsTest) { 627 // Starts to import the IE7 passwords. 628 // Deletes itself. 629 ExternalProcessImporterHost* host = new ExternalProcessImporterHost; 630 TestObserver* observer = new TestObserver(importer::PASSWORDS, 631 TestObserver::IE7); 632 host->set_observer(observer); 633 634 base::string16 key_path(importer::GetIE7PasswordsKey()); 635 base::win::RegKey key; 636 ASSERT_EQ(ERROR_SUCCESS, 637 key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE)); 638 key.WriteValue(L"Test1", 1); 639 640 importer::SourceProfile source_profile; 641 source_profile.importer_type = importer::TYPE_IE; 642 source_profile.source_path = temp_dir_.path(); 643 644 host->StartImportSettings( 645 source_profile, 646 browser()->profile(), 647 importer::PASSWORDS, 648 observer); 649 base::MessageLoop::current()->Run(); 650} 651 652IN_PROC_BROWSER_TEST_F(IEImporterBrowserTest, IEImporterHomePageTest) { 653 // Starts to import the IE home page. 654 // Deletes itself. 655 ExternalProcessImporterHost* host = new ExternalProcessImporterHost; 656 TestObserver* observer = new TestObserver(importer::HOME_PAGE, 657 TestObserver::IE6); 658 host->set_observer(observer); 659 660 base::string16 key_path(importer::GetIESettingsKey()); 661 base::win::RegKey key; 662 ASSERT_EQ(ERROR_SUCCESS, 663 key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE)); 664 key.WriteValue(L"Start Page", L"http://www.test.com/"); 665 666 importer::SourceProfile source_profile; 667 source_profile.importer_type = importer::TYPE_IE; 668 source_profile.source_path = temp_dir_.path(); 669 670 host->StartImportSettings( 671 source_profile, 672 browser()->profile(), 673 importer::HOME_PAGE, 674 observer); 675 base::MessageLoop::current()->Run(); 676} 677 678