extension_uninstall_dialog_view.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/extensions/extension_uninstall_dialog.h" 6 7#include "base/basictypes.h" 8#include "base/compiler_specific.h" 9#include "base/strings/string_util.h" 10#include "base/strings/utf_string_conversions.h" 11#include "chrome/browser/ui/app_list/app_list_service.h" 12#include "chrome/browser/ui/browser.h" 13#include "chrome/browser/ui/browser_window.h" 14#include "chrome/browser/ui/views/constrained_window_views.h" 15#include "extensions/common/extension.h" 16#include "grit/generated_resources.h" 17#include "ui/base/l10n/l10n_util.h" 18#include "ui/compositor/compositor.h" 19#include "ui/compositor/layer.h" 20#include "ui/views/controls/image_view.h" 21#include "ui/views/controls/label.h" 22#include "ui/views/layout/layout_constants.h" 23#include "ui/views/view.h" 24#include "ui/views/widget/widget.h" 25#include "ui/views/window/dialog_delegate.h" 26 27namespace { 28 29const int kRightColumnWidth = 210; 30const int kIconSize = 64; 31 32class ExtensionUninstallDialogDelegateView; 33 34// Returns parent window for extension uninstall dialog. 35gfx::NativeWindow GetParent(Browser* browser) { 36 if (browser && browser->window()) 37 return browser->window()->GetNativeWindow(); 38 return NULL; 39} 40 41// Views implementation of the uninstall dialog. 42class ExtensionUninstallDialogViews 43 : public extensions::ExtensionUninstallDialog { 44 public: 45 ExtensionUninstallDialogViews( 46 Profile* profile, 47 Browser* browser, 48 extensions::ExtensionUninstallDialog::Delegate* delegate); 49 virtual ~ExtensionUninstallDialogViews(); 50 51 // Forwards the accept and cancels to the delegate. 52 void ExtensionUninstallAccepted(); 53 void ExtensionUninstallCanceled(); 54 55 ExtensionUninstallDialogDelegateView* view() { return view_; } 56 57 private: 58 virtual void Show() OVERRIDE; 59 60 ExtensionUninstallDialogDelegateView* view_; 61 bool show_in_app_list_; 62 63 DISALLOW_COPY_AND_ASSIGN(ExtensionUninstallDialogViews); 64}; 65 66// The dialog's view, owned by the views framework. 67class ExtensionUninstallDialogDelegateView : public views::DialogDelegateView { 68 public: 69 ExtensionUninstallDialogDelegateView( 70 ExtensionUninstallDialogViews* dialog_view, 71 const extensions::Extension* extension, 72 const extensions::Extension* triggering_extension, 73 gfx::ImageSkia* icon); 74 virtual ~ExtensionUninstallDialogDelegateView(); 75 76 // Called when the ExtensionUninstallDialog has been destroyed to make sure 77 // we invalidate pointers. 78 void DialogDestroyed() { dialog_ = NULL; } 79 80 private: 81 // views::DialogDelegate: 82 virtual base::string16 GetDialogButtonLabel( 83 ui::DialogButton button) const OVERRIDE; 84 virtual int GetDefaultDialogButton() const OVERRIDE { 85 // Default to accept when triggered via chrome://extensions page. 86 return triggered_by_extension_ ? 87 ui::DIALOG_BUTTON_CANCEL : ui::DIALOG_BUTTON_OK; 88 } 89 virtual bool Accept() OVERRIDE; 90 virtual bool Cancel() OVERRIDE; 91 92 // views::WidgetDelegate: 93 virtual ui::ModalType GetModalType() const OVERRIDE { 94 return ui::MODAL_TYPE_WINDOW; 95 } 96 virtual base::string16 GetWindowTitle() const OVERRIDE; 97 98 // views::View: 99 virtual gfx::Size GetPreferredSize() const OVERRIDE; 100 101 virtual void Layout() OVERRIDE; 102 103 ExtensionUninstallDialogViews* dialog_; 104 105 views::ImageView* icon_; 106 views::Label* heading_; 107 bool triggered_by_extension_; 108 109 DISALLOW_COPY_AND_ASSIGN(ExtensionUninstallDialogDelegateView); 110}; 111 112ExtensionUninstallDialogViews::ExtensionUninstallDialogViews( 113 Profile* profile, 114 Browser* browser, 115 extensions::ExtensionUninstallDialog::Delegate* delegate) 116 : extensions::ExtensionUninstallDialog(profile, browser, delegate), 117 view_(NULL), 118 show_in_app_list_(!browser) { 119} 120 121ExtensionUninstallDialogViews::~ExtensionUninstallDialogViews() { 122 // Close the widget (the views framework will delete view_). 123 if (view_) { 124 view_->DialogDestroyed(); 125 view_->GetWidget()->CloseNow(); 126 } 127} 128 129void ExtensionUninstallDialogViews::Show() { 130 // TODO(tapted): A true |desktop_type| needs to be passed in at creation time 131 // to remove reliance on GetActiveDesktop(). http://crbug.com/308360 132 gfx::NativeWindow parent = show_in_app_list_ ? 133 AppListService::Get(chrome::GetActiveDesktop())->GetAppListWindow() : 134 GetParent(browser_); 135 if (browser_ && !parent) { 136 delegate_->ExtensionUninstallCanceled(); 137 return; 138 } 139 140 view_ = new ExtensionUninstallDialogDelegateView( 141 this, extension_, triggering_extension_, &icon_); 142 CreateBrowserModalDialogViews(view_, parent)->Show(); 143} 144 145void ExtensionUninstallDialogViews::ExtensionUninstallAccepted() { 146 // The widget gets destroyed when the dialog is accepted. 147 view_ = NULL; 148 delegate_->ExtensionUninstallAccepted(); 149} 150 151void ExtensionUninstallDialogViews::ExtensionUninstallCanceled() { 152 // The widget gets destroyed when the dialog is canceled. 153 view_ = NULL; 154 delegate_->ExtensionUninstallCanceled(); 155} 156 157ExtensionUninstallDialogDelegateView::ExtensionUninstallDialogDelegateView( 158 ExtensionUninstallDialogViews* dialog_view, 159 const extensions::Extension* extension, 160 const extensions::Extension* triggering_extension, 161 gfx::ImageSkia* icon) 162 : dialog_(dialog_view), 163 triggered_by_extension_(triggering_extension != NULL) { 164 // Scale down to icon size, but allow smaller icons (don't scale up). 165 gfx::Size size(icon->width(), icon->height()); 166 if (size.width() > kIconSize || size.height() > kIconSize) 167 size = gfx::Size(kIconSize, kIconSize); 168 icon_ = new views::ImageView(); 169 icon_->SetImageSize(size); 170 icon_->SetImage(*icon); 171 AddChildView(icon_); 172 173 heading_ = new views::Label(base::UTF8ToUTF16(dialog_->GetHeadingText())); 174 heading_->SetMultiLine(true); 175 heading_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 176 AddChildView(heading_); 177} 178 179ExtensionUninstallDialogDelegateView::~ExtensionUninstallDialogDelegateView() { 180} 181 182base::string16 ExtensionUninstallDialogDelegateView::GetDialogButtonLabel( 183 ui::DialogButton button) const { 184 return l10n_util::GetStringUTF16((button == ui::DIALOG_BUTTON_OK) ? 185 IDS_EXTENSION_PROMPT_UNINSTALL_BUTTON : IDS_CANCEL); 186} 187 188bool ExtensionUninstallDialogDelegateView::Accept() { 189 if (dialog_) 190 dialog_->ExtensionUninstallAccepted(); 191 return true; 192} 193 194bool ExtensionUninstallDialogDelegateView::Cancel() { 195 if (dialog_) 196 dialog_->ExtensionUninstallCanceled(); 197 return true; 198} 199 200base::string16 ExtensionUninstallDialogDelegateView::GetWindowTitle() const { 201 return l10n_util::GetStringUTF16(IDS_EXTENSION_UNINSTALL_PROMPT_TITLE); 202} 203 204gfx::Size ExtensionUninstallDialogDelegateView::GetPreferredSize() const { 205 int width = kRightColumnWidth; 206 width += kIconSize; 207 width += views::kButtonHEdgeMarginNew * 2; 208 width += views::kRelatedControlHorizontalSpacing; 209 210 int height = views::kPanelVertMargin * 2; 211 height += heading_->GetHeightForWidth(kRightColumnWidth); 212 213 return gfx::Size(width, 214 std::max(height, kIconSize + views::kPanelVertMargin * 2)); 215} 216 217void ExtensionUninstallDialogDelegateView::Layout() { 218 int x = views::kButtonHEdgeMarginNew; 219 int y = views::kPanelVertMargin; 220 221 heading_->SizeToFit(kRightColumnWidth); 222 223 if (heading_->height() <= kIconSize) { 224 icon_->SetBounds(x, y, kIconSize, kIconSize); 225 x += kIconSize; 226 x += views::kRelatedControlHorizontalSpacing; 227 228 heading_->SetX(x); 229 heading_->SetY(y + (kIconSize - heading_->height()) / 2); 230 } else { 231 icon_->SetBounds(x, 232 y + (heading_->height() - kIconSize) / 2, 233 kIconSize, 234 kIconSize); 235 x += kIconSize; 236 x += views::kRelatedControlHorizontalSpacing; 237 238 heading_->SetX(x); 239 heading_->SetY(y); 240 } 241} 242 243} // namespace 244 245// static 246extensions::ExtensionUninstallDialog* 247extensions::ExtensionUninstallDialog::Create(Profile* profile, 248 Browser* browser, 249 Delegate* delegate) { 250 return new ExtensionUninstallDialogViews(profile, browser, delegate); 251} 252