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

Side by Side Diff: chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.cc

Issue 2029863002: Refactor ChooserBubbleUiViewDelegate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 6 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.h" 5 #include "chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm>
10 #include <string>
11 #include <vector>
12
13 #include "base/macros.h" 9 #include "base/macros.h"
14 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
15 #include "base/strings/string16.h" 11 #include "base/strings/string16.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h" 12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_window.h"
14 #include "chrome/browser/ui/views/chooser_content_view.h"
19 #include "chrome/browser/ui/views/exclusive_access_bubble_views.h" 15 #include "chrome/browser/ui/views/exclusive_access_bubble_views.h"
20 #include "chrome/browser/ui/views/frame/browser_view.h" 16 #include "chrome/browser/ui/views/frame/browser_view.h"
21 #include "chrome/browser/ui/views/frame/top_container_view.h" 17 #include "chrome/browser/ui/views/frame/top_container_view.h"
22 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" 18 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
23 #include "chrome/browser/ui/views/location_bar/location_icon_view.h" 19 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
24 #include "chrome/browser/ui/website_settings/chooser_bubble_delegate.h" 20 #include "chrome/browser/ui/website_settings/chooser_bubble_delegate.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/grit/generated_resources.h" 21 #include "chrome/grit/generated_resources.h"
27 #include "components/bubble/bubble_controller.h" 22 #include "components/bubble/bubble_controller.h"
28 #include "components/chooser_controller/chooser_controller.h" 23 #include "components/chooser_controller/chooser_controller.h"
29 #include "components/prefs/pref_service.h"
30 #include "components/url_formatter/elide_url.h" 24 #include "components/url_formatter/elide_url.h"
31 #include "ui/accessibility/ax_view_state.h"
32 #include "ui/base/l10n/l10n_util.h" 25 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/base/resource/resource_bundle.h"
34 #include "ui/gfx/paint_vector_icon.h"
35 #include "ui/gfx/text_constants.h"
36 #include "ui/gfx/vector_icons_public.h"
37 #include "ui/views/bubble/bubble_dialog_delegate.h"
38 #include "ui/views/bubble/bubble_frame_view.h"
39 #include "ui/views/controls/styled_label.h"
40 #include "ui/views/controls/styled_label_listener.h"
41 #include "ui/views/controls/table/table_view.h" 26 #include "ui/views/controls/table/table_view.h"
42 #include "ui/views/controls/table/table_view_observer.h"
43 #include "ui/views/layout/grid_layout.h"
44 #include "ui/views/window/dialog_client_view.h"
45 #include "url/origin.h" 27 #include "url/origin.h"
46 28
47 namespace {
48
49 // Chooser permission bubble width
50 const int kChooserPermissionBubbleWidth = 300;
51
52 // Chooser permission bubble height
53 const int kChooserPermissionBubbleHeight = 200;
54
55 } // namespace
56
57 std::unique_ptr<BubbleUi> ChooserBubbleDelegate::BuildBubbleUi() { 29 std::unique_ptr<BubbleUi> ChooserBubbleDelegate::BuildBubbleUi() {
58 return base::WrapUnique( 30 return base::WrapUnique(
59 new ChooserBubbleUiView(browser_, chooser_controller())); 31 new ChooserBubbleUiView(browser_, chooser_controller()));
60 } 32 }
61 33
62 class ChooserTableModel;
63
64 /////////////////////////////////////////////////////////////////////////////// 34 ///////////////////////////////////////////////////////////////////////////////
65 // View implementation for the chooser bubble. 35 // View implementation for the chooser bubble.
66 class ChooserBubbleUiViewDelegate : public views::BubbleDialogDelegateView, 36 class ChooserBubbleUiViewDelegate : public ChooserContentView {
67 public views::StyledLabelListener,
68 public views::TableViewObserver {
69 public: 37 public:
70 ChooserBubbleUiViewDelegate(views::View* anchor_view, 38 ChooserBubbleUiViewDelegate(views::View* anchor_view,
71 views::BubbleBorder::Arrow anchor_arrow, 39 views::BubbleBorder::Arrow anchor_arrow,
72 ChooserController* controller, 40 ChooserController* chooser_controller,
73 BubbleReference bubble_reference); 41 BubbleReference bubble_reference);
74 ~ChooserBubbleUiViewDelegate() override; 42 ~ChooserBubbleUiViewDelegate() override;
75 43
76 // views::BubbleDialogDelegateView: 44 // views::BubbleDialogDelegateView:
77 bool ShouldShowWindowTitle() const override;
78 base::string16 GetWindowTitle() const override; 45 base::string16 GetWindowTitle() const override;
79 base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
80 bool IsDialogButtonEnabled(ui::DialogButton button) const override;
81 views::View* CreateFootnoteView() override;
82 bool Accept() override; 46 bool Accept() override;
83 bool Cancel() override; 47 bool Cancel() override;
84 bool Close() override; 48 bool Close() override;
85 49
86 // views::StyledLabelListener:
87 void StyledLabelLinkClicked(views::StyledLabel* label,
88 const gfx::Range& range,
89 int event_flags) override;
90
91 // views::TableViewObserver:
92 void OnSelectionChanged() override;
93
94 // Updates the anchor's arrow and view. Also repositions the bubble so it's 50 // Updates the anchor's arrow and view. Also repositions the bubble so it's
95 // displayed in the correct location. 51 // displayed in the correct location.
96 void UpdateAnchor(views::View* anchor_view, 52 void UpdateAnchor(views::View* anchor_view,
97 views::BubbleBorder::Arrow anchor_arrow); 53 views::BubbleBorder::Arrow anchor_arrow);
98 54
99 // Called by ChooserBubbleUiView's destructor. When ChooserBubbleUiView object
100 // is destroyed, the |controller_| it passed to this class may not be used any
101 // more since it may be destroyed too.
102 void ControllerDestroying();
103
104 ChooserTableModel* chooser_table_model() const;
105
106 private: 55 private:
107 ChooserController* controller_;
108 BubbleReference bubble_reference_; 56 BubbleReference bubble_reference_;
109
110 views::TableView* table_view_;
111 ChooserTableModel* chooser_table_model_;
112
113 DISALLOW_COPY_AND_ASSIGN(ChooserBubbleUiViewDelegate); 57 DISALLOW_COPY_AND_ASSIGN(ChooserBubbleUiViewDelegate);
114 }; 58 };
115 59
116 ui::TableColumn ChooserTableColumn(int id, const std::string& title) {
117 ui::TableColumn column;
118 column.id = id;
119 column.title = base::ASCIIToUTF16(title.c_str());
120 return column;
121 }
122
123 class ChooserTableModel : public ui::TableModel,
124 public ChooserController::Observer {
125 public:
126 explicit ChooserTableModel(ChooserController* controller);
127
128 // ui::TableModel:
129 int RowCount() override;
130 base::string16 GetText(int row, int column_id) override;
131 void SetObserver(ui::TableModelObserver* observer) override;
132
133 // ChooserController::Observer:
134 void OnOptionsInitialized() override;
135 void OnOptionAdded(size_t index) override;
136 void OnOptionRemoved(size_t index) override;
137
138 void Update();
139
140 private:
141 ui::TableModelObserver* observer_;
142 ChooserController* controller_;
143 };
144
145 ChooserBubbleUiViewDelegate::ChooserBubbleUiViewDelegate( 60 ChooserBubbleUiViewDelegate::ChooserBubbleUiViewDelegate(
146 views::View* anchor_view, 61 views::View* anchor_view,
147 views::BubbleBorder::Arrow anchor_arrow, 62 views::BubbleBorder::Arrow anchor_arrow,
148 ChooserController* controller, 63 ChooserController* chooser_controller,
149 BubbleReference bubble_reference) 64 BubbleReference bubble_reference)
150 : views::BubbleDialogDelegateView(anchor_view, anchor_arrow), 65 : ChooserContentView(anchor_view, anchor_arrow, chooser_controller),
151 controller_(controller),
152 bubble_reference_(bubble_reference) { 66 bubble_reference_(bubble_reference) {
153 // ------------------------------------
154 // | Chooser bubble title |
155 // | -------------------------------- |
156 // | | option 0 | |
157 // | | option 1 | |
158 // | | option 2 | |
159 // | | | |
160 // | | | |
161 // | | | |
162 // | -------------------------------- |
163 // | [ Connect ] [ Cancel ] |
164 // |----------------------------------|
165 // | Not seeing your device? Get help |
166 // ------------------------------------
167
168 DCHECK(bubble_reference_); 67 DCHECK(bubble_reference_);
169
170 views::GridLayout* layout = new views::GridLayout(this);
171 SetLayoutManager(layout);
172
173 views::ColumnSet* column_set = layout->AddColumnSet(0);
174 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
175 views::GridLayout::USE_PREF, 0, 0);
176
177 // Lay out the table view.
178 layout->StartRow(0, 0);
179 std::vector<ui::TableColumn> table_columns;
180 table_columns.push_back(ChooserTableColumn(
181 0, "" /* Empty string makes the column title invisible */));
182 chooser_table_model_ = new ChooserTableModel(controller_);
183 table_view_ = new views::TableView(chooser_table_model_, table_columns,
184 views::TEXT_ONLY, true);
185 table_view_->set_select_on_remove(false);
186 chooser_table_model_->SetObserver(table_view_);
187 table_view_->SetObserver(this);
188 table_view_->SetEnabled(controller_->NumOptions() > 0);
189 layout->AddView(table_view_->CreateParentIfNecessary(), 1, 1,
190 views::GridLayout::FILL, views::GridLayout::FILL,
191 kChooserPermissionBubbleWidth,
192 kChooserPermissionBubbleHeight);
193 } 68 }
194 69
195 ChooserBubbleUiViewDelegate::~ChooserBubbleUiViewDelegate() { 70 ChooserBubbleUiViewDelegate::~ChooserBubbleUiViewDelegate() {}
196 chooser_table_model_->SetObserver(nullptr);
197 }
198
199 bool ChooserBubbleUiViewDelegate::ShouldShowWindowTitle() const {
200 return true;
201 }
202 71
203 base::string16 ChooserBubbleUiViewDelegate::GetWindowTitle() const { 72 base::string16 ChooserBubbleUiViewDelegate::GetWindowTitle() const {
204 return l10n_util::GetStringFUTF16( 73 return l10n_util::GetStringFUTF16(
205 IDS_CHOOSER_BUBBLE_PROMPT, 74 IDS_CHOOSER_BUBBLE_PROMPT,
206 url_formatter::FormatOriginForSecurityDisplay( 75 url_formatter::FormatOriginForSecurityDisplay(
207 controller_->GetOrigin(), 76 chooser_controller()->GetOrigin(),
208 url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); 77 url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
209 } 78 }
210 79
211 base::string16 ChooserBubbleUiViewDelegate::GetDialogButtonLabel(
212 ui::DialogButton button) const {
213 return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK
214 ? IDS_CHOOSER_BUBBLE_CONNECT_BUTTON_TEXT
215 : IDS_CHOOSER_BUBBLE_CANCEL_BUTTON_TEXT);
216 }
217
218 bool ChooserBubbleUiViewDelegate::IsDialogButtonEnabled(
219 ui::DialogButton button) const {
220 return button == ui::DIALOG_BUTTON_OK
221 ? !table_view_->selection_model().empty()
222 : true;
223 }
224
225 views::View* ChooserBubbleUiViewDelegate::CreateFootnoteView() {
226 base::string16 link =
227 l10n_util::GetStringUTF16(IDS_CHOOSER_BUBBLE_GET_HELP_LINK_TEXT);
228 size_t offset;
229 base::string16 text = l10n_util::GetStringFUTF16(
230 IDS_CHOOSER_BUBBLE_FOOTNOTE_TEXT, link, &offset);
231 views::StyledLabel* label = new views::StyledLabel(text, this);
232 label->AddStyleRange(gfx::Range(offset, offset + link.length()),
233 views::StyledLabel::RangeStyleInfo::CreateForLink());
234 return label;
235 }
236
237 bool ChooserBubbleUiViewDelegate::Accept() { 80 bool ChooserBubbleUiViewDelegate::Accept() {
238 if (controller_) 81 if (chooser_controller())
239 controller_->Select(table_view_->selection_model().active()); 82 chooser_controller()->Select(table_view()->selection_model().active());
240 bubble_reference_->CloseBubble(BUBBLE_CLOSE_ACCEPTED); 83 bubble_reference_->CloseBubble(BUBBLE_CLOSE_ACCEPTED);
msw 2016/06/03 20:04:09 +groby: it's too bad the unused bubble manager inf
241 return true; 84 return true;
242 } 85 }
243 86
244 bool ChooserBubbleUiViewDelegate::Cancel() { 87 bool ChooserBubbleUiViewDelegate::Cancel() {
245 if (controller_) 88 if (chooser_controller())
246 controller_->Cancel(); 89 chooser_controller()->Cancel();
247 bubble_reference_->CloseBubble(BUBBLE_CLOSE_CANCELED); 90 bubble_reference_->CloseBubble(BUBBLE_CLOSE_CANCELED);
248 return true; 91 return true;
249 } 92 }
250 93
251 bool ChooserBubbleUiViewDelegate::Close() { 94 bool ChooserBubbleUiViewDelegate::Close() {
252 if (controller_) 95 if (chooser_controller())
253 controller_->Close(); 96 chooser_controller()->Close();
254 return true; 97 return true;
255 } 98 }
256 99
257 void ChooserBubbleUiViewDelegate::StyledLabelLinkClicked(
258 views::StyledLabel* label,
259 const gfx::Range& range,
260 int event_flags) {
261 controller_->OpenHelpCenterUrl();
262 }
263
264 void ChooserBubbleUiViewDelegate::OnSelectionChanged() {
265 GetDialogClientView()->UpdateDialogButtons();
266 }
267
268 void ChooserBubbleUiViewDelegate::UpdateAnchor( 100 void ChooserBubbleUiViewDelegate::UpdateAnchor(
269 views::View* anchor_view, 101 views::View* anchor_view,
270 views::BubbleBorder::Arrow anchor_arrow) { 102 views::BubbleBorder::Arrow anchor_arrow) {
271 if (GetAnchorView() == anchor_view && arrow() == anchor_arrow) 103 if (GetAnchorView() == anchor_view && arrow() == anchor_arrow)
272 return; 104 return;
273 105
274 set_arrow(anchor_arrow); 106 set_arrow(anchor_arrow);
275 107
276 // Reposition the bubble based on the updated arrow and view. 108 // Reposition the bubble based on the updated arrow and view.
277 SetAnchorView(anchor_view); 109 SetAnchorView(anchor_view);
278 } 110 }
279 111
280 void ChooserBubbleUiViewDelegate::ControllerDestroying() {
281 controller_ = nullptr;
282 }
283
284 ChooserTableModel* ChooserBubbleUiViewDelegate::chooser_table_model() const {
285 return chooser_table_model_;
286 }
287
288 ChooserTableModel::ChooserTableModel(ChooserController* controller)
289 : observer_(nullptr), controller_(controller) {
290 controller_->set_observer(this);
291 }
292
293 int ChooserTableModel::RowCount() {
294 // When there are no devices, the table contains a message saying there
295 // are no devices, so the number of rows is always at least 1.
296 return std::max(static_cast<int>(controller_->NumOptions()), 1);
297 }
298
299 base::string16 ChooserTableModel::GetText(int row, int column_id) {
300 int num_options = static_cast<int>(controller_->NumOptions());
301 if (num_options == 0) {
302 DCHECK_EQ(0, row);
303 return l10n_util::GetStringUTF16(
304 IDS_CHOOSER_BUBBLE_NO_DEVICES_FOUND_PROMPT);
305 }
306
307 DCHECK_GE(row, 0);
308 DCHECK_LT(row, num_options);
309 return controller_->GetOption(static_cast<size_t>(row));
310 }
311
312 void ChooserTableModel::SetObserver(ui::TableModelObserver* observer) {
313 observer_ = observer;
314 }
315
316 void ChooserTableModel::OnOptionsInitialized() {
317 if (observer_) {
318 observer_->OnModelChanged();
319 Update();
320 }
321 }
322
323 void ChooserTableModel::OnOptionAdded(size_t index) {
324 if (observer_) {
325 observer_->OnItemsAdded(static_cast<int>(index), 1);
326 Update();
327 }
328 }
329
330 void ChooserTableModel::OnOptionRemoved(size_t index) {
331 if (observer_) {
332 observer_->OnItemsRemoved(static_cast<int>(index), 1);
333 Update();
334 }
335 }
336
337 void ChooserTableModel::Update() {
338 views::TableView* table_view = static_cast<views::TableView*>(observer_);
339
340 if (controller_->NumOptions() == 0) {
341 observer_->OnModelChanged();
342 table_view->SetEnabled(false);
343 } else {
344 table_view->SetEnabled(true);
345 }
346 }
347
348 ////////////////////////////////////////////////////////////////////////////// 112 //////////////////////////////////////////////////////////////////////////////
349 // ChooserBubbleUiView 113 // ChooserBubbleUiView
350 114
351 ChooserBubbleUiView::ChooserBubbleUiView(Browser* browser, 115 ChooserBubbleUiView::ChooserBubbleUiView(Browser* browser,
352 ChooserController* controller) 116 ChooserController* chooser_controller)
353 : browser_(browser), 117 : browser_(browser),
354 controller_(controller), 118 chooser_controller_(chooser_controller),
355 chooser_bubble_ui_view_delegate_(nullptr) { 119 chooser_bubble_ui_view_delegate_(nullptr) {
356 DCHECK(browser_); 120 DCHECK(browser_);
357 DCHECK(controller_); 121 DCHECK(chooser_controller_);
358 } 122 }
359 123
360 ChooserBubbleUiView::~ChooserBubbleUiView() { 124 ChooserBubbleUiView::~ChooserBubbleUiView() {
361 if (chooser_bubble_ui_view_delegate_) 125 if (chooser_bubble_ui_view_delegate_)
362 chooser_bubble_ui_view_delegate_->ControllerDestroying(); 126 chooser_bubble_ui_view_delegate_->ChooserControllerDestroying();
363 } 127 }
364 128
365 void ChooserBubbleUiView::Show(BubbleReference bubble_reference) { 129 void ChooserBubbleUiView::Show(BubbleReference bubble_reference) {
366 chooser_bubble_ui_view_delegate_ = new ChooserBubbleUiViewDelegate( 130 chooser_bubble_ui_view_delegate_ = new ChooserBubbleUiViewDelegate(
367 GetAnchorView(), GetAnchorArrow(), controller_, bubble_reference); 131 GetAnchorView(), GetAnchorArrow(), chooser_controller_, bubble_reference);
368 132
369 // Set |parent_window| because some valid anchors can become hidden. 133 // Set |parent_window| because some valid anchors can become hidden.
370 views::Widget* widget = views::Widget::GetWidgetForNativeWindow( 134 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(
371 browser_->window()->GetNativeWindow()); 135 browser_->window()->GetNativeWindow());
372 chooser_bubble_ui_view_delegate_->set_parent_window(widget->GetNativeView()); 136 chooser_bubble_ui_view_delegate_->set_parent_window(widget->GetNativeView());
373 137
374 views::BubbleDialogDelegateView::CreateBubble( 138 views::BubbleDialogDelegateView::CreateBubble(
375 chooser_bubble_ui_view_delegate_) 139 chooser_bubble_ui_view_delegate_)
376 ->Show(); 140 ->Show();
377
378 chooser_bubble_ui_view_delegate_->chooser_table_model()->Update();
msw 2016/06/03 20:04:09 Why is this update no longer required? Has it move
juncai 2016/06/07 18:11:06 At ChooserContentView constructor, it enables/disa
msw 2016/06/08 00:58:45 Acknowledged, I hope this is okay, since ChooserTa
juncai 2016/06/09 01:59:21 Added it back to be safe, :).
379 } 141 }
380 142
381 void ChooserBubbleUiView::Close() {} 143 void ChooserBubbleUiView::Close() {}
382 144
383 void ChooserBubbleUiView::UpdateAnchorPosition() { 145 void ChooserBubbleUiView::UpdateAnchorPosition() {
384 chooser_bubble_ui_view_delegate_->UpdateAnchor(GetAnchorView(), 146 chooser_bubble_ui_view_delegate_->UpdateAnchor(GetAnchorView(),
385 GetAnchorArrow()); 147 GetAnchorArrow());
386 } 148 }
387 149
388 views::View* ChooserBubbleUiView::GetAnchorView() { 150 views::View* ChooserBubbleUiView::GetAnchorView() {
389 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); 151 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
390 152
391 if (browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR)) 153 if (browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR))
392 return browser_view->GetLocationBarView()->location_icon_view(); 154 return browser_view->GetLocationBarView()->location_icon_view();
393 155
394 if (browser_view->IsFullscreenBubbleVisible()) 156 if (browser_view->IsFullscreenBubbleVisible())
395 return browser_view->exclusive_access_bubble()->GetView(); 157 return browser_view->exclusive_access_bubble()->GetView();
396 158
397 return browser_view->top_container(); 159 return browser_view->top_container();
398 } 160 }
399 161
400 views::BubbleBorder::Arrow ChooserBubbleUiView::GetAnchorArrow() { 162 views::BubbleBorder::Arrow ChooserBubbleUiView::GetAnchorArrow() {
401 if (browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR)) 163 if (browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR))
402 return views::BubbleBorder::TOP_LEFT; 164 return views::BubbleBorder::TOP_LEFT;
403 return views::BubbleBorder::NONE; 165 return views::BubbleBorder::NONE;
404 } 166 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698