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