diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index d96eb2ce50b610..b7376e560d4c77 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc @@ -45,7 +45,6 @@ #include "chrome/browser/ui/find_bar/find_bar_controller.h" #include "chrome/browser/ui/find_bar/find_tab_helper.h" #include "chrome/browser/ui/fullscreen/fullscreen_controller.h" -#include "chrome/browser/ui/metro_pin_tab_helper.h" #include "chrome/browser/ui/omnibox/location_bar.h" #include "chrome/browser/ui/search/search.h" #include "chrome/browser/ui/search/search_model.h" @@ -80,6 +79,7 @@ #if defined(OS_WIN) #include "base/win/metro.h" +#include "chrome/browser/ui/metro_pin_tab_helper_win.h" #endif namespace { @@ -651,8 +651,10 @@ bool CanBookmarkAllTabs(const Browser* browser) { } void TogglePagePinnedToStartScreen(Browser* browser) { +#if defined(OS_WIN) MetroPinTabHelper::FromWebContents(GetActiveWebContents(browser))-> TogglePinnedToStartScreen(); +#endif } void SavePage(Browser* browser) { diff --git a/chrome/browser/ui/metro_pin_tab_helper.cc b/chrome/browser/ui/metro_pin_tab_helper.cc deleted file mode 100644 index 7644355c6a5b85..00000000000000 --- a/chrome/browser/ui/metro_pin_tab_helper.cc +++ /dev/null @@ -1,76 +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.h" - -#include "base/logging.h" -#include "base/utf_string_conversions.h" -#include "content/public/browser/web_contents.h" - -#if defined(OS_WIN) -#include "base/win/metro.h" -#endif - -DEFINE_WEB_CONTENTS_USER_DATA_KEY(MetroPinTabHelper) - -MetroPinTabHelper::MetroPinTabHelper(content::WebContents* web_contents) - : content::WebContentsObserver(web_contents), - is_pinned_(false) {} - -MetroPinTabHelper::~MetroPinTabHelper() {} - -void MetroPinTabHelper::TogglePinnedToStartScreen() { -#if defined(OS_WIN) - HMODULE metro_module = base::win::GetMetroModule(); - if (metro_module) { - typedef void (*MetroTogglePinnedToStartScreen)(const string16&, - const string16&); - MetroTogglePinnedToStartScreen metro_toggle_pinned_to_start_screen = - reinterpret_cast( - ::GetProcAddress(metro_module, "MetroTogglePinnedToStartScreen")); - if (!metro_toggle_pinned_to_start_screen) { - NOTREACHED(); - return; - } - - GURL url = web_contents()->GetURL(); - string16 title = web_contents()->GetTitle(); - VLOG(1) << __FUNCTION__ << " calling pin with title: " << title - << " and url " << UTF8ToUTF16(url.spec()); - metro_toggle_pinned_to_start_screen(title, UTF8ToUTF16(url.spec())); - // TODO(benwells): This will update the state incorrectly if the user - // cancels. To fix this some sort of callback needs to be introduced as - // the pinning happens on another thread. - is_pinned_ = !is_pinned_; - return; - } -#endif -} - -void MetroPinTabHelper::DidNavigateMainFrame( - const content::LoadCommittedDetails& /*details*/, - const content::FrameNavigateParams& /*params*/) { - UpdatePinnedStateForCurrentURL(); -} - -void MetroPinTabHelper::UpdatePinnedStateForCurrentURL() { -#if defined(OS_WIN) - HMODULE metro_module = base::win::GetMetroModule(); - if (metro_module) { - typedef BOOL (*MetroIsPinnedToStartScreen)(const string16&); - MetroIsPinnedToStartScreen metro_is_pinned_to_start_screen = - reinterpret_cast( - ::GetProcAddress(metro_module, "MetroIsPinnedToStartScreen")); - if (!metro_is_pinned_to_start_screen) { - NOTREACHED(); - return; - } - - GURL url = web_contents()->GetURL(); - is_pinned_ = metro_is_pinned_to_start_screen(UTF8ToUTF16(url.spec())) != 0; - VLOG(1) << __FUNCTION__ << " with url " << UTF8ToUTF16(url.spec()) - << " result: " << is_pinned_; - } -#endif -} diff --git a/chrome/browser/ui/metro_pin_tab_helper_win.cc b/chrome/browser/ui/metro_pin_tab_helper_win.cc new file mode 100644 index 00000000000000..e3fa0faca50c4e --- /dev/null +++ b/chrome/browser/ui/metro_pin_tab_helper_win.cc @@ -0,0 +1,297 @@ +// 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 "base/base_paths.h" +#include "base/bind.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_memory.h" +#include "base/path_service.h" +#include "base/string_number_conversions.h" +#include "base/utf_string_conversions.h" +#include "base/win/metro.h" +#include "chrome/browser/favicon/favicon_tab_helper.h" +#include "chrome/browser/ui/tab_contents/tab_contents.h" +#include "chrome/common/chrome_paths.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" +#include "crypto/sha2.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/image/image.h" +#include "ui/gfx/rect.h" +#include "ui/gfx/size.h" + +DEFINE_WEB_CONTENTS_USER_DATA_KEY(MetroPinTabHelper) + +namespace { + +// Generate an ID for the tile based on |url_str|. The ID is simply a hash of +// the URL. +string16 GenerateTileId(const string16& url_str) { + uint8 hash[crypto::kSHA256Length]; + crypto::SHA256HashString(UTF16ToUTF8(url_str), hash, sizeof(hash)); + std::string hash_str = base::HexEncode(hash, sizeof(hash)); + return UTF8ToUTF16(hash_str); +} + +// Get the path of the directory to store the tile logos in. +FilePath GetTileImagesDir() { + FilePath time_images_dir; + DCHECK(PathService::Get(chrome::DIR_USER_DATA, &time_images_dir)); + time_images_dir = time_images_dir.Append(L"TileImages"); + if (!file_util::DirectoryExists(time_images_dir) && + !file_util::CreateDirectory(time_images_dir)) + return FilePath(); + + return time_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 gfx::ImageSkia& image, + const string16& tile_id, + const FilePath& logo_dir, + 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; + const int kColorMeanDarknessLimit = 100; + const int kColorMeanLightnessLimit = 100; + + if (image.isNull()) + return false; + + *logo_path = logo_dir.Append(tile_id).ReplaceExtension(L".png"); + + // Use a canvas to paint the tile logo. + gfx::Canvas canvas(gfx::Size(kLogoWidth, kLogoHeight), ui::SCALE_FACTOR_100P, + true); + + // Fill the tile logo with the average color from bitmap. To do this we need + // to work out the 'average color' which is calculated using PNG encoded data + // of the bitmap. + SkPaint paint; + std::vector icon_png; + if (!gfx::PNGCodec::EncodeBGRASkBitmap(*image.bitmap(), true, &icon_png)) + return false; + + scoped_refptr icon_mem( + new base::RefCountedStaticMemory(&icon_png.front(), icon_png.size())); + color_utils::GridSampler sampler; + SkColor mean_color = color_utils::CalculateKMeanColorOfPNG( + icon_mem, kColorMeanDarknessLimit, kColorMeanLightnessLimit, sampler); + paint.setColor(mean_color); + 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(mean_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 - image.width()) / 2; + int top = (kLogoHeight - kCaptionHeight - image.height()) / 2; + canvas.DrawImageInt(image, left, top); + + SkBitmap logo_bitmap = canvas.ExtractImageRep().sk_bitmap(); + std::vector logo_png; + if (!gfx::PNGCodec::EncodeBGRASkBitmap(logo_bitmap, true, &logo_png)) + return false; + + return file_util::WriteFile(*logo_path, + reinterpret_cast(&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 FilePath& logo_dir, + FilePath* logo_path) { + const wchar_t kDefaultLogoFileName[] = L"SecondaryTile.png"; + *logo_path = logo_dir.Append(kDefaultLogoFileName); + if (file_util::PathExists(*logo_path)) + return true; + + FilePath default_logo_path; + DCHECK(PathService::Get(base::DIR_MODULE, &default_logo_path)); + default_logo_path = default_logo_path.Append(kDefaultLogoFileName); + return file_util::CopyFile(default_logo_path, *logo_path); +} + +} // namespace + +class MetroPinTabHelper::TaskRunner + : public base::RefCountedThreadSafe { + public: + TaskRunner() {} + + void PinPageToStartScreen(const string16& title, + const string16& url, + const gfx::ImageSkia& image); + + private: + ~TaskRunner() {} + + friend class base::RefCountedThreadSafe; + DISALLOW_COPY_AND_ASSIGN(TaskRunner); +}; + +void MetroPinTabHelper::TaskRunner::PinPageToStartScreen( + const string16& title, + const string16& url, + const gfx::ImageSkia& image) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + + string16 tile_id = GenerateTileId(url); + FilePath logo_dir = GetTileImagesDir(); + if (logo_dir.empty()) { + LOG(ERROR) << "Could not create directory to store tile image."; + return; + } + + FilePath logo_path; + if (!CreateSiteSpecificLogo(image, tile_id, logo_dir, &logo_path) && + !GetPathToBackupLogo(logo_dir, &logo_path)) { + LOG(ERROR) << "Count not get path to logo tile."; + return; + } + + HMODULE metro_module = base::win::GetMetroModule(); + if (!metro_module) + return; + + typedef void (*MetroPinToStartScreen)(const string16&, const string16&, + const string16&, const FilePath&); + MetroPinToStartScreen metro_pin_to_start_screen = + reinterpret_cast( + ::GetProcAddress(metro_module, "MetroPinToStartScreen")); + if (!metro_pin_to_start_screen) { + NOTREACHED(); + return; + } + + VLOG(1) << __FUNCTION__ << " calling pin with title: " << title + << " and url: " << url; + metro_pin_to_start_screen(tile_id, title, url, logo_path); +} + +MetroPinTabHelper::MetroPinTabHelper(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents), + is_pinned_(false), + task_runner_(new TaskRunner) {} + +MetroPinTabHelper::~MetroPinTabHelper() {} + +void MetroPinTabHelper::TogglePinnedToStartScreen() { + UpdatePinnedStateForCurrentURL(); + bool was_pinned = is_pinned_; + + // TODO(benwells): This will update the state incorrectly if the user + // cancels. To fix this some sort of callback needs to be introduced as + // the pinning happens on another thread. + is_pinned_ = !is_pinned_; + + if (was_pinned) { + UnPinPageFromStartScreen(); + return; + } + + // TODO(benwells): Handle downloading a larger favicon if there is one. + GURL url = web_contents()->GetURL(); + string16 url_str = UTF8ToUTF16(url.spec()); + string16 title = web_contents()->GetTitle(); + TabContents* tab_contents = TabContents::FromWebContents(web_contents()); + DCHECK(tab_contents); + FaviconTabHelper* favicon_tab_helper = FaviconTabHelper::FromWebContents( + tab_contents->web_contents()); + if (favicon_tab_helper->FaviconIsValid()) { + gfx::Image favicon = favicon_tab_helper->GetFavicon(); + gfx::ImageSkia favicon_skia = favicon.AsImageSkia().DeepCopy(); + content::BrowserThread::PostTask( + content::BrowserThread::FILE, + FROM_HERE, + base::Bind(&TaskRunner::PinPageToStartScreen, + task_runner_, + title, + url_str, + favicon_skia)); + return; + } + + content::BrowserThread::PostTask( + content::BrowserThread::FILE, + FROM_HERE, + base::Bind(&TaskRunner::PinPageToStartScreen, + task_runner_, + title, + url_str, + gfx::ImageSkia())); +} + +void MetroPinTabHelper::DidNavigateMainFrame( + const content::LoadCommittedDetails& /*details*/, + const content::FrameNavigateParams& /*params*/) { + UpdatePinnedStateForCurrentURL(); +} + +void MetroPinTabHelper::UpdatePinnedStateForCurrentURL() { + HMODULE metro_module = base::win::GetMetroModule(); + if (!metro_module) + return; + + typedef BOOL (*MetroIsPinnedToStartScreen)(const string16&); + MetroIsPinnedToStartScreen metro_is_pinned_to_start_screen = + reinterpret_cast( + ::GetProcAddress(metro_module, "MetroIsPinnedToStartScreen")); + if (!metro_is_pinned_to_start_screen) { + NOTREACHED(); + return; + } + + GURL url = web_contents()->GetURL(); + string16 tile_id = GenerateTileId(UTF8ToUTF16(url.spec())); + is_pinned_ = metro_is_pinned_to_start_screen(tile_id) != 0; + VLOG(1) << __FUNCTION__ << " with url " << UTF8ToUTF16(url.spec()) + << " result: " << is_pinned_; +} + +void MetroPinTabHelper::UnPinPageFromStartScreen() { + HMODULE metro_module = base::win::GetMetroModule(); + if (!metro_module) + return; + + typedef void (*MetroUnPinFromStartScreen)(const string16&); + MetroUnPinFromStartScreen metro_un_pin_from_start_screen = + reinterpret_cast( + ::GetProcAddress(metro_module, "MetroUnPinFromStartScreen")); + if (!metro_un_pin_from_start_screen) { + NOTREACHED(); + return; + } + + GURL url = web_contents()->GetURL(); + VLOG(1) << __FUNCTION__ << " calling unpin with url: " + << UTF8ToUTF16(url.spec()); + string16 tile_id = GenerateTileId(UTF8ToUTF16(url.spec())); + metro_un_pin_from_start_screen(tile_id); +} diff --git a/chrome/browser/ui/metro_pin_tab_helper.h b/chrome/browser/ui/metro_pin_tab_helper_win.h similarity index 71% rename from chrome/browser/ui/metro_pin_tab_helper.h rename to chrome/browser/ui/metro_pin_tab_helper_win.h index 23084a2fef9201..3cb2532d508e52 100644 --- a/chrome/browser/ui/metro_pin_tab_helper.h +++ b/chrome/browser/ui/metro_pin_tab_helper_win.h @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_METRO_PIN_TAB_HELPER_H_ -#define CHROME_BROWSER_UI_METRO_PIN_TAB_HELPER_H_ +#ifndef CHROME_BROWSER_UI_METRO_PIN_TAB_HELPER_WIN_H_ +#define CHROME_BROWSER_UI_METRO_PIN_TAB_HELPER_WIN_H_ #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" +#include "ui/gfx/image/image_skia.h" // Per-tab class to help manage metro pinning. class MetroPinTabHelper @@ -25,16 +26,25 @@ class MetroPinTabHelper const content::FrameNavigateParams& params) OVERRIDE; private: + // The TaskRunner handles running tasks for this helper on the FILE thread. + class TaskRunner; + explicit MetroPinTabHelper(content::WebContents* tab_contents); friend class content::WebContentsUserData; // Queries the metro driver about the pinned state of the current URL. void UpdatePinnedStateForCurrentURL(); + void UnPinPageFromStartScreen(); + // Whether the current URL is pinned to the metro start screen. bool is_pinned_; + // The task runner for the helper, which runs things for it on the FILE + // thread. + scoped_refptr task_runner_; + DISALLOW_COPY_AND_ASSIGN(MetroPinTabHelper); }; -#endif // CHROME_BROWSER_UI_METRO_PIN_TAB_HELPER_H_ +#endif // CHROME_BROWSER_UI_METRO_PIN_TAB_HELPER_WIN_H_ diff --git a/chrome/browser/ui/tab_contents/tab_contents.cc b/chrome/browser/ui/tab_contents/tab_contents.cc index ff08ca2c43eacb..aceaa05299ebe7 100644 --- a/chrome/browser/ui/tab_contents/tab_contents.cc +++ b/chrome/browser/ui/tab_contents/tab_contents.cc @@ -39,7 +39,6 @@ #include "chrome/browser/ui/find_bar/find_tab_helper.h" #include "chrome/browser/ui/hung_plugin_tab_helper.h" #include "chrome/browser/ui/intents/web_intent_picker_controller.h" -#include "chrome/browser/ui/metro_pin_tab_helper.h" #include "chrome/browser/ui/pdf/pdf_tab_helper.h" #include "chrome/browser/ui/prefs/prefs_tab_helper.h" #include "chrome/browser/ui/sad_tab_helper.h" @@ -60,6 +59,10 @@ #include "chrome/browser/captive_portal/captive_portal_tab_helper.h" #endif +#if defined(OS_WIN) +#include "chrome/browser/ui/metro_pin_tab_helper_win.h" +#endif + using content::WebContents; namespace { @@ -135,7 +138,6 @@ TabContents::TabContents(WebContents* contents) HistoryTabHelper::CreateForWebContents(contents); HungPluginTabHelper::CreateForWebContents(contents); InfoBarTabHelper::CreateForWebContents(contents); - MetroPinTabHelper::CreateForWebContents(contents); NavigationMetricsRecorder::CreateForWebContents(contents); PasswordManagerDelegateImpl::CreateForWebContents(contents); PasswordManager::CreateForWebContentsAndDelegate( @@ -185,6 +187,10 @@ TabContents::TabContents(WebContents* contents) if (OneClickSigninHelper::CanOffer(contents, "", false)) OneClickSigninHelper::CreateForWebContents(contents); #endif + +#if defined(OS_WIN) + MetroPinTabHelper::CreateForWebContents(contents); +#endif } TabContents::~TabContents() { diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc index 0781fc9b04e843..e8ff92c4d91a36 100644 --- a/chrome/browser/ui/toolbar/wrench_menu_model.cc +++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc @@ -33,7 +33,6 @@ #include "chrome/browser/ui/global_error/global_error.h" #include "chrome/browser/ui/global_error/global_error_service.h" #include "chrome/browser/ui/global_error/global_error_service_factory.h" -#include "chrome/browser/ui/metro_pin_tab_helper.h" #include "chrome/browser/ui/tab_contents/tab_contents.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/toolbar/encoding_menu_controller.h" @@ -68,6 +67,7 @@ #include "base/win/metro.h" #include "base/win/windows_version.h" #include "chrome/browser/enumerate_modules_model_win.h" +#include "chrome/browser/ui/metro_pin_tab_helper_win.h" #endif #if defined(USE_ASH) @@ -244,11 +244,12 @@ bool WrenchMenuModel::IsItemForCommandIdDynamic(int command_id) const { return command_id == IDC_ZOOM_PERCENT_DISPLAY || #if defined(OS_MACOSX) command_id == IDC_FULLSCREEN || +#elif defined(OS_WIN) + command_id == IDC_PIN_TO_START_SCREEN || #endif command_id == IDC_VIEW_BACKGROUND_PAGES || command_id == IDC_UPGRADE_DIALOG || - command_id == IDC_SHOW_SYNC_SETUP || - command_id == IDC_PIN_TO_START_SCREEN; + command_id == IDC_SHOW_SYNC_SETUP; } string16 WrenchMenuModel::GetLabelForCommandId(int command_id) const { @@ -263,6 +264,17 @@ string16 WrenchMenuModel::GetLabelForCommandId(int command_id) const { string_id = IDS_EXIT_FULLSCREEN_MAC; return l10n_util::GetStringUTF16(string_id); } +#elif defined(OS_WIN) + case IDC_PIN_TO_START_SCREEN: { + int string_id = IDS_PIN_TO_START_SCREEN; + WebContents* web_contents = chrome::GetActiveWebContents(browser_); + MetroPinTabHelper* tab_helper = + web_contents ? MetroPinTabHelper::FromWebContents(web_contents) + : NULL; + if (tab_helper && tab_helper->is_pinned()) + string_id = IDS_UNPIN_FROM_START_SCREEN; + return l10n_util::GetStringUTF16(string_id); + } #endif case IDC_VIEW_BACKGROUND_PAGES: { string16 num_background_pages = base::FormatNumber( @@ -290,16 +302,6 @@ string16 WrenchMenuModel::GetLabelForCommandId(int command_id) const { return l10n_util::GetStringFUTF16(IDS_SYNC_MENU_PRE_SYNCED_LABEL, l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); } - case IDC_PIN_TO_START_SCREEN: { - int string_id = IDS_PIN_TO_START_SCREEN; - WebContents* web_contents = chrome::GetActiveWebContents(browser_); - MetroPinTabHelper* tab_helper = - web_contents ? MetroPinTabHelper::FromWebContents(web_contents) - : NULL; - if (tab_helper && tab_helper->is_pinned()) - string_id = IDS_UNPIN_FROM_START_SCREEN; - return l10n_util::GetStringUTF16(string_id); - } default: NOTREACHED(); return string16(); diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index c1f648c657872a..c9eaade305875f 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -1119,8 +1119,8 @@ 'browser/ui/login/login_prompt.h', 'browser/ui/media_stream_infobar_delegate.h', 'browser/ui/media_stream_infobar_delegate.cc', - 'browser/ui/metro_pin_tab_helper.cc', - 'browser/ui/metro_pin_tab_helper.h', + 'browser/ui/metro_pin_tab_helper_win.cc', + 'browser/ui/metro_pin_tab_helper_win.h', 'browser/ui/network_profile_bubble.cc', 'browser/ui/network_profile_bubble.h', 'browser/ui/ntp_background_util.cc', diff --git a/win8/metro_driver/secondary_tile.cc b/win8/metro_driver/secondary_tile.cc index c784fdcf3904d7..97109c1924b5f7 100644 --- a/win8/metro_driver/secondary_tile.cc +++ b/win8/metro_driver/secondary_tile.cc @@ -7,49 +7,16 @@ #include -#include "base/base_paths.h" #include "base/bind.h" -#include "base/file_path.h" #include "base/logging.h" -#include "base/path_service.h" -#include "base/string_number_conversions.h" #include "base/utf_string_conversions.h" -#include "crypto/sha2.h" #include "googleurl/src/gurl.h" #include "win8/metro_driver/chrome_app_view.h" #include "win8/metro_driver/winrt_utils.h" namespace { -string16 GenerateTileId(const string16& url_str) { - uint8 hash[crypto::kSHA256Length]; - crypto::SHA256HashString(UTF16ToUTF8(url_str), hash, sizeof(hash)); - std::string hash_str = base::HexEncode(hash, sizeof(hash)); - return UTF8ToUTF16(hash_str); -} - -string16 GetLogoUrlString() { - FilePath module_path; - PathService::Get(base::DIR_MODULE, &module_path); - string16 scheme(L"ms-appx:///"); - return scheme.append(module_path.BaseName().value()) - .append(L"/SecondaryTile.png"); -} - -BOOL IsPinnedToStartScreen(const string16& url_str) { - mswr::ComPtr tile_statics; - HRESULT hr = winrt_utils::CreateActivationFactory( - RuntimeClass_Windows_UI_StartScreen_SecondaryTile, - tile_statics.GetAddressOf()); - CheckHR(hr, "Failed to create instance of ISecondaryTileStatics"); - - boolean exists; - hr = tile_statics->Exists(MakeHString(GenerateTileId(url_str)), &exists); - CheckHR(hr, "ISecondaryTileStatics.Exists failed"); - return exists; -} - -void DeleteTileFromStartScreen(const string16& url_str) { +void DeleteTileFromStartScreen(const string16& tile_id) { DVLOG(1) << __FUNCTION__; mswr::ComPtr tile_factory; HRESULT hr = winrt_utils::CreateActivationFactory( @@ -58,7 +25,7 @@ void DeleteTileFromStartScreen(const string16& url_str) { CheckHR(hr, "Failed to create instance of ISecondaryTileFactory"); mswrw::HString id; - id.Attach(MakeHString(GenerateTileId(url_str))); + id.Attach(MakeHString(tile_id)); mswr::ComPtr tile; hr = tile_factory->CreateWithId(id.Get(), tile.GetAddressOf()); @@ -76,9 +43,12 @@ void DeleteTileFromStartScreen(const string16& url_str) { CheckHR(hr, "Failed to put_Completed"); } -void CreateTileOnStartScreen(const string16& title_str, - const string16& url_str) { +void CreateTileOnStartScreen(const string16& tile_id, + const string16& title_str, + const string16& url_str, + const FilePath& logo_path) { VLOG(1) << __FUNCTION__; + mswr::ComPtr tile_factory; HRESULT hr = winrt_utils::CreateActivationFactory( RuntimeClass_Windows_UI_StartScreen_SecondaryTile, @@ -89,8 +59,10 @@ void CreateTileOnStartScreen(const string16& title_str, winui::StartScreen::TileOptions_ShowNameOnLogo; mswrw::HString title; title.Attach(MakeHString(title_str)); + mswrw::HString id; - id.Attach(MakeHString(GenerateTileId(url_str))); + id.Attach(MakeHString(tile_id)); + mswrw::HString args; // The url is just passed into the tile agruments as is. Metro and desktop // chrome will see the arguments as command line parameters. @@ -105,7 +77,7 @@ void CreateTileOnStartScreen(const string16& title_str, CheckHR(hr, "Failed to create URIFactory"); mswrw::HString logo_url; - logo_url.Attach(MakeHString(GetLogoUrlString())); + logo_url.Attach(MakeHString(string16(L"file:///").append(logo_path.value()))); mswr::ComPtr uri; hr = uri_factory->CreateUri(logo_url.Get(), &uri); CheckHR(hr, "Failed to create URI"); @@ -135,26 +107,34 @@ void CreateTileOnStartScreen(const string16& title_str, CheckHR(hr, "Failed to put_Completed"); } -void TogglePinnedToStartScreen(const string16& title_str, - const string16& url_str) { - if (IsPinnedToStartScreen(url_str)) { - DeleteTileFromStartScreen(url_str); - return; - } +} // namespace - CreateTileOnStartScreen(title_str, url_str); -} +BOOL MetroIsPinnedToStartScreen(const string16& tile_id) { + mswr::ComPtr tile_statics; + HRESULT hr = winrt_utils::CreateActivationFactory( + RuntimeClass_Windows_UI_StartScreen_SecondaryTile, + tile_statics.GetAddressOf()); + CheckHR(hr, "Failed to create instance of ISecondaryTileStatics"); -} // namespace + boolean exists; + hr = tile_statics->Exists(MakeHString(tile_id), &exists); + CheckHR(hr, "ISecondaryTileStatics.Exists failed"); + return exists; +} -BOOL MetroIsPinnedToStartScreen(const string16& url) { - VLOG(1) << __FUNCTION__ << " url: " << url; - return IsPinnedToStartScreen(url); +void MetroUnPinFromStartScreen(const string16& tile_id) { + globals.appview_msg_loop->PostTask( + FROM_HERE, base::Bind(&DeleteTileFromStartScreen, tile_id)); } -void MetroTogglePinnedToStartScreen(const string16& title, - const string16& url) { - DVLOG(1) << __FUNCTION__ << " title:" << title << " url: " << url; +void MetroPinToStartScreen(const string16& tile_id, + const string16& title, + const string16& url, + const FilePath& logo_path) { globals.appview_msg_loop->PostTask( - FROM_HERE, base::Bind(&TogglePinnedToStartScreen, title, url)); + FROM_HERE, base::Bind(&CreateTileOnStartScreen, + tile_id, + title, + url, + logo_path)); } diff --git a/win8/metro_driver/secondary_tile.h b/win8/metro_driver/secondary_tile.h index 796e881fa0e6a2..caee7e816d732f 100644 --- a/win8/metro_driver/secondary_tile.h +++ b/win8/metro_driver/secondary_tile.h @@ -4,13 +4,20 @@ #ifndef CHROME_BROWSER_UI_METRO_DRIVER_SECONDARY_TILE_H_ #define CHROME_BROWSER_UI_METRO_DRIVER_SECONDARY_TILE_H_ +#include "base/file_path.h" #include "base/string16.h" extern "C" __declspec(dllexport) -BOOL MetroIsPinnedToStartScreen(const string16& url); +BOOL MetroIsPinnedToStartScreen(const string16& tile_id); extern "C" __declspec(dllexport) -void MetroTogglePinnedToStartScreen(const string16& title, const string16& url); +void MetroUnPinFromStartScreen(const string16& tile_id); + +extern "C" __declspec(dllexport) +void MetroPinToStartScreen(const string16& tile_id, + const string16& title, + const string16& url, + const FilePath& logo_path); #endif // CHROME_BROWSER_UI_METRO_DRIVER_SECONDARY_TILE_H_