| // 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 "base/memory/ptr_util.h" |
| #include "blimp/client/core/contents/ime_feature.h" |
| #include "blimp/client/core/contents/mock_ime_feature_delegate.h" |
| #include "blimp/client/core/contents/mock_navigation_feature_delegate.h" |
| #include "blimp/client/core/contents/navigation_feature.h" |
| #include "blimp/client/core/contents/tab_control_feature.h" |
| #include "blimp/client/core/render_widget/mock_render_widget_feature_delegate.h" |
| #include "blimp/client/core/render_widget/render_widget_feature.h" |
| #include "blimp/client/core/session/assignment_source.h" |
| #include "blimp/client/public/session/assignment.h" |
| #include "blimp/client/session/test_client_session.h" |
| #include "blimp/engine/browser_tests/blimp_browser_test.h" |
| #include "content/public/test/browser_test.h" |
| #include "net/base/ip_address.h" |
| #include "net/base/ip_endpoint.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/WebKit/public/web/WebInputEvent.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "url/gurl.h" |
| |
| using ::testing::_; |
| using ::testing::AtLeast; |
| using ::testing::DoAll; |
| using ::testing::InvokeWithoutArgs; |
| using ::testing::SaveArg; |
| |
| namespace blimp { |
| namespace { |
| |
| const int kDummyTabId = 0; |
| const char kPage1Path[] = "/page1.html"; |
| const char kPage2Path[] = "/page2.html"; |
| const char kInputPagePath[] = "/input.html"; |
| const char kPage1Title[] = "page1"; |
| const char kPage2Title[] = "page2"; |
| |
| // Uses a headless client session to test a full engine. |
| class EngineBrowserTest : public BlimpBrowserTest { |
| public: |
| EngineBrowserTest() {} |
| |
| protected: |
| void SetUpOnMainThread() override { |
| BlimpBrowserTest::SetUpOnMainThread(); |
| |
| // Create a headless client on UI thread. |
| client_session_.reset(new client::TestClientSession); |
| |
| // Set feature delegates. |
| client_session_->GetNavigationFeature()->SetDelegate( |
| kDummyTabId, &client_nav_feature_delegate_); |
| client_session_->GetRenderWidgetFeature()->SetDelegate( |
| kDummyTabId, &client_rw_feature_delegate_); |
| client_session_->GetImeFeature()->set_delegate( |
| &client_ime_feature_delegate_); |
| |
| // Skip assigner. Engine info is already available. |
| client_session_->ConnectWithAssignment(client::ASSIGNMENT_REQUEST_RESULT_OK, |
| GetAssignment()); |
| client_session_->GetTabControlFeature()->SetSizeAndScale( |
| gfx::Size(100, 100), 1); |
| client_session_->GetTabControlFeature()->CreateTab(kDummyTabId); |
| |
| // Record the last page title known to the client. Page loads will sometimes |
| // involve multiple title changes in transition, including the requested |
| // URL. When a page is done loading, the last title should be the one from |
| // the <title> tag. |
| ON_CALL(client_nav_feature_delegate_, OnTitleChanged(kDummyTabId, _)) |
| .WillByDefault(SaveArg<1>(&last_page_title_)); |
| |
| EXPECT_TRUE(embedded_test_server()->Start()); |
| } |
| |
| // Given a path on the embedded local server, tell the client to navigate to |
| // that page by URL. |
| void NavigateToLocalUrl(const std::string& path) { |
| GURL url = embedded_test_server()->GetURL(path); |
| client_session_->GetNavigationFeature()->NavigateToUrlText(kDummyTabId, |
| url.spec()); |
| } |
| |
| // Set mock expectations that a page will load. A page has loaded when the |
| // page load status changes to true, and then to false. |
| void ExpectPageLoad() { |
| testing::InSequence s; |
| |
| // There may be redundant events indicating the page load status is true, |
| // so allow more than one. |
| EXPECT_CALL(client_nav_feature_delegate_, |
| OnLoadingChanged(kDummyTabId, true)) |
| .Times(AtLeast(1)); |
| EXPECT_CALL(client_nav_feature_delegate_, |
| OnLoadingChanged(kDummyTabId, false)) |
| .WillOnce( |
| InvokeWithoutArgs(this, &EngineBrowserTest::SignalCompletion)); |
| } |
| |
| void RunAndVerify() { |
| RunUntilCompletion(); |
| testing::Mock::VerifyAndClearExpectations(&client_rw_feature_delegate_); |
| testing::Mock::VerifyAndClearExpectations(&client_nav_feature_delegate_); |
| testing::Mock::VerifyAndClearExpectations(&client_ime_feature_delegate_); |
| } |
| |
| // Tell the client to navigate to a URL on the local server, and then wait |
| // for the page to load. |
| void LoadPage(const std::string& path) { |
| ExpectPageLoad(); |
| NavigateToLocalUrl(path); |
| RunAndVerify(); |
| } |
| |
| client::MockNavigationFeatureDelegate client_nav_feature_delegate_; |
| client::MockRenderWidgetFeatureDelegate client_rw_feature_delegate_; |
| client::MockImeFeatureDelegate client_ime_feature_delegate_; |
| std::unique_ptr<client::TestClientSession> client_session_; |
| std::string last_page_title_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(EngineBrowserTest); |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(EngineBrowserTest, LoadUrl) { |
| EXPECT_CALL(client_rw_feature_delegate_, OnRenderWidgetCreated(1)); |
| ExpectPageLoad(); |
| NavigateToLocalUrl(kPage1Path); |
| RunAndVerify(); |
| EXPECT_EQ(kPage1Title, last_page_title_); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(EngineBrowserTest, Reload) { |
| LoadPage(kPage1Path); |
| EXPECT_EQ(kPage1Title, last_page_title_); |
| |
| ExpectPageLoad(); |
| client_session_->GetNavigationFeature()->Reload(kDummyTabId); |
| RunAndVerify(); |
| EXPECT_EQ(kPage1Title, last_page_title_); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(EngineBrowserTest, GoBackAndGoForward) { |
| LoadPage(kPage1Path); |
| EXPECT_EQ(kPage1Title, last_page_title_); |
| |
| ExpectPageLoad(); |
| NavigateToLocalUrl(kPage2Path); |
| RunAndVerify(); |
| EXPECT_EQ(kPage2Title, last_page_title_); |
| |
| ExpectPageLoad(); |
| client_session_->GetNavigationFeature()->GoBack(kDummyTabId); |
| RunAndVerify(); |
| EXPECT_EQ(kPage1Title, last_page_title_); |
| |
| ExpectPageLoad(); |
| client_session_->GetNavigationFeature()->GoForward(kDummyTabId); |
| RunAndVerify(); |
| EXPECT_EQ(kPage2Title, last_page_title_); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(EngineBrowserTest, InvalidGoBack) { |
| // Try an invalid GoBack before loading a page, and assert that the page still |
| // loads correctly. |
| ExpectPageLoad(); |
| client_session_->GetNavigationFeature()->GoBack(kDummyTabId); |
| NavigateToLocalUrl(kPage1Path); |
| RunAndVerify(); |
| EXPECT_EQ(kPage1Title, last_page_title_); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(EngineBrowserTest, InvalidGoForward) { |
| LoadPage(kPage1Path); |
| EXPECT_EQ(kPage1Title, last_page_title_); |
| |
| // Try an invalid GoForward before loading a different page, and |
| // assert that the page still loads correctly. |
| ExpectPageLoad(); |
| client_session_->GetNavigationFeature()->GoForward(kDummyTabId); |
| NavigateToLocalUrl(kPage2Path); |
| RunAndVerify(); |
| EXPECT_EQ(kPage2Title, last_page_title_); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(EngineBrowserTest, InputText) { |
| LoadPage(kInputPagePath); |
| |
| blink::WebGestureEvent event; |
| event.type = blink::WebInputEvent::Type::GestureTap; |
| client::ImeFeature::ShowImeCallback callback; |
| |
| // Send a tap event from the client and expect the IME dialog to show. |
| EXPECT_CALL(client_ime_feature_delegate_, OnShowImeRequested(_, "", _)) |
| .Times(AtLeast(1)) |
| .WillOnce( |
| DoAll(InvokeWithoutArgs(this, &EngineBrowserTest::SignalCompletion), |
| SaveArg<2>(&callback))); |
| client_session_->GetRenderWidgetFeature()->SendWebGestureEvent(kDummyTabId, 1, |
| event); |
| RunAndVerify(); |
| |
| // Enter text from the client and expect the input.html JavaScript to update |
| // the page title. |
| EXPECT_CALL(client_nav_feature_delegate_, OnTitleChanged(kDummyTabId, "test")) |
| .WillOnce(InvokeWithoutArgs(this, &EngineBrowserTest::SignalCompletion)); |
| callback.Run("test"); |
| RunAndVerify(); |
| } |
| |
| } // namespace |
| } // namespace blimp |