Index: chrome/browser/ui/metro_pin_tab_helper_win.cc |
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 2506a004ae1c0e774c615ef8b09dce8cc9ed2e9e..0000000000000000000000000000000000000000 |
--- 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(); |
-} |