// Copyright (c) 2011 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"
#include <string>
#include <vector>
#include "base/string16.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/importer/toolbar_importer.h"
#include "chrome/common/libxml_utils.h"
#include "googleurl/src/gurl.h"
// See http://crbug.com/11838
TEST(Toolbar5ImporterTest, BookmarkParse) {
static const string16 kTitle = ASCIIToUTF16("MyTitle");
static const char kUrl[] = "http://www.google.com/";
static const string16 kFolder = ASCIIToUTF16("Google");
static const string16 kFolder2 = ASCIIToUTF16("Homepage");
static const string16 kFolderArray[3] = {
ASCIIToUTF16("Google"),
ASCIIToUTF16("Search"),
ASCIIToUTF16("Page")
};
static const string16 kOtherTitle = ASCIIToUTF16("MyOtherTitle");
static const char* kOtherUrl = "http://www.google.com/mail";
static const string16 kOtherFolder = ASCIIToUTF16("Mail");
static const string16 kBookmarkGroupTitle = ASCIIToUTF16("BookmarkGroupTitle");
// Since the following is very dense to read I enumerate the test cases here.
// 1. Correct bookmark structure with one label.
// 2. Correct bookmark structure with no labels.
// 3. Correct bookmark structure with two labels.
// 4. Correct bookmark structure with a folder->label translation by toolbar.
// 5. Correct bookmark structure with no favicon.
// 6. Two correct bookmarks.
// The following are error cases by removing sections from the xml:
// 7. Empty string passed as xml.
// 8. No <bookmarks> section in the xml.
// 9. No <bookmark> section below the <bookmarks> section.
// 10. No <title> in a <bookmark> section.
// 11. No <url> in a <bookmark> section.
// 12. No <timestamp> in a <bookmark> section.
// 13. No <labels> in a <bookmark> section.
static const char* kGoodBookmark =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
" <bookmark> "
"<title>MyTitle</title> "
"<url>http://www.google.com/</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Google</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
static const char* kGoodBookmarkNoLabel =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
" <bookmark> "
"<title>MyTitle</title> "
"<url>http://www.google.com/</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
static const char* kGoodBookmarkTwoLabels =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
" <bookmark> "
"<title>MyTitle</title> "
"<url>http://www.google.com/</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Google</label> <label>Homepage</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
static const char* kGoodBookmarkFolderLabel =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
" <bookmark> "
"<title>MyTitle</title> "
"<url>http://www.google.com/</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Google:Search:Page</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
static const char* kGoodBookmarkNoFavicon =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
" <bookmark> "
"<title>MyTitle</title> "
"<url>http://www.google.com/</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Google</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
static const char* kGoodBookmark2Items =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
" <bookmark> "
"<title>MyTitle</title> "
"<url>http://www.google.com/</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Google</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark>"
" <bookmark> "
"<title>MyOtherTitle</title> "
"<url>http://www.google.com/mail</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Mail</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name>"
"<value>http://www.google.com/mail/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1253328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark>"
"</bookmarks>";
static const char* kEmptyString = "";
static const char* kBadBookmarkNoBookmarks =
" <bookmark> "
"<title>MyTitle</title> "
"<url>http://www.google.com/</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Google</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
static const char* kBadBookmarkNoBookmark =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
"<title>MyTitle</title> "
"<url>http://www.google.com/</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Google</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
static const char* kBadBookmarkNoTitle =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
" <bookmark> "
"<url>http://www.google.com/</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Google</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
static const char* kBadBookmarkNoUrl =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
" <bookmark> "
"<title>MyTitle</title> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Google</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
static const char* kBadBookmarkNoTimestamp =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
" <bookmark> "
"<title>MyTitle</title> "
"<url>http://www.google.com/</url> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<labels> <label>Google</label> </labels> "
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
static const char* kBadBookmarkNoLabels =
"<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
" <bookmark> "
"<title>MyTitle</title> "
"<url>http://www.google.com/</url> "
"<timestamp>1153328691085181</timestamp> "
"<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
"<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
"<attributes> "
"<attribute> "
"<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
"</attribute> "
"<attribute> "
"<name>favicon_timestamp</name> <value>1153328653</value> "
"</attribute> "
"<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
"</attribute> "
"<attribute> <name>section_name</name> <value>My section 0 "
"</value> </attribute> </attributes> "
"</bookmark> </bookmarks>";
XmlReader reader;
std::string bookmark_xml;
std::vector<ProfileWriter::BookmarkEntry> bookmarks;
const GURL url(kUrl);
const GURL other_url(kOtherUrl);
// Test doesn't work if the importer thinks this is the first run of Chromium.
// Mark this as a subsequent run of the browser.
FirstRun::first_run_ = FirstRun::FIRST_RUN_FALSE;
// Test case 1 is parsing a basic bookmark with a single label.
bookmark_xml = kGoodBookmark;
bookmarks.clear();
XmlReader reader1;
EXPECT_TRUE(reader1.Load(bookmark_xml));
EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader1, &bookmarks,
kBookmarkGroupTitle));
ASSERT_EQ(1U, bookmarks.size());
EXPECT_FALSE(bookmarks[0].in_toolbar);
EXPECT_EQ(kTitle, bookmarks[0].title);
EXPECT_EQ(url, bookmarks[0].url);
ASSERT_EQ(2U, bookmarks[0].path.size());
EXPECT_EQ(kFolder, bookmarks[0].path[1]);
// Test case 2 is parsing a single bookmark with no label.
bookmark_xml = kGoodBookmarkNoLabel;
bookmarks.clear();
XmlReader reader2;
EXPECT_TRUE(reader2.Load(bookmark_xml));
EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader2, &bookmarks,
kBookmarkGroupTitle));
ASSERT_EQ(1U, bookmarks.size());
EXPECT_FALSE(bookmarks[0].in_toolbar);
EXPECT_EQ(kTitle, bookmarks[0].title);
EXPECT_EQ(url, bookmarks[0].url);
EXPECT_EQ(1U, bookmarks[0].path.size());
// Test case 3 is parsing a single bookmark with two labels.
bookmark_xml = kGoodBookmarkTwoLabels;
bookmarks.clear();
XmlReader reader3;
EXPECT_TRUE(reader3.Load(bookmark_xml));
EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader3, &bookmarks,
kBookmarkGroupTitle));
ASSERT_EQ(2U, bookmarks.size());
EXPECT_FALSE(bookmarks[0].in_toolbar);
EXPECT_FALSE(bookmarks[1].in_toolbar);
EXPECT_EQ(kTitle, bookmarks[0].title);
EXPECT_EQ(kTitle, bookmarks[1].title);
EXPECT_EQ(url, bookmarks[0].url);
EXPECT_EQ(url, bookmarks[1].url);
ASSERT_EQ(2U, bookmarks[0].path.size());
EXPECT_EQ(kFolder, bookmarks[0].path[1]);
ASSERT_EQ(2U, bookmarks[1].path.size());
EXPECT_EQ(kFolder2, bookmarks[1].path[1]);
// Test case 4 is parsing a single bookmark which has a label with a colon,
// this test file name translation between Toolbar and Chrome.
bookmark_xml = kGoodBookmarkFolderLabel;
bookmarks.clear();
XmlReader reader4;
EXPECT_TRUE(reader4.Load(bookmark_xml));
EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader4, &bookmarks,
kBookmarkGroupTitle));
ASSERT_EQ(1U, bookmarks.size());
EXPECT_FALSE(bookmarks[0].in_toolbar);
EXPECT_EQ(kTitle, bookmarks[0].title);
EXPECT_EQ(url, bookmarks[0].url);
ASSERT_EQ(4U, bookmarks[0].path.size());
EXPECT_EQ(string16(kFolderArray[0]),
bookmarks[0].path[1]);
EXPECT_EQ(string16(kFolderArray[1]),
bookmarks[0].path[2]);
EXPECT_EQ(string16(kFolderArray[2]),
bookmarks[0].path[3]);
// Test case 5 is parsing a single bookmark without a favicon URL.
bookmark_xml = kGoodBookmarkNoFavicon;
bookmarks.clear();
XmlReader reader5;
EXPECT_TRUE(reader5.Load(bookmark_xml));
EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader5, &bookmarks,
kBookmarkGroupTitle));
ASSERT_EQ(1U, bookmarks.size());
EXPECT_FALSE(bookmarks[0].in_toolbar);
EXPECT_EQ(kTitle, bookmarks[0].title);
EXPECT_EQ(url, bookmarks[0].url);
ASSERT_EQ(2U, bookmarks[0].path.size());
EXPECT_EQ(kFolder, bookmarks[0].path[1]);
// Test case 6 is parsing two bookmarks.
bookmark_xml = kGoodBookmark2Items;
bookmarks.clear();
XmlReader reader6;
EXPECT_TRUE(reader6.Load(bookmark_xml));
EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader6, &bookmarks,
kBookmarkGroupTitle));
ASSERT_EQ(2U, bookmarks.size());
EXPECT_FALSE(bookmarks[0].in_toolbar);
EXPECT_FALSE(bookmarks[1].in_toolbar);
EXPECT_EQ(kTitle, bookmarks[0].title);
EXPECT_EQ(kOtherTitle, bookmarks[1].title);
EXPECT_EQ(url, bookmarks[0].url);
EXPECT_EQ(other_url, bookmarks[1].url);
ASSERT_EQ(2U, bookmarks[0].path.size());
EXPECT_EQ(kFolder, bookmarks[0].path[1]);
ASSERT_EQ(2U, bookmarks[1].path.size());
EXPECT_EQ(kOtherFolder, bookmarks[1].path[1]);
// Test case 7 is parsing an empty string for bookmarks.
bookmark_xml = kEmptyString;
bookmarks.clear();
XmlReader reader7;
EXPECT_FALSE(reader7.Load(bookmark_xml));
// Test case 8 is testing the error when no <bookmarks> section is present.
bookmark_xml = kBadBookmarkNoBookmarks;
bookmarks.clear();
XmlReader reader8;
EXPECT_TRUE(reader8.Load(bookmark_xml));
EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader8,
&bookmarks, kBookmarkGroupTitle));
// Test case 9 tests when no <bookmark> section is present.
bookmark_xml = kBadBookmarkNoBookmark;
bookmarks.clear();
XmlReader reader9;
EXPECT_TRUE(reader9.Load(bookmark_xml));
EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader9,
&bookmarks, kBookmarkGroupTitle));
// Test case 10 tests when a bookmark has no <title> section.
bookmark_xml = kBadBookmarkNoTitle;
bookmarks.clear();
XmlReader reader10;
EXPECT_TRUE(reader10.Load(bookmark_xml));
EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader10,
&bookmarks, kBookmarkGroupTitle));
// Test case 11 tests when a bookmark has no <url> section.
bookmark_xml = kBadBookmarkNoUrl;
bookmarks.clear();
XmlReader reader11;
EXPECT_TRUE(reader11.Load(bookmark_xml));
EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader11,
&bookmarks, kBookmarkGroupTitle));
// Test case 12 tests when a bookmark has no <timestamp> section.
bookmark_xml = kBadBookmarkNoTimestamp;
bookmarks.clear();
XmlReader reader12;
EXPECT_TRUE(reader12.Load(bookmark_xml));
EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader12,
&bookmarks, kBookmarkGroupTitle));
// Test case 13 tests when a bookmark has no <labels> section.
bookmark_xml = kBadBookmarkNoLabels;
bookmarks.clear();
XmlReader reader13;
EXPECT_TRUE(reader13.Load(bookmark_xml));
EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader13,
&bookmarks, kBookmarkGroupTitle));
}