diff options
Diffstat (limited to 'chrome/browser/ui/metro_pin_tab_helper_win.cc')
-rw-r--r-- | chrome/browser/ui/metro_pin_tab_helper_win.cc | 463 |
1 files changed, 0 insertions, 463 deletions
diff --git a/chrome/browser/ui/metro_pin_tab_helper_win.cc b/chrome/browser/ui/metro_pin_tab_helper_win.cc deleted file mode 100644 index 2506a004..0000000 --- a/chrome/browser/ui/metro_pin_tab_helper_win.cc +++ /dev/null @@ -1,463 +0,0 @@ -// Copyright (c) 2012 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/metro_pin_tab_helper_win.h" - -#include <stdint.h> - -#include <set> - -#include "base/base_paths.h" -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/ref_counted_memory.h" -#include "base/metrics/histogram.h" -#include "base/path_service.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/win/metro.h" -#include "chrome/common/chrome_paths.h" -#include "components/favicon/content/content_favicon_driver.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/web_contents.h" -#include "crypto/sha2.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/codec/png_codec.h" -#include "ui/gfx/color_analysis.h" -#include "ui/gfx/color_utils.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gfx/image/image.h" - -DEFINE_WEB_CONTENTS_USER_DATA_KEY(MetroPinTabHelper); - -namespace { - -// Histogram name for site-specific tile pinning metrics. -const char kMetroPinMetric[] = "Metro.SecondaryTilePin"; - -// Generate an ID for the tile based on |url_str|. The ID is simply a hash of -// the URL. -base::string16 GenerateTileId(const base::string16& url_str) { - uint8_t hash[crypto::kSHA256Length]; - crypto::SHA256HashString(base::UTF16ToUTF8(url_str), hash, sizeof(hash)); - std::string hash_str = base::HexEncode(hash, sizeof(hash)); - return base::UTF8ToUTF16(hash_str); -} - -// Get the path of the directory to store the tile logos in. -base::FilePath GetTileImagesDir() { - base::FilePath tile_images_dir; - if (!PathService::Get(chrome::DIR_USER_DATA, &tile_images_dir)) - return base::FilePath(); - - tile_images_dir = tile_images_dir.Append(L"TileImages"); - if (!base::DirectoryExists(tile_images_dir) && - !base::CreateDirectory(tile_images_dir)) - return base::FilePath(); - - return tile_images_dir; -} - -// For the given |image| and |tile_id|, try to create a site specific logo in -// |logo_dir|. The path of any created logo is returned in |logo_path|. Return -// value indicates whether a site specific logo was created. -bool CreateSiteSpecificLogo(const SkBitmap& bitmap, - const base::string16& tile_id, - const base::FilePath& logo_dir, - base::FilePath* logo_path) { - const int kLogoWidth = 120; - const int kLogoHeight = 120; - const int kBoxWidth = 40; - const int kBoxHeight = 40; - const int kCaptionHeight = 20; - const double kBoxFade = 0.75; - - if (bitmap.isNull()) - return false; - - // Fill the tile logo with the dominant color of the favicon bitmap. - SkColor dominant_color = color_utils::CalculateKMeanColorOfBitmap(bitmap); - SkPaint paint; - paint.setColor(dominant_color); - gfx::Canvas canvas(gfx::Size(kLogoWidth, kLogoHeight), 1.0f, - true); - canvas.DrawRect(gfx::Rect(0, 0, kLogoWidth, kLogoHeight), paint); - - // Now paint a faded square for the favicon to go in. - color_utils::HSL shift = {-1, -1, kBoxFade}; - paint.setColor(color_utils::HSLShift(dominant_color, shift)); - int box_left = (kLogoWidth - kBoxWidth) / 2; - int box_top = (kLogoHeight - kCaptionHeight - kBoxHeight) / 2; - canvas.DrawRect(gfx::Rect(box_left, box_top, kBoxWidth, kBoxHeight), paint); - - // Now paint the favicon into the tile, leaving some room at the bottom for - // the caption. - int left = (kLogoWidth - bitmap.width()) / 2; - int top = (kLogoHeight - kCaptionHeight - bitmap.height()) / 2; - canvas.DrawImageInt(gfx::ImageSkia::CreateFrom1xBitmap(bitmap), left, top); - - SkBitmap logo_bitmap = canvas.ExtractImageRep().sk_bitmap(); - std::vector<unsigned char> logo_png; - if (!gfx::PNGCodec::EncodeBGRASkBitmap(logo_bitmap, true, &logo_png)) - return false; - - *logo_path = logo_dir.Append(tile_id).ReplaceExtension(L".png"); - return base::WriteFile(*logo_path, - reinterpret_cast<char*>(&logo_png[0]), - logo_png.size()) > 0; -} - -// Get the path to the backup logo. If the backup logo already exists in -// |logo_dir|, it will be used, otherwise it will be copied out of the install -// folder. (The version in the install folder is not used as it may disappear -// after an upgrade, causing tiles to lose their images if Windows rebuilds -// its tile image cache.) -// The path to the logo is returned in |logo_path|, with the return value -// indicating success. -bool GetPathToBackupLogo(const base::FilePath& logo_dir, - base::FilePath* logo_path) { - const wchar_t kDefaultLogoFileName[] = L"SecondaryTile.png"; - *logo_path = logo_dir.Append(kDefaultLogoFileName); - if (base::PathExists(*logo_path)) - return true; - - base::FilePath default_logo_path; - if (!PathService::Get(base::DIR_MODULE, &default_logo_path)) - return false; - - default_logo_path = default_logo_path.Append(kDefaultLogoFileName); - return base::CopyFile(default_logo_path, *logo_path); -} - -// UMA reporting callback for site-specific secondary tile creation. -void PinPageReportUmaCallback( - base::win::MetroSecondaryTilePinUmaResult result) { - UMA_HISTOGRAM_ENUMERATION(kMetroPinMetric, - result, - base::win::METRO_PIN_STATE_LIMIT); -} - -// The PinPageTaskRunner class performs the necessary FILE thread actions to -// pin a page, such as generating or copying the tile image file. When it -// has performed these actions it will send the tile creation request to the -// metro driver. -class PinPageTaskRunner : public base::RefCountedThreadSafe<PinPageTaskRunner> { - public: - // Creates a task runner for the pinning operation with the given details. - // |favicon| can be a null image (i.e. favicon.isNull() can be true), in - // which case the backup tile image will be used. - PinPageTaskRunner(const base::string16& title, - const base::string16& url, - const SkBitmap& favicon); - - void Run(); - void RunOnFileThread(); - - private: - ~PinPageTaskRunner() {} - - // Details of the page being pinned. - const base::string16 title_; - const base::string16 url_; - SkBitmap favicon_; - - friend class base::RefCountedThreadSafe<PinPageTaskRunner>; - DISALLOW_COPY_AND_ASSIGN(PinPageTaskRunner); -}; - -PinPageTaskRunner::PinPageTaskRunner(const base::string16& title, - const base::string16& url, - const SkBitmap& favicon) - : title_(title), - url_(url), - favicon_(favicon) {} - -void PinPageTaskRunner::Run() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - content::BrowserThread::PostTask( - content::BrowserThread::FILE, - FROM_HERE, - base::Bind(&PinPageTaskRunner::RunOnFileThread, this)); -} - -void PinPageTaskRunner::RunOnFileThread() { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); - - base::string16 tile_id = GenerateTileId(url_); - base::FilePath logo_dir = GetTileImagesDir(); - if (logo_dir.empty()) { - LOG(ERROR) << "Could not create directory to store tile image."; - return; - } - - base::FilePath logo_path; - if (!CreateSiteSpecificLogo(favicon_, tile_id, logo_dir, &logo_path) && - !GetPathToBackupLogo(logo_dir, &logo_path)) { - LOG(ERROR) << "Count not get path to logo tile."; - return; - } - - UMA_HISTOGRAM_ENUMERATION(kMetroPinMetric, - base::win::METRO_PIN_LOGO_READY, - base::win::METRO_PIN_STATE_LIMIT); - - HMODULE metro_module = base::win::GetMetroModule(); - if (!metro_module) - return; - - base::win::MetroPinToStartScreen metro_pin_to_start_screen = - reinterpret_cast<base::win::MetroPinToStartScreen>( - ::GetProcAddress(metro_module, "MetroPinToStartScreen")); - if (!metro_pin_to_start_screen) { - NOTREACHED(); - return; - } - - metro_pin_to_start_screen(tile_id, - title_, - url_, - logo_path, - base::Bind(&PinPageReportUmaCallback)); -} - -} // namespace - -class MetroPinTabHelper::FaviconChooser { - public: - FaviconChooser(MetroPinTabHelper* helper, - const base::string16& title, - const base::string16& url, - const SkBitmap& history_bitmap); - - ~FaviconChooser() {} - - // Pin the page on the FILE thread using the current |best_candidate_| and - // delete the FaviconChooser. - void UseChosenCandidate(); - - // Update the |best_candidate_| with the newly downloaded favicons provided. - void UpdateCandidate(int id, - const GURL& image_url, - const std::vector<SkBitmap>& bitmaps); - - void AddPendingRequest(int request_id); - - private: - // The tab helper that this chooser is operating for. - MetroPinTabHelper* helper_; - - // Title and URL of the page being pinned. - const base::string16 title_; - const base::string16 url_; - - // The best candidate we have so far for the current pin operation. - SkBitmap best_candidate_; - - // Outstanding favicon download requests. - std::set<int> in_progress_requests_; - - DISALLOW_COPY_AND_ASSIGN(FaviconChooser); -}; - -MetroPinTabHelper::FaviconChooser::FaviconChooser( - MetroPinTabHelper* helper, - const base::string16& title, - const base::string16& url, - const SkBitmap& history_bitmap) - : helper_(helper), - title_(title), - url_(url), - best_candidate_(history_bitmap) {} - -void MetroPinTabHelper::FaviconChooser::UseChosenCandidate() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - scoped_refptr<PinPageTaskRunner> runner( - new PinPageTaskRunner(title_, url_, best_candidate_)); - runner->Run(); - helper_->FaviconDownloaderFinished(); -} - -void MetroPinTabHelper::FaviconChooser::UpdateCandidate( - int id, - const GURL& image_url, - const std::vector<SkBitmap>& bitmaps) { - const int kMaxIconSize = 32; - - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - std::set<int>::iterator iter = in_progress_requests_.find(id); - // Check that this request is one of ours. - if (iter == in_progress_requests_.end()) - return; - - in_progress_requests_.erase(iter); - - // Process the bitmaps, keeping the one that is best so far. - for (std::vector<SkBitmap>::const_iterator iter = bitmaps.begin(); - iter != bitmaps.end(); - ++iter) { - - // If the new bitmap is too big, ignore it. - if (iter->height() > kMaxIconSize || iter->width() > kMaxIconSize) - continue; - - // If we don't have a best candidate yet, this is better so just grab it. - if (best_candidate_.isNull()) { - best_candidate_ = *iter; - continue; - } - - // If it is smaller than our best one so far, ignore it. - if (iter->height() <= best_candidate_.height() || - iter->width() <= best_candidate_.width()) { - continue; - } - - // Othewise it is our new best candidate. - best_candidate_ = *iter; - } - - // If there are no more outstanding requests, pin the page on the FILE thread. - // Once this happens this downloader has done its job, so delete it. - if (in_progress_requests_.empty()) - UseChosenCandidate(); -} - -void MetroPinTabHelper::FaviconChooser::AddPendingRequest(int request_id) { - in_progress_requests_.insert(request_id); -} - -MetroPinTabHelper::MetroPinTabHelper(content::WebContents* web_contents) - : content::WebContentsObserver(web_contents) { -} - -MetroPinTabHelper::~MetroPinTabHelper() {} - -bool MetroPinTabHelper::IsPinned() const { - HMODULE metro_module = base::win::GetMetroModule(); - if (!metro_module) - return false; - - typedef BOOL (*MetroIsPinnedToStartScreen)(const base::string16&); - MetroIsPinnedToStartScreen metro_is_pinned_to_start_screen = - reinterpret_cast<MetroIsPinnedToStartScreen>( - ::GetProcAddress(metro_module, "MetroIsPinnedToStartScreen")); - if (!metro_is_pinned_to_start_screen) { - NOTREACHED(); - return false; - } - - GURL url = web_contents()->GetURL(); - base::string16 tile_id = GenerateTileId(base::UTF8ToUTF16(url.spec())); - return metro_is_pinned_to_start_screen(tile_id) != 0; -} - -void MetroPinTabHelper::TogglePinnedToStartScreen() { - if (IsPinned()) { - UMA_HISTOGRAM_ENUMERATION(kMetroPinMetric, - base::win::METRO_UNPIN_INITIATED, - base::win::METRO_PIN_STATE_LIMIT); - UnPinPageFromStartScreen(); - return; - } - - UMA_HISTOGRAM_ENUMERATION(kMetroPinMetric, - base::win::METRO_PIN_INITIATED, - base::win::METRO_PIN_STATE_LIMIT); - GURL url = web_contents()->GetURL(); - base::string16 url_str = base::UTF8ToUTF16(url.spec()); - base::string16 title = web_contents()->GetTitle(); - // TODO(oshima): Use scoped_ptr::Pass to pass it to other thread. - SkBitmap favicon; - favicon::FaviconDriver* favicon_driver = - favicon::ContentFaviconDriver::FromWebContents(web_contents()); - if (favicon_driver->FaviconIsValid()) { - // Only the 1x bitmap data is needed. - favicon = favicon_driver->GetFavicon() - .AsImageSkia() - .GetRepresentation(1.0f) - .sk_bitmap(); - } - - favicon_chooser_.reset(new FaviconChooser(this, title, url_str, favicon)); - - if (favicon_url_candidates_.empty()) { - favicon_chooser_->UseChosenCandidate(); - return; - } - - // Request all the candidates. - int max_image_size = 0; // Do not resize images. - for (std::vector<content::FaviconURL>::const_iterator iter = - favicon_url_candidates_.begin(); - iter != favicon_url_candidates_.end(); - ++iter) { - favicon_chooser_->AddPendingRequest( - web_contents()->DownloadImage(iter->icon_url, - true, - max_image_size, - false, - base::Bind(&MetroPinTabHelper::DidDownloadFavicon, - base::Unretained(this)))); - } - -} - -void MetroPinTabHelper::DidNavigateMainFrame( - const content::LoadCommittedDetails& /*details*/, - const content::FrameNavigateParams& /*params*/) { - // Cancel any outstanding pin operations once the user navigates away from - // the page. - if (favicon_chooser_.get()) - favicon_chooser_.reset(); - // Any candidate favicons we have are now out of date so clear them. - favicon_url_candidates_.clear(); -} - -void MetroPinTabHelper::DidUpdateFaviconURL( - const std::vector<content::FaviconURL>& candidates) { - favicon_url_candidates_ = candidates; -} - -void MetroPinTabHelper::DidDownloadFavicon( - int id, - int http_status_code, - const GURL& image_url, - const std::vector<SkBitmap>& bitmaps, - const std::vector<gfx::Size>& original_bitmap_sizes) { - if (favicon_chooser_.get()) { - favicon_chooser_->UpdateCandidate(id, image_url, bitmaps); - } -} - -void MetroPinTabHelper::UnPinPageFromStartScreen() { - HMODULE metro_module = base::win::GetMetroModule(); - if (!metro_module) - return; - - base::win::MetroUnPinFromStartScreen metro_un_pin_from_start_screen = - reinterpret_cast<base::win::MetroUnPinFromStartScreen>( - ::GetProcAddress(metro_module, "MetroUnPinFromStartScreen")); - if (!metro_un_pin_from_start_screen) { - NOTREACHED(); - return; - } - - GURL url = web_contents()->GetURL(); - base::string16 tile_id = GenerateTileId(base::UTF8ToUTF16(url.spec())); - metro_un_pin_from_start_screen(tile_id, - base::Bind(&PinPageReportUmaCallback)); -} - -void MetroPinTabHelper::FaviconDownloaderFinished() { - favicon_chooser_.reset(); -} |