1 // Copyright 2014 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 #ifndef CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSION_INSTALL_DIALOG_VIEW_H_ 6 #define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSION_INSTALL_DIALOG_VIEW_H_ 7 8 #include "chrome/browser/extensions/extension_install_prompt.h" 9 #include "ui/gfx/animation/animation_delegate.h" 10 #include "ui/gfx/animation/slide_animation.h" 11 #include "ui/views/controls/button/button.h" 12 #include "ui/views/controls/link_listener.h" 13 #include "ui/views/view.h" 14 #include "ui/views/window/dialog_delegate.h" 15 16 typedef std::vector<base::string16> PermissionDetails; 17 class ExpandableContainerView; 18 19 namespace content { 20 class PageNavigator; 21 } 22 23 namespace extensions { 24 class ExperienceSamplingEvent; 25 } 26 27 namespace ui { 28 class ResourceBundle; 29 } 30 31 namespace views { 32 class GridLayout; 33 class ImageButton; 34 class Label; 35 class Link; 36 } 37 38 // A custom scrollable view implementation for the dialog. 39 class CustomScrollableView : public views::View { 40 public: 41 CustomScrollableView(); 42 virtual ~CustomScrollableView(); 43 44 private: 45 virtual void Layout() OVERRIDE; 46 47 DISALLOW_COPY_AND_ASSIGN(CustomScrollableView); 48 }; 49 50 // Implements the extension installation dialog for TOOLKIT_VIEWS. 51 class ExtensionInstallDialogView : public views::DialogDelegateView, 52 public views::LinkListener, 53 public views::ButtonListener { 54 public: 55 ExtensionInstallDialogView( 56 content::PageNavigator* navigator, 57 ExtensionInstallPrompt::Delegate* delegate, 58 scoped_refptr<ExtensionInstallPrompt::Prompt> prompt); 59 virtual ~ExtensionInstallDialogView(); 60 61 // Returns the interior ScrollView of the dialog. This allows us to inspect 62 // the contents of the DialogView. 63 const views::ScrollView* scroll_view() const { return scroll_view_; } 64 65 // Called when one of the child elements has expanded/collapsed. 66 void ContentsChanged(); 67 68 private: 69 // views::DialogDelegateView: 70 virtual int GetDialogButtons() const OVERRIDE; 71 virtual base::string16 GetDialogButtonLabel( 72 ui::DialogButton button) const OVERRIDE; 73 virtual int GetDefaultDialogButton() const OVERRIDE; 74 virtual bool Cancel() OVERRIDE; 75 virtual bool Accept() OVERRIDE; 76 virtual ui::ModalType GetModalType() const OVERRIDE; 77 virtual base::string16 GetWindowTitle() const OVERRIDE; 78 virtual void Layout() OVERRIDE; 79 virtual gfx::Size GetPreferredSize() const OVERRIDE; 80 virtual void ViewHierarchyChanged( 81 const ViewHierarchyChangedDetails& details) OVERRIDE; 82 83 // views::LinkListener: 84 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 85 86 // views::ButtonListener: 87 virtual void ButtonPressed(views::Button* sender, 88 const ui::Event& event) OVERRIDE; 89 90 // Experimental: Toggles inline permission explanations with an animation. 91 void ToggleInlineExplanations(); 92 93 // Initializes the dialog view, adding in permissions if they exist. 94 void InitView(); 95 96 // Adds permissions of |perm_type| to the dialog view if they exist. 97 bool AddPermissions(views::GridLayout* layout, 98 ui::ResourceBundle& rb, 99 int column_set_id, 100 int left_column_width, 101 ExtensionInstallPrompt::PermissionsType perm_type); 102 103 // Creates a layout consisting of dialog header, extension name and icon. 104 views::GridLayout* CreateLayout( 105 views::View* parent, 106 int left_column_width, 107 int column_set_id, 108 bool single_detail_row) const; 109 110 bool is_inline_install() const { 111 return prompt_->type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT; 112 } 113 114 bool is_bundle_install() const { 115 return prompt_->type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT; 116 } 117 118 bool is_external_install() const { 119 return prompt_->type() == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT; 120 } 121 122 // Updates the histogram that holds installation accepted/aborted data. 123 void UpdateInstallResultHistogram(bool accepted) const; 124 125 // Updates the histogram that holds data about whether "Show details" or 126 // "Show permissions" links were shown and/or clicked. 127 void UpdateLinkActionHistogram(int action_type) const; 128 129 content::PageNavigator* navigator_; 130 ExtensionInstallPrompt::Delegate* delegate_; 131 scoped_refptr<ExtensionInstallPrompt::Prompt> prompt_; 132 133 // The scroll view containing all the details for the dialog (including all 134 // collapsible/expandable sections). 135 views::ScrollView* scroll_view_; 136 137 // The container view for the scroll view. 138 CustomScrollableView* scrollable_; 139 140 // The container for the simpler view with only the dialog header and the 141 // extension icon. Used for the experiment where the permissions are 142 // initially hidden when the dialog shows. 143 CustomScrollableView* scrollable_header_only_; 144 145 // The preferred size of the dialog. 146 gfx::Size dialog_size_; 147 148 // Experimental: "Show details" link to expand inline explanations and reveal 149 // permision dialog. 150 views::Link* show_details_link_; 151 152 // Experimental: Label for showing information about the checkboxes. 153 views::Label* checkbox_info_label_; 154 155 // Experimental: Contains pointers to inline explanation views. 156 typedef std::vector<ExpandableContainerView*> InlineExplanations; 157 InlineExplanations inline_explanations_; 158 159 // Experimental: Number of unchecked checkboxes in the permission list. 160 // If this becomes zero, the accept button is enabled, otherwise disabled. 161 int unchecked_boxes_; 162 163 // ExperienceSampling: Track this UI event. 164 scoped_ptr<extensions::ExperienceSamplingEvent> sampling_event_; 165 166 // Set to true once the user's selection has been received and the 167 // |delegate_| has been notified. 168 bool handled_result_; 169 170 DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogView); 171 }; 172 173 // A simple view that prepends a view with a bullet with the help of a grid 174 // layout. 175 class BulletedView : public views::View { 176 public: 177 explicit BulletedView(views::View* view); 178 private: 179 DISALLOW_COPY_AND_ASSIGN(BulletedView); 180 }; 181 182 // A simple view that prepends a view with a checkbox with the help of a grid 183 // layout. Used for the permission experiment. 184 // TODO(meacer): Remove once the experiment is completed. 185 class CheckboxedView : public views::View { 186 public: 187 CheckboxedView(views::View* view, views::ButtonListener* listener); 188 private: 189 DISALLOW_COPY_AND_ASSIGN(CheckboxedView); 190 }; 191 192 // A view to display text with an expandable details section. 193 class ExpandableContainerView : public views::View, 194 public views::ButtonListener, 195 public views::LinkListener, 196 public gfx::AnimationDelegate { 197 public: 198 ExpandableContainerView(ExtensionInstallDialogView* owner, 199 const base::string16& description, 200 const PermissionDetails& details, 201 int horizontal_space, 202 bool parent_bulleted, 203 bool show_expand_link, 204 bool lighter_color_details); 205 virtual ~ExpandableContainerView(); 206 207 // views::View: 208 virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE; 209 210 // views::ButtonListener: 211 virtual void ButtonPressed(views::Button* sender, 212 const ui::Event& event) OVERRIDE; 213 214 // views::LinkListener: 215 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 216 217 // gfx::AnimationDelegate: 218 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; 219 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; 220 221 // Expand/Collapse the detail section for this ExpandableContainerView. 222 void ToggleDetailLevel(); 223 224 // Expand the detail section without any animation. 225 // TODO(meacer): Remove once the experiment is completed. 226 void ExpandWithoutAnimation(); 227 228 private: 229 // A view which displays all the details of an IssueAdviceInfoEntry. 230 class DetailsView : public views::View { 231 public: 232 explicit DetailsView(int horizontal_space, bool parent_bulleted, 233 bool lighter_color); 234 virtual ~DetailsView() {} 235 236 // views::View: 237 virtual gfx::Size GetPreferredSize() const OVERRIDE; 238 239 void AddDetail(const base::string16& detail); 240 241 // Animates this to be a height proportional to |state|. 242 void AnimateToState(double state); 243 244 private: 245 views::GridLayout* layout_; 246 double state_; 247 248 // Whether the detail text should be shown with a lighter color. 249 bool lighter_color_; 250 251 DISALLOW_COPY_AND_ASSIGN(DetailsView); 252 }; 253 254 // The dialog that owns |this|. It's also an ancestor in the View hierarchy. 255 ExtensionInstallDialogView* owner_; 256 257 // A view for showing |issue_advice.details|. 258 DetailsView* details_view_; 259 260 // The 'more details' link shown under the heading (changes to 'hide details' 261 // when the details section is expanded). 262 views::Link* more_details_; 263 264 gfx::SlideAnimation slide_animation_; 265 266 // The up/down arrow next to the 'more detail' link (points up/down depending 267 // on whether the details section is expanded). 268 views::ImageButton* arrow_toggle_; 269 270 // Whether the details section is expanded. 271 bool expanded_; 272 273 DISALLOW_COPY_AND_ASSIGN(ExpandableContainerView); 274 }; 275 276 void ShowExtensionInstallDialogImpl( 277 const ExtensionInstallPrompt::ShowParams& show_params, 278 ExtensionInstallPrompt::Delegate* delegate, 279 scoped_refptr<ExtensionInstallPrompt::Prompt> prompt); 280 281 #endif // CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSION_INSTALL_DIALOG_VIEW_H_ 282