OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "mash/browser/browser.h" | 5 #include "mash/browser/browser.h" |
6 | 6 |
7 #include "base/macros.h" | 7 #include "base/macros.h" |
8 #include "base/memory/ptr_util.h" | |
8 #include "base/memory/weak_ptr.h" | 9 #include "base/memory/weak_ptr.h" |
9 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
10 #include "base/strings/string16.h" | 11 #include "base/strings/string16.h" |
11 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
12 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
14 #include "base/threading/thread_task_runner_handle.h" | |
13 #include "base/timer/timer.h" | 15 #include "base/timer/timer.h" |
14 #include "components/mus/public/cpp/window.h" | 16 #include "components/mus/public/cpp/window.h" |
15 #include "components/mus/public/cpp/window_tree_client.h" | 17 #include "components/mus/public/cpp/window_tree_client.h" |
16 #include "mash/browser/debug_view.h" | 18 #include "mash/browser/debug_view.h" |
17 #include "mash/public/interfaces/launchable.mojom.h" | 19 #include "mash/public/interfaces/launchable.mojom.h" |
18 #include "mojo/public/c/system/main.h" | 20 #include "mojo/public/c/system/main.h" |
19 #include "services/navigation/public/interfaces/view.mojom.h" | 21 #include "services/navigation/public/interfaces/view.mojom.h" |
20 #include "services/shell/public/cpp/application_runner.h" | 22 #include "services/shell/public/cpp/application_runner.h" |
21 #include "services/shell/public/cpp/connector.h" | 23 #include "services/shell/public/cpp/connector.h" |
22 #include "services/shell/public/cpp/shell_client.h" | 24 #include "services/shell/public/cpp/shell_client.h" |
23 #include "services/tracing/public/cpp/tracing_impl.h" | 25 #include "services/tracing/public/cpp/tracing_impl.h" |
24 #include "ui/aura/mus/mus_util.h" | 26 #include "ui/aura/mus/mus_util.h" |
27 #include "ui/base/models/menu_model.h" | |
25 #include "ui/gfx/canvas.h" | 28 #include "ui/gfx/canvas.h" |
26 #include "ui/gfx/paint_throbber.h" | 29 #include "ui/gfx/paint_throbber.h" |
27 #include "ui/gfx/text_constants.h" | 30 #include "ui/gfx/text_constants.h" |
28 #include "ui/native_theme/native_theme.h" | 31 #include "ui/native_theme/native_theme.h" |
29 #include "ui/views/background.h" | 32 #include "ui/views/background.h" |
30 #include "ui/views/controls/button/label_button.h" | 33 #include "ui/views/controls/button/label_button.h" |
34 #include "ui/views/controls/menu/menu_model_adapter.h" | |
35 #include "ui/views/controls/menu/menu_runner.h" | |
31 #include "ui/views/controls/textfield/textfield.h" | 36 #include "ui/views/controls/textfield/textfield.h" |
32 #include "ui/views/controls/textfield/textfield_controller.h" | 37 #include "ui/views/controls/textfield/textfield_controller.h" |
33 #include "ui/views/mus/aura_init.h" | 38 #include "ui/views/mus/aura_init.h" |
34 #include "ui/views/mus/window_manager_connection.h" | 39 #include "ui/views/mus/window_manager_connection.h" |
35 #include "ui/views/widget/widget_delegate.h" | 40 #include "ui/views/widget/widget_delegate.h" |
36 #include "url/gurl.h" | 41 #include "url/gurl.h" |
37 | 42 |
38 namespace mash { | 43 namespace mash { |
39 namespace browser { | 44 namespace browser { |
40 | 45 |
41 void EnableButton(views::CustomButton* button, bool enabled) { | 46 void EnableButton(views::CustomButton* button, bool enabled) { |
42 button->SetState(enabled ? views::Button::STATE_NORMAL | 47 button->SetState(enabled ? views::Button::STATE_NORMAL |
43 : views::Button::STATE_DISABLED); | 48 : views::Button::STATE_DISABLED); |
44 } | 49 } |
45 | 50 |
51 struct NavEntry { | |
52 NavEntry(const base::string16& title, int offset) | |
53 : title(title), offset(offset) {} | |
54 ~NavEntry() {} | |
55 | |
56 base::string16 title; | |
57 int offset; | |
sky
2016/06/08 21:31:21
What is offset? At least document it.
| |
58 }; | |
59 | |
60 class NavMenuModel : public ui::MenuModel { | |
61 public: | |
62 class Delegate { | |
63 public: | |
64 virtual void NavigateToOffset(int offset) = 0; | |
65 }; | |
66 | |
67 NavMenuModel(const std::vector<NavEntry>& entries, Delegate* delegate) | |
68 : entries_(entries), navigation_delegate_(delegate) {} | |
69 ~NavMenuModel() override {} | |
70 | |
71 private: | |
72 bool HasIcons() const override { return false; } | |
73 int GetItemCount() const override { | |
74 return static_cast<int>(entries_.size()); | |
75 } | |
76 ui::MenuModel::ItemType GetTypeAt(int index) const override { | |
77 return ui::MenuModel::TYPE_COMMAND; | |
78 } | |
79 ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override { | |
80 return ui::NORMAL_SEPARATOR; | |
81 } | |
82 int GetCommandIdAt(int index) const override { | |
83 return index; | |
84 } | |
85 base::string16 GetLabelAt(int index) const override { | |
86 return entries_[index].title; | |
87 } | |
88 base::string16 GetSublabelAt(int index) const override { | |
89 return base::string16(); | |
90 } | |
91 base::string16 GetMinorTextAt(int index) const override { | |
92 return base::string16(); | |
93 } | |
94 bool IsItemDynamicAt(int index) const override { return false; } | |
95 bool GetAcceleratorAt(int index, | |
96 ui::Accelerator* accelerator) const override { | |
97 return false; | |
98 } | |
99 bool IsItemCheckedAt(int index) const override { return false; } | |
100 int GetGroupIdAt(int index) const override { return -1; } | |
101 bool GetIconAt(int index, gfx::Image* icon) override { return false; } | |
102 ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override { | |
103 return nullptr; | |
104 } | |
105 bool IsEnabledAt(int index) const override { return true; } | |
106 bool IsVisibleAt(int index) const override { return true; } | |
107 ui::MenuModel* GetSubmenuModelAt(int index) const override { return nullptr; } | |
108 void HighlightChangedTo(int index) override {} | |
109 void ActivatedAt(int index) override { | |
110 ActivatedAt(index, 0); | |
111 } | |
112 void ActivatedAt(int index, int event_flags) override { | |
113 navigation_delegate_->NavigateToOffset(entries_[index].offset); | |
114 } | |
115 void SetMenuModelDelegate(ui::MenuModelDelegate* delegate) override { | |
116 delegate_ = delegate; | |
117 } | |
118 ui::MenuModelDelegate* GetMenuModelDelegate() const override { | |
119 return delegate_; | |
120 } | |
121 | |
122 int multiplier_; | |
sky
2016/06/08 21:31:20
remove as not used.
| |
123 ui::MenuModelDelegate* delegate_ = nullptr; | |
124 Delegate* navigation_delegate_; | |
125 std::vector<NavEntry> entries_; | |
126 int cursor_; | |
sky
2016/06/08 21:31:20
Not used?
| |
127 | |
128 DISALLOW_COPY_AND_ASSIGN(NavMenuModel); | |
129 }; | |
130 | |
131 class NavButton : public views::LabelButton { | |
132 public: | |
133 enum class Type { | |
134 BACK, | |
135 FORWARD | |
136 }; | |
137 | |
138 class ModelProvider { | |
139 public: | |
140 virtual std::unique_ptr<ui::MenuModel> CreateMenuModel(Type type) = 0; | |
141 }; | |
142 | |
143 NavButton(Type type, | |
144 ModelProvider* model_provider, | |
145 views::ButtonListener* listener, | |
146 const base::string16& label) | |
147 : views::LabelButton(listener, label), | |
148 type_(type), | |
149 model_provider_(model_provider), | |
150 show_menu_factory_(this) {} | |
151 ~NavButton() override {} | |
152 | |
153 private: | |
154 bool OnMousePressed(const ui::MouseEvent& event) override { | |
sky
2016/06/08 21:31:21
Prefix with // views::LabelButton: (or something s
| |
155 if (IsTriggerableEvent(event) && enabled() && | |
156 HitTestPoint(event.location())) { | |
157 y_pos_on_lbuttondown_ = event.y(); | |
158 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
159 FROM_HERE, | |
160 base::Bind(&NavButton::ShowMenu, show_menu_factory_.GetWeakPtr(), | |
161 ui::GetMenuSourceTypeForEvent(event)), | |
162 base::TimeDelta::FromMilliseconds(500)); | |
163 } | |
164 return LabelButton::OnMousePressed(event); | |
165 } | |
166 bool OnMouseDragged(const ui::MouseEvent& event) override { | |
167 bool result = LabelButton::OnMouseDragged(event); | |
168 if (show_menu_factory_.HasWeakPtrs()) { | |
169 if (event.y() > y_pos_on_lbuttondown_ + GetHorizontalDragThreshold()) { | |
170 show_menu_factory_.InvalidateWeakPtrs(); | |
171 ShowMenu(ui::GetMenuSourceTypeForEvent(event)); | |
172 } | |
173 } | |
174 return result; | |
175 } | |
176 void OnMouseReleased(const ui::MouseEvent& event) override { | |
177 if (IsTriggerableEvent(event)) | |
178 show_menu_factory_.InvalidateWeakPtrs(); | |
179 LabelButton::OnMouseReleased(event); | |
180 } | |
181 | |
sky
2016/06/08 21:31:21
nit: remove extra whitespace.
| |
182 | |
183 void ShowMenu(ui::MenuSourceType source_type) { | |
184 gfx::Rect local = GetLocalBounds(); | |
185 gfx::Point menu_position(local.origin()); | |
186 menu_position.Offset(0, local.height() - 1); | |
187 View::ConvertPointToScreen(this, &menu_position); | |
188 | |
189 model_ = std::move(model_provider_->CreateMenuModel(type_)); | |
190 menu_model_adapter_.reset(new views::MenuModelAdapter( | |
191 model_.get(), | |
192 base::Bind(&NavButton::OnMenuClosed, base::Unretained(this)))); | |
193 menu_model_adapter_->set_triggerable_event_flags(triggerable_event_flags()); | |
194 menu_runner_.reset(new views::MenuRunner( | |
195 menu_model_adapter_->CreateMenu(), | |
196 views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::ASYNC)); | |
197 ignore_result(menu_runner_->RunMenuAt( | |
198 GetWidget(), nullptr, gfx::Rect(menu_position, gfx::Size(0, 0)), | |
199 views::MENU_ANCHOR_TOPLEFT, source_type)); | |
200 } | |
201 | |
202 void OnMenuClosed() { | |
203 SetMouseHandler(nullptr); | |
204 model_.reset(); | |
205 menu_runner_.reset(); | |
206 menu_model_adapter_.reset(); | |
207 } | |
208 | |
209 Type type_; | |
210 ModelProvider* model_provider_; | |
211 int y_pos_on_lbuttondown_ = 0; | |
212 std::unique_ptr<ui::MenuModel> model_; | |
213 std::unique_ptr<views::MenuModelAdapter> menu_model_adapter_; | |
214 std::unique_ptr<views::MenuRunner> menu_runner_; | |
215 base::WeakPtrFactory<NavButton> show_menu_factory_; | |
216 | |
217 DISALLOW_COPY_AND_ASSIGN(NavButton); | |
218 }; | |
219 | |
46 class ProgressBar : public views::View { | 220 class ProgressBar : public views::View { |
47 public: | 221 public: |
48 ProgressBar() {} | 222 ProgressBar() {} |
49 ~ProgressBar() override {} | 223 ~ProgressBar() override {} |
50 | 224 |
51 void SetProgress(double progress) { | 225 void SetProgress(double progress) { |
52 progress_ = progress; | 226 progress_ = progress; |
53 SchedulePaint(); | 227 SchedulePaint(); |
54 } | 228 } |
55 | 229 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
108 base::TimeTicks start_time_; | 282 base::TimeTicks start_time_; |
109 base::Timer timer_; | 283 base::Timer timer_; |
110 base::WeakPtrFactory<Throbber> weak_factory_; | 284 base::WeakPtrFactory<Throbber> weak_factory_; |
111 | 285 |
112 DISALLOW_COPY_AND_ASSIGN(Throbber); | 286 DISALLOW_COPY_AND_ASSIGN(Throbber); |
113 }; | 287 }; |
114 | 288 |
115 class UI : public views::WidgetDelegateView, | 289 class UI : public views::WidgetDelegateView, |
116 public views::ButtonListener, | 290 public views::ButtonListener, |
117 public views::TextfieldController, | 291 public views::TextfieldController, |
118 public navigation::mojom::ViewClient { | 292 public navigation::mojom::ViewClient, |
293 public NavButton::ModelProvider, | |
294 public NavMenuModel::Delegate { | |
119 public: | 295 public: |
120 enum class Type { WINDOW, POPUP }; | 296 enum class Type { WINDOW, POPUP }; |
121 | 297 |
122 UI(Browser* browser, | 298 UI(Browser* browser, |
123 Type type, | 299 Type type, |
124 navigation::mojom::ViewPtr view, | 300 navigation::mojom::ViewPtr view, |
125 navigation::mojom::ViewClientRequest request) | 301 navigation::mojom::ViewClientRequest request) |
126 : browser_(browser), | 302 : browser_(browser), |
127 type_(type), | 303 type_(type), |
128 back_button_(new views::LabelButton(this, base::ASCIIToUTF16("Back"))), | 304 back_button_(new NavButton(NavButton::Type::BACK, this, this, |
129 forward_button_( | 305 base::ASCIIToUTF16("Back"))), |
130 new views::LabelButton(this, base::ASCIIToUTF16("Forward"))), | 306 forward_button_(new NavButton(NavButton::Type::FORWARD, this, this, |
307 base::ASCIIToUTF16("Forward"))), | |
131 reload_button_( | 308 reload_button_( |
132 new views::LabelButton(this, base::ASCIIToUTF16("Reload"))), | 309 new views::LabelButton(this, base::ASCIIToUTF16("Reload"))), |
133 prompt_(new views::Textfield), | 310 prompt_(new views::Textfield), |
134 debug_button_( | 311 debug_button_( |
135 new views::LabelButton(this, base::ASCIIToUTF16("DV"))), | 312 new views::LabelButton(this, base::ASCIIToUTF16("DV"))), |
136 throbber_(new Throbber), | 313 throbber_(new Throbber), |
137 progress_bar_(new ProgressBar), | 314 progress_bar_(new ProgressBar), |
138 debug_view_(new DebugView), | 315 debug_view_(new DebugView), |
139 view_(std::move(view)), | 316 view_(std::move(view)), |
140 view_client_binding_(this, std::move(request)) { | 317 view_client_binding_(this, std::move(request)) { |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 const gfx::Rect& initial_rect, | 491 const gfx::Rect& initial_rect, |
315 bool user_gesture) override { | 492 bool user_gesture) override { |
316 views::Widget* window = views::Widget::CreateWindowWithContextAndBounds( | 493 views::Widget* window = views::Widget::CreateWindowWithContextAndBounds( |
317 new UI(browser_, is_popup ? UI::Type::POPUP : UI::Type::WINDOW, | 494 new UI(browser_, is_popup ? UI::Type::POPUP : UI::Type::WINDOW, |
318 std::move(view), std::move(request)), | 495 std::move(view), std::move(request)), |
319 nullptr, initial_rect); | 496 nullptr, initial_rect); |
320 window->Show(); | 497 window->Show(); |
321 browser_->AddWindow(window); | 498 browser_->AddWindow(window); |
322 } | 499 } |
323 void Close() override { GetWidget()->Close(); } | 500 void Close() override { GetWidget()->Close(); } |
501 void NavigationPending(navigation::mojom::NavigationEntryPtr entry) override { | |
502 pending_nav_ = std::move(entry); | |
503 } | |
504 void NavigationCommitted( | |
505 navigation::mojom::NavigationCommittedDetailsPtr details, | |
506 int current_index) override { | |
507 switch (details->type) { | |
508 case navigation::mojom::NavigationType::NEW_PAGE: { | |
509 if (navigation_list_.size() > 1) { | |
510 auto it = navigation_list_.begin() + (cursor_ + 1); | |
511 if (it < navigation_list_.end()) | |
512 navigation_list_.erase(++it, navigation_list_.end()); | |
513 } | |
514 navigation_list_.push_back(std::move(pending_nav_)); | |
sky
2016/06/08 21:31:20
Don't you want to add at current_index?
Ben Goodger (Google)
2016/06/08 21:55:03
At this point we should have trimmed the navigatio
| |
515 cursor_ = current_index; | |
516 break; | |
517 } | |
518 case navigation::mojom::NavigationType::EXISTING_PAGE: | |
519 cursor_ = current_index; | |
sky
2016/06/08 21:31:20
How come you don't replace the entry at current_in
Ben Goodger (Google)
2016/06/08 21:55:04
That appears to lose data. Sometimes the pending e
| |
520 break; | |
521 } | |
522 } | |
523 void NavigationEntryChanged(navigation::mojom::NavigationEntryPtr entry, | |
524 int entry_index) override { | |
525 navigation_list_[entry_index] = std::move(entry); | |
526 } | |
527 void NavigationListPruned(bool from_front, int count) override { | |
528 DCHECK(count < static_cast<int>(navigation_list_.size())); | |
529 if (from_front) { | |
sky
2016/06/08 21:31:20
Did you mean to have !from_front here as the first
Ben Goodger (Google)
2016/06/08 21:55:04
For navigations, the list reversed. The "front" of
| |
530 auto it = navigation_list_.end() - count; | |
531 navigation_list_.erase(it, navigation_list_.end()); | |
532 } else { | |
533 auto it = navigation_list_.begin() + count; | |
534 navigation_list_.erase(navigation_list_.begin(), it); | |
535 } | |
536 } | |
537 | |
538 // NavButton::ModelProvider: | |
539 std::unique_ptr<ui::MenuModel> CreateMenuModel( | |
540 NavButton::Type type) override { | |
541 std::vector<NavEntry> entries; | |
542 if (type == NavButton::Type::BACK) { | |
543 for (int i = cursor_ - 1, offset = -1; i >= 0; --i, --offset) { | |
544 std::string title = navigation_list_[i]->title; | |
545 entries.push_back(NavEntry(base::UTF8ToUTF16(title), offset)); | |
546 } | |
547 } else { | |
548 for (int i = cursor_ + 1, offset = 1; i < navigation_list_.size(); | |
549 ++i, ++offset) { | |
550 std::string title = navigation_list_[i]->title; | |
551 entries.push_back(NavEntry(base::UTF8ToUTF16(title), offset)); | |
552 } | |
553 } | |
554 return base::WrapUnique(new NavMenuModel(entries, this)); | |
555 } | |
556 | |
557 // NavMenuModel::Delegate: | |
558 void NavigateToOffset(int offset) override { | |
559 view_->NavigateToOffset(offset); | |
sky
2016/06/08 21:31:20
What happens if navigation_list_ changed while the
Ben Goodger (Google)
2016/06/08 21:55:03
These are great questions for an implementation of
| |
560 } | |
324 | 561 |
325 void ToggleDebugView() { | 562 void ToggleDebugView() { |
326 showing_debug_view_ = !showing_debug_view_; | 563 showing_debug_view_ = !showing_debug_view_; |
327 Layout(); | 564 Layout(); |
328 } | 565 } |
329 | 566 |
330 Browser* browser_; | 567 Browser* browser_; |
331 | 568 |
332 Type type_; | 569 Type type_; |
333 | 570 |
334 views::LabelButton* back_button_; | 571 views::LabelButton* back_button_; |
335 views::LabelButton* forward_button_; | 572 views::LabelButton* forward_button_; |
336 views::LabelButton* reload_button_; | 573 views::LabelButton* reload_button_; |
337 views::Textfield* prompt_; | 574 views::Textfield* prompt_; |
338 views::LabelButton* debug_button_; | 575 views::LabelButton* debug_button_; |
339 Throbber* throbber_; | 576 Throbber* throbber_; |
340 ProgressBar* progress_bar_; | 577 ProgressBar* progress_bar_; |
341 | 578 |
342 mus::Window* content_area_ = nullptr; | 579 mus::Window* content_area_ = nullptr; |
343 | 580 |
344 DebugView* debug_view_; | 581 DebugView* debug_view_; |
345 | 582 |
346 navigation::mojom::ViewPtr view_; | 583 navigation::mojom::ViewPtr view_; |
347 mojo::Binding<navigation::mojom::ViewClient> view_client_binding_; | 584 mojo::Binding<navigation::mojom::ViewClient> view_client_binding_; |
348 | 585 |
349 bool is_loading_ = false; | 586 bool is_loading_ = false; |
350 base::string16 current_title_; | 587 base::string16 current_title_; |
351 GURL current_url_; | 588 GURL current_url_; |
352 | 589 |
590 navigation::mojom::NavigationEntryPtr pending_nav_; | |
591 std::vector<navigation::mojom::NavigationEntryPtr> navigation_list_; | |
592 int cursor_ = 0; | |
sky
2016/06/08 21:31:20
Document what this is. I would be inclined to name
| |
593 | |
353 bool showing_debug_view_ = false; | 594 bool showing_debug_view_ = false; |
354 | 595 |
355 DISALLOW_COPY_AND_ASSIGN(UI); | 596 DISALLOW_COPY_AND_ASSIGN(UI); |
356 }; | 597 }; |
357 | 598 |
358 Browser::Browser() {} | 599 Browser::Browser() {} |
359 Browser::~Browser() {} | 600 Browser::~Browser() {} |
360 | 601 |
361 void Browser::AddWindow(views::Widget* window) { | 602 void Browser::AddWindow(views::Widget* window) { |
362 windows_.push_back(window); | 603 windows_.push_back(window); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
410 AddWindow(window); | 651 AddWindow(window); |
411 } | 652 } |
412 | 653 |
413 void Browser::Create(shell::Connection* connection, | 654 void Browser::Create(shell::Connection* connection, |
414 mojom::LaunchableRequest request) { | 655 mojom::LaunchableRequest request) { |
415 bindings_.AddBinding(this, std::move(request)); | 656 bindings_.AddBinding(this, std::move(request)); |
416 } | 657 } |
417 | 658 |
418 } // namespace browser | 659 } // namespace browser |
419 } // namespace mash | 660 } // namespace mash |
OLD | NEW |