extension_install_dialog_view.h revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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
16typedef std::vector<base::string16> PermissionDetails;
17class ExpandableContainerView;
18
19namespace content {
20class PageNavigator;
21}
22
23namespace extensions {
24class ExperienceSamplingEvent;
25}
26
27namespace ui {
28class ResourceBundle;
29}
30
31namespace views {
32class GridLayout;
33class ImageButton;
34class Label;
35class Link;
36}
37
38// A custom scrollable view implementation for the dialog.
39class 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.
51class 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.
175class 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.
185class 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.
193class 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
276void 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