15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/ash/launcher/launcher_favicon_loader.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shelf/shelf_constants.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_observer.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using content::WebContents; 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using content::WebContentsObserver; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Observer class to determine when favicons have completed loading. 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ContentsObserver : public WebContentsObserver { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) explicit ContentsObserver(WebContents* web_contents) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : WebContentsObserver(web_contents), 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) loaded_(false), 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_favicons_(false) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ContentsObserver() {} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Reset() { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_favicons_ = false; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool loaded() const { return loaded_; } 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool got_favicons() const { return got_favicons_; } 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // WebContentsObserver overrides. 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void DidFinishLoad(content::RenderFrameHost* render_frame_host, 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const GURL& validated_url) OVERRIDE { 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) loaded_ = true; 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual void DidUpdateFaviconURL( 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<content::FaviconURL>& candidates) OVERRIDE { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!candidates.empty()) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_favicons_ = true; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool loaded_; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool got_favicons_; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class LauncherFaviconLoaderBrowsertest 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : public InProcessBrowserTest, 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public LauncherFaviconLoader::Delegate { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LauncherFaviconLoaderBrowsertest() : favicon_updated_(false) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~LauncherFaviconLoaderBrowsertest() { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void SetUpOnMainThread() OVERRIDE { 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebContents* web_contents = 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser()->tab_strip_model()->GetActiveWebContents(); 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) contents_observer_.reset(new ContentsObserver(web_contents)); 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_loader_.reset(new LauncherFaviconLoader(this, web_contents)); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // LauncherFaviconLoader::Delegate overrides: 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void FaviconUpdated() OVERRIDE { 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_updated_ = true; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool NavigateTo(const char* url) { 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string url_path = base::StringPrintf("files/ash/launcher/%s", url); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ui_test_utils::NavigateToURL(browser(), test_server()->GetURL(url_path)); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool WaitForContentsLoaded() { 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int64 max_seconds = 10; 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Time start_time = base::Time::Now(); 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (!(contents_observer_->loaded() && 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) contents_observer_->got_favicons())) { 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::RunAllPendingInMessageLoop(); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::TimeDelta delta = base::Time::Now() - start_time; 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (delta.InSeconds() >= max_seconds) { 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << " WaitForContentsLoaded timed out."; 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool WaitForFaviconUpdated() { 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int64 max_seconds = 10; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time start_time = base::Time::Now(); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (favicon_loader_->HasPendingDownloads()) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RunAllPendingInMessageLoop(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta delta = base::Time::Now() - start_time; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delta.InSeconds() >= max_seconds) { 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << " WaitForFaviconDownlads timed out."; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void ResetDownloads() { 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) contents_observer_->Reset(); 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool favicon_updated_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ContentsObserver> contents_observer_; 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<LauncherFaviconLoader> favicon_loader_; 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(LauncherFaviconLoaderBrowsertest); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(LauncherFaviconLoaderBrowsertest, SmallLauncherIcon) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(test_server()->Start()); 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(NavigateTo("launcher-smallfavicon.html")); 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(WaitForContentsLoaded()); 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(WaitForFaviconUpdated()); 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No large favicons specified, bitmap should be empty. 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(favicon_loader_->GetFavicon().empty()); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(LauncherFaviconLoaderBrowsertest, LargeLauncherIcon) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(test_server()->Start()); 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(NavigateTo("launcher-largefavicon.html")); 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(WaitForContentsLoaded()); 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(WaitForFaviconUpdated()); 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(favicon_loader_->GetFavicon().empty()); 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(128, favicon_loader_->GetFavicon().height()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(LauncherFaviconLoaderBrowsertest, ManyLauncherIcons) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(test_server()->Start()); 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(NavigateTo("launcher-manyfavicon.html")); 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(WaitForContentsLoaded()); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(WaitForFaviconUpdated()); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(favicon_loader_->GetFavicon().empty()); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When multiple favicons are present, the correctly sized icon should be 158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // chosen. The icons are sized assuming ash::kShelfSize < 128. 159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EXPECT_GT(128, ash::kShelfSize); 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(48, favicon_loader_->GetFavicon().height()); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(LauncherFaviconLoaderBrowsertest, ChangeLauncherIcons) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(test_server()->Start()); 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(NavigateTo("launcher-manyfavicon.html")); 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(WaitForContentsLoaded()); 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(WaitForFaviconUpdated()); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(favicon_loader_->GetFavicon().empty()); 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(48, favicon_loader_->GetFavicon().height()); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_NO_FATAL_FAILURE(ResetDownloads()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(NavigateTo("launcher-smallfavicon.html")); 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(WaitForContentsLoaded()); 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(WaitForFaviconUpdated()); 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(favicon_loader_->GetFavicon().empty()); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_NO_FATAL_FAILURE(ResetDownloads()); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(NavigateTo("launcher-largefavicon.html")); 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(WaitForContentsLoaded()); 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(WaitForFaviconUpdated()); 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(favicon_loader_->GetFavicon().empty()); 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(128, favicon_loader_->GetFavicon().height()); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 187