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

Unified Diff: chrome/browser/importer/ie_importer_browsertest_win.cc

Issue 13954013: Port some importer unit tests to browser tests to be able to fully exercise the ExternalProcessImpo… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix includes post-merge Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/importer/ie_importer_browsertest_win.cc
diff --git a/chrome/browser/importer/ie_importer_unittest_win.cc b/chrome/browser/importer/ie_importer_browsertest_win.cc
similarity index 84%
copy from chrome/browser/importer/ie_importer_unittest_win.cc
copy to chrome/browser/importer/ie_importer_browsertest_win.cc
index 85b915be57fd2c8035b5df8a7503a3fe8c4b82b3..d7f9bf338a943bf33642091764d00c2900127bd6 100644
--- a/chrome/browser/importer/ie_importer_unittest_win.cc
+++ b/chrome/browser/importer/ie_importer_browsertest_win.cc
@@ -1,652 +1,608 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-// The order of these includes is important.
-#include <windows.h>
-#include <unknwn.h>
-#include <intshcut.h>
-#include <shlguid.h>
-#include <urlhist.h>
-#include <shlobj.h>
-#include <propvarutil.h>
-
-#include <algorithm>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/file_util.h"
-#include "base/message_loop.h"
-#include "base/path_service.h"
-#include "base/stl_util.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "base/win/registry.h"
-#include "base/win/scoped_com_initializer.h"
-#include "base/win/scoped_comptr.h"
-#include "base/win/scoped_propvariant.h"
-#include "base/win/windows_version.h"
-#include "chrome/browser/history/history_types.h"
-#include "chrome/browser/importer/ie_importer.h"
-#include "chrome/browser/importer/importer_bridge.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/importer/importer_host.h"
-#include "chrome/browser/importer/importer_progress_observer.h"
-#include "chrome/browser/importer/importer_unittest_utils.h"
-#include "chrome/browser/importer/pstore_declarations.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/test/base/testing_profile.h"
-#include "components/webdata/encryptor/ie7_password.h"
-#include "content/public/common/password_form.h"
-
-namespace {
-
-const char16 kUnitTestRegistrySubKey[] = L"SOFTWARE\\Chromium Unit Tests";
-const char16 kUnitTestUserOverrideSubKey[] =
- L"SOFTWARE\\Chromium Unit Tests\\HKCU Override";
-
-const BookmarkInfo kIEBookmarks[] = {
- {true, 2, {L"Links", L"SubFolderOfLinks"},
- L"SubLink",
- "http://www.links-sublink.com/"},
- {true, 1, {L"Links"},
- L"TheLink",
- "http://www.links-thelink.com/"},
- {false, 0, {},
- L"Google Home Page",
- "http://www.google.com/"},
- {false, 0, {},
- L"TheLink",
- "http://www.links-thelink.com/"},
- {false, 1, {L"SubFolder"},
- L"Title",
- "http://www.link.com/"},
- {false, 0, {},
- L"WithPortAndQuery",
- "http://host:8080/cgi?q=query"},
- {false, 1, {L"a"},
- L"\x4E2D\x6587",
- "http://chinese-title-favorite/"},
- {false, 0, {},
- L"SubFolder",
- "http://www.subfolder.com/"},
-};
-
-const BookmarkInfo kIESortedBookmarks[] = {
- {false, 0, {}, L"a", "http://www.google.com/0"},
- {false, 1, {L"b"}, L"a", "http://www.google.com/1"},
- {false, 1, {L"b"}, L"b", "http://www.google.com/2"},
- {false, 0, {}, L"c", "http://www.google.com/3"},
-};
-
-const char16 kIEIdentifyUrl[] =
- L"http://A79029D6-753E-4e27-B807-3D46AB1545DF.com:8080/path?key=value";
-const char16 kIEIdentifyTitle[] =
- L"Unittest GUID";
-
-const char16 kIEFavoritesOrderKey[] =
- L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\"
- L"MenuOrder\\Favorites";
-
-const char16 kFaviconStreamSuffix[] = L"url:favicon:$DATA";
-const char kDummyFaviconImageData[] =
- "\x42\x4D" // Magic signature 'BM'
- "\x1E\x00\x00\x00" // File size
- "\x00\x00\x00\x00" // Reserved
- "\x1A\x00\x00\x00" // Offset of the pixel data
- "\x0C\x00\x00\x00" // Header Size
- "\x01\x00\x01\x00" // Size: 1x1
- "\x01\x00" // Reserved
- "\x18\x00" // 24-bits
- "\x00\xFF\x00\x00"; // The pixel
-
-struct FaviconGroup {
- const char16* favicon_url;
- const char16* site_url[2];
-};
-
-const FaviconGroup kIEFaviconGroup[2] = {
- {L"http://www.google.com/favicon.ico",
- {L"http://www.google.com/",
- L"http://www.subfolder.com/"}},
- {L"http://example.com/favicon.ico",
- {L"http://host:8080/cgi?q=query",
- L"http://chinese-title-favorite/"}},
-};
-
-bool CreateOrderBlob(const base::FilePath& favorites_folder,
- const string16& path,
- const std::vector<string16>& entries) {
- if (entries.size() > 255)
- return false;
-
- // Create a binary sequence for setting a specific order of favorites.
- // The format depends on the version of Shell32.dll, so we cannot embed
- // a binary constant here.
- std::vector<uint8> blob(20, 0);
- blob[16] = static_cast<uint8>(entries.size());
-
- for (size_t i = 0; i < entries.size(); ++i) {
- PIDLIST_ABSOLUTE id_list_full = ILCreateFromPath(
- favorites_folder.Append(path).Append(entries[i]).value().c_str());
- PUITEMID_CHILD id_list = ILFindLastID(id_list_full);
- // Include the trailing zero-length item id. Don't include the single
- // element array.
- size_t id_list_size = id_list->mkid.cb + sizeof(id_list->mkid.cb);
-
- blob.resize(blob.size() + 8);
- uint32 total_size = id_list_size + 8;
- memcpy(&blob[blob.size() - 8], &total_size, 4);
- uint32 sort_index = i;
- memcpy(&blob[blob.size() - 4], &sort_index, 4);
- blob.resize(blob.size() + id_list_size);
- memcpy(&blob[blob.size() - id_list_size], id_list, id_list_size);
- ILFree(id_list_full);
- }
-
- string16 key_path = kIEFavoritesOrderKey;
- if (!path.empty())
- key_path += L"\\" + path;
- base::win::RegKey key;
- if (key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE) !=
- ERROR_SUCCESS) {
- return false;
- }
- if (key.WriteValue(L"Order", &blob[0], blob.size(), REG_BINARY) !=
- ERROR_SUCCESS) {
- return false;
- }
- return true;
-}
-
-bool CreateUrlFileWithFavicon(const base::FilePath& file,
- const std::wstring& url,
- const std::wstring& favicon_url) {
- base::win::ScopedComPtr<IUniformResourceLocator> locator;
- HRESULT result = locator.CreateInstance(CLSID_InternetShortcut, NULL,
- CLSCTX_INPROC_SERVER);
- if (FAILED(result))
- return false;
- base::win::ScopedComPtr<IPersistFile> persist_file;
- result = persist_file.QueryFrom(locator);
- if (FAILED(result))
- return false;
- result = locator->SetURL(url.c_str(), 0);
- if (FAILED(result))
- return false;
-
- // Write favicon url if specified.
- if (!favicon_url.empty()) {
- base::win::ScopedComPtr<IPropertySetStorage> property_set_storage;
- if (FAILED(property_set_storage.QueryFrom(locator)))
- return false;
- base::win::ScopedComPtr<IPropertyStorage> property_storage;
- if (FAILED(property_set_storage->Open(FMTID_Intshcut,
- STGM_WRITE,
- property_storage.Receive()))) {
- return false;
- }
- PROPSPEC properties[] = {{PRSPEC_PROPID, PID_IS_ICONFILE}};
- // WriteMultiple takes an array of PROPVARIANTs, but since this code only
- // needs an array of size 1: a pointer to |pv_icon| is equivalent.
- base::win::ScopedPropVariant pv_icon;
- if (FAILED(InitPropVariantFromString(favicon_url.c_str(),
- pv_icon.Receive())) ||
- FAILED(property_storage->WriteMultiple(1, properties, &pv_icon, 0))) {
- return false;
- }
- }
-
- // Save the .url file.
- result = persist_file->Save(file.value().c_str(), TRUE);
- if (FAILED(result))
- return false;
-
- // Write dummy favicon image data in NTFS alternate data stream.
- return favicon_url.empty() || (file_util::WriteFile(
- file.ReplaceExtension(kFaviconStreamSuffix), kDummyFaviconImageData,
- sizeof kDummyFaviconImageData) != -1);
-}
-
-bool CreateUrlFile(const base::FilePath& file, const std::wstring& url) {
- return CreateUrlFileWithFavicon(file, url, std::wstring());
-}
-
-void ClearPStoreType(IPStore* pstore, const GUID* type, const GUID* subtype) {
- base::win::ScopedComPtr<IEnumPStoreItems, NULL> item;
- HRESULT result = pstore->EnumItems(0, type, subtype, 0, item.Receive());
- if (result == PST_E_OK) {
- char16* item_name;
- while (SUCCEEDED(item->Next(1, &item_name, 0))) {
- pstore->DeleteItem(0, type, subtype, item_name, NULL, 0);
- CoTaskMemFree(item_name);
- }
- }
- pstore->DeleteSubtype(0, type, subtype, 0);
- pstore->DeleteType(0, type, 0);
-}
-
-void WritePStore(IPStore* pstore, const GUID* type, const GUID* subtype) {
- struct PStoreItem {
- char16* name;
- int data_size;
- char* data;
- } items[] = {
- {L"http://localhost:8080/security/index.htm#ref:StringData", 8,
- "\x31\x00\x00\x00\x32\x00\x00\x00"},
- {L"http://localhost:8080/security/index.htm#ref:StringIndex", 20,
- "\x57\x49\x43\x4b\x18\x00\x00\x00\x02\x00"
- "\x00\x00\x2f\x00\x74\x00\x01\x00\x00\x00"},
- {L"user:StringData", 4,
- "\x31\x00\x00\x00"},
- {L"user:StringIndex", 20,
- "\x57\x49\x43\x4b\x18\x00\x00\x00\x01\x00"
- "\x00\x00\x2f\x00\x74\x00\x00\x00\x00\x00"},
- };
-
- for (int i = 0; i < arraysize(items); ++i) {
- HRESULT res = pstore->WriteItem(0, type, subtype, items[i].name,
- items[i].data_size, reinterpret_cast<BYTE*>(items[i].data),
- NULL, 0, 0);
- ASSERT_TRUE(res == PST_E_OK);
- }
-}
-
-class TestObserver : public ProfileWriter,
- public importer::ImporterProgressObserver {
- public:
- TestObserver() : ProfileWriter(NULL) {
- bookmark_count_ = 0;
- history_count_ = 0;
- password_count_ = 0;
- favicon_count_ = 0;
- }
-
- // importer::ImporterProgressObserver:
- virtual void ImportStarted() OVERRIDE {}
- virtual void ImportItemStarted(importer::ImportItem item) OVERRIDE {}
- virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE {}
- virtual void ImportEnded() OVERRIDE {
- MessageLoop::current()->Quit();
- EXPECT_EQ(arraysize(kIEBookmarks), bookmark_count_);
- EXPECT_EQ(1, history_count_);
- EXPECT_EQ(arraysize(kIEFaviconGroup), favicon_count_);
- }
-
- virtual bool BookmarkModelIsLoaded() const {
- // Profile is ready for writing.
- return true;
- }
-
- virtual bool TemplateURLServiceIsLoaded() const {
- return true;
- }
-
- virtual void AddPasswordForm(const content::PasswordForm& form) {
- // Importer should obtain this password form only.
- EXPECT_EQ(GURL("http://localhost:8080/security/index.htm"), form.origin);
- EXPECT_EQ("http://localhost:8080/", form.signon_realm);
- EXPECT_EQ(L"user", form.username_element);
- EXPECT_EQ(L"1", form.username_value);
- EXPECT_EQ(L"", form.password_element);
- EXPECT_EQ(L"2", form.password_value);
- EXPECT_EQ("", form.action.spec());
- ++password_count_;
- }
-
- virtual void AddHistoryPage(const history::URLRows& page,
- history::VisitSource visit_source) {
- // Importer should read the specified URL.
- for (size_t i = 0; i < page.size(); ++i) {
- if (page[i].title() == kIEIdentifyTitle &&
- page[i].url() == GURL(kIEIdentifyUrl))
- ++history_count_;
- }
- EXPECT_EQ(history::SOURCE_IE_IMPORTED, visit_source);
- }
-
- virtual void AddBookmarks(const std::vector<BookmarkEntry>& bookmarks,
- const string16& top_level_folder_name) OVERRIDE {
- ASSERT_LE(bookmark_count_ + bookmarks.size(), arraysize(kIEBookmarks));
- // Importer should import the IE Favorites folder the same as the list,
- // in the same order.
- for (size_t i = 0; i < bookmarks.size(); ++i) {
- EXPECT_TRUE(EqualBookmarkEntry(bookmarks[i],
- kIEBookmarks[bookmark_count_]));
- ++bookmark_count_;
- }
- }
-
- virtual void AddKeyword(std::vector<TemplateURL*> template_url,
- int default_keyword_index) {
- // TODO(jcampan): bug 1169230: we should test keyword importing for IE.
- // In order to do that we'll probably need to mock the Windows registry.
- NOTREACHED();
- STLDeleteContainerPointers(template_url.begin(), template_url.end());
- }
-
- virtual void AddFavicons(
- const std::vector<history::ImportedFaviconUsage>& usage) OVERRIDE {
- // Importer should group the favicon information for each favicon URL.
- for (size_t i = 0; i < arraysize(kIEFaviconGroup); ++i) {
- GURL favicon_url(kIEFaviconGroup[i].favicon_url);
- std::set<GURL> urls;
- for (size_t j = 0; j < arraysize(kIEFaviconGroup[i].site_url); ++j)
- urls.insert(GURL(kIEFaviconGroup[i].site_url[j]));
-
- SCOPED_TRACE(testing::Message() << "Expected Favicon: " << favicon_url);
-
- bool expected_favicon_url_found = false;
- for (size_t j = 0; j < usage.size(); ++j) {
- if (usage[j].favicon_url == favicon_url) {
- EXPECT_EQ(urls, usage[j].urls);
- expected_favicon_url_found = true;
- break;
- }
- }
- EXPECT_TRUE(expected_favicon_url_found);
- }
-
- favicon_count_ += usage.size();
- }
-
- private:
- ~TestObserver() {}
-
- size_t bookmark_count_;
- size_t history_count_;
- size_t password_count_;
- size_t favicon_count_;
-};
-
-class MalformedFavoritesRegistryTestObserver
- : public ProfileWriter,
- public importer::ImporterProgressObserver {
- public:
- MalformedFavoritesRegistryTestObserver() : ProfileWriter(NULL) {
- bookmark_count_ = 0;
- }
-
- // importer::ImporterProgressObserver:
- virtual void ImportStarted() OVERRIDE {}
- virtual void ImportItemStarted(importer::ImportItem item) OVERRIDE {}
- virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE {}
- virtual void ImportEnded() OVERRIDE {
- MessageLoop::current()->Quit();
- EXPECT_EQ(arraysize(kIESortedBookmarks), bookmark_count_);
- }
-
- virtual bool BookmarkModelIsLoaded() const { return true; }
- virtual bool TemplateURLServiceIsLoaded() const { return true; }
-
- virtual void AddPasswordForm(const content::PasswordForm& form) {}
- virtual void AddHistoryPage(const history::URLRows& page,
- history::VisitSource visit_source) {}
- virtual void AddKeyword(std::vector<TemplateURL*> template_url,
- int default_keyword_index) {}
- virtual void AddBookmarks(const std::vector<BookmarkEntry>& bookmarks,
- const string16& top_level_folder_name) OVERRIDE {
- ASSERT_LE(bookmark_count_ + bookmarks.size(),
- arraysize(kIESortedBookmarks));
- for (size_t i = 0; i < bookmarks.size(); ++i) {
- EXPECT_TRUE(EqualBookmarkEntry(bookmarks[i],
- kIESortedBookmarks[bookmark_count_]));
- ++bookmark_count_;
- }
- }
-
- private:
- ~MalformedFavoritesRegistryTestObserver() {}
-
- size_t bookmark_count_;
-};
-
-} // namespace
-
-class IEImporterTest : public ImporterTest {
- protected:
- virtual void SetUp() OVERRIDE {
- ImporterTest::SetUp();
- StartRegistryOverride();
- }
-
- virtual void TearDown() OVERRIDE {
- EndRegistryOverride();
- }
-
- void StartRegistryOverride() {
- EXPECT_EQ(ERROR_SUCCESS, RegOverridePredefKey(HKEY_CURRENT_USER, NULL));
- temp_hkcu_hive_key_.Create(HKEY_CURRENT_USER,
- kUnitTestUserOverrideSubKey,
- KEY_ALL_ACCESS);
- EXPECT_TRUE(temp_hkcu_hive_key_.Valid());
- EXPECT_EQ(ERROR_SUCCESS,
- RegOverridePredefKey(HKEY_CURRENT_USER,
- temp_hkcu_hive_key_.Handle()));
- }
-
- void EndRegistryOverride() {
- EXPECT_EQ(ERROR_SUCCESS, RegOverridePredefKey(HKEY_CURRENT_USER, NULL));
- temp_hkcu_hive_key_.Close();
- base::win::RegKey key(HKEY_CURRENT_USER, kUnitTestRegistrySubKey,
- KEY_ALL_ACCESS);
- key.DeleteKey(L"");
- }
-
- base::win::RegKey temp_hkcu_hive_key_;
-};
-
-TEST_F(IEImporterTest, IEImporter) {
- // Sets up a favorites folder.
- base::win::ScopedCOMInitializer com_init;
- base::FilePath path = temp_dir_.path().AppendASCII("Favorites");
- CreateDirectory(path.value().c_str(), NULL);
- CreateDirectory(path.AppendASCII("SubFolder").value().c_str(), NULL);
- base::FilePath links_path = path.AppendASCII("Links");
- CreateDirectory(links_path.value().c_str(), NULL);
- CreateDirectory(links_path.AppendASCII("SubFolderOfLinks").value().c_str(),
- NULL);
- CreateDirectory(path.AppendASCII("\x0061").value().c_str(), NULL);
- ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("Google Home Page.url"),
- L"http://www.google.com/",
- L"http://www.google.com/favicon.ico"));
- ASSERT_TRUE(CreateUrlFile(path.AppendASCII("SubFolder\\Title.url"),
- L"http://www.link.com/"));
- ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("SubFolder.url"),
- L"http://www.subfolder.com/",
- L"http://www.google.com/favicon.ico"));
- ASSERT_TRUE(CreateUrlFile(path.AppendASCII("TheLink.url"),
- L"http://www.links-thelink.com/"));
- ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("WithPortAndQuery.url"),
- L"http://host:8080/cgi?q=query",
- L"http://example.com/favicon.ico"));
- ASSERT_TRUE(CreateUrlFileWithFavicon(
- path.AppendASCII("\x0061").Append(L"\x4E2D\x6587.url"),
- L"http://chinese-title-favorite/",
- L"http://example.com/favicon.ico"));
- ASSERT_TRUE(CreateUrlFile(links_path.AppendASCII("TheLink.url"),
- L"http://www.links-thelink.com/"));
- ASSERT_TRUE(CreateUrlFile(
- links_path.AppendASCII("SubFolderOfLinks").AppendASCII("SubLink.url"),
- L"http://www.links-sublink.com/"));
- ASSERT_TRUE(CreateUrlFile(path.AppendASCII("IEDefaultLink.url"),
- L"http://go.microsoft.com/fwlink/?linkid=140813"));
- file_util::WriteFile(path.AppendASCII("InvalidUrlFile.url"), "x", 1);
- file_util::WriteFile(path.AppendASCII("PlainTextFile.txt"), "x", 1);
-
- const char16* root_links[] = {
- L"Links",
- L"Google Home Page.url",
- L"TheLink.url",
- L"SubFolder",
- L"WithPortAndQuery.url",
- L"a",
- L"SubFolder.url",
- };
- ASSERT_TRUE(CreateOrderBlob(
- base::FilePath(path), L"",
- std::vector<string16>(root_links, root_links + arraysize(root_links))));
-
- HRESULT res;
-
- // Sets up a special history link.
- base::win::ScopedComPtr<IUrlHistoryStg2> url_history_stg2;
- res = url_history_stg2.CreateInstance(CLSID_CUrlHistory, NULL,
- CLSCTX_INPROC_SERVER);
- ASSERT_TRUE(res == S_OK);
- res = url_history_stg2->AddUrl(kIEIdentifyUrl, kIEIdentifyTitle, 0);
- ASSERT_TRUE(res == S_OK);
-
- // Starts to import the above settings.
- MessageLoop* loop = MessageLoop::current();
- scoped_refptr<ImporterHost> host(new ImporterHost);
-
- TestObserver* observer = new TestObserver();
- host->SetObserver(observer);
- importer::SourceProfile source_profile;
- source_profile.importer_type = importer::TYPE_IE;
- source_profile.source_path = temp_dir_.path();
-
- // IUrlHistoryStg2::AddUrl seems to reset the override. Ensure it here.
- StartRegistryOverride();
-
- loop->PostTask(FROM_HERE, base::Bind(
- &ImporterHost::StartImportSettings,
- host.get(),
- source_profile,
- profile_.get(),
- importer::HISTORY | importer::PASSWORDS | importer::FAVORITES,
- observer));
- loop->Run();
-
- // Cleans up.
- url_history_stg2->DeleteUrl(kIEIdentifyUrl, 0);
- url_history_stg2.Release();
-}
-
-TEST_F(IEImporterTest, IEImporterMalformedFavoritesRegistry) {
- // Sets up a favorites folder.
- base::win::ScopedCOMInitializer com_init;
- base::FilePath path = temp_dir_.path().AppendASCII("Favorites");
- CreateDirectory(path.value().c_str(), NULL);
- CreateDirectory(path.AppendASCII("b").value().c_str(), NULL);
- ASSERT_TRUE(CreateUrlFile(path.AppendASCII("a.url"),
- L"http://www.google.com/0"));
- ASSERT_TRUE(CreateUrlFile(path.AppendASCII("b").AppendASCII("a.url"),
- L"http://www.google.com/1"));
- ASSERT_TRUE(CreateUrlFile(path.AppendASCII("b").AppendASCII("b.url"),
- L"http://www.google.com/2"));
- ASSERT_TRUE(CreateUrlFile(path.AppendASCII("c.url"),
- L"http://www.google.com/3"));
-
- struct BadBinaryData {
- const char* data;
- int length;
- };
- static const BadBinaryData kBadBinary[] = {
- // number_of_items field is truncated
- {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\xff\xff\xff", 17},
- // number_of_items = 0xffff, but the byte sequence is too short.
- {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\xff\xff\x00\x00", 20},
- // number_of_items = 1, size_of_item is too big.
- {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x01\x00\x00\x00"
- "\xff\xff\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00", 32},
- // number_of_items = 1, size_of_item = 16, size_of_shid is too big.
- {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x01\x00\x00\x00"
- "\x10\x00\x00\x00\x00\x00\x00\x00"
- "\xff\x7f\x00\x00" "\x00\x00\x00\x00", 36},
- // number_of_items = 1, size_of_item = 16, size_of_shid is too big.
- {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x01\x00\x00\x00"
- "\x10\x00\x00\x00\x00\x00\x00\x00"
- "\x06\x00\x00\x00" "\x00\x00\x00\x00", 36},
- };
-
- // Verify malformed registry data are safely ignored and alphabetical
- // sort is performed.
- for (size_t i = 0; i < arraysize(kBadBinary); ++i) {
- base::win::RegKey key;
- ASSERT_EQ(ERROR_SUCCESS,
- key.Create(HKEY_CURRENT_USER, kIEFavoritesOrderKey, KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS,
- key.WriteValue(L"Order", kBadBinary[i].data, kBadBinary[i].length,
- REG_BINARY));
-
- // Starts to import the above settings.
- MessageLoop* loop = MessageLoop::current();
- scoped_refptr<ImporterHost> host(new ImporterHost);
-
- MalformedFavoritesRegistryTestObserver* observer =
- new MalformedFavoritesRegistryTestObserver();
- host->SetObserver(observer);
- importer::SourceProfile source_profile;
- source_profile.importer_type = importer::TYPE_IE;
- source_profile.source_path = temp_dir_.path();
-
- loop->PostTask(FROM_HERE, base::Bind(
- &ImporterHost::StartImportSettings,
- host.get(),
- source_profile,
- profile_.get(),
- importer::FAVORITES,
- observer));
- loop->Run();
- }
-}
-
-TEST_F(IEImporterTest, IE7Importer) {
- // This is the unencrypted values of my keys under Storage2.
- // The passwords have been manually changed to abcdef... but the size remains
- // the same.
- unsigned char data1[] = "\x0c\x00\x00\x00\x38\x00\x00\x00\x2c\x00\x00\x00"
- "\x57\x49\x43\x4b\x18\x00\x00\x00\x02\x00\x00\x00"
- "\x67\x00\x72\x00\x01\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x4e\xfa\x67\x76\x22\x94\xc8\x01"
- "\x08\x00\x00\x00\x12\x00\x00\x00\x4e\xfa\x67\x76"
- "\x22\x94\xc8\x01\x0c\x00\x00\x00\x61\x00\x62\x00"
- "\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00"
- "\x00\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00"
- "\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00"
- "\x6c\x00\x00\x00";
-
- unsigned char data2[] = "\x0c\x00\x00\x00\x38\x00\x00\x00\x24\x00\x00\x00"
- "\x57\x49\x43\x4b\x18\x00\x00\x00\x02\x00\x00\x00"
- "\x67\x00\x72\x00\x01\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\xa8\xea\xf4\xe5\x9f\x9a\xc8\x01"
- "\x09\x00\x00\x00\x14\x00\x00\x00\xa8\xea\xf4\xe5"
- "\x9f\x9a\xc8\x01\x07\x00\x00\x00\x61\x00\x62\x00"
- "\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00"
- "\x69\x00\x00\x00\x61\x00\x62\x00\x63\x00\x64\x00"
- "\x65\x00\x66\x00\x67\x00\x00\x00";
-
-
-
- std::vector<unsigned char> decrypted_data1;
- decrypted_data1.resize(arraysize(data1));
- memcpy(&decrypted_data1.front(), data1, sizeof(data1));
-
- std::vector<unsigned char> decrypted_data2;
- decrypted_data2.resize(arraysize(data2));
- memcpy(&decrypted_data2.front(), data2, sizeof(data2));
-
- string16 password;
- string16 username;
- ASSERT_TRUE(ie7_password::GetUserPassFromData(decrypted_data1, &username,
- &password));
- EXPECT_EQ(L"abcdefgh", username);
- EXPECT_EQ(L"abcdefghijkl", password);
-
- ASSERT_TRUE(ie7_password::GetUserPassFromData(decrypted_data2, &username,
- &password));
- EXPECT_EQ(L"abcdefghi", username);
- EXPECT_EQ(L"abcdefg", password);
-}
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The order of these includes is important.
+#include <windows.h>
+#include <unknwn.h>
+#include <intshcut.h>
+#include <shlguid.h>
+#include <urlhist.h>
+#include <shlobj.h>
+#include <propvarutil.h>
+
+#include <algorithm>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/stl_util.h"
+#include "base/string16.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "base/win/registry.h"
+#include "base/win/scoped_comptr.h"
+#include "base/win/scoped_propvariant.h"
+#include "base/win/windows_version.h"
+#include "chrome/browser/history/history_types.h"
+#include "chrome/browser/importer/ie_importer.h"
+#include "chrome/browser/importer/importer_bridge.h"
+#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/browser/importer/importer_host.h"
+#include "chrome/browser/importer/importer_progress_observer.h"
+#include "chrome/browser/importer/importer_unittest_utils.h"
+#include "chrome/browser/importer/pstore_declarations.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/common/password_form.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char16 kUnitTestRegistrySubKey[] = L"SOFTWARE\\Chromium Unit Tests";
+const char16 kUnitTestUserOverrideSubKey[] =
+ L"SOFTWARE\\Chromium Unit Tests\\HKCU Override";
+
+const BookmarkInfo kIEBookmarks[] = {
+ {true, 2, {L"Links", L"SubFolderOfLinks"},
+ L"SubLink",
+ "http://www.links-sublink.com/"},
+ {true, 1, {L"Links"},
+ L"TheLink",
+ "http://www.links-thelink.com/"},
+ {false, 0, {},
+ L"Google Home Page",
+ "http://www.google.com/"},
+ {false, 0, {},
+ L"TheLink",
+ "http://www.links-thelink.com/"},
+ {false, 1, {L"SubFolder"},
+ L"Title",
+ "http://www.link.com/"},
+ {false, 0, {},
+ L"WithPortAndQuery",
+ "http://host:8080/cgi?q=query"},
+ {false, 1, {L"a"},
+ L"\x4E2D\x6587",
+ "http://chinese-title-favorite/"},
+ {false, 0, {},
+ L"SubFolder",
+ "http://www.subfolder.com/"},
+};
+
+const BookmarkInfo kIESortedBookmarks[] = {
+ {false, 0, {}, L"a", "http://www.google.com/0"},
+ {false, 1, {L"b"}, L"a", "http://www.google.com/1"},
+ {false, 1, {L"b"}, L"b", "http://www.google.com/2"},
+ {false, 0, {}, L"c", "http://www.google.com/3"},
+};
+
+const char16 kIEIdentifyUrl[] =
+ L"http://A79029D6-753E-4e27-B807-3D46AB1545DF.com:8080/path?key=value";
+const char16 kIEIdentifyTitle[] =
+ L"Unittest GUID";
+
+const char16 kIEFavoritesOrderKey[] =
+ L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\"
+ L"MenuOrder\\Favorites";
+
+const char16 kFaviconStreamSuffix[] = L"url:favicon:$DATA";
+const char kDummyFaviconImageData[] =
+ "\x42\x4D" // Magic signature 'BM'
+ "\x1E\x00\x00\x00" // File size
+ "\x00\x00\x00\x00" // Reserved
+ "\x1A\x00\x00\x00" // Offset of the pixel data
+ "\x0C\x00\x00\x00" // Header Size
+ "\x01\x00\x01\x00" // Size: 1x1
+ "\x01\x00" // Reserved
+ "\x18\x00" // 24-bits
+ "\x00\xFF\x00\x00"; // The pixel
+
+struct FaviconGroup {
+ const char16* favicon_url;
+ const char16* site_url[2];
+};
+
+const FaviconGroup kIEFaviconGroup[2] = {
+ {L"http://www.google.com/favicon.ico",
+ {L"http://www.google.com/",
+ L"http://www.subfolder.com/"}},
+ {L"http://example.com/favicon.ico",
+ {L"http://host:8080/cgi?q=query",
+ L"http://chinese-title-favorite/"}},
+};
+
+bool CreateOrderBlob(const base::FilePath& favorites_folder,
+ const string16& path,
+ const std::vector<string16>& entries) {
+ if (entries.size() > 255)
+ return false;
+
+ // Create a binary sequence for setting a specific order of favorites.
+ // The format depends on the version of Shell32.dll, so we cannot embed
+ // a binary constant here.
+ std::vector<uint8> blob(20, 0);
+ blob[16] = static_cast<uint8>(entries.size());
+
+ for (size_t i = 0; i < entries.size(); ++i) {
+ PIDLIST_ABSOLUTE id_list_full = ILCreateFromPath(
+ favorites_folder.Append(path).Append(entries[i]).value().c_str());
+ PUITEMID_CHILD id_list = ILFindLastID(id_list_full);
+ // Include the trailing zero-length item id. Don't include the single
+ // element array.
+ size_t id_list_size = id_list->mkid.cb + sizeof(id_list->mkid.cb);
+
+ blob.resize(blob.size() + 8);
+ uint32 total_size = id_list_size + 8;
+ memcpy(&blob[blob.size() - 8], &total_size, 4);
+ uint32 sort_index = i;
+ memcpy(&blob[blob.size() - 4], &sort_index, 4);
+ blob.resize(blob.size() + id_list_size);
+ memcpy(&blob[blob.size() - id_list_size], id_list, id_list_size);
+ ILFree(id_list_full);
+ }
+
+ string16 key_path = kIEFavoritesOrderKey;
+ if (!path.empty())
+ key_path += L"\\" + path;
+ base::win::RegKey key;
+ if (key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE) !=
+ ERROR_SUCCESS) {
+ return false;
+ }
+ if (key.WriteValue(L"Order", &blob[0], blob.size(), REG_BINARY) !=
+ ERROR_SUCCESS) {
+ return false;
+ }
+ return true;
+}
+
+bool CreateUrlFileWithFavicon(const base::FilePath& file,
+ const string16& url,
+ const string16& favicon_url) {
+ base::win::ScopedComPtr<IUniformResourceLocator> locator;
+ HRESULT result = locator.CreateInstance(CLSID_InternetShortcut, NULL,
+ CLSCTX_INPROC_SERVER);
+ if (FAILED(result))
+ return false;
+ base::win::ScopedComPtr<IPersistFile> persist_file;
+ result = persist_file.QueryFrom(locator);
+ if (FAILED(result))
+ return false;
+ result = locator->SetURL(url.c_str(), 0);
+ if (FAILED(result))
+ return false;
+
+ // Write favicon url if specified.
+ if (!favicon_url.empty()) {
+ base::win::ScopedComPtr<IPropertySetStorage> property_set_storage;
+ if (FAILED(property_set_storage.QueryFrom(locator)))
+ return false;
+ base::win::ScopedComPtr<IPropertyStorage> property_storage;
+ if (FAILED(property_set_storage->Open(FMTID_Intshcut,
+ STGM_WRITE,
+ property_storage.Receive()))) {
+ return false;
+ }
+ PROPSPEC properties[] = {{PRSPEC_PROPID, PID_IS_ICONFILE}};
+ // WriteMultiple takes an array of PROPVARIANTs, but since this code only
+ // needs an array of size 1: a pointer to |pv_icon| is equivalent.
+ base::win::ScopedPropVariant pv_icon;
+ if (FAILED(InitPropVariantFromString(favicon_url.c_str(),
+ pv_icon.Receive())) ||
+ FAILED(property_storage->WriteMultiple(1, properties, &pv_icon, 0))) {
+ return false;
+ }
+ }
+
+ // Save the .url file.
+ result = persist_file->Save(file.value().c_str(), TRUE);
+ if (FAILED(result))
+ return false;
+
+ // Write dummy favicon image data in NTFS alternate data stream.
+ return favicon_url.empty() || (file_util::WriteFile(
+ file.ReplaceExtension(kFaviconStreamSuffix), kDummyFaviconImageData,
+ sizeof kDummyFaviconImageData) != -1);
+}
+
+bool CreateUrlFile(const base::FilePath& file, const string16& url) {
+ return CreateUrlFileWithFavicon(file, url, string16());
+}
+
+void ClearPStoreType(IPStore* pstore, const GUID* type, const GUID* subtype) {
+ base::win::ScopedComPtr<IEnumPStoreItems, NULL> item;
+ HRESULT result = pstore->EnumItems(0, type, subtype, 0, item.Receive());
+ if (result == PST_E_OK) {
+ char16* item_name;
+ while (SUCCEEDED(item->Next(1, &item_name, 0))) {
+ pstore->DeleteItem(0, type, subtype, item_name, NULL, 0);
+ CoTaskMemFree(item_name);
+ }
+ }
+ pstore->DeleteSubtype(0, type, subtype, 0);
+ pstore->DeleteType(0, type, 0);
+}
+
+void WritePStore(IPStore* pstore, const GUID* type, const GUID* subtype) {
+ struct PStoreItem {
+ char16* name;
+ int data_size;
+ char* data;
+ } items[] = {
+ {L"http://localhost:8080/security/index.htm#ref:StringData", 8,
+ "\x31\x00\x00\x00\x32\x00\x00\x00"},
+ {L"http://localhost:8080/security/index.htm#ref:StringIndex", 20,
+ "\x57\x49\x43\x4b\x18\x00\x00\x00\x02\x00"
+ "\x00\x00\x2f\x00\x74\x00\x01\x00\x00\x00"},
+ {L"user:StringData", 4,
+ "\x31\x00\x00\x00"},
+ {L"user:StringIndex", 20,
+ "\x57\x49\x43\x4b\x18\x00\x00\x00\x01\x00"
+ "\x00\x00\x2f\x00\x74\x00\x00\x00\x00\x00"},
+ };
+
+ for (int i = 0; i < arraysize(items); ++i) {
+ HRESULT res = pstore->WriteItem(0, type, subtype, items[i].name,
+ items[i].data_size, reinterpret_cast<BYTE*>(items[i].data),
+ NULL, 0, 0);
+ ASSERT_TRUE(res == PST_E_OK);
+ }
+}
+
+class TestObserver : public ProfileWriter,
+ public importer::ImporterProgressObserver {
+ public:
+ TestObserver() : ProfileWriter(NULL) {
+ bookmark_count_ = 0;
+ history_count_ = 0;
+ password_count_ = 0;
+ favicon_count_ = 0;
+ }
+
+ // importer::ImporterProgressObserver:
+ virtual void ImportStarted() OVERRIDE {}
+ virtual void ImportItemStarted(importer::ImportItem item) OVERRIDE {}
+ virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE {}
+ virtual void ImportEnded() OVERRIDE {
+ MessageLoop::current()->Quit();
+ EXPECT_EQ(arraysize(kIEBookmarks), bookmark_count_);
+ EXPECT_EQ(1, history_count_);
+ EXPECT_EQ(arraysize(kIEFaviconGroup), favicon_count_);
+ }
+
+ virtual bool BookmarkModelIsLoaded() const {
+ // Profile is ready for writing.
+ return true;
+ }
+
+ virtual bool TemplateURLServiceIsLoaded() const {
+ return true;
+ }
+
+ virtual void AddPasswordForm(const content::PasswordForm& form) {
+ // Importer should obtain this password form only.
+ EXPECT_EQ(GURL("http://localhost:8080/security/index.htm"), form.origin);
+ EXPECT_EQ("http://localhost:8080/", form.signon_realm);
+ EXPECT_EQ(L"user", form.username_element);
+ EXPECT_EQ(L"1", form.username_value);
+ EXPECT_EQ(L"", form.password_element);
+ EXPECT_EQ(L"2", form.password_value);
+ EXPECT_EQ("", form.action.spec());
+ ++password_count_;
+ }
+
+ virtual void AddHistoryPage(const history::URLRows& page,
+ history::VisitSource visit_source) {
+ // Importer should read the specified URL.
+ for (size_t i = 0; i < page.size(); ++i) {
+ if (page[i].title() == kIEIdentifyTitle &&
+ page[i].url() == GURL(kIEIdentifyUrl))
+ ++history_count_;
+ }
+ EXPECT_EQ(history::SOURCE_IE_IMPORTED, visit_source);
+ }
+
+ virtual void AddBookmarks(const std::vector<BookmarkEntry>& bookmarks,
+ const string16& top_level_folder_name) OVERRIDE {
+ ASSERT_LE(bookmark_count_ + bookmarks.size(), arraysize(kIEBookmarks));
+ // Importer should import the IE Favorites folder the same as the list,
+ // in the same order.
+ for (size_t i = 0; i < bookmarks.size(); ++i) {
+ EXPECT_NO_FATAL_FAILURE(
+ TestEqualBookmarkEntry(bookmarks[i],
+ kIEBookmarks[bookmark_count_])) << i;
+ ++bookmark_count_;
+ }
+ }
+
+ virtual void AddKeyword(std::vector<TemplateURL*> template_url,
+ int default_keyword_index) {
+ // TODO(jcampan): bug 1169230: we should test keyword importing for IE.
+ // In order to do that we'll probably need to mock the Windows registry.
+ NOTREACHED();
+ STLDeleteContainerPointers(template_url.begin(), template_url.end());
+ }
+
+ virtual void AddFavicons(
+ const std::vector<history::ImportedFaviconUsage>& usage) OVERRIDE {
+ // Importer should group the favicon information for each favicon URL.
+ for (size_t i = 0; i < arraysize(kIEFaviconGroup); ++i) {
+ GURL favicon_url(kIEFaviconGroup[i].favicon_url);
+ std::set<GURL> urls;
+ for (size_t j = 0; j < arraysize(kIEFaviconGroup[i].site_url); ++j)
+ urls.insert(GURL(kIEFaviconGroup[i].site_url[j]));
+
+ SCOPED_TRACE(testing::Message() << "Expected Favicon: " << favicon_url);
+
+ bool expected_favicon_url_found = false;
+ for (size_t j = 0; j < usage.size(); ++j) {
+ if (usage[j].favicon_url == favicon_url) {
+ EXPECT_EQ(urls, usage[j].urls);
+ expected_favicon_url_found = true;
+ break;
+ }
+ }
+ EXPECT_TRUE(expected_favicon_url_found);
+ }
+
+ favicon_count_ += usage.size();
+ }
+
+ private:
+ ~TestObserver() {}
+
+ size_t bookmark_count_;
+ size_t history_count_;
+ size_t password_count_;
+ size_t favicon_count_;
+};
+
+class MalformedFavoritesRegistryTestObserver
+ : public ProfileWriter,
+ public importer::ImporterProgressObserver {
+ public:
+ MalformedFavoritesRegistryTestObserver() : ProfileWriter(NULL) {
+ bookmark_count_ = 0;
+ }
+
+ // importer::ImporterProgressObserver:
+ virtual void ImportStarted() OVERRIDE {}
+ virtual void ImportItemStarted(importer::ImportItem item) OVERRIDE {}
+ virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE {}
+ virtual void ImportEnded() OVERRIDE {
+ MessageLoop::current()->Quit();
+ EXPECT_EQ(arraysize(kIESortedBookmarks), bookmark_count_);
+ }
+
+ virtual bool BookmarkModelIsLoaded() const { return true; }
+ virtual bool TemplateURLServiceIsLoaded() const { return true; }
+
+ virtual void AddPasswordForm(const content::PasswordForm& form) {}
+ virtual void AddHistoryPage(const history::URLRows& page,
+ history::VisitSource visit_source) {}
+ virtual void AddKeyword(std::vector<TemplateURL*> template_url,
+ int default_keyword_index) {}
+ virtual void AddBookmarks(const std::vector<BookmarkEntry>& bookmarks,
+ const string16& top_level_folder_name) OVERRIDE {
+ ASSERT_LE(bookmark_count_ + bookmarks.size(),
+ arraysize(kIESortedBookmarks));
+ for (size_t i = 0; i < bookmarks.size(); ++i) {
+ EXPECT_NO_FATAL_FAILURE(
+ TestEqualBookmarkEntry(bookmarks[i],
+ kIESortedBookmarks[bookmark_count_])) << i;
+ ++bookmark_count_;
+ }
+ }
+
+ private:
+ ~MalformedFavoritesRegistryTestObserver() {}
+
+ size_t bookmark_count_;
+};
+
+} // namespace
+
+// These tests need to be browser tests in order to be able to run the OOP
+// import (via ExternalProcessImporterHost) which launches a utility process.
+class IEImporterBrowserTest : public InProcessBrowserTest {
+ protected:
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ StartRegistryOverride();
+
+ // This will launch the browser test and thus needs to happen last.
+ InProcessBrowserTest::SetUp();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ EndRegistryOverride();
+ }
+
+ void StartRegistryOverride() {
+ EXPECT_EQ(ERROR_SUCCESS, RegOverridePredefKey(HKEY_CURRENT_USER, NULL));
+ temp_hkcu_hive_key_.Create(HKEY_CURRENT_USER,
+ kUnitTestUserOverrideSubKey,
+ KEY_ALL_ACCESS);
+ EXPECT_TRUE(temp_hkcu_hive_key_.Valid());
+ EXPECT_EQ(ERROR_SUCCESS,
+ RegOverridePredefKey(HKEY_CURRENT_USER,
+ temp_hkcu_hive_key_.Handle()));
+ }
+
+ void EndRegistryOverride() {
+ EXPECT_EQ(ERROR_SUCCESS, RegOverridePredefKey(HKEY_CURRENT_USER, NULL));
+ temp_hkcu_hive_key_.Close();
+ base::win::RegKey key(HKEY_CURRENT_USER, kUnitTestRegistrySubKey,
+ KEY_ALL_ACCESS);
+ key.DeleteKey(L"");
+ }
+
+ base::ScopedTempDir temp_dir_;
+ base::win::RegKey temp_hkcu_hive_key_;
+};
+
+IN_PROC_BROWSER_TEST_F(IEImporterBrowserTest, IEImporter) {
+ // Sets up a favorites folder.
+ base::FilePath path = temp_dir_.path().AppendASCII("Favorites");
+ CreateDirectory(path.value().c_str(), NULL);
+ CreateDirectory(path.AppendASCII("SubFolder").value().c_str(), NULL);
+ base::FilePath links_path = path.AppendASCII("Links");
+ CreateDirectory(links_path.value().c_str(), NULL);
+ CreateDirectory(links_path.AppendASCII("SubFolderOfLinks").value().c_str(),
+ NULL);
+ CreateDirectory(path.AppendASCII("\x0061").value().c_str(), NULL);
+ ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("Google Home Page.url"),
+ L"http://www.google.com/",
+ L"http://www.google.com/favicon.ico"));
+ ASSERT_TRUE(CreateUrlFile(path.AppendASCII("SubFolder\\Title.url"),
+ L"http://www.link.com/"));
+ ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("SubFolder.url"),
+ L"http://www.subfolder.com/",
+ L"http://www.google.com/favicon.ico"));
+ ASSERT_TRUE(CreateUrlFile(path.AppendASCII("TheLink.url"),
+ L"http://www.links-thelink.com/"));
+ ASSERT_TRUE(CreateUrlFileWithFavicon(path.AppendASCII("WithPortAndQuery.url"),
+ L"http://host:8080/cgi?q=query",
+ L"http://example.com/favicon.ico"));
+ ASSERT_TRUE(CreateUrlFileWithFavicon(
+ path.AppendASCII("\x0061").Append(L"\x4E2D\x6587.url"),
+ L"http://chinese-title-favorite/",
+ L"http://example.com/favicon.ico"));
+ ASSERT_TRUE(CreateUrlFile(links_path.AppendASCII("TheLink.url"),
+ L"http://www.links-thelink.com/"));
+ ASSERT_TRUE(CreateUrlFile(
+ links_path.AppendASCII("SubFolderOfLinks").AppendASCII("SubLink.url"),
+ L"http://www.links-sublink.com/"));
+ ASSERT_TRUE(CreateUrlFile(path.AppendASCII("IEDefaultLink.url"),
+ L"http://go.microsoft.com/fwlink/?linkid=140813"));
+ file_util::WriteFile(path.AppendASCII("InvalidUrlFile.url"), "x", 1);
+ file_util::WriteFile(path.AppendASCII("PlainTextFile.txt"), "x", 1);
+
+ const char16* root_links[] = {
+ L"Links",
+ L"Google Home Page.url",
+ L"TheLink.url",
+ L"SubFolder",
+ L"WithPortAndQuery.url",
+ L"a",
+ L"SubFolder.url",
+ };
+ ASSERT_TRUE(CreateOrderBlob(
+ base::FilePath(path), L"",
+ std::vector<string16>(root_links, root_links + arraysize(root_links))));
+
+ HRESULT res;
+
+ // Sets up a special history link.
+ base::win::ScopedComPtr<IUrlHistoryStg2> url_history_stg2;
+ res = url_history_stg2.CreateInstance(CLSID_CUrlHistory, NULL,
+ CLSCTX_INPROC_SERVER);
+ ASSERT_TRUE(res == S_OK);
+ res = url_history_stg2->AddUrl(kIEIdentifyUrl, kIEIdentifyTitle, 0);
+ ASSERT_TRUE(res == S_OK);
+
+ // Starts to import the above settings.
+ // TODO(gab): Use ExternalProcessImporterHost on Windows.
+ scoped_refptr<ImporterHost> host(new ImporterHost);
+ TestObserver* observer = new TestObserver();
+ host->SetObserver(observer);
+
+ importer::SourceProfile source_profile;
+ source_profile.importer_type = importer::TYPE_IE;
+ source_profile.source_path = temp_dir_.path();
+
+ // IUrlHistoryStg2::AddUrl seems to reset the override. Ensure it here.
+ StartRegistryOverride();
+
+ host->StartImportSettings(
+ source_profile,
+ browser()->profile(),
+ importer::HISTORY | importer::PASSWORDS | importer::FAVORITES,
+ observer);
+ MessageLoop::current()->Run();
+
+ // Cleans up.
+ url_history_stg2->DeleteUrl(kIEIdentifyUrl, 0);
+ url_history_stg2.Release();
+}
+
+IN_PROC_BROWSER_TEST_F(IEImporterBrowserTest,
+ IEImporterMalformedFavoritesRegistry) {
+ // Sets up a favorites folder.
+ base::FilePath path = temp_dir_.path().AppendASCII("Favorites");
+ CreateDirectory(path.value().c_str(), NULL);
+ CreateDirectory(path.AppendASCII("b").value().c_str(), NULL);
+ ASSERT_TRUE(CreateUrlFile(path.AppendASCII("a.url"),
+ L"http://www.google.com/0"));
+ ASSERT_TRUE(CreateUrlFile(path.AppendASCII("b").AppendASCII("a.url"),
+ L"http://www.google.com/1"));
+ ASSERT_TRUE(CreateUrlFile(path.AppendASCII("b").AppendASCII("b.url"),
+ L"http://www.google.com/2"));
+ ASSERT_TRUE(CreateUrlFile(path.AppendASCII("c.url"),
+ L"http://www.google.com/3"));
+
+ struct BadBinaryData {
+ const char* data;
+ int length;
+ };
+ static const BadBinaryData kBadBinary[] = {
+ // number_of_items field is truncated
+ {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\xff\xff\xff", 17},
+ // number_of_items = 0xffff, but the byte sequence is too short.
+ {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\xff\xff\x00\x00", 20},
+ // number_of_items = 1, size_of_item is too big.
+ {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x01\x00\x00\x00"
+ "\xff\xff\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00", 32},
+ // number_of_items = 1, size_of_item = 16, size_of_shid is too big.
+ {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x01\x00\x00\x00"
+ "\x10\x00\x00\x00\x00\x00\x00\x00"
+ "\xff\x7f\x00\x00" "\x00\x00\x00\x00", 36},
+ // number_of_items = 1, size_of_item = 16, size_of_shid is too big.
+ {"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x01\x00\x00\x00"
+ "\x10\x00\x00\x00\x00\x00\x00\x00"
+ "\x06\x00\x00\x00" "\x00\x00\x00\x00", 36},
+ };
+
+ // Verify malformed registry data are safely ignored and alphabetical
+ // sort is performed.
+ for (size_t i = 0; i < arraysize(kBadBinary); ++i) {
+ base::win::RegKey key;
+ ASSERT_EQ(ERROR_SUCCESS,
+ key.Create(HKEY_CURRENT_USER, kIEFavoritesOrderKey, KEY_WRITE));
+ ASSERT_EQ(ERROR_SUCCESS,
+ key.WriteValue(L"Order", kBadBinary[i].data, kBadBinary[i].length,
+ REG_BINARY));
+
+ // Starts to import the above settings.
+ // TODO(gab): Use ExternalProcessImporterHost on Windows.
+ scoped_refptr<ImporterHost> host(new ImporterHost);
+ MalformedFavoritesRegistryTestObserver* observer =
+ new MalformedFavoritesRegistryTestObserver();
+ host->SetObserver(observer);
+
+ importer::SourceProfile source_profile;
+ source_profile.importer_type = importer::TYPE_IE;
+ source_profile.source_path = temp_dir_.path();
+
+ host->StartImportSettings(
+ source_profile,
+ browser()->profile(),
+ importer::FAVORITES,
+ observer);
+ MessageLoop::current()->Run();
+ }
+}
« no previous file with comments | « chrome/browser/importer/firefox_importer_unittest.cc ('k') | chrome/browser/importer/ie_importer_unittest_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698