Index: chrome/browser/ui/views/create_application_shortcut_view.cc |
diff --git a/chrome/browser/ui/views/create_application_shortcut_view.cc b/chrome/browser/ui/views/create_application_shortcut_view.cc |
index a8f215ca53ecf98b42e1dcfc209bb88d67a84656..db46f2c7a42a11f1d7f1259b99f9bdce18f68ffa 100644 |
--- a/chrome/browser/ui/views/create_application_shortcut_view.cc |
+++ b/chrome/browser/ui/views/create_application_shortcut_view.cc |
@@ -4,216 +4,29 @@ |
#include "chrome/browser/ui/views/create_application_shortcut_view.h" |
-#include <stddef.h> |
-#include <algorithm> |
-#include <cmath> |
-#include <utility> |
- |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
-#include "base/strings/utf_string_conversions.h" |
#include "build/build_config.h" |
-#include "chrome/browser/extensions/tab_helper.h" |
#include "chrome/browser/profiles/profile.h" |
-#include "chrome/browser/ui/browser.h" |
-#include "chrome/browser/ui/browser_commands.h" |
-#include "chrome/browser/ui/browser_finder.h" |
-#include "chrome/browser/ui/views/harmony/chrome_typography.h" |
-#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" |
-#include "chrome/browser/web_applications/web_app.h" |
-#include "chrome/common/chrome_constants.h" |
#include "chrome/common/pref_names.h" |
#include "chrome/grit/generated_resources.h" |
-#include "chrome/grit/locale_settings.h" |
#include "components/constrained_window/constrained_window_views.h" |
-#include "components/favicon_base/select_favicon_frames.h" |
#include "components/prefs/pref_service.h" |
-#include "content/public/browser/render_view_host.h" |
-#include "content/public/browser/render_widget_host_view.h" |
-#include "content/public/browser/web_contents.h" |
#include "extensions/common/extension.h" |
-#include "net/base/load_flags.h" |
-#include "net/url_request/url_request.h" |
-#include "skia/ext/image_operations.h" |
-#include "third_party/skia/include/core/SkBitmap.h" |
-#include "third_party/skia/include/core/SkRect.h" |
#include "ui/base/l10n/l10n_util.h" |
-#include "ui/base/layout.h" |
-#include "ui/base/resource/resource_bundle.h" |
-#include "ui/gfx/canvas.h" |
-#include "ui/gfx/codec/png_codec.h" |
-#include "ui/gfx/image/image_family.h" |
-#include "ui/gfx/image/image_skia.h" |
#include "ui/views/controls/button/checkbox.h" |
-#include "ui/views/controls/image_view.h" |
#include "ui/views/controls/label.h" |
#include "ui/views/layout/grid_layout.h" |
#include "ui/views/layout/layout_constants.h" |
-#include "ui/views/widget/widget.h" |
#include "ui/views/window/dialog_client_view.h" |
-#include "url/gurl.h" |
#if defined(OS_WIN) |
#include "base/win/shortcut.h" |
#include "base/win/windows_version.h" |
#endif // defined(OS_WIN) |
-namespace { |
- |
-const int kIconPreviewSizePixels = 32; |
- |
-// AppInfoView shows the application icon and title. |
-class AppInfoView : public views::View { |
- public: |
- AppInfoView(const base::string16& title, |
- const base::string16& description, |
- const gfx::ImageFamily& icon); |
- |
- // Updates the icon of the web app. |
- void UpdateIcon(const gfx::ImageFamily& image); |
- |
- // Overridden from views::View: |
- void OnPaint(gfx::Canvas* canvas) override; |
- |
- private: |
- // Initializes the controls |
- void Init(const base::string16& title, |
- const base::string16& description, const gfx::ImageFamily& icon); |
- |
- // Creates or updates description label. |
- void PrepareDescriptionLabel(const base::string16& description); |
- |
- // Sets up layout manager. |
- void SetupLayout(); |
- |
- views::ImageView* icon_; |
- views::Label* title_; |
- views::Label* description_; |
-}; |
- |
-AppInfoView::AppInfoView(const base::string16& title, |
- const base::string16& description, |
- const gfx::ImageFamily& icon) |
- : icon_(nullptr), |
- title_(nullptr), |
- description_(nullptr) { |
- Init(title, description, icon); |
-} |
- |
-void AppInfoView::Init(const base::string16& title_text, |
- const base::string16& description_text, |
- const gfx::ImageFamily& icon) { |
- icon_ = new views::ImageView(); |
- UpdateIcon(icon); |
- icon_->SetImageSize(gfx::Size(kIconPreviewSizePixels, |
- kIconPreviewSizePixels)); |
- |
- title_ = |
- new views::Label(title_text, CONTEXT_BODY_TEXT_SMALL, STYLE_EMPHASIZED); |
- title_->SetMultiLine(true); |
- title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- |
- PrepareDescriptionLabel(description_text); |
- |
- SetupLayout(); |
-} |
- |
-void AppInfoView::PrepareDescriptionLabel(const base::string16& description) { |
- // Do not make space for the description if it is empty. |
- if (description.empty()) |
- return; |
- |
- const size_t kMaxLength = 200; |
- const base::string16 kEllipsis(base::ASCIIToUTF16(" ... ")); |
- |
- base::string16 text = description; |
- if (text.length() > kMaxLength) { |
- text = text.substr(0, kMaxLength); |
- text += kEllipsis; |
- } |
- |
- if (description_) { |
- description_->SetText(text); |
- } else { |
- description_ = new views::Label(text); |
- description_->SetMultiLine(true); |
- description_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- } |
-} |
- |
-void AppInfoView::SetupLayout() { |
- views::GridLayout* layout = views::GridLayout::CreatePanel(this); |
- SetLayoutManager(layout); |
- |
- static const int kColumnSetId = 0; |
- views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId); |
- column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::LEADING, |
- 20.0f, views::GridLayout::FIXED, |
- kIconPreviewSizePixels, kIconPreviewSizePixels); |
- column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, |
- 80.0f, views::GridLayout::USE_PREF, 0, 0); |
- |
- layout->StartRow(0, kColumnSetId); |
- layout->AddView(icon_, 1, description_ ? 2 : 1); |
- layout->AddView(title_); |
- |
- if (description_) { |
- layout->StartRow(0, kColumnSetId); |
- layout->SkipColumns(1); |
- layout->AddView(description_); |
- } |
-} |
- |
-void AppInfoView::UpdateIcon(const gfx::ImageFamily& image) { |
- // Get an icon at the desired preview size (scaling from a larger image if |
- // none is available at that exact size). |
- gfx::Image icon = |
- image.CreateExact(kIconPreviewSizePixels, kIconPreviewSizePixels); |
- icon_->SetImage(icon.ToImageSkia()); |
-} |
- |
-void AppInfoView::OnPaint(gfx::Canvas* canvas) { |
- gfx::Rect bounds = GetLocalBounds(); |
- |
- SkRect border_rect = { |
- SkIntToScalar(bounds.x()), |
- SkIntToScalar(bounds.y()), |
- SkIntToScalar(bounds.right()), |
- SkIntToScalar(bounds.bottom()) |
- }; |
- |
- cc::PaintFlags border_flags; |
- border_flags.setAntiAlias(true); |
- border_flags.setARGB(0xFF, 0xC8, 0xC8, 0xC8); |
- |
- canvas->sk_canvas()->drawRoundRect(border_rect, SkIntToScalar(2), |
- SkIntToScalar(2), border_flags); |
- |
- SkRect inner_rect = { |
- border_rect.fLeft + SkDoubleToScalar(0.5), |
- border_rect.fTop + SkDoubleToScalar(0.5), |
- border_rect.fRight - SkDoubleToScalar(0.5), |
- border_rect.fBottom - SkDoubleToScalar(0.5), |
- }; |
- |
- cc::PaintFlags inner_flags; |
- inner_flags.setAntiAlias(true); |
- inner_flags.setARGB(0xFF, 0xF8, 0xF8, 0xF8); |
- canvas->sk_canvas()->drawRoundRect(inner_rect, SkDoubleToScalar(1.5), |
- SkDoubleToScalar(1.5), inner_flags); |
-} |
- |
-} // namespace |
- |
namespace chrome { |
-void ShowCreateWebAppShortcutsDialog(gfx::NativeWindow parent_window, |
- content::WebContents* web_contents) { |
- constrained_window::CreateBrowserModalDialogViews( |
- new CreateUrlApplicationShortcutView(web_contents), |
- parent_window)->Show(); |
-} |
- |
void ShowCreateChromeAppShortcutsDialog( |
gfx::NativeWindow parent_window, |
Profile* profile, |
@@ -226,23 +39,29 @@ void ShowCreateChromeAppShortcutsDialog( |
} // namespace chrome |
-CreateApplicationShortcutView::CreateApplicationShortcutView(Profile* profile) |
+CreateChromeApplicationShortcutView::CreateChromeApplicationShortcutView( |
+ Profile* profile, |
+ const extensions::Extension* app, |
+ const base::Callback<void(bool)>& close_callback) |
: profile_(profile), |
- app_info_(nullptr), |
+ close_callback_(close_callback), |
create_shortcuts_label_(nullptr), |
desktop_check_box_(nullptr), |
menu_check_box_(nullptr), |
- quick_launch_check_box_(nullptr) { |
+ quick_launch_check_box_(nullptr), |
+ weak_ptr_factory_(this) { |
+ InitControls(); |
+ |
+ // Get shortcut and icon information; needed for creating the shortcut. |
+ web_app::GetShortcutInfoForApp( |
+ app, profile, |
+ base::Bind(&CreateChromeApplicationShortcutView::OnAppInfoLoaded, |
+ weak_ptr_factory_.GetWeakPtr())); |
} |
-CreateApplicationShortcutView::~CreateApplicationShortcutView() {} |
+CreateChromeApplicationShortcutView::~CreateChromeApplicationShortcutView() {} |
-void CreateApplicationShortcutView::InitControls(DialogLayout dialog_layout) { |
- if (dialog_layout == DIALOG_LAYOUT_URL_SHORTCUT && shortcut_info_) { |
- app_info_ = |
- new AppInfoView(shortcut_info_->title, shortcut_info_->description, |
- shortcut_info_->favicon); |
- } |
+void CreateChromeApplicationShortcutView::InitControls() { |
create_shortcuts_label_ = new views::Label( |
l10n_util::GetStringUTF16(IDS_CREATE_SHORTCUTS_LABEL)); |
create_shortcuts_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
@@ -294,12 +113,6 @@ void CreateApplicationShortcutView::InitControls(DialogLayout dialog_layout) { |
column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, |
100.0f, views::GridLayout::USE_PREF, 0, 0); |
- if (app_info_) { |
- layout->StartRow(0, kHeaderColumnSetId); |
- layout->AddView(app_info_); |
- layout->AddPaddingRow(0, views::kPanelSubVerticalSpacing); |
- } |
- |
layout->StartRow(0, kHeaderColumnSetId); |
layout->AddView(create_shortcuts_label_); |
@@ -320,7 +133,7 @@ void CreateApplicationShortcutView::InitControls(DialogLayout dialog_layout) { |
} |
} |
-gfx::Size CreateApplicationShortcutView::GetPreferredSize() const { |
+gfx::Size CreateChromeApplicationShortcutView::GetPreferredSize() const { |
// TODO(evanm): should this use IDS_CREATE_SHORTCUTS_DIALOG_WIDTH_CHARS? |
static const int kDialogWidth = 360; |
int height = GetLayoutManager()->GetPreferredHeightForWidth(this, |
@@ -328,14 +141,14 @@ gfx::Size CreateApplicationShortcutView::GetPreferredSize() const { |
return gfx::Size(kDialogWidth, height); |
} |
-base::string16 CreateApplicationShortcutView::GetDialogButtonLabel( |
+base::string16 CreateChromeApplicationShortcutView::GetDialogButtonLabel( |
ui::DialogButton button) const { |
if (button == ui::DIALOG_BUTTON_OK) |
return l10n_util::GetStringUTF16(IDS_CREATE_SHORTCUTS_COMMIT); |
return views::DialogDelegateView::GetDialogButtonLabel(button); |
} |
-bool CreateApplicationShortcutView::IsDialogButtonEnabled( |
+bool CreateChromeApplicationShortcutView::IsDialogButtonEnabled( |
ui::DialogButton button) const { |
if (button == ui::DIALOG_BUTTON_OK) |
return desktop_check_box_->checked() || |
@@ -347,16 +160,18 @@ bool CreateApplicationShortcutView::IsDialogButtonEnabled( |
return true; |
} |
-ui::ModalType CreateApplicationShortcutView::GetModalType() const { |
+ui::ModalType CreateChromeApplicationShortcutView::GetModalType() const { |
return ui::MODAL_TYPE_WINDOW; |
} |
-base::string16 CreateApplicationShortcutView::GetWindowTitle() const { |
+base::string16 CreateChromeApplicationShortcutView::GetWindowTitle() const { |
return l10n_util::GetStringUTF16(IDS_CREATE_SHORTCUTS_TITLE); |
} |
-bool CreateApplicationShortcutView::Accept() { |
+bool CreateChromeApplicationShortcutView::Accept() { |
// NOTE: This procedure will reset |shortcut_info_| to null. |
+ if (!close_callback_.is_null()) |
+ close_callback_.Run(true); |
// Can happen if the shortcut data is not yet loaded. |
if (!shortcut_info_) |
@@ -369,9 +184,7 @@ bool CreateApplicationShortcutView::Accept() { |
creation_locations.on_desktop = desktop_check_box_->checked(); |
if (menu_check_box_ != nullptr && menu_check_box_->checked()) { |
creation_locations.applications_menu_location = |
- create_in_chrome_apps_subdir_ ? |
- web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS : |
- web_app::APP_MENU_LOCATION_ROOT; |
+ web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS; |
} |
#if defined(OS_WIN) |
@@ -389,16 +202,15 @@ bool CreateApplicationShortcutView::Accept() { |
return true; |
} |
-views::Checkbox* CreateApplicationShortcutView::AddCheckbox( |
- const base::string16& text, bool checked) { |
- views::Checkbox* checkbox = new views::Checkbox(text); |
- checkbox->SetChecked(checked); |
- checkbox->set_listener(this); |
- return checkbox; |
+bool CreateChromeApplicationShortcutView::Cancel() { |
+ if (!close_callback_.is_null()) |
+ close_callback_.Run(false); |
+ return true; |
} |
-void CreateApplicationShortcutView::ButtonPressed(views::Button* sender, |
- const ui::Event& event) { |
+void CreateChromeApplicationShortcutView::ButtonPressed( |
+ views::Button* sender, |
+ const ui::Event& event) { |
if (sender == desktop_check_box_) { |
profile_->GetPrefs()->SetBoolean(prefs::kWebAppCreateOnDesktop, |
desktop_check_box_->checked()); |
@@ -414,130 +226,13 @@ void CreateApplicationShortcutView::ButtonPressed(views::Button* sender, |
GetDialogClientView()->UpdateDialogButtons(); |
} |
-CreateUrlApplicationShortcutView::CreateUrlApplicationShortcutView( |
- content::WebContents* web_contents) |
- : CreateApplicationShortcutView( |
- Profile::FromBrowserContext(web_contents->GetBrowserContext())), |
- web_contents_(web_contents), |
- pending_download_id_(-1), |
- weak_ptr_factory_(this) { |
- shortcut_info_ = web_app::GetShortcutInfoForTab(web_contents_); |
- const WebApplicationInfo& app_info = |
- extensions::TabHelper::FromWebContents(web_contents_)->web_app_info(); |
- if (!app_info.icons.empty()) { |
- web_app::GetIconsInfo(app_info, &unprocessed_icons_); |
- FetchIcon(); |
- } |
- |
- // Create URL app shortcuts in the top-level menu. |
- create_in_chrome_apps_subdir_ = false; |
- |
- InitControls(DIALOG_LAYOUT_URL_SHORTCUT); |
-} |
- |
-CreateUrlApplicationShortcutView::~CreateUrlApplicationShortcutView() { |
-} |
- |
-bool CreateUrlApplicationShortcutView::Accept() { |
- // Get the smallest icon in the icon family (should have only 1). This must be |
- // done before the call to Accept(), which will reset |shortcut_info_|. |
- DCHECK(shortcut_info_); |
- const gfx::Image* icon = shortcut_info_->favicon.GetBest(0, 0); |
- SkBitmap bitmap = icon ? icon->AsBitmap() : SkBitmap(); |
- |
- if (!CreateApplicationShortcutView::Accept()) |
- return false; |
- |
- extensions::TabHelper::FromWebContents(web_contents_)->SetAppIcon(bitmap); |
- Browser* browser = chrome::FindBrowserWithWebContents(web_contents_); |
- if (browser) |
- chrome::ConvertTabToAppWindow(browser, web_contents_); |
- return true; |
-} |
- |
-void CreateUrlApplicationShortcutView::FetchIcon() { |
- // There should only be fetch job at a time. |
- DCHECK_EQ(-1, pending_download_id_); |
- |
- if (unprocessed_icons_.empty()) // No icons to fetch. |
- return; |
- |
- int preferred_size = std::max(unprocessed_icons_.back().width, |
- unprocessed_icons_.back().height); |
- pending_download_id_ = web_contents_->DownloadImage( |
- unprocessed_icons_.back().url, |
- true, // is a favicon |
- 0, // no maximum size |
- false, // normal cache policy |
- base::Bind(&CreateUrlApplicationShortcutView::DidDownloadFavicon, |
- weak_ptr_factory_.GetWeakPtr(), |
- preferred_size)); |
- |
- unprocessed_icons_.pop_back(); |
-} |
- |
-void CreateUrlApplicationShortcutView::DidDownloadFavicon( |
- int requested_size, |
- int id, |
- int http_status_code, |
- const GURL& image_url, |
- const std::vector<SkBitmap>& bitmaps, |
- const std::vector<gfx::Size>& original_bitmap_sizes) { |
- if (id != pending_download_id_) |
- return; |
- pending_download_id_ = -1; |
- |
- // Can happen if the dialog has already been accepted. |
- if (!shortcut_info_) |
- return; |
- |
- gfx::ImageSkia image_skia = CreateFaviconImageSkia( |
- bitmaps, |
- original_bitmap_sizes, |
- requested_size, |
- nullptr); |
- if (!image_skia.isNull()) { |
- // As |shortcut_info_| will be passed to the FILE thread upon accepting the |
- // dialog, this image must be made read-only and thread-safe. |
- image_skia.MakeThreadSafe(); |
- shortcut_info_->favicon.Add(image_skia); |
- static_cast<AppInfoView*>(app_info_)->UpdateIcon(shortcut_info_->favicon); |
- } else { |
- FetchIcon(); |
- } |
-} |
- |
-CreateChromeApplicationShortcutView::CreateChromeApplicationShortcutView( |
- Profile* profile, |
- const extensions::Extension* app, |
- const base::Callback<void(bool)>& close_callback) |
- : CreateApplicationShortcutView(profile), |
- close_callback_(close_callback), |
- weak_ptr_factory_(this) { |
- // Place Chrome app shortcuts in the "Chrome Apps" submenu. |
- create_in_chrome_apps_subdir_ = true; |
- |
- InitControls(DIALOG_LAYOUT_APP_SHORTCUT); |
- |
- // Get shortcut and icon information; needed for creating the shortcut. |
- web_app::GetShortcutInfoForApp( |
- app, profile, |
- base::Bind(&CreateChromeApplicationShortcutView::OnAppInfoLoaded, |
- weak_ptr_factory_.GetWeakPtr())); |
-} |
- |
-CreateChromeApplicationShortcutView::~CreateChromeApplicationShortcutView() {} |
- |
-bool CreateChromeApplicationShortcutView::Accept() { |
- if (!close_callback_.is_null()) |
- close_callback_.Run(true); |
- return CreateApplicationShortcutView::Accept(); |
-} |
- |
-bool CreateChromeApplicationShortcutView::Cancel() { |
- if (!close_callback_.is_null()) |
- close_callback_.Run(false); |
- return CreateApplicationShortcutView::Cancel(); |
+views::Checkbox* CreateChromeApplicationShortcutView::AddCheckbox( |
+ const base::string16& text, |
+ bool checked) { |
+ views::Checkbox* checkbox = new views::Checkbox(text); |
+ checkbox->SetChecked(checked); |
+ checkbox->set_listener(this); |
+ return checkbox; |
} |
void CreateChromeApplicationShortcutView::OnAppInfoLoaded( |