 Chromium Code Reviews
 Chromium Code Reviews Issue 64853004:
  Use high resolution icons where possible for streamlined hosted app icons.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@browser_experiment_create_app_from_page
    
  
    Issue 64853004:
  Use high resolution icons where possible for streamlined hosted app icons.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@browser_experiment_create_app_from_page| Index: chrome/browser/ui/web_applications/hosted_app_tab_helper.cc | 
| diff --git a/chrome/browser/ui/web_applications/hosted_app_tab_helper.cc b/chrome/browser/ui/web_applications/hosted_app_tab_helper.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..47edc64f8025cb7462b474ec1273ab799b5f077f | 
| --- /dev/null | 
| +++ b/chrome/browser/ui/web_applications/hosted_app_tab_helper.cc | 
| @@ -0,0 +1,155 @@ | 
| +// Copyright 2013 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "chrome/browser/ui/web_applications/hosted_app_tab_helper.h" | 
| + | 
| +#include "base/strings/utf_string_conversions.h" | 
| +#include "chrome/browser/extensions/crx_installer.h" | 
| +#include "chrome/browser/favicon/favicon_tab_helper.h" | 
| +#include "chrome/browser/profiles/profile.h" | 
| +#include "chrome/browser/ui/browser.h" | 
| +#include "chrome/common/web_application_info.h" | 
| +#include "content/public/browser/web_contents.h" | 
| +#include "content/public/common/favicon_url.h" | 
| + | 
| +DEFINE_WEB_CONTENTS_USER_DATA_KEY(HostedAppTabHelper); | 
| + | 
| +HostedAppTabHelper::HostedAppTabHelper(content::WebContents* web_contents) | 
| + : content::WebContentsObserver(web_contents) { | 
| +} | 
| + | 
| +HostedAppTabHelper::~HostedAppTabHelper() { | 
| +} | 
| + | 
| +void HostedAppTabHelper::CreateHostedApp( | 
| + const WebApplicationInfo& web_app_info) { | 
| + // If a hosted app creation request is already pending, ignore subsequent | 
| + // requests. | 
| + if (web_app_info_) | 
| + return; | 
| + | 
| + web_app_info_.reset(new WebApplicationInfo(web_app_info)); | 
| + | 
| + // It's possible for |favicon_url_candidates_| to be populated after this is | 
| + // called. DidUpdateFaviconURL() will resume the app creation process in this | 
| + // case. | 
| + if (!favicon_url_candidates_) | 
| + return; | 
| + | 
| + FetchIcons(); | 
| 
pkotwicz
2013/11/25 01:21:28
Can we add a method to FaviconTabHelper to get the
 | 
| +} | 
| + | 
| +void HostedAppTabHelper::FetchIcons() { | 
| + // Download icons from the favicon url candidates | 
| + for (std::set<GURL>::const_iterator it = favicon_url_candidates_->begin(); | 
| + it != favicon_url_candidates_->end(); ++it) | 
| + in_progress_requests_.insert(DownloadImage(*it)); | 
| + | 
| + // If there are extra icon URLs in the WebApplicationInfo, download them. | 
| + for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it = | 
| + web_app_info_->icons.begin(); it != web_app_info_->icons.end(); | 
| + ++it) { | 
| + if (it->url.is_valid() && favicon_url_candidates_->count(it->url) == 0) | 
| + in_progress_requests_.insert(DownloadImage(it->url)); | 
| + } | 
| + | 
| + // If no downloads are pending, we can proceed directly to creating the hosted | 
| + // app. | 
| + if (in_progress_requests_.empty()) | 
| + FinishCreateHostedApp(); | 
| +} | 
| + | 
| +void HostedAppTabHelper::FinishCreateHostedApp() { | 
| + if (web_app_info_->app_url.is_empty()) | 
| + web_app_info_->app_url = web_contents()->GetURL(); | 
| + | 
| + if (web_app_info_->title.empty()) | 
| + web_app_info_->title = web_contents()->GetTitle(); | 
| + if (web_app_info_->title.empty()) | 
| + web_app_info_->title = UTF8ToUTF16(web_app_info_->app_url.spec()); | 
| + | 
| + web_app_info_->urls.push_back(web_app_info_->app_url); | 
| + web_app_info_->is_bookmark_app = true; | 
| + | 
| + // Add the downloaded icons. | 
| + for (gfx::ImageFamily::const_iterator it = image_family_.begin(); | 
| + it != image_family_.end(); ++it) { | 
| + if (!it->IsEmpty()) { | 
| + WebApplicationInfo::IconInfo icon_info; | 
| + icon_info.data = it->AsBitmap(); | 
| + icon_info.width = icon_info.data.width(); | 
| + icon_info.height = icon_info.data.height(); | 
| + web_app_info_->icons.push_back(icon_info); | 
| + } | 
| + } | 
| + | 
| + Profile* profile = | 
| + Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | 
| + scoped_refptr<extensions::CrxInstaller> installer( | 
| + extensions::CrxInstaller::CreateSilent(profile->GetExtensionService())); | 
| + installer->set_error_on_unsupported_requirements(true); | 
| + installer->InstallWebApp(*web_app_info_); | 
| + | 
| + web_app_info_.reset(); | 
| +} | 
| + | 
| +void HostedAppTabHelper::DidDownloadFavicon( | 
| + int id, | 
| + int http_status_code, | 
| + const GURL& image_url, | 
| + const std::vector<SkBitmap>& bitmaps, | 
| + const std::vector<gfx::Size>& original_bitmap_sizes) { | 
| + // Request canceled by DidUpdateFaviconURL() or DidNavigateMainFrame(). | 
| + if (in_progress_requests_.erase(id) == 0) | 
| + return; | 
| + for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin(); | 
| + it != bitmaps.end(); ++it) { | 
| + image_family_.Add(gfx::Image::CreateFrom1xBitmap(*it)); | 
| + } | 
| + | 
| + // Once all requests have been resolved, perform post-download tasks. | 
| + if (!in_progress_requests_.empty()) | 
| + return; | 
| + | 
| + if (web_app_info_) | 
| + FinishCreateHostedApp(); | 
| +} | 
| + | 
| +// content::WebContentsObserver overrides: | 
| +void HostedAppTabHelper::DidNavigateMainFrame( | 
| + const content::LoadCommittedDetails& details, | 
| + const content::FrameNavigateParams& params) { | 
| + // Clear all pending requests. | 
| + favicon_url_candidates_.reset(); | 
| + in_progress_requests_.clear(); | 
| + web_app_info_.reset(); | 
| + image_family_.clear(); | 
| +} | 
| + | 
| +void HostedAppTabHelper::DidUpdateFaviconURL( | 
| + int32 page_id, | 
| + const std::vector<content::FaviconURL>& candidates) { | 
| + in_progress_requests_.clear(); | 
| + image_family_.clear(); | 
| + favicon_url_candidates_.reset(new std::set<GURL>()); | 
| + for (std::vector<content::FaviconURL>::const_iterator it = candidates.begin(); | 
| + it != candidates.end(); ++it) { | 
| + if (it->icon_type != content::FaviconURL::INVALID_ICON) | 
| + favicon_url_candidates_->insert(it->icon_url); | 
| + } | 
| + | 
| + // If |web_app_info_| is populated, we are in the middle of creating a hosted | 
| + // app. Resume this process. | 
| + if (web_app_info_) | 
| + FetchIcons(); | 
| +} | 
| + | 
| +int HostedAppTabHelper::DownloadImage(const GURL& url) { | 
| + return web_contents()->DownloadImage( | 
| + url, | 
| + true, // is_favicon | 
| + 0, // no max size | 
| + base::Bind(&HostedAppTabHelper::DidDownloadFavicon, | 
| + base::Unretained(this))); | 
| +} |