| 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..f08ea215557b324016c0f570f029d8e0f17e048b
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/web_applications/hosted_app_tab_helper.cc
|
| @@ -0,0 +1,179 @@
|
| +// 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/web_applications/hosted_app_tab_helper_delegate.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),
|
| + fetch_icons_immediately_(false),
|
| + delegate_(NULL) {
|
| +}
|
| +
|
| +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;
|
| +
|
| + FetchIconsIfNecessaryForCreateHostedApp();
|
| +}
|
| +
|
| +void HostedAppTabHelper::SetDelegate(HostedAppTabHelperDelegate* delegate) {
|
| + delegate_ = delegate;
|
| +#if defined(OS_WIN)
|
| + // On Windows the icons are needed for the window icon which should be fetched
|
| + // as soon as we have the favicon URLs.
|
| + fetch_icons_immediately_ = true;
|
| +#endif
|
| +}
|
| +
|
| +void HostedAppTabHelper::FetchIcons() {
|
| + for (std::set<GURL>::const_iterator it = favicon_url_candidates_->begin();
|
| + it != favicon_url_candidates_->end(); ++it)
|
| + in_progress_requests_.insert(DownloadImage(*it));
|
| +
|
| +}
|
| +
|
| +void HostedAppTabHelper::FetchIconsIfNecessaryForCreateHostedApp() {
|
| + // If the delegate doesn't need the window icon, we wouldn't have fetched the
|
| + // icons yet.
|
| + if (!fetch_icons_immediately_)
|
| + FetchIcons();
|
| +
|
| + // 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 (delegate_)
|
| + delegate_->OnWindowIconLoaded(web_contents());
|
| +
|
| + if (web_app_info_)
|
| + FinishCreateHostedApp();
|
| +}
|
| +
|
| +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)));
|
| +}
|
| +
|
| +// 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 (fetch_icons_immediately_)
|
| + FetchIcons();
|
| +
|
| + // If |web_app_info_| is populated, we are in the middle of creating a hosted
|
| + // app. Resume this process.
|
| + if (web_app_info_)
|
| + FetchIconsIfNecessaryForCreateHostedApp();
|
| +}
|
|
|