Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(302)

Side by Side Diff: chrome/browser/ui/views/extensions/extension_install_dialog_view.cc

Issue 18854021: Making the extension permissions dialog scrollable, when needed (adding expandable sections for thi… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Polish Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <vector> 5 #include <vector>
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
(...skipping 11 matching lines...) Expand all
22 #include "grit/chromium_strings.h" 22 #include "grit/chromium_strings.h"
23 #include "grit/generated_resources.h" 23 #include "grit/generated_resources.h"
24 #include "grit/google_chrome_strings.h" 24 #include "grit/google_chrome_strings.h"
25 #include "grit/theme_resources.h" 25 #include "grit/theme_resources.h"
26 #include "ui/base/animation/animation_delegate.h" 26 #include "ui/base/animation/animation_delegate.h"
27 #include "ui/base/animation/slide_animation.h" 27 #include "ui/base/animation/slide_animation.h"
28 #include "ui/base/l10n/l10n_util.h" 28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/resource/resource_bundle.h" 29 #include "ui/base/resource/resource_bundle.h"
30 #include "ui/gfx/transform.h" 30 #include "ui/gfx/transform.h"
31 #include "ui/views/border.h" 31 #include "ui/views/border.h"
32 #include "ui/views/controls/button/image_button.h"
32 #include "ui/views/controls/image_view.h" 33 #include "ui/views/controls/image_view.h"
33 #include "ui/views/controls/label.h" 34 #include "ui/views/controls/label.h"
34 #include "ui/views/controls/link.h" 35 #include "ui/views/controls/link.h"
35 #include "ui/views/controls/link_listener.h" 36 #include "ui/views/controls/link_listener.h"
36 #include "ui/views/controls/scroll_view.h" 37 #include "ui/views/controls/scroll_view.h"
37 #include "ui/views/controls/separator.h" 38 #include "ui/views/controls/separator.h"
38 #include "ui/views/layout/box_layout.h" 39 #include "ui/views/layout/box_layout.h"
39 #include "ui/views/layout/grid_layout.h" 40 #include "ui/views/layout/grid_layout.h"
40 #include "ui/views/layout/layout_constants.h" 41 #include "ui/views/layout/layout_constants.h"
41 #include "ui/views/view.h" 42 #include "ui/views/view.h"
42 #include "ui/views/widget/widget.h" 43 #include "ui/views/widget/widget.h"
43 #include "ui/views/window/dialog_delegate.h" 44 #include "ui/views/window/dialog_delegate.h"
44 45
45 using content::OpenURLParams; 46 using content::OpenURLParams;
46 using content::Referrer; 47 using content::Referrer;
47 using extensions::BundleInstaller; 48 using extensions::BundleInstaller;
48 49
49 namespace { 50 namespace {
50 51
51 // Size of extension icon in top left of dialog. 52 // Size of extension icon in top left of dialog.
52 const int kIconSize = 69; 53 const int kIconSize = 69;
53 54
55 // The dialog width.
56 const int kDialogWidth = 385;
57
58 // The dialog will resize based on its content, but this sets a maximum height
59 // before overflowing a scrollbar.
60 const int kDialogMaxHeight = 300;
61
54 // Width of the left column of the dialog when the extension requests 62 // Width of the left column of the dialog when the extension requests
55 // permissions. 63 // permissions.
56 const int kPermissionsLeftColumnWidth = 250; 64 const int kPermissionsLeftColumnWidth = 250;
57 65
58 // Width of the left column of the dialog when the extension requests no 66 // Width of the left column of the dialog when the extension requests no
59 // permissions. 67 // permissions.
60 const int kNoPermissionsLeftColumnWidth = 200; 68 const int kNoPermissionsLeftColumnWidth = 200;
61 69
62 // Width of the left column for bundle install prompts. There's only one column 70 // Width of the left column for bundle install prompts. There's only one column
63 // in this case, so make it wider than normal. 71 // in this case, so make it wider than normal.
64 const int kBundleLeftColumnWidth = 300; 72 const int kBundleLeftColumnWidth = 300;
65 73
66 // Width of the left column for external install prompts. The text is long in 74 // Width of the left column for external install prompts. The text is long in
67 // this case, so make it wider than normal. 75 // this case, so make it wider than normal.
68 const int kExternalInstallLeftColumnWidth = 350; 76 const int kExternalInstallLeftColumnWidth = 350;
69 77
70 // Maximum height of the retained files view. 78 // Maximum height of the retained files view.
71 const int kMaxRetainedFilesHeight = 100; 79 const int kMaxRetainedFilesHeight = 100;
72 80
81 typedef std::vector<string16> PermissionDetails;
82
73 void AddResourceIcon(const gfx::ImageSkia* skia_image, void* data) { 83 void AddResourceIcon(const gfx::ImageSkia* skia_image, void* data) {
74 views::View* parent = static_cast<views::View*>(data); 84 views::View* parent = static_cast<views::View*>(data);
75 views::ImageView* image_view = new views::ImageView(); 85 views::ImageView* image_view = new views::ImageView();
76 image_view->SetImage(*skia_image); 86 image_view->SetImage(*skia_image);
77 parent->AddChildView(image_view); 87 parent->AddChildView(image_view);
78 } 88 }
79 89
80 // Creates a string for displaying |message| to the user. If it has to look 90 // Creates a string for displaying |message| to the user. If it has to look
81 // like a entry in a bullet point list, one is added. 91 // like a entry in a bullet point list, one is added.
82 string16 PrepareForDisplay(const string16& message, bool bullet_point) { 92 string16 PrepareForDisplay(const string16& message, bool bullet_point) {
83 return bullet_point ? l10n_util::GetStringFUTF16( 93 return bullet_point ? l10n_util::GetStringFUTF16(
84 IDS_EXTENSION_PERMISSION_LINE, 94 IDS_EXTENSION_PERMISSION_LINE,
85 message) : message; 95 message) : message;
86 } 96 }
87 97
88 // Implements the extension installation dialog for TOOLKIT_VIEWS. 98 // Implements the extension installation dialog for TOOLKIT_VIEWS.
89 class ExtensionInstallDialogView : public views::DialogDelegateView, 99 class ExtensionInstallDialogView : public views::DialogDelegateView,
90 public views::LinkListener { 100 public views::LinkListener {
91 public: 101 public:
92 ExtensionInstallDialogView(content::PageNavigator* navigator, 102 ExtensionInstallDialogView(content::PageNavigator* navigator,
93 ExtensionInstallPrompt::Delegate* delegate, 103 ExtensionInstallPrompt::Delegate* delegate,
94 const ExtensionInstallPrompt::Prompt& prompt); 104 const ExtensionInstallPrompt::Prompt& prompt);
95 virtual ~ExtensionInstallDialogView(); 105 virtual ~ExtensionInstallDialogView();
96 106
97 // Changes the size of the containing widget to match the preferred size 107 // Called when one of the child elements has expanded/collapsed.
98 // of this dialog. 108 void ContentsChanged();
99 void SizeToContents();
100 109
101 private: 110 private:
102 // views::DialogDelegateView: 111 // views::DialogDelegateView:
103 virtual int GetDialogButtons() const OVERRIDE; 112 virtual int GetDialogButtons() const OVERRIDE;
104 virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE; 113 virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE;
105 virtual int GetDefaultDialogButton() const OVERRIDE; 114 virtual int GetDefaultDialogButton() const OVERRIDE;
106 virtual bool Cancel() OVERRIDE; 115 virtual bool Cancel() OVERRIDE;
107 virtual bool Accept() OVERRIDE; 116 virtual bool Accept() OVERRIDE;
108
109 // views::WidgetDelegate:
110 virtual ui::ModalType GetModalType() const OVERRIDE; 117 virtual ui::ModalType GetModalType() const OVERRIDE;
111 virtual string16 GetWindowTitle() const OVERRIDE; 118 virtual string16 GetWindowTitle() const OVERRIDE;
119 virtual void Layout() OVERRIDE;
120 virtual gfx::Size GetPreferredSize() OVERRIDE;
112 121
113 // views::LinkListener: 122 // views::LinkListener:
114 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 123 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
115 124
116 bool is_inline_install() const { 125 bool is_inline_install() const {
117 return prompt_.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT; 126 return prompt_.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT;
118 } 127 }
119 128
120 bool is_bundle_install() const { 129 bool is_bundle_install() const {
121 return prompt_.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT; 130 return prompt_.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT;
122 } 131 }
123 132
124 bool is_external_install() const { 133 bool is_external_install() const {
125 return prompt_.type() == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT; 134 return prompt_.type() == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT;
126 } 135 }
127 136
128 content::PageNavigator* navigator_; 137 content::PageNavigator* navigator_;
129 ExtensionInstallPrompt::Delegate* delegate_; 138 ExtensionInstallPrompt::Delegate* delegate_;
130 ExtensionInstallPrompt::Prompt prompt_; 139 ExtensionInstallPrompt::Prompt prompt_;
131 140
141 // The scroll view containing all the details for the dialog (including all
142 // collapsible/expandable sections).
143 views::ScrollView* scroll_view_;
144
145 // The container view for the scroll view.
146 views::View* scrollable_;
147
148 // The preferred size of the dialog.
149 gfx::Size dialog_size_;
150
132 DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogView); 151 DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogView);
133 }; 152 };
134 153
135 // A view to display a single IssueAdviceInfoEntry. 154 // A view to display text with an expandable details section.
136 class IssueAdviceView : public views::View, 155 class ExpandableContainerView : public views::View,
137 public ui::AnimationDelegate { 156 public views::ButtonListener,
157 public views::LinkListener,
158 public ui::AnimationDelegate {
138 public: 159 public:
139 IssueAdviceView(ExtensionInstallDialogView* owner, 160 ExpandableContainerView(ExtensionInstallDialogView* owner,
140 const IssueAdviceInfoEntry& issue_advice, 161 const string16& description,
141 int horizontal_space); 162 const PermissionDetails& details,
142 virtual ~IssueAdviceView() {} 163 int horizontal_space,
164 bool show_bullets);
165 virtual ~ExpandableContainerView();
143 166
144 // Implementation of views::View: 167 // views::View:
145 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
146 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
147 virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE; 168 virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE;
148 169
149 // Implementation of ui::AnimationDelegate: 170 // views::ButtonListener:
171 virtual void ButtonPressed(views::Button* sender,
172 const ui::Event& event) OVERRIDE;
173
174 // views::LinkListener:
175 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
176
177 // ui::AnimationDelegate:
150 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; 178 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
179 virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE;
151 180
152 private: 181 private:
153 // A view which displays all the details of an IssueAdviceInfoEntry. 182 // A view which displays all the details of an IssueAdviceInfoEntry.
154 class DetailsView : public views::View { 183 class DetailsView : public views::View {
155 public: 184 public:
156 explicit DetailsView(int horizontal_space); 185 explicit DetailsView(int horizontal_space, bool show_bullets);
157 virtual ~DetailsView() {} 186 virtual ~DetailsView() {}
158 187
159 // Implementation of views::View: 188 // views::View:
160 virtual gfx::Size GetPreferredSize() OVERRIDE; 189 virtual gfx::Size GetPreferredSize() OVERRIDE;
161 190
162 void AddDetail(const string16& detail); 191 void AddDetail(const string16& detail);
163 192
164 // Animates this to be a height proportional to |state|. 193 // Animates this to be a height proportional to |state|.
165 void AnimateToState(double state); 194 void AnimateToState(double state);
166 195
167 private: 196 private:
168 views::GridLayout* layout_; 197 views::GridLayout* layout_;
169 double state_; 198 double state_;
170 199
200 // Whether to show bullets in front of each item in the details.
201 bool show_bullets_;
202
171 DISALLOW_COPY_AND_ASSIGN(DetailsView); 203 DISALLOW_COPY_AND_ASSIGN(DetailsView);
172 }; 204 };
173 205
206 // Expand/Collapse the detail section for this ExpandableContainerView.
207 void ToggleDetailLevel();
208
174 // The dialog that owns |this|. It's also an ancestor in the View hierarchy. 209 // The dialog that owns |this|. It's also an ancestor in the View hierarchy.
175 ExtensionInstallDialogView* owner_; 210 ExtensionInstallDialogView* owner_;
176 211
177 // A view for showing |issue_advice.details|. 212 // A view for showing |issue_advice.details|.
178 DetailsView* details_view_; 213 DetailsView* details_view_;
179 214
180 // The '>' zippy control. 215 // The '>' zippy control.
181 views::ImageView* arrow_view_; 216 views::ImageView* arrow_view_;
182 217
183 ui::SlideAnimation slide_animation_; 218 ui::SlideAnimation slide_animation_;
184 219
185 DISALLOW_COPY_AND_ASSIGN(IssueAdviceView); 220 // The 'more details' link shown under the heading (changes to 'hide details'
221 // when the details section is expanded).
222 views::Link* more_details_;
223
224 // The up/down arrow next to the 'more detail' link (points up/down depending
225 // on whether the details section is expanded).
226 views::ImageButton* arrow_toggle_;
227
228 // Whether the details section is expanded.
229 bool expanded_;
230
231 DISALLOW_COPY_AND_ASSIGN(ExpandableContainerView);
186 }; 232 };
187 233
188 void ShowExtensionInstallDialogImpl( 234 void ShowExtensionInstallDialogImpl(
189 const ExtensionInstallPrompt::ShowParams& show_params, 235 const ExtensionInstallPrompt::ShowParams& show_params,
190 ExtensionInstallPrompt::Delegate* delegate, 236 ExtensionInstallPrompt::Delegate* delegate,
191 const ExtensionInstallPrompt::Prompt& prompt) { 237 const ExtensionInstallPrompt::Prompt& prompt) {
192 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 238 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
193 CreateBrowserModalDialogViews( 239 CreateBrowserModalDialogViews(
194 new ExtensionInstallDialogView(show_params.navigator, delegate, prompt), 240 new ExtensionInstallDialogView(show_params.navigator, delegate, prompt),
195 show_params.parent_window)->Show(); 241 show_params.parent_window)->Show();
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 // +--------------------| | 327 // +--------------------| |
282 // | permission2 | | 328 // | permission2 | |
283 // +--------------------+------+ 329 // +--------------------+------+
284 // | oauth header | 330 // | oauth header |
285 // +---------------------------+ 331 // +---------------------------+
286 // | oauth issue 1 | 332 // | oauth issue 1 |
287 // +---------------------------+ 333 // +---------------------------+
288 // | oauth issue 2 | 334 // | oauth issue 2 |
289 // +---------------------------+ 335 // +---------------------------+
290 336
291 views::GridLayout* layout = views::GridLayout::CreatePanel(this); 337 scroll_view_ = new views::ScrollView();
292 SetLayoutManager(layout); 338 AddChildView(scroll_view_);
339 scrollable_ = new views::View();
340 scroll_view_->SetContents(scrollable_);
341
342 views::GridLayout* layout = views::GridLayout::CreatePanel(scrollable_);
343 scrollable_->SetLayoutManager(layout);
293 344
294 int column_set_id = 0; 345 int column_set_id = 0;
295 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); 346 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id);
296 int left_column_width = 347 int left_column_width =
297 (prompt.ShouldShowPermissions() + prompt.GetOAuthIssueCount() + 348 (prompt.ShouldShowPermissions() + prompt.GetOAuthIssueCount() +
298 prompt.GetRetainedFileCount()) > 0 ? 349 prompt.GetRetainedFileCount()) > 0 ?
299 kPermissionsLeftColumnWidth : kNoPermissionsLeftColumnWidth; 350 kPermissionsLeftColumnWidth : kNoPermissionsLeftColumnWidth;
300 if (is_bundle_install()) 351 if (is_bundle_install())
301 left_column_width = kBundleLeftColumnWidth; 352 left_column_width = kBundleLeftColumnWidth;
302 if (is_external_install()) 353 if (is_external_install())
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 } else { 404 } else {
354 // This is the 'no special permissions' case, so span the line we add 405 // This is the 'no special permissions' case, so span the line we add
355 // (without a header) saying the extension has no special privileges. 406 // (without a header) saying the extension has no special privileges.
356 icon_row_span = 4; 407 icon_row_span = 4;
357 } 408 }
358 } else if (prompt.GetOAuthIssueCount()) { 409 } else if (prompt.GetOAuthIssueCount()) {
359 // Also span the permission header and each of the permission rows (all 410 // Also span the permission header and each of the permission rows (all
360 // have a padding row above it). 411 // have a padding row above it).
361 icon_row_span = 3 + prompt.GetOAuthIssueCount() * 2; 412 icon_row_span = 3 + prompt.GetOAuthIssueCount() * 2;
362 } else if (prompt.GetRetainedFileCount()) { 413 } else if (prompt.GetRetainedFileCount()) {
363 // Also span the permission header and each of the permission rows (all 414 // Also span the permission header and the retained files container.
364 // have a padding row above it). 415 icon_row_span = 4;
365 icon_row_span = 3 + prompt.GetRetainedFileCount() * 2;
366 } 416 }
367 layout->AddView(icon, 1, icon_row_span); 417 layout->AddView(icon, 1, icon_row_span);
368 } 418 }
369 419
370 if (is_inline_install()) { 420 if (is_inline_install()) {
371 layout->StartRow(0, column_set_id); 421 layout->StartRow(0, column_set_id);
372 views::View* rating = new views::View(); 422 views::View* rating = new views::View();
373 rating->SetLayoutManager(new views::BoxLayout( 423 rating->SetLayoutManager(new views::BoxLayout(
374 views::BoxLayout::kHorizontal, 0, 0, 0)); 424 views::BoxLayout::kHorizontal, 0, 0, 0));
375 layout->AddView(rating); 425 layout->AddView(rating);
(...skipping 14 matching lines...) Expand all
390 440
391 layout->StartRow(0, column_set_id); 441 layout->StartRow(0, column_set_id);
392 views::Link* store_link = new views::Link( 442 views::Link* store_link = new views::Link(
393 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_STORE_LINK)); 443 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_STORE_LINK));
394 store_link->SetFont(rb.GetFont(ui::ResourceBundle::SmallFont)); 444 store_link->SetFont(rb.GetFont(ui::ResourceBundle::SmallFont));
395 store_link->set_listener(this); 445 store_link->set_listener(this);
396 layout->AddView(store_link); 446 layout->AddView(store_link);
397 } 447 }
398 448
399 if (is_bundle_install()) { 449 if (is_bundle_install()) {
400 BundleInstaller::ItemList items = prompt_.bundle()->GetItemsWithState( 450 BundleInstaller::ItemList items = prompt.bundle()->GetItemsWithState(
401 BundleInstaller::Item::STATE_PENDING); 451 BundleInstaller::Item::STATE_PENDING);
402 for (size_t i = 0; i < items.size(); ++i) { 452 for (size_t i = 0; i < items.size(); ++i) {
403 string16 extension_name = UTF8ToUTF16(items[i].localized_name); 453 string16 extension_name = UTF8ToUTF16(items[i].localized_name);
404 base::i18n::AdjustStringForLocaleDirection(&extension_name); 454 base::i18n::AdjustStringForLocaleDirection(&extension_name);
405 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 455 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
406 layout->StartRow(0, column_set_id); 456 layout->StartRow(0, column_set_id);
407 views::Label* extension_label = new views::Label( 457 views::Label* extension_label = new views::Label(
408 PrepareForDisplay(extension_name, true)); 458 PrepareForDisplay(extension_name, true));
409 extension_label->SetMultiLine(true); 459 extension_label->SetMultiLine(true);
410 extension_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 460 extension_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 493
444 for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) { 494 for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) {
445 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 495 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
446 layout->StartRow(0, column_set_id); 496 layout->StartRow(0, column_set_id);
447 views::Label* permission_label = new views::Label(PrepareForDisplay( 497 views::Label* permission_label = new views::Label(PrepareForDisplay(
448 prompt.GetPermission(i), true)); 498 prompt.GetPermission(i), true));
449 permission_label->SetMultiLine(true); 499 permission_label->SetMultiLine(true);
450 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 500 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
451 permission_label->SizeToFit(left_column_width); 501 permission_label->SizeToFit(left_column_width);
452 layout->AddView(permission_label); 502 layout->AddView(permission_label);
503
504 // If we have more details to provide, show them in collapsed form.
505 if (!prompt.GetPermissionsDetails(i).empty()) {
506 layout->StartRow(0, column_set_id);
507 PermissionDetails details;
508 details.push_back(
509 PrepareForDisplay(prompt.GetPermissionsDetails(i), false));
510 ExpandableContainerView* details_container =
511 new ExpandableContainerView(
512 this, string16(), details, left_column_width, false);
513 layout->AddView(details_container);
514 }
453 } 515 }
454 } else { 516 } else {
455 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 517 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
456 layout->StartRow(0, column_set_id); 518 layout->StartRow(0, column_set_id);
457 views::Label* permission_label = new views::Label( 519 views::Label* permission_label = new views::Label(
458 l10n_util::GetStringUTF16(IDS_EXTENSION_NO_SPECIAL_PERMISSIONS)); 520 l10n_util::GetStringUTF16(IDS_EXTENSION_NO_SPECIAL_PERMISSIONS));
459 permission_label->SetMultiLine(true); 521 permission_label->SetMultiLine(true);
460 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 522 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
461 permission_label->SizeToFit(left_column_width); 523 permission_label->SizeToFit(left_column_width);
462 layout->AddView(permission_label); 524 layout->AddView(permission_label);
(...skipping 23 matching lines...) Expand all
486 oauth_header->SetMultiLine(true); 548 oauth_header->SetMultiLine(true);
487 oauth_header->SetHorizontalAlignment(gfx::ALIGN_LEFT); 549 oauth_header->SetHorizontalAlignment(gfx::ALIGN_LEFT);
488 oauth_header->SizeToFit(left_column_width); 550 oauth_header->SizeToFit(left_column_width);
489 layout->AddView(oauth_header); 551 layout->AddView(oauth_header);
490 552
491 for (size_t i = 0; i < prompt.GetOAuthIssueCount(); ++i) { 553 for (size_t i = 0; i < prompt.GetOAuthIssueCount(); ++i) {
492 layout->StartRowWithPadding( 554 layout->StartRowWithPadding(
493 0, column_set_id, 555 0, column_set_id,
494 0, views::kRelatedControlVerticalSpacing); 556 0, views::kRelatedControlVerticalSpacing);
495 557
496 IssueAdviceView* issue_advice_view = 558 PermissionDetails details;
497 new IssueAdviceView(this, prompt.GetOAuthIssue(i), space_for_oauth); 559 const IssueAdviceInfoEntry& entry = prompt.GetOAuthIssue(i);
560 for (size_t x = 0; x < entry.details.size(); ++x)
561 details.push_back(entry.details[x]);
562 ExpandableContainerView* issue_advice_view =
563 new ExpandableContainerView(
564 this, entry.description, details, space_for_oauth, false);
498 layout->AddView(issue_advice_view); 565 layout->AddView(issue_advice_view);
499 } 566 }
500 } 567 }
501 if (prompt.GetRetainedFileCount()) { 568 if (prompt.GetRetainedFileCount()) {
502 // Slide in under the permissions or OAuth, if there are any. If there are 569 // Slide in under the permissions or OAuth, if there are any. If there are
503 // either, the retained files prompt stretches all the way to the right of 570 // either, the retained files prompt stretches all the way to the right of
504 // the dialog. If there are no permissions or OAuth, the retained files 571 // the dialog. If there are no permissions or OAuth, the retained files
505 // prompt just takes up the left column. 572 // prompt just takes up the left column.
506 int space_for_files = left_column_width; 573 int space_for_files = left_column_width;
507 if (prompt.GetPermissionCount() || prompt.GetOAuthIssueCount()) { 574 if (prompt.GetPermissionCount() || prompt.GetOAuthIssueCount()) {
508 space_for_files += kIconSize; 575 space_for_files += kIconSize;
509 column_set = layout->AddColumnSet(++column_set_id); 576 column_set = layout->AddColumnSet(++column_set_id);
510 column_set->AddColumn(views::GridLayout::FILL, 577 column_set->AddColumn(views::GridLayout::FILL,
511 views::GridLayout::FILL, 578 views::GridLayout::FILL,
512 1, 579 1,
513 views::GridLayout::USE_PREF, 580 views::GridLayout::USE_PREF,
514 0, // no fixed width 581 0, // no fixed width
515 space_for_files); 582 space_for_files);
516 } 583 }
517 584
518 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 585 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
519 586
520 layout->StartRow(0, column_set_id); 587 layout->StartRow(0, column_set_id);
521 views::Label* retained_files_header = NULL; 588 views::Label* retained_files_header = NULL;
522 retained_files_header = new views::Label(prompt.GetRetainedFilesHeading()); 589 retained_files_header =
590 new views::Label(prompt.GetRetainedFilesHeadingWithCount());
523 retained_files_header->SetMultiLine(true); 591 retained_files_header->SetMultiLine(true);
524 retained_files_header->SetHorizontalAlignment(gfx::ALIGN_LEFT); 592 retained_files_header->SetHorizontalAlignment(gfx::ALIGN_LEFT);
525 retained_files_header->SizeToFit(space_for_files); 593 retained_files_header->SizeToFit(space_for_files);
526 layout->AddView(retained_files_header); 594 layout->AddView(retained_files_header);
527 595
528 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
529 layout->StartRow(0, column_set_id); 596 layout->StartRow(0, column_set_id);
530 views::View* files_view = new views::View(); 597 PermissionDetails details;
531 files_view->SetLayoutManager(new views::BoxLayout( 598 for (size_t i = 0; i < prompt.GetRetainedFileCount(); ++i)
532 views::BoxLayout::kVertical, 599 details.push_back(prompt.GetRetainedFile(i));
533 views::kRelatedControlHorizontalSpacing, 600 ExpandableContainerView* issue_advice_view =
534 0, 601 new ExpandableContainerView(
535 0)); 602 this, string16(), details, space_for_files, false);
536 for (size_t i = 0; i < prompt.GetRetainedFileCount(); ++i) { 603 layout->AddView(issue_advice_view);
537 views::Label* retained_file_label = new views::Label(PrepareForDisplay(
538 prompt.GetRetainedFile(i), true));
539 retained_file_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
540 files_view->AddChildView(retained_file_label);
541 }
542 views::ScrollView* scroll_view =
543 new MaxSizeScrollView(kMaxRetainedFilesHeight, space_for_files);
544 scroll_view->SetContents(files_view);
545 layout->AddView(scroll_view);
546 } 604 }
605
606 gfx::Size scrollable_size = scrollable_->GetPreferredSize();
607 scrollable_->SetBoundsRect(gfx::Rect(scrollable_size));
608 dialog_size_ = gfx::Size(
609 kDialogWidth,
610 std::min(scrollable_size.height(), kDialogMaxHeight));
547 } 611 }
548 612
549 ExtensionInstallDialogView::~ExtensionInstallDialogView() {} 613 ExtensionInstallDialogView::~ExtensionInstallDialogView() {}
550 614
551 void ExtensionInstallDialogView::SizeToContents() { 615 void ExtensionInstallDialogView::ContentsChanged() {
552 GetWidget()->SetSize(GetWidget()->non_client_view()->GetPreferredSize()); 616 Layout();
553 } 617 }
554 618
555 int ExtensionInstallDialogView::GetDialogButtons() const { 619 int ExtensionInstallDialogView::GetDialogButtons() const {
556 int buttons = prompt_.GetDialogButtons(); 620 int buttons = prompt_.GetDialogButtons();
557 // Simply having just an OK button is *not* supported. See comment on function 621 // Simply having just an OK button is *not* supported. See comment on function
558 // GetDialogButtons in dialog_delegate.h for reasons. 622 // GetDialogButtons in dialog_delegate.h for reasons.
559 DCHECK_GT(buttons & ui::DIALOG_BUTTON_CANCEL, 0); 623 DCHECK_GT(buttons & ui::DIALOG_BUTTON_CANCEL, 0);
560 return buttons; 624 return buttons;
561 } 625 }
562 626
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 int event_flags) { 665 int event_flags) {
602 GURL store_url(extension_urls::GetWebstoreItemDetailURLPrefix() + 666 GURL store_url(extension_urls::GetWebstoreItemDetailURLPrefix() +
603 prompt_.extension()->id()); 667 prompt_.extension()->id());
604 OpenURLParams params( 668 OpenURLParams params(
605 store_url, Referrer(), NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_LINK, 669 store_url, Referrer(), NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_LINK,
606 false); 670 false);
607 navigator_->OpenURL(params); 671 navigator_->OpenURL(params);
608 GetWidget()->Close(); 672 GetWidget()->Close();
609 } 673 }
610 674
675 void ExtensionInstallDialogView::Layout() {
676 views::View* contents_view = scroll_view_->contents();
677 int content_width = width();
678 int content_height = contents_view->GetHeightForWidth(content_width);
679 if (content_height > height()) {
680 content_width -= scroll_view_->GetScrollBarWidth();
681 content_height = contents_view->GetHeightForWidth(content_width);
682 }
683 contents_view->SetBounds(0, 0, content_width, content_height);
684 scroll_view_->SetBounds(0, 0, width(), height());
685
686 DialogDelegateView::Layout();
687 }
688
689 gfx::Size ExtensionInstallDialogView::GetPreferredSize() {
690 return dialog_size_;
691 }
692
611 // static 693 // static
612 ExtensionInstallPrompt::ShowDialogCallback 694 ExtensionInstallPrompt::ShowDialogCallback
613 ExtensionInstallPrompt::GetDefaultShowDialogCallback() { 695 ExtensionInstallPrompt::GetDefaultShowDialogCallback() {
614 return base::Bind(&ShowExtensionInstallDialogImpl); 696 return base::Bind(&ShowExtensionInstallDialogImpl);
615 } 697 }
616 698
617 // IssueAdviceView::DetailsView ------------------------------------------------ 699 // ExpandableContainerView::DetailsView ----------------------------------------
618 700
619 IssueAdviceView::DetailsView::DetailsView(int horizontal_space) 701 ExpandableContainerView::DetailsView::DetailsView(int horizontal_space,
702 bool show_bullets)
620 : layout_(new views::GridLayout(this)), 703 : layout_(new views::GridLayout(this)),
621 state_(0) { 704 state_(0),
705 show_bullets_(show_bullets) {
622 SetLayoutManager(layout_); 706 SetLayoutManager(layout_);
623 views::ColumnSet* column_set = layout_->AddColumnSet(0); 707 views::ColumnSet* column_set = layout_->AddColumnSet(0);
708 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
624 column_set->AddColumn(views::GridLayout::LEADING, 709 column_set->AddColumn(views::GridLayout::LEADING,
625 views::GridLayout::LEADING, 710 views::GridLayout::LEADING,
626 0, 711 0,
627 views::GridLayout::FIXED, 712 views::GridLayout::FIXED,
628 horizontal_space, 713 horizontal_space,
629 0); 714 0);
630 } 715 }
631 716
632 void IssueAdviceView::DetailsView::AddDetail(const string16& detail) { 717 void ExpandableContainerView::DetailsView::AddDetail(const string16& detail) {
633 layout_->StartRowWithPadding(0, 0, 718 layout_->StartRowWithPadding(0, 0,
634 0, views::kRelatedControlSmallVerticalSpacing); 719 0, views::kRelatedControlSmallVerticalSpacing);
635 views::Label* detail_label = 720 views::Label* detail_label =
636 new views::Label(PrepareForDisplay(detail, true)); 721 new views::Label(PrepareForDisplay(detail, show_bullets_));
637 detail_label->SetMultiLine(true); 722 detail_label->SetMultiLine(true);
638 detail_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 723 detail_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
639 layout_->AddView(detail_label); 724 layout_->AddView(detail_label);
640 } 725 }
641 726
642 gfx::Size IssueAdviceView::DetailsView::GetPreferredSize() { 727 gfx::Size ExpandableContainerView::DetailsView::GetPreferredSize() {
643 gfx::Size size = views::View::GetPreferredSize(); 728 gfx::Size size = views::View::GetPreferredSize();
644 return gfx::Size(size.width(), size.height() * state_); 729 return gfx::Size(size.width(), size.height() * state_);
645 } 730 }
646 731
647 void IssueAdviceView::DetailsView::AnimateToState(double state) { 732 void ExpandableContainerView::DetailsView::AnimateToState(double state) {
648 state_ = state; 733 state_ = state;
649 PreferredSizeChanged(); 734 PreferredSizeChanged();
650 SchedulePaint(); 735 SchedulePaint();
651 } 736 }
652 737
653 // IssueAdviceView ------------------------------------------------------------- 738 // ExpandableContainerView -----------------------------------------------------
654 739
655 IssueAdviceView::IssueAdviceView(ExtensionInstallDialogView* owner, 740 ExpandableContainerView::ExpandableContainerView(
656 const IssueAdviceInfoEntry& issue_advice, 741 ExtensionInstallDialogView* owner,
657 int horizontal_space) 742 const string16& description,
743 const PermissionDetails& details,
744 int horizontal_space,
745 bool show_bullets)
658 : owner_(owner), 746 : owner_(owner),
659 details_view_(NULL), 747 details_view_(NULL),
660 arrow_view_(NULL), 748 arrow_view_(NULL),
661 slide_animation_(this) { 749 slide_animation_(this),
662 // TODO(estade): replace this with a more appropriate image. 750 expanded_(false) {
663 const gfx::ImageSkia& image = *ui::ResourceBundle::GetSharedInstance().
664 GetImageSkiaNamed(IDR_OMNIBOX_TTS);
665
666 views::GridLayout* layout = new views::GridLayout(this); 751 views::GridLayout* layout = new views::GridLayout(this);
667 SetLayoutManager(layout); 752 SetLayoutManager(layout);
668 int column_set_id = 0; 753 int column_set_id = 0;
669 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); 754 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id);
670 if (!issue_advice.details.empty()) {
671 column_set->AddColumn(views::GridLayout::LEADING,
672 views::GridLayout::LEADING,
673 0,
674 views::GridLayout::FIXED,
675 image.width(),
676 0);
677 horizontal_space -= image.width();
678 details_view_ = new DetailsView(horizontal_space);
679 }
680 column_set->AddColumn(views::GridLayout::LEADING, 755 column_set->AddColumn(views::GridLayout::LEADING,
681 views::GridLayout::FILL, 756 views::GridLayout::LEADING,
682 0, 757 0,
683 views::GridLayout::FIXED, 758 views::GridLayout::USE_PREF,
684 horizontal_space, 759 0,
685 0); 760 0);
686 layout->StartRow(0, column_set_id); 761 if (!description.empty()) {
762 layout->StartRow(0, column_set_id);
687 763
688 if (details_view_) { 764 views::Label* description_label =
689 arrow_view_ = new views::ImageView(); 765 new views::Label(PrepareForDisplay(description, true));
690 arrow_view_->SetImage(image); 766 description_label->SetMultiLine(true);
691 arrow_view_->SetVerticalAlignment(views::ImageView::CENTER); 767 description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
692 layout->AddView(arrow_view_); 768 description_label->SizeToFit(horizontal_space);
769 layout->AddView(description_label);
693 } 770 }
694 771
695 views::Label* description_label = 772 if (details.empty())
696 new views::Label(PrepareForDisplay(issue_advice.description,
697 !details_view_));
698 description_label->SetMultiLine(true);
699 description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
700 description_label->SizeToFit(horizontal_space);
701 layout->AddView(description_label);
702
703 if (!details_view_)
704 return; 773 return;
705 774
775 details_view_ = new DetailsView(horizontal_space, show_bullets);
776
706 layout->StartRow(0, column_set_id); 777 layout->StartRow(0, column_set_id);
707 layout->SkipColumns(1);
708 layout->AddView(details_view_); 778 layout->AddView(details_view_);
709 779
710 for (size_t i = 0; i < issue_advice.details.size(); ++i) 780 for (size_t i = 0; i < details.size(); ++i)
711 details_view_->AddDetail(issue_advice.details[i]); 781 details_view_->AddDetail(details[i]);
782
783 // Prepare the columns for the More Details row.
784 column_set = layout->AddColumnSet(++column_set_id);
785 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
786 column_set->AddColumn(views::GridLayout::LEADING,
787 views::GridLayout::LEADING,
788 0,
789 views::GridLayout::USE_PREF,
790 0,
791 0);
792 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
793 column_set->AddColumn(views::GridLayout::LEADING,
794 views::GridLayout::LEADING,
795 0,
796 views::GridLayout::USE_PREF,
797 0,
798 0);
799 column_set->AddColumn(views::GridLayout::LEADING,
800 views::GridLayout::LEADING,
801 0,
802 views::GridLayout::USE_PREF,
803 0,
804 0);
805
806 // Add the More Details link.
807 layout->StartRow(0, column_set_id);
808 more_details_ = new views::Link(
809 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_DETAILS));
810 more_details_->set_listener(this);
811 more_details_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
812 layout->AddView(more_details_);
813
814 // Add the arrow after the More Details link.
815 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
816 arrow_toggle_ = new views::ImageButton(this);
817 arrow_toggle_->SetImage(views::Button::STATE_NORMAL,
818 rb.GetImageSkiaNamed(IDR_DOWN_ARROW));
819 layout->AddView(arrow_toggle_);
712 } 820 }
713 821
714 bool IssueAdviceView::OnMousePressed(const ui::MouseEvent& event) { 822 ExpandableContainerView::~ExpandableContainerView() {
715 return details_view_ && event.IsLeftMouseButton();
716 } 823 }
717 824
718 void IssueAdviceView::OnMouseReleased(const ui::MouseEvent& event) { 825 void ExpandableContainerView::ButtonPressed(
826 views::Button* sender, const ui::Event& event) {
827 ToggleDetailLevel();
828 }
829
830 void ExpandableContainerView::LinkClicked(
831 views::Link* source, int event_flags) {
832 ToggleDetailLevel();
833 }
834
835 void ExpandableContainerView::AnimationProgressed(
836 const ui::Animation* animation) {
837 DCHECK_EQ(&slide_animation_, animation);
838 if (details_view_)
839 details_view_->AnimateToState(animation->GetCurrentValue());
840 }
841
842 void ExpandableContainerView::AnimationEnded(const ui::Animation* animation) {
843 if (animation->GetCurrentValue() != 0.0) {
844 arrow_toggle_->SetImage(
845 views::Button::STATE_NORMAL,
846 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
847 IDR_UP_ARROW));
848 } else {
849 arrow_toggle_->SetImage(
850 views::Button::STATE_NORMAL,
851 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
852 IDR_DOWN_ARROW));
853 }
854
855 more_details_->SetText(expanded_ ?
856 l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_DETAILS) :
857 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_DETAILS));
858 }
859
860 void ExpandableContainerView::ChildPreferredSizeChanged(views::View* child) {
861 owner_->ContentsChanged();
862 }
863
864 void ExpandableContainerView::ToggleDetailLevel() {
865 expanded_ = !expanded_;
866
719 if (slide_animation_.IsShowing()) 867 if (slide_animation_.IsShowing())
720 slide_animation_.Hide(); 868 slide_animation_.Hide();
721 else 869 else
722 slide_animation_.Show(); 870 slide_animation_.Show();
723 } 871 }
724
725 void IssueAdviceView::AnimationProgressed(const ui::Animation* animation) {
726 DCHECK_EQ(animation, &slide_animation_);
727
728 if (details_view_)
729 details_view_->AnimateToState(animation->GetCurrentValue());
730
731 if (arrow_view_) {
732 gfx::Transform rotate;
733 if (animation->GetCurrentValue() != 0.0) {
734 rotate.Translate(arrow_view_->width() / 2.0,
735 arrow_view_->height() / 2.0);
736 // TODO(estade): for some reason there are rendering errors at 90 degrees.
737 // Figure out why.
738 rotate.Rotate(animation->GetCurrentValue() * 89);
739 rotate.Translate(-arrow_view_->width() / 2.0,
740 -arrow_view_->height() / 2.0);
741 }
742 arrow_view_->SetTransform(rotate);
743 }
744 }
745
746 void IssueAdviceView::ChildPreferredSizeChanged(views::View* child) {
747 owner_->SizeToContents();
748 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_install_prompt.cc ('k') | chrome/common/extensions/permissions/permission_message.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698