| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "mash/webtest/webtest.h" |
| |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/strings/string16.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/timer/timer.h" |
| #include "mash/public/interfaces/launchable.mojom.h" |
| #include "mojo/public/c/system/main.h" |
| #include "services/navigation/public/interfaces/view.mojom.h" |
| #include "services/shell/public/cpp/connector.h" |
| #include "services/shell/public/cpp/service.h" |
| #include "services/shell/public/cpp/service_runner.h" |
| #include "services/tracing/public/cpp/tracing_impl.h" |
| #include "services/ui/public/cpp/window.h" |
| #include "services/ui/public/cpp/window_tree_client.h" |
| #include "ui/aura/mus/mus_util.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/paint_throbber.h" |
| #include "ui/native_theme/native_theme.h" |
| #include "ui/views/background.h" |
| #include "ui/views/controls/button/label_button.h" |
| #include "ui/views/controls/textfield/textfield.h" |
| #include "ui/views/controls/textfield/textfield_controller.h" |
| #include "ui/views/mus/aura_init.h" |
| #include "ui/views/mus/window_manager_connection.h" |
| #include "ui/views/widget/widget_delegate.h" |
| #include "url/gurl.h" |
| |
| namespace views { |
| class AuraInit; |
| } |
| |
| namespace mash { |
| namespace webtest { |
| |
| class UI : public views::WidgetDelegateView, |
| public navigation::mojom::ViewClient { |
| public: |
| UI(Webtest* webtest, |
| navigation::mojom::ViewPtr view, |
| navigation::mojom::ViewClientRequest request) |
| : webtest_(webtest), |
| view_(std::move(view)), |
| view_client_binding_(this, std::move(request)) {} |
| ~UI() override { |
| webtest_->RemoveWindow(GetWidget()); |
| } |
| |
| void NavigateTo(const GURL& url) { |
| view_->NavigateTo(url); |
| } |
| |
| private: |
| // Overridden from views::WidgetDelegate: |
| views::View* GetContentsView() override { return this; } |
| base::string16 GetWindowTitle() const override { |
| // TODO(beng): use resources. |
| if (current_title_.empty()) |
| return base::ASCIIToUTF16("navigation::View client"); |
| base::string16 format = base::ASCIIToUTF16("%s - navigation::View client"); |
| base::ReplaceFirstSubstringAfterOffset( |
| &format, 0, base::ASCIIToUTF16("%s"), current_title_); |
| return format; |
| } |
| bool CanResize() const override { return true; } |
| bool CanMaximize() const override { return true; } |
| bool CanMinimize() const override { return true; } |
| |
| // Overridden from views::View: |
| void Layout() override { |
| gfx::Rect local_bounds = GetLocalBounds(); |
| if (content_area_) { |
| gfx::Point offset = local_bounds.origin(); |
| ConvertPointToWidget(this, &offset); |
| int width = local_bounds.width(); |
| int height = local_bounds.height(); |
| content_area_->SetBounds( |
| gfx::Rect(offset.x(), offset.y(), width, height)); |
| } |
| } |
| void ViewHierarchyChanged( |
| const views::View::ViewHierarchyChangedDetails& details) override { |
| if (details.is_add && GetWidget() && !content_area_) { |
| ui::Window* window = aura::GetMusWindow(GetWidget()->GetNativeWindow()); |
| content_area_ = window->window_tree()->NewWindow(nullptr); |
| window->AddChild(content_area_); |
| |
| ui::mojom::WindowTreeClientPtr client; |
| view_->GetWindowTreeClient(GetProxy(&client)); |
| content_area_->Embed(std::move(client)); |
| } |
| } |
| |
| // navigation::mojom::ViewClient: |
| void OpenURL(navigation::mojom::OpenURLParamsPtr params) override {} |
| void LoadingStateChanged(bool is_loading) override {} |
| void NavigationStateChanged(const GURL& url, |
| const mojo::String& title, |
| bool can_go_back, |
| bool can_go_forward) override { |
| current_title_ = base::UTF8ToUTF16(title.get()); |
| GetWidget()->UpdateWindowTitle(); |
| } |
| void LoadProgressChanged(double progress) override {} |
| void UpdateHoverURL(const GURL& url) override {} |
| void ViewCreated(navigation::mojom::ViewPtr view, |
| navigation::mojom::ViewClientRequest request, |
| bool is_popup, |
| const gfx::Rect& initial_rect, |
| bool user_gesture) override { |
| views::Widget* window = views::Widget::CreateWindowWithContextAndBounds( |
| new UI(webtest_, std::move(view), std::move(request)), nullptr, |
| initial_rect); |
| window->Show(); |
| webtest_->AddWindow(window); |
| } |
| void Close() override { |
| GetWidget()->Close(); |
| } |
| void NavigationPending(navigation::mojom::NavigationEntryPtr entry) override { |
| } |
| void NavigationCommitted( |
| navigation::mojom::NavigationCommittedDetailsPtr details, |
| int current_index) override {} |
| void NavigationEntryChanged(navigation::mojom::NavigationEntryPtr entry, |
| int entry_index) override {} |
| void NavigationListPruned(bool from_front, int count) override {} |
| |
| Webtest* webtest_; |
| ui::Window* content_area_ = nullptr; |
| navigation::mojom::ViewPtr view_; |
| mojo::Binding<navigation::mojom::ViewClient> view_client_binding_; |
| base::string16 current_title_; |
| |
| DISALLOW_COPY_AND_ASSIGN(UI); |
| }; |
| |
| Webtest::Webtest() {} |
| Webtest::~Webtest() {} |
| |
| void Webtest::AddWindow(views::Widget* window) { |
| windows_.push_back(window); |
| } |
| |
| void Webtest::RemoveWindow(views::Widget* window) { |
| auto it = std::find(windows_.begin(), windows_.end(), window); |
| DCHECK(it != windows_.end()); |
| windows_.erase(it); |
| if (windows_.empty()) |
| base::MessageLoop::current()->QuitWhenIdle(); |
| } |
| |
| void Webtest::OnStart(const shell::Identity& identity) { |
| tracing_.Initialize(connector(), identity.name()); |
| |
| aura_init_.reset( |
| new views::AuraInit(connector(), "views_mus_resources.pak")); |
| window_manager_connection_ = |
| views::WindowManagerConnection::Create(connector(), identity); |
| } |
| |
| bool Webtest::OnConnect(shell::Connection* connection) { |
| connection->AddInterface<mojom::Launchable>(this); |
| return true; |
| } |
| |
| void Webtest::Launch(uint32_t what, mojom::LaunchMode how) { |
| bool reuse = how == mojom::LaunchMode::REUSE || |
| how == mojom::LaunchMode::DEFAULT; |
| if (reuse && !windows_.empty()) { |
| windows_.back()->Activate(); |
| return; |
| } |
| |
| navigation::mojom::ViewFactoryPtr view_factory; |
| connector()->ConnectToInterface("exe:navigation", &view_factory); |
| navigation::mojom::ViewPtr view; |
| navigation::mojom::ViewClientPtr view_client; |
| navigation::mojom::ViewClientRequest view_client_request = |
| GetProxy(&view_client); |
| view_factory->CreateView(std::move(view_client), GetProxy(&view)); |
| UI* ui = new UI(this, std::move(view), std::move(view_client_request)); |
| views::Widget* window = views::Widget::CreateWindowWithContextAndBounds( |
| ui, nullptr, gfx::Rect(50, 10, 600, 600)); |
| ui->NavigateTo(GURL("http://www.theverge.com/")); |
| window->Show(); |
| AddWindow(window); |
| } |
| |
| void Webtest::Create(const shell::Identity& remote_identity, |
| mojom::LaunchableRequest request) { |
| bindings_.AddBinding(this, std::move(request)); |
| } |
| |
| } // namespace webtest |
| } // namespace mash |