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 class NavMenuModel : public ui::MenuModel { |
| 52 public: |
| 53 class Delegate { |
| 54 public: |
| 55 virtual void NavigateToOffset(int offset) = 0; |
| 56 }; |
| 57 |
| 58 struct Entry { |
| 59 Entry(const base::string16& title, int offset) |
| 60 : title(title), offset(offset) {} |
| 61 ~Entry() {} |
| 62 |
| 63 // Title of the entry in the menu. |
| 64 base::string16 title; |
| 65 // Offset from the currently visible page to navigate to this item. |
| 66 int offset; |
| 67 }; |
| 68 |
| 69 NavMenuModel(const std::vector<Entry>& entries, Delegate* delegate) |
| 70 : navigation_delegate_(delegate), entries_(entries) {} |
| 71 ~NavMenuModel() override {} |
| 72 |
| 73 private: |
| 74 bool HasIcons() const override { return false; } |
| 75 int GetItemCount() const override { |
| 76 return static_cast<int>(entries_.size()); |
| 77 } |
| 78 ui::MenuModel::ItemType GetTypeAt(int index) const override { |
| 79 return ui::MenuModel::TYPE_COMMAND; |
| 80 } |
| 81 ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override { |
| 82 return ui::NORMAL_SEPARATOR; |
| 83 } |
| 84 int GetCommandIdAt(int index) const override { |
| 85 return index; |
| 86 } |
| 87 base::string16 GetLabelAt(int index) const override { |
| 88 return entries_[index].title; |
| 89 } |
| 90 base::string16 GetSublabelAt(int index) const override { |
| 91 return base::string16(); |
| 92 } |
| 93 base::string16 GetMinorTextAt(int index) const override { |
| 94 return base::string16(); |
| 95 } |
| 96 bool IsItemDynamicAt(int index) const override { return false; } |
| 97 bool GetAcceleratorAt(int index, |
| 98 ui::Accelerator* accelerator) const override { |
| 99 return false; |
| 100 } |
| 101 bool IsItemCheckedAt(int index) const override { return false; } |
| 102 int GetGroupIdAt(int index) const override { return -1; } |
| 103 bool GetIconAt(int index, gfx::Image* icon) override { return false; } |
| 104 ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override { |
| 105 return nullptr; |
| 106 } |
| 107 bool IsEnabledAt(int index) const override { return true; } |
| 108 bool IsVisibleAt(int index) const override { return true; } |
| 109 ui::MenuModel* GetSubmenuModelAt(int index) const override { return nullptr; } |
| 110 void HighlightChangedTo(int index) override {} |
| 111 void ActivatedAt(int index) override { |
| 112 ActivatedAt(index, 0); |
| 113 } |
| 114 void ActivatedAt(int index, int event_flags) override { |
| 115 navigation_delegate_->NavigateToOffset(entries_[index].offset); |
| 116 } |
| 117 void SetMenuModelDelegate(ui::MenuModelDelegate* delegate) override { |
| 118 delegate_ = delegate; |
| 119 } |
| 120 ui::MenuModelDelegate* GetMenuModelDelegate() const override { |
| 121 return delegate_; |
| 122 } |
| 123 |
| 124 ui::MenuModelDelegate* delegate_ = nullptr; |
| 125 Delegate* navigation_delegate_; |
| 126 std::vector<Entry> entries_; |
| 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 // views::LabelButton overrides: |
| 155 bool OnMousePressed(const ui::MouseEvent& event) override { |
| 156 if (IsTriggerableEvent(event) && enabled() && |
| 157 HitTestPoint(event.location())) { |
| 158 y_pos_on_lbuttondown_ = event.y(); |
| 159 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 160 FROM_HERE, |
| 161 base::Bind(&NavButton::ShowMenu, show_menu_factory_.GetWeakPtr(), |
| 162 ui::GetMenuSourceTypeForEvent(event)), |
| 163 base::TimeDelta::FromMilliseconds(500)); |
| 164 } |
| 165 return LabelButton::OnMousePressed(event); |
| 166 } |
| 167 bool OnMouseDragged(const ui::MouseEvent& event) override { |
| 168 bool result = LabelButton::OnMouseDragged(event); |
| 169 if (show_menu_factory_.HasWeakPtrs()) { |
| 170 if (event.y() > y_pos_on_lbuttondown_ + GetHorizontalDragThreshold()) { |
| 171 show_menu_factory_.InvalidateWeakPtrs(); |
| 172 ShowMenu(ui::GetMenuSourceTypeForEvent(event)); |
| 173 } |
| 174 } |
| 175 return result; |
| 176 } |
| 177 void OnMouseReleased(const ui::MouseEvent& event) override { |
| 178 if (IsTriggerableEvent(event)) |
| 179 show_menu_factory_.InvalidateWeakPtrs(); |
| 180 LabelButton::OnMouseReleased(event); |
| 181 } |
| 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_ = 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 navigation_list_.push_back(std::move(pending_nav_)); |
| 510 navigation_list_position_ = current_index; |
| 511 break; |
| 512 } |
| 513 case navigation::mojom::NavigationType::EXISTING_PAGE: |
| 514 navigation_list_position_ = current_index; |
| 515 break; |
| 516 default: |
| 517 break; |
| 518 } |
| 519 } |
| 520 void NavigationEntryChanged(navigation::mojom::NavigationEntryPtr entry, |
| 521 int entry_index) override { |
| 522 navigation_list_[entry_index] = std::move(entry); |
| 523 } |
| 524 void NavigationListPruned(bool from_front, int count) override { |
| 525 DCHECK(count < static_cast<int>(navigation_list_.size())); |
| 526 if (from_front) { |
| 527 auto it = navigation_list_.begin() + count; |
| 528 navigation_list_.erase(navigation_list_.begin(), it); |
| 529 } else { |
| 530 auto it = navigation_list_.end() - count; |
| 531 navigation_list_.erase(it, navigation_list_.end()); |
| 532 } |
| 533 } |
| 534 |
| 535 // NavButton::ModelProvider: |
| 536 std::unique_ptr<ui::MenuModel> CreateMenuModel( |
| 537 NavButton::Type type) override { |
| 538 std::vector<NavMenuModel::Entry> entries; |
| 539 if (type == NavButton::Type::BACK) { |
| 540 for (int i = navigation_list_position_ - 1, offset = -1; |
| 541 i >= 0; --i, --offset) { |
| 542 std::string title = navigation_list_[i]->title; |
| 543 entries.push_back( |
| 544 NavMenuModel::Entry(base::UTF8ToUTF16(title), offset)); |
| 545 } |
| 546 } else { |
| 547 for (int i = navigation_list_position_ + 1, offset = 1; |
| 548 i < static_cast<int>(navigation_list_.size()); ++i, ++offset) { |
| 549 std::string title = navigation_list_[i]->title; |
| 550 entries.push_back( |
| 551 NavMenuModel::Entry(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); |
| 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 navigation_list_position_ = 0; |
| 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 |