• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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