bookmark_html_writer_unittest.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1// Copyright (c) 2012 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#include "chrome/browser/bookmarks/bookmark_html_writer.h" 6 7#include "base/files/scoped_temp_dir.h" 8#include "base/i18n/time_formatting.h" 9#include "base/message_loop.h" 10#include "base/path_service.h" 11#include "base/strings/string16.h" 12#include "base/strings/string_util.h" 13#include "base/strings/utf_string_conversions.h" 14#include "base/time.h" 15#include "chrome/browser/bookmarks/bookmark_html_reader.h" 16#include "chrome/browser/bookmarks/bookmark_model.h" 17#include "chrome/browser/bookmarks/bookmark_model_factory.h" 18#include "chrome/browser/bookmarks/imported_bookmark_entry.h" 19#include "chrome/browser/favicon/favicon_service.h" 20#include "chrome/browser/favicon/favicon_service_factory.h" 21#include "chrome/browser/favicon/imported_favicon_usage.h" 22#include "chrome/browser/history/history_service.h" 23#include "chrome/browser/history/history_service_factory.h" 24#include "chrome/test/base/testing_profile.h" 25#include "chrome/test/base/ui_test_utils.h" 26#include "content/public/test/test_browser_thread.h" 27#include "grit/generated_resources.h" 28#include "testing/gtest/include/gtest/gtest.h" 29#include "third_party/skia/include/core/SkBitmap.h" 30#include "ui/base/l10n/l10n_util.h" 31#include "ui/gfx/codec/png_codec.h" 32 33using content::BrowserThread; 34 35namespace { 36 37const int kIconWidth = 16; 38const int kIconHeight = 16; 39 40void MakeTestSkBitmap(int w, int h, SkBitmap* bmp) { 41 bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h); 42 bmp->allocPixels(); 43 44 uint32_t* src_data = bmp->getAddr32(0, 0); 45 for (int i = 0; i < w * h; i++) { 46 src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240); 47 } 48} 49 50} // namespace 51 52class BookmarkHTMLWriterTest : public testing::Test { 53 protected: 54 virtual void SetUp() { 55 testing::Test::SetUp(); 56 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 57 path_ = temp_dir_.path().AppendASCII("bookmarks.html"); 58 } 59 60 // Converts an ImportedBookmarkEntry to a string suitable for assertion 61 // testing. 62 string16 BookmarkEntryToString(const ImportedBookmarkEntry& entry) { 63 string16 result; 64 result.append(ASCIIToUTF16("on_toolbar=")); 65 if (entry.in_toolbar) 66 result.append(ASCIIToUTF16("true")); 67 else 68 result.append(ASCIIToUTF16("false")); 69 70 result.append(ASCIIToUTF16(" url=") + UTF8ToUTF16(entry.url.spec())); 71 72 result.append(ASCIIToUTF16(" path=")); 73 for (size_t i = 0; i < entry.path.size(); ++i) { 74 if (i != 0) 75 result.append(ASCIIToUTF16("/")); 76 result.append(entry.path[i]); 77 } 78 79 result.append(ASCIIToUTF16(" title=")); 80 result.append(entry.title); 81 82 result.append(ASCIIToUTF16(" time=")); 83 result.append(base::TimeFormatFriendlyDateAndTime(entry.creation_time)); 84 return result; 85 } 86 87 // Creates a set of bookmark values to a string for assertion testing. 88 string16 BookmarkValuesToString(bool on_toolbar, 89 const GURL& url, 90 const string16& title, 91 base::Time creation_time, 92 const string16& f1, 93 const string16& f2, 94 const string16& f3) { 95 ImportedBookmarkEntry entry; 96 entry.in_toolbar = on_toolbar; 97 entry.url = url; 98 if (!f1.empty()) { 99 entry.path.push_back(f1); 100 if (!f2.empty()) { 101 entry.path.push_back(f2); 102 if (!f3.empty()) 103 entry.path.push_back(f3); 104 } 105 } 106 entry.title = title; 107 entry.creation_time = creation_time; 108 return BookmarkEntryToString(entry); 109 } 110 111 void AssertBookmarkEntryEquals(const ImportedBookmarkEntry& entry, 112 bool on_toolbar, 113 const GURL& url, 114 const string16& title, 115 base::Time creation_time, 116 const string16& f1, 117 const string16& f2, 118 const string16& f3) { 119 EXPECT_EQ(BookmarkValuesToString(on_toolbar, url, title, creation_time, 120 f1, f2, f3), 121 BookmarkEntryToString(entry)); 122 } 123 124 base::ScopedTempDir temp_dir_; 125 base::FilePath path_; 126}; 127 128// Class that will notify message loop when file is written. 129class BookmarksObserver : public BookmarksExportObserver { 130 public: 131 explicit BookmarksObserver(base::MessageLoop* loop) : loop_(loop) { 132 DCHECK(loop); 133 } 134 135 virtual void OnExportFinished() OVERRIDE { 136 loop_->Quit(); 137 } 138 139 private: 140 base::MessageLoop* loop_; 141 DISALLOW_COPY_AND_ASSIGN(BookmarksObserver); 142}; 143 144// Tests bookmark_html_writer by populating a BookmarkModel, writing it out by 145// way of bookmark_html_writer, then using the importer to read it back in. 146TEST_F(BookmarkHTMLWriterTest, Test) { 147 base::MessageLoop message_loop; 148 content::TestBrowserThread fake_ui_thread(BrowserThread::UI, &message_loop); 149 content::TestBrowserThread fake_file_thread(BrowserThread::FILE, 150 &message_loop); 151 152 TestingProfile profile; 153 profile.CreateHistoryService(true, false); 154 profile.BlockUntilHistoryProcessesPendingRequests(); 155 profile.CreateFaviconService(); 156 profile.CreateBookmarkModel(true); 157 158 BookmarkModel* model = BookmarkModelFactory::GetForProfile(&profile); 159 ui_test_utils::WaitForBookmarkModelToLoad(model); 160 161 // Create test PNG representing favicon for url1. 162 SkBitmap bitmap; 163 MakeTestSkBitmap(kIconWidth, kIconHeight, &bitmap); 164 std::vector<unsigned char> icon_data; 165 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &icon_data); 166 167 // Populate the BookmarkModel. This creates the following bookmark structure: 168 // Bookmarks bar 169 // F1 170 // url1 171 // F2 172 // url2 173 // url3 174 // url4 175 // Other 176 // url1 177 // url2 178 // F3 179 // F4 180 // url1 181 // Mobile 182 // url1 183 // <bookmark without a title.> 184 string16 f1_title = ASCIIToUTF16("F\"&;<1\""); 185 string16 f2_title = ASCIIToUTF16("F2"); 186 string16 f3_title = ASCIIToUTF16("F 3"); 187 string16 f4_title = ASCIIToUTF16("F4"); 188 string16 url1_title = ASCIIToUTF16("url 1"); 189 string16 url2_title = ASCIIToUTF16("url&2"); 190 string16 url3_title = ASCIIToUTF16("url\"3"); 191 string16 url4_title = ASCIIToUTF16("url\"&;"); 192 string16 unnamed_bookmark_title = ASCIIToUTF16(""); 193 GURL url1("http://url1"); 194 GURL url1_favicon("http://url1/icon.ico"); 195 GURL url2("http://url2"); 196 GURL url3("http://url3"); 197 GURL url4("javascript:alert(\"Hello!\");"); 198 GURL unnamed_bookmark_url("about:blank"); 199 base::Time t1(base::Time::Now()); 200 base::Time t2(t1 + base::TimeDelta::FromHours(1)); 201 base::Time t3(t1 + base::TimeDelta::FromHours(1)); 202 base::Time t4(t1 + base::TimeDelta::FromHours(1)); 203 const BookmarkNode* f1 = model->AddFolder( 204 model->bookmark_bar_node(), 0, f1_title); 205 model->AddURLWithCreationTime(f1, 0, url1_title, url1, t1); 206 HistoryServiceFactory::GetForProfile(&profile, Profile::EXPLICIT_ACCESS)-> 207 AddPage(url1, base::Time::Now(), history::SOURCE_BROWSED); 208 FaviconServiceFactory::GetForProfile( 209 &profile, Profile::EXPLICIT_ACCESS)->SetFavicons( 210 url1, url1_favicon, chrome::FAVICON, 211 gfx::Image::CreateFrom1xBitmap(bitmap)); 212 message_loop.RunUntilIdle(); 213 const BookmarkNode* f2 = model->AddFolder(f1, 1, f2_title); 214 model->AddURLWithCreationTime(f2, 0, url2_title, url2, t2); 215 model->AddURLWithCreationTime(model->bookmark_bar_node(), 216 1, url3_title, url3, t3); 217 218 model->AddURLWithCreationTime(model->other_node(), 0, url1_title, url1, t1); 219 model->AddURLWithCreationTime(model->other_node(), 1, url2_title, url2, t2); 220 const BookmarkNode* f3 = model->AddFolder(model->other_node(), 2, f3_title); 221 const BookmarkNode* f4 = model->AddFolder(f3, 0, f4_title); 222 model->AddURLWithCreationTime(f4, 0, url1_title, url1, t1); 223 model->AddURLWithCreationTime(model->bookmark_bar_node(), 2, url4_title, 224 url4, t4); 225 model->AddURLWithCreationTime(model->mobile_node(), 0, url1_title, url1, t1); 226 model->AddURLWithCreationTime(model->mobile_node(), 1, unnamed_bookmark_title, 227 unnamed_bookmark_url, t2); 228 229 // Write to a temp file. 230 BookmarksObserver observer(&message_loop); 231 bookmark_html_writer::WriteBookmarks(&profile, path_, &observer); 232 message_loop.Run(); 233 234 // Clear favicon so that it would be read from file. 235 FaviconServiceFactory::GetForProfile( 236 &profile, Profile::EXPLICIT_ACCESS)->SetFavicons( 237 url1, url1_favicon, chrome::FAVICON, gfx::Image()); 238 message_loop.RunUntilIdle(); 239 240 // Read the bookmarks back in. 241 std::vector<ImportedBookmarkEntry> parsed_bookmarks; 242 std::vector<ImportedFaviconUsage> favicons; 243 bookmark_html_reader::ImportBookmarksFile(base::Callback<bool(void)>(), 244 base::Callback<bool(const GURL&)>(), 245 path_, 246 &parsed_bookmarks, 247 &favicons); 248 249 // Check loaded favicon (url1 is represented by 4 separate bookmarks). 250 EXPECT_EQ(4U, favicons.size()); 251 for (size_t i = 0; i < favicons.size(); i++) { 252 if (url1_favicon == favicons[i].favicon_url) { 253 EXPECT_EQ(1U, favicons[i].urls.size()); 254 std::set<GURL>::const_iterator iter = favicons[i].urls.find(url1); 255 ASSERT_TRUE(iter != favicons[i].urls.end()); 256 ASSERT_TRUE(*iter == url1); 257 ASSERT_TRUE(favicons[i].png_data == icon_data); 258 } 259 } 260 261 // Verify we got back what we wrote. 262 ASSERT_EQ(9U, parsed_bookmarks.size()); 263 // Windows and ChromeOS builds use Sentence case. 264 string16 bookmark_folder_name = 265 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_FOLDER_NAME); 266 AssertBookmarkEntryEquals(parsed_bookmarks[0], true, url1, url1_title, t1, 267 bookmark_folder_name, f1_title, string16()); 268 AssertBookmarkEntryEquals(parsed_bookmarks[1], true, url2, url2_title, t2, 269 bookmark_folder_name, f1_title, f2_title); 270 AssertBookmarkEntryEquals(parsed_bookmarks[2], true, url3, url3_title, t3, 271 bookmark_folder_name, string16(), string16()); 272 AssertBookmarkEntryEquals(parsed_bookmarks[3], true, url4, url4_title, t4, 273 bookmark_folder_name, string16(), string16()); 274 AssertBookmarkEntryEquals(parsed_bookmarks[4], false, url1, url1_title, t1, 275 string16(), string16(), string16()); 276 AssertBookmarkEntryEquals(parsed_bookmarks[5], false, url2, url2_title, t2, 277 string16(), string16(), string16()); 278 AssertBookmarkEntryEquals(parsed_bookmarks[6], false, url1, url1_title, t1, 279 f3_title, f4_title, string16()); 280 AssertBookmarkEntryEquals(parsed_bookmarks[7], false, url1, url1_title, t1, 281 string16(), string16(), string16()); 282 AssertBookmarkEntryEquals(parsed_bookmarks[8], false, unnamed_bookmark_url, 283 unnamed_bookmark_title, t2, 284 string16(), string16(), string16()); 285} 286