1 // Copyright (c) 2011 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/favicon_helper.h"
6
7 #include "content/browser/renderer_host/test_render_view_host.h"
8 #include "content/browser/tab_contents/navigation_entry.h"
9 #include "content/browser/tab_contents/test_tab_contents.h"
10 #include "ui/gfx/codec/png_codec.h"
11 #include "ui/gfx/favicon_size.h"
12
13 class TestFaviconHelper;
14
15 namespace {
16
17 // Fill the given bmp with valid png data.
FillDataToBitmap(int w,int h,SkBitmap * bmp)18 void FillDataToBitmap(int w, int h, SkBitmap* bmp) {
19 bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h);
20 bmp->allocPixels();
21
22 unsigned char* src_data =
23 reinterpret_cast<unsigned char*>(bmp->getAddr32(0, 0));
24 for (int i = 0; i < w * h; i++) {
25 src_data[i * 4 + 0] = static_cast<unsigned char>(i % 255);
26 src_data[i * 4 + 1] = static_cast<unsigned char>(i % 255);
27 src_data[i * 4 + 2] = static_cast<unsigned char>(i % 255);
28 src_data[i * 4 + 3] = static_cast<unsigned char>(i % 255);
29 }
30 }
31
32 // Fill the given data buffer with valid png data.
FillBitmap(int w,int h,std::vector<unsigned char> * output)33 void FillBitmap(int w, int h, std::vector<unsigned char>* output) {
34 SkBitmap bitmap;
35 FillDataToBitmap(w, h, &bitmap);
36 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, output);
37 }
38
39 // This class is used to save the download request for verifying with test case.
40 // It also will be used to invoke the onDidDownload callback.
41 class DownloadHandler {
42 public:
DownloadHandler(int download_id,const GURL & image_url,int image_size,TestFaviconHelper * favicon_helper)43 DownloadHandler(int download_id,
44 const GURL& image_url,
45 int image_size,
46 TestFaviconHelper* favicon_helper)
47 : image_url_(image_url),
48 image_size_(image_size),
49 failed_(false),
50 download_id_(download_id),
51 favicon_helper_(favicon_helper) {
52 FillDataToBitmap(16, 16, &bitmap_);
53 }
54
~DownloadHandler()55 virtual ~DownloadHandler() {
56 }
57
58 static void UpdateFaviconURL(FaviconHelper* helper,
59 const std::vector<FaviconURL> urls);
60
61 void InvokeCallback();
62
63 void UpdateFaviconURL(const std::vector<FaviconURL> urls);
64
65 const GURL image_url_;
66 const int image_size_;
67
68 // Simulates download failed or not.
69 bool failed_;
70
71 private:
72 // Identified the specific download, will also be passed in
73 // OnDidDownloadFavicon callback.
74 int download_id_;
75 TestFaviconHelper* favicon_helper_;
76 SkBitmap bitmap_;
77
78 DISALLOW_COPY_AND_ASSIGN(DownloadHandler);
79 };
80
81 // This class is used to save the history request for verifying with test case.
82 // It also will be used to simulate the history response.
83 class HistoryRequestHandler {
84 public:
HistoryRequestHandler(const GURL & page_url,const GURL & icon_url,int icon_type,FaviconService::FaviconDataCallback * callback)85 HistoryRequestHandler(const GURL& page_url,
86 const GURL& icon_url,
87 int icon_type,
88 FaviconService::FaviconDataCallback* callback)
89 : page_url_(page_url),
90 icon_url_(icon_url),
91 icon_type_(icon_type),
92 callback_(callback) {
93 }
94
HistoryRequestHandler(const GURL & page_url,const GURL & icon_url,int icon_type,const std::vector<unsigned char> & image_data,FaviconService::FaviconDataCallback * callback)95 HistoryRequestHandler(const GURL& page_url,
96 const GURL& icon_url,
97 int icon_type,
98 const std::vector<unsigned char>& image_data,
99 FaviconService::FaviconDataCallback* callback)
100 : page_url_(page_url),
101 icon_url_(icon_url),
102 icon_type_(icon_type),
103 image_data_(image_data),
104 callback_(callback) {
105 }
106
~HistoryRequestHandler()107 virtual ~HistoryRequestHandler() {
108 delete callback_;
109 }
110 void InvokeCallback();
111
112 const GURL page_url_;
113 const GURL icon_url_;
114 const int icon_type_;
115 const std::vector<unsigned char> image_data_;
116 history::FaviconData favicon_data_;
117 FaviconService::FaviconDataCallback* callback_;
118
119 private:
120 DISALLOW_COPY_AND_ASSIGN(HistoryRequestHandler);
121 };
122
123 } // namespace
124
125 // This class is used to catch the FaviconHelper's download and history request,
126 // and also provide the methods to access the FaviconHelper internal.
127 class TestFaviconHelper : public FaviconHelper {
128 public:
TestFaviconHelper(const GURL & page_url,TabContents * tab_contents,Type type)129 TestFaviconHelper(const GURL& page_url,
130 TabContents* tab_contents,
131 Type type)
132 : FaviconHelper(tab_contents, type),
133 download_image_size_(0),
134 download_id_(0),
135 tab_contents_(tab_contents){
136 entry_.set_url(page_url);
137 }
138
~TestFaviconHelper()139 virtual ~TestFaviconHelper() {
140 }
141
history_handler()142 HistoryRequestHandler* history_handler() {
143 return history_handler_.get();
144 }
145
146 // This method will take the ownership of the given handler.
set_history_handler(HistoryRequestHandler * handler)147 void set_history_handler(HistoryRequestHandler* handler) {
148 history_handler_.reset(handler);
149 }
150
download_handler()151 DownloadHandler* download_handler() {
152 return download_handler_.get();
153 }
154
155 // This method will take the ownership of the given download_handler.
set_download_handler(DownloadHandler * download_handler)156 void set_download_handler(DownloadHandler* download_handler) {
157 download_handler_.reset(download_handler);
158 }
159
GetEntry()160 virtual NavigationEntry* GetEntry() {
161 return &entry_;
162 }
163
urls()164 const std::vector<FaviconURL>& urls() {
165 return urls_;
166 }
167
FetchFavicon(const GURL & url)168 void FetchFavicon(const GURL& url) {
169 FaviconHelper::FetchFavicon(url);
170 }
171
172 // The methods to access favicon internal.
current_candidate()173 FaviconURL* current_candidate() {
174 return FaviconHelper::current_candidate();
175 }
176
OnDidDownloadFavicon(int id,const GURL & image_url,bool errored,const SkBitmap & image)177 void OnDidDownloadFavicon(int id,
178 const GURL& image_url,
179 bool errored,
180 const SkBitmap& image) {
181 FaviconHelper::OnDidDownloadFavicon(id, image_url, errored, image);
182 }
183
184 protected:
UpdateFaviconMappingAndFetch(const GURL & page_url,const GURL & icon_url,history::IconType icon_type,CancelableRequestConsumerBase * consumer,FaviconService::FaviconDataCallback * callback)185 virtual void UpdateFaviconMappingAndFetch(
186 const GURL& page_url,
187 const GURL& icon_url,
188 history::IconType icon_type,
189 CancelableRequestConsumerBase* consumer,
190 FaviconService::FaviconDataCallback* callback) OVERRIDE {
191 history_handler_.reset(new HistoryRequestHandler(page_url, icon_url,
192 icon_type, callback));
193 }
194
GetFavicon(const GURL & icon_url,history::IconType icon_type,CancelableRequestConsumerBase * consumer,FaviconService::FaviconDataCallback * callback)195 virtual void GetFavicon(
196 const GURL& icon_url,
197 history::IconType icon_type,
198 CancelableRequestConsumerBase* consumer,
199 FaviconService::FaviconDataCallback* callback) OVERRIDE {
200 history_handler_.reset(new HistoryRequestHandler(GURL(), icon_url,
201 icon_type, callback));
202 }
203
GetFaviconForURL(const GURL & page_url,int icon_types,CancelableRequestConsumerBase * consumer,FaviconService::FaviconDataCallback * callback)204 virtual void GetFaviconForURL(
205 const GURL& page_url,
206 int icon_types,
207 CancelableRequestConsumerBase* consumer,
208 FaviconService::FaviconDataCallback* callback) OVERRIDE {
209 history_handler_.reset(new HistoryRequestHandler(page_url, GURL(),
210 icon_types, callback));
211 }
212
DownloadFavicon(const GURL & image_url,int image_size)213 virtual int DownloadFavicon(const GURL& image_url, int image_size) OVERRIDE {
214 download_id_++;
215 download_handler_.reset(new DownloadHandler(download_id_, image_url,
216 image_size, this));
217 return download_id_;
218 }
219
SetHistoryFavicon(const GURL & page_url,const GURL & icon_url,const std::vector<unsigned char> & image_data,history::IconType icon_type)220 virtual void SetHistoryFavicon(const GURL& page_url,
221 const GURL& icon_url,
222 const std::vector<unsigned char>& image_data,
223 history::IconType icon_type) OVERRIDE {
224 history_handler_.reset(new HistoryRequestHandler(page_url, icon_url,
225 icon_type, image_data, NULL));
226 }
227
GetFaviconService()228 virtual FaviconService* GetFaviconService() OVERRIDE {
229 // Just give none NULL value, so overridden methods can be hit.
230 return (FaviconService*)(1);
231 }
232
ShouldSaveFavicon(const GURL & url)233 virtual bool ShouldSaveFavicon(const GURL& url) OVERRIDE {
234 return true;
235 }
236
237 GURL page_url_;
238
239 GURL download_image_url_;
240 int download_image_size_;
241
242 private:
243 NavigationEntry entry_;
244
245 // The unique id of a download request. It will be returned to a
246 // FaviconHelper.
247 int download_id_;
248
249 TabContents* tab_contents_;
250 scoped_ptr<DownloadHandler> download_handler_;
251 scoped_ptr<HistoryRequestHandler> history_handler_;
252
253 DISALLOW_COPY_AND_ASSIGN(TestFaviconHelper);
254 };
255
256 namespace {
257
UpdateFaviconURL(FaviconHelper * helper,const std::vector<FaviconURL> urls)258 void DownloadHandler::UpdateFaviconURL(FaviconHelper* helper,
259 const std::vector<FaviconURL> urls) {
260 helper->OnUpdateFaviconURL(0, urls);
261 }
262
UpdateFaviconURL(const std::vector<FaviconURL> urls)263 void DownloadHandler::UpdateFaviconURL(const std::vector<FaviconURL> urls) {
264 UpdateFaviconURL(favicon_helper_, urls);
265 }
266
InvokeCallback()267 void DownloadHandler::InvokeCallback() {
268 favicon_helper_->OnDidDownloadFavicon(download_id_, image_url_, failed_,
269 bitmap_);
270 }
271
InvokeCallback()272 void HistoryRequestHandler::InvokeCallback() {
273 callback_->Run(0, favicon_data_);
274 }
275
276 class FaviconHelperTest : public RenderViewHostTestHarness {
277 };
278
TEST_F(FaviconHelperTest,GetFaviconFromHistory)279 TEST_F(FaviconHelperTest, GetFaviconFromHistory) {
280 const GURL page_url("http://www.google.com");
281 const GURL icon_url("http://www.google.com/favicon");
282
283 TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON);
284
285 helper.FetchFavicon(page_url);
286 HistoryRequestHandler* history_handler = helper.history_handler();
287 // Ensure the data given to history is correct.
288 ASSERT_TRUE(history_handler);
289 EXPECT_EQ(page_url, history_handler->page_url_);
290 EXPECT_EQ(GURL(), history_handler->icon_url_);
291 EXPECT_EQ(history::FAVICON, history_handler->icon_type_);
292
293 // Set valid icon data.
294 history_handler->favicon_data_.known_icon = true;
295 history_handler->favicon_data_.icon_type = history::FAVICON;
296 history_handler->favicon_data_.expired = false;
297 history_handler->favicon_data_.icon_url = icon_url;
298 scoped_refptr<RefCountedBytes> data = new RefCountedBytes();
299 FillBitmap(kFaviconSize, kFaviconSize, &data->data);
300 history_handler->favicon_data_.image_data = data;
301
302 // Send history response.
303 history_handler->InvokeCallback();
304 // Verify FaviconHelper status
305 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
306 EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url());
307
308 // Simulates update favicon url.
309 std::vector<FaviconURL> urls;
310 urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON));
311 DownloadHandler::UpdateFaviconURL(&helper, urls);
312
313 // Verify FaviconHelper status
314 EXPECT_EQ(1U, helper.urls().size());
315 ASSERT_TRUE(helper.current_candidate());
316 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
317 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
318
319 // Favicon shouldn't request to download icon.
320 DownloadHandler* download_handler = helper.download_handler();
321 ASSERT_FALSE(download_handler);
322 }
323
TEST_F(FaviconHelperTest,DownloadFavicon)324 TEST_F(FaviconHelperTest, DownloadFavicon) {
325 const GURL page_url("http://www.google.com");
326 const GURL icon_url("http://www.google.com/favicon");
327
328 TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON);
329
330 helper.FetchFavicon(page_url);
331 HistoryRequestHandler* history_handler = helper.history_handler();
332 // Ensure the data given to history is correct.
333 ASSERT_TRUE(history_handler);
334 EXPECT_EQ(page_url, history_handler->page_url_);
335 EXPECT_EQ(GURL(), history_handler->icon_url_);
336 EXPECT_EQ(history::FAVICON, history_handler->icon_type_);
337
338 // Set icon data expired
339 history_handler->favicon_data_.known_icon = true;
340 history_handler->favicon_data_.icon_type = history::FAVICON;
341 history_handler->favicon_data_.expired = true;
342 history_handler->favicon_data_.icon_url = icon_url;
343 // Send history response.
344 history_handler->InvokeCallback();
345 // Verify FaviconHelper status
346 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
347 EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url());
348
349 // Simulates update favicon url.
350 std::vector<FaviconURL> urls;
351 urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON));
352 DownloadHandler::UpdateFaviconURL(&helper, urls);
353
354 // Verify FaviconHelper status
355 EXPECT_EQ(1U, helper.urls().size());
356 ASSERT_TRUE(helper.current_candidate());
357 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
358 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
359
360 // Favicon should request to download icon now.
361 DownloadHandler* download_handler = helper.download_handler();
362 ASSERT_TRUE(download_handler);
363 // Verify the download request.
364 EXPECT_EQ(icon_url, download_handler->image_url_);
365 EXPECT_EQ(kFaviconSize, download_handler->image_size_);
366
367 // Reset the history_handler to verify whether favicon is set.
368 helper.set_history_handler(NULL);
369
370 // Smulates download done.
371 download_handler->InvokeCallback();
372
373 // New icon should be saved to history backend and navigation entry.
374 history_handler = helper.history_handler();
375 ASSERT_TRUE(history_handler);
376 EXPECT_EQ(icon_url, history_handler->icon_url_);
377 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
378 EXPECT_LT(0U, history_handler->image_data_.size());
379 EXPECT_EQ(page_url, history_handler->page_url_);
380
381 // Verify NavigationEntry.
382 EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url());
383 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
384 EXPECT_FALSE(helper.GetEntry()->favicon().bitmap().empty());
385 }
386
TEST_F(FaviconHelperTest,UpdateAndDownloadFavicon)387 TEST_F(FaviconHelperTest, UpdateAndDownloadFavicon) {
388 const GURL page_url("http://www.google.com");
389 const GURL icon_url("http://www.google.com/favicon");
390 const GURL new_icon_url("http://www.google.com/new_favicon");
391
392 TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON);
393
394 helper.FetchFavicon(page_url);
395 HistoryRequestHandler* history_handler = helper.history_handler();
396 // Ensure the data given to history is correct.
397 ASSERT_TRUE(history_handler);
398 EXPECT_EQ(page_url, history_handler->page_url_);
399 EXPECT_EQ(GURL(), history_handler->icon_url_);
400 EXPECT_EQ(history::FAVICON, history_handler->icon_type_);
401
402 // Set valid icon data.
403 history_handler->favicon_data_.known_icon = true;
404 history_handler->favicon_data_.icon_type = history::FAVICON;
405 history_handler->favicon_data_.expired = false;
406 history_handler->favicon_data_.icon_url = icon_url;
407 scoped_refptr<RefCountedBytes> data = new RefCountedBytes();
408 FillBitmap(kFaviconSize, kFaviconSize, &data->data);
409 history_handler->favicon_data_.image_data = data;
410
411 // Send history response.
412 history_handler->InvokeCallback();
413 // Verify FaviconHelper status.
414 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
415 EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url());
416
417 // Reset the history_handler to verify whether new icon is requested from
418 // history.
419 helper.set_history_handler(NULL);
420
421 // Simulates update with the different favicon url.
422 std::vector<FaviconURL> urls;
423 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
424 DownloadHandler::UpdateFaviconURL(&helper, urls);
425
426 // Verify FaviconHelper status.
427 EXPECT_EQ(1U, helper.urls().size());
428 ASSERT_TRUE(helper.current_candidate());
429 ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url);
430 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
431 // The favicon status's url should be updated.
432 ASSERT_EQ(new_icon_url, helper.GetEntry()->favicon().url());
433
434 // Favicon should be requested from history.
435 history_handler = helper.history_handler();
436 ASSERT_TRUE(history_handler);
437 EXPECT_EQ(new_icon_url, history_handler->icon_url_);
438 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
439 EXPECT_EQ(page_url, history_handler->page_url_);
440
441 // Simulate not find icon.
442 history_handler->favicon_data_.known_icon = false;
443 history_handler->InvokeCallback();
444
445 // Favicon should request to download icon now.
446 DownloadHandler* download_handler = helper.download_handler();
447 ASSERT_TRUE(download_handler);
448 // Verify the download request.
449 EXPECT_EQ(new_icon_url, download_handler->image_url_);
450 EXPECT_EQ(kFaviconSize, download_handler->image_size_);
451
452 // Reset the history_handler to verify whether favicon is set.
453 helper.set_history_handler(NULL);
454
455 // Smulates download done.
456 download_handler->InvokeCallback();
457
458 // New icon should be saved to history backend and navigation entry.
459 history_handler = helper.history_handler();
460 ASSERT_TRUE(history_handler);
461 EXPECT_EQ(new_icon_url, history_handler->icon_url_);
462 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
463 EXPECT_LT(0U, history_handler->image_data_.size());
464 EXPECT_EQ(page_url, history_handler->page_url_);
465
466 // Verify NavigationEntry.
467 EXPECT_EQ(new_icon_url, helper.GetEntry()->favicon().url());
468 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
469 EXPECT_FALSE(helper.GetEntry()->favicon().bitmap().empty());
470 }
471
TEST_F(FaviconHelperTest,UpdateFavicon)472 TEST_F(FaviconHelperTest, UpdateFavicon) {
473 const GURL page_url("http://www.google.com");
474 const GURL icon_url("http://www.google.com/favicon");
475 const GURL new_icon_url("http://www.google.com/new_favicon");
476
477 TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON);
478
479 helper.FetchFavicon(page_url);
480 HistoryRequestHandler* history_handler = helper.history_handler();
481 // Ensure the data given to history is correct.
482 ASSERT_TRUE(history_handler);
483 EXPECT_EQ(page_url, history_handler->page_url_);
484 EXPECT_EQ(GURL(), history_handler->icon_url_);
485 EXPECT_EQ(history::FAVICON, history_handler->icon_type_);
486
487 // Set valid icon data.
488 history_handler->favicon_data_.known_icon = true;
489 history_handler->favicon_data_.icon_type = history::FAVICON;
490 history_handler->favicon_data_.expired = false;
491 history_handler->favicon_data_.icon_url = icon_url;
492 scoped_refptr<RefCountedBytes> data = new RefCountedBytes();
493 FillBitmap(kFaviconSize, kFaviconSize, &data->data);
494 history_handler->favicon_data_.image_data = data;
495
496 // Send history response.
497 history_handler->InvokeCallback();
498 // Verify FaviconHelper status.
499 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
500 EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url());
501
502 // Reset the history_handler to verify whether new icon is requested from
503 // history.
504 helper.set_history_handler(NULL);
505
506 // Simulates update with the different favicon url.
507 std::vector<FaviconURL> urls;
508 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
509 DownloadHandler::UpdateFaviconURL(&helper, urls);
510
511 // Verify FaviconHelper status.
512 EXPECT_EQ(1U, helper.urls().size());
513 ASSERT_TRUE(helper.current_candidate());
514 ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url);
515 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
516 // The favicon status's url should be updated.
517 ASSERT_EQ(new_icon_url, helper.GetEntry()->favicon().url());
518
519 // Favicon should be requested from history.
520 history_handler = helper.history_handler();
521 ASSERT_TRUE(history_handler);
522 EXPECT_EQ(new_icon_url, history_handler->icon_url_);
523 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
524 EXPECT_EQ(page_url, history_handler->page_url_);
525
526 // Simulate find icon.
527 history_handler->favicon_data_.known_icon = true;
528 history_handler->favicon_data_.icon_type = history::FAVICON;
529 history_handler->favicon_data_.expired = false;
530 history_handler->favicon_data_.icon_url = new_icon_url;
531 history_handler->favicon_data_.image_data = data;
532 history_handler->InvokeCallback();
533
534 // Shouldn't request download favicon
535 EXPECT_FALSE(helper.download_handler());
536
537 // Verify the favicon status.
538 EXPECT_EQ(new_icon_url, helper.GetEntry()->favicon().url());
539 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
540 EXPECT_FALSE(helper.GetEntry()->favicon().bitmap().empty());
541 }
542
TEST_F(FaviconHelperTest,Download2ndFaviconURLCandidate)543 TEST_F(FaviconHelperTest, Download2ndFaviconURLCandidate) {
544 const GURL page_url("http://www.google.com");
545 const GURL icon_url("http://www.google.com/favicon");
546 const GURL new_icon_url("http://www.google.com/new_favicon");
547
548 TestFaviconHelper helper(page_url, contents(), FaviconHelper::TOUCH);
549
550 helper.FetchFavicon(page_url);
551 HistoryRequestHandler* history_handler = helper.history_handler();
552 // Ensure the data given to history is correct.
553 ASSERT_TRUE(history_handler);
554 EXPECT_EQ(page_url, history_handler->page_url_);
555 EXPECT_EQ(GURL(), history_handler->icon_url_);
556 EXPECT_EQ(history::TOUCH_PRECOMPOSED_ICON | history::TOUCH_ICON,
557 history_handler->icon_type_);
558
559 // Icon not found.
560 history_handler->favicon_data_.known_icon = false;
561 // Send history response.
562 history_handler->InvokeCallback();
563 // Verify FaviconHelper status.
564 EXPECT_FALSE(helper.GetEntry()->favicon().is_valid());
565 EXPECT_EQ(GURL(), helper.GetEntry()->favicon().url());
566
567 // Reset the history_handler to verify whether new icon is requested from
568 // history.
569 helper.set_history_handler(NULL);
570
571 // Simulates update with the different favicon url.
572 std::vector<FaviconURL> urls;
573 urls.push_back(FaviconURL(icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON));
574 urls.push_back(FaviconURL(new_icon_url, FaviconURL::TOUCH_ICON));
575 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
576
577 DownloadHandler::UpdateFaviconURL(&helper, urls);
578
579 // Verify FaviconHelper status.
580 EXPECT_EQ(2U, helper.urls().size());
581 ASSERT_TRUE(helper.current_candidate());
582 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
583 ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON,
584 helper.current_candidate()->icon_type);
585
586 // Favicon should be requested from history.
587 history_handler = helper.history_handler();
588 ASSERT_TRUE(history_handler);
589 EXPECT_EQ(icon_url, history_handler->icon_url_);
590 EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_);
591 EXPECT_EQ(page_url, history_handler->page_url_);
592
593 // Simulate not find icon.
594 history_handler->favicon_data_.known_icon = false;
595 history_handler->InvokeCallback();
596
597 // Should request download favicon.
598 DownloadHandler* download_handler = helper.download_handler();
599 EXPECT_TRUE(download_handler);
600 // Verify the download request.
601 EXPECT_EQ(icon_url, download_handler->image_url_);
602 EXPECT_EQ(0, download_handler->image_size_);
603
604 // Reset the history_handler to verify whether favicon is request from
605 // history.
606 helper.set_history_handler(NULL);
607 // Smulates download failed.
608 download_handler->failed_ = true;
609 download_handler->InvokeCallback();
610
611 // Left 1 url.
612 EXPECT_EQ(1U, helper.urls().size());
613 ASSERT_TRUE(helper.current_candidate());
614 EXPECT_EQ(new_icon_url, helper.current_candidate()->icon_url);
615 EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type);
616
617 // Favicon should be requested from history.
618 history_handler = helper.history_handler();
619 ASSERT_TRUE(history_handler);
620 EXPECT_EQ(new_icon_url, history_handler->icon_url_);
621 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
622 EXPECT_EQ(page_url, history_handler->page_url_);
623
624 // Reset download handler
625 helper.set_download_handler(NULL);
626
627 // Smulates getting a expired icon from history.
628 history_handler->favicon_data_.known_icon = true;
629 history_handler->favicon_data_.icon_type = history::TOUCH_ICON;
630 history_handler->favicon_data_.expired = true;
631 history_handler->favicon_data_.icon_url = new_icon_url;
632 scoped_refptr<RefCountedBytes> data = new RefCountedBytes();
633 FillBitmap(kFaviconSize, kFaviconSize, &data->data);
634 history_handler->favicon_data_.image_data = data;
635 history_handler->InvokeCallback();
636
637 // Verify the download request.
638 download_handler = helper.download_handler();
639 EXPECT_TRUE(download_handler);
640 EXPECT_EQ(new_icon_url, download_handler->image_url_);
641 EXPECT_EQ(0, download_handler->image_size_);
642
643 helper.set_history_handler(NULL);
644
645 // Simulates icon being downloaded.
646 download_handler->InvokeCallback();
647
648 // New icon should be saved to history backend.
649 history_handler = helper.history_handler();
650 ASSERT_TRUE(history_handler);
651 EXPECT_EQ(new_icon_url, history_handler->icon_url_);
652 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
653 EXPECT_LT(0U, history_handler->image_data_.size());
654 EXPECT_EQ(page_url, history_handler->page_url_);
655 }
656
TEST_F(FaviconHelperTest,UpdateDuringDownloading)657 TEST_F(FaviconHelperTest, UpdateDuringDownloading) {
658 const GURL page_url("http://www.google.com");
659 const GURL icon_url("http://www.google.com/favicon");
660 const GURL new_icon_url("http://www.google.com/new_favicon");
661
662 TestFaviconHelper helper(page_url, contents(), FaviconHelper::TOUCH);
663
664 helper.FetchFavicon(page_url);
665 HistoryRequestHandler* history_handler = helper.history_handler();
666 // Ensure the data given to history is correct.
667 ASSERT_TRUE(history_handler);
668 EXPECT_EQ(page_url, history_handler->page_url_);
669 EXPECT_EQ(GURL(), history_handler->icon_url_);
670 EXPECT_EQ(history::TOUCH_PRECOMPOSED_ICON | history::TOUCH_ICON,
671 history_handler->icon_type_);
672
673 // Icon not found.
674 history_handler->favicon_data_.known_icon = false;
675 // Send history response.
676 history_handler->InvokeCallback();
677 // Verify FaviconHelper status.
678 EXPECT_FALSE(helper.GetEntry()->favicon().is_valid());
679 EXPECT_EQ(GURL(), helper.GetEntry()->favicon().url());
680
681 // Reset the history_handler to verify whether new icon is requested from
682 // history.
683 helper.set_history_handler(NULL);
684
685 // Simulates update with the different favicon url.
686 std::vector<FaviconURL> urls;
687 urls.push_back(FaviconURL(icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON));
688 urls.push_back(FaviconURL(new_icon_url, FaviconURL::TOUCH_ICON));
689 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
690
691 DownloadHandler::UpdateFaviconURL(&helper, urls);
692
693 // Verify FaviconHelper status.
694 EXPECT_EQ(2U, helper.urls().size());
695 ASSERT_TRUE(helper.current_candidate());
696 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
697 ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON,
698 helper.current_candidate()->icon_type);
699
700 // Favicon should be requested from history.
701 history_handler = helper.history_handler();
702 ASSERT_TRUE(history_handler);
703 EXPECT_EQ(icon_url, history_handler->icon_url_);
704 EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_);
705 EXPECT_EQ(page_url, history_handler->page_url_);
706
707 // Simulate not find icon.
708 history_handler->favicon_data_.known_icon = false;
709 history_handler->InvokeCallback();
710
711 // Should request download favicon.
712 DownloadHandler* download_handler = helper.download_handler();
713 EXPECT_TRUE(download_handler);
714 // Verify the download request.
715 EXPECT_EQ(icon_url, download_handler->image_url_);
716 EXPECT_EQ(0, download_handler->image_size_);
717
718 // Reset the history_handler to verify whether favicon is request from
719 // history.
720 helper.set_history_handler(NULL);
721 const GURL latest_icon_url("http://www.google.com/latest_favicon");
722 std::vector<FaviconURL> latest_urls;
723 latest_urls.push_back(FaviconURL(latest_icon_url, FaviconURL::TOUCH_ICON));
724 DownloadHandler::UpdateFaviconURL(&helper, latest_urls);
725 EXPECT_EQ(1U, helper.urls().size());
726 EXPECT_EQ(latest_icon_url, helper.current_candidate()->icon_url);
727 EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type);
728
729 // Whether new icon is requested from history
730 history_handler = helper.history_handler();
731 ASSERT_TRUE(history_handler);
732 EXPECT_EQ(latest_icon_url, history_handler->icon_url_);
733 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
734 EXPECT_EQ(page_url, history_handler->page_url_);
735
736 // Reset the history_handler to verify whether favicon is request from
737 // history.
738 // Save the callback for late use.
739 FaviconService::FaviconDataCallback* callback = history_handler->callback_;
740 // Prevent the callback from being released.
741 history_handler->callback_ = NULL;
742 helper.set_history_handler(NULL);
743
744 // Smulates download succeed.
745 download_handler->InvokeCallback();
746 // The downloaded icon should be thrown away as there is faviocn update.
747 EXPECT_FALSE(helper.history_handler());
748
749 helper.set_download_handler(NULL);
750
751 // Smulates getting the icon from history.
752 scoped_ptr<HistoryRequestHandler> handler;
753 handler.reset(new HistoryRequestHandler(page_url, latest_icon_url,
754 history::TOUCH_ICON, callback));
755 handler->favicon_data_.known_icon = true;
756 handler->favicon_data_.expired = false;
757 handler->favicon_data_.icon_type = history::TOUCH_ICON;
758 handler->favicon_data_.icon_url = latest_icon_url;
759 scoped_refptr<RefCountedBytes> data = new RefCountedBytes();
760 FillBitmap(kFaviconSize, kFaviconSize, &data->data);
761 handler->favicon_data_.image_data = data;
762
763 handler->InvokeCallback();
764
765 // No download request.
766 EXPECT_FALSE(helper.download_handler());
767 }
768
769 } // namespace.
770