1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/bind.h"
6 #include "base/callback.h"
7 #include "base/check_op.h"
8 #include "base/test/scoped_run_loop_timeout.h"
9 #include "chromecast/base/chromecast_switches.h"
10 #include "chromecast/browser/cast_browser_process.h"
11 #include "chromecast/browser/extensions/cast_extension_system_factory.h"
12 #include "chromecast/browser/webview/webview_controller.h"
13 #include "components/keyed_service/content/browser_context_dependency_manager.h"
14 #include "content/public/common/content_switches.h"
15 #include "content/public/test/browser_test.h"
16 #include "content/public/test/browser_test_base.h"
17 #include "content/public/test/test_browser_context.h"
18 #include "content/public/test/web_contents_tester.h"
19 #include "net/dns/mock_host_resolver.h"
20 #include "net/http/http_status_code.h"
21 #include "net/test/embedded_test_server/http_request.h"
22 #include "net/test/embedded_test_server/http_response.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 using testing::_;
27 using testing::Truly;
28
29 namespace chromecast {
30 namespace {
31 constexpr base::TimeDelta kDefaultTimeout =
32 base::TimeDelta::FromMilliseconds(5000);
33 }
34
35 class MockClient : public WebviewController::Client {
36 public:
37 MOCK_METHOD(void,
38 EnqueueSend,
39 (std::unique_ptr<webview::WebviewResponse> response));
40 MOCK_METHOD(void, OnError, (const std::string& error_message));
41 };
42
43 class WebviewTest : public content::BrowserTestBase {
44 protected:
45 WebviewTest() = default;
46 ~WebviewTest() override = default;
47
PreRunTestOnMainThread()48 void PreRunTestOnMainThread() override {
49 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
50 base::RunLoop().RunUntilIdle();
51
52 context_ = std::make_unique<content::TestBrowserContext>();
53 run_loop_.reset(new base::RunLoop());
54 }
SetUp()55 void SetUp() final {
56 SetUpCommandLine(base::CommandLine::ForCurrentProcess());
57 embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
58 &WebviewTest::HandleRequest, base::Unretained(this)));
59 ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
60 BrowserTestBase::SetUp();
61 }
SetUpOnMainThread()62 void SetUpOnMainThread() final {
63 host_resolver()->AddRule("*", "127.0.0.1");
64 embedded_test_server()->StartAcceptingConnections();
65 }
TearDownOnMainThread()66 void TearDownOnMainThread() final {
67 BrowserContextDependencyManager::GetInstance()
68 ->DestroyBrowserContextServices(context_.get());
69 context_.reset();
70 }
SetUpCommandLine(base::CommandLine * command_line)71 void SetUpCommandLine(base::CommandLine* command_line) final {
72 command_line->AppendSwitchASCII(switches::kTestType, "browser");
73 }
RunTestOnMainThread()74 void RunTestOnMainThread() override {}
PostRunTestOnMainThread()75 void PostRunTestOnMainThread() override {}
76
RunMessageLoop()77 void RunMessageLoop() {
78 base::test::ScopedRunLoopTimeout timeout(
79 FROM_HERE, kDefaultTimeout,
80 base::BindRepeating(&WebviewTest::OnTimeout, base::Unretained(this)));
81 run_loop_->Run();
82 }
83
HandleRequest(const net::test_server::HttpRequest & request)84 std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
85 const net::test_server::HttpRequest& request) {
86 GURL absolute_url = embedded_test_server()->GetURL(request.relative_url);
87 if (absolute_url.path() != "/test")
88 return std::unique_ptr<net::test_server::HttpResponse>();
89
90 auto http_response =
91 std::make_unique<net::test_server::BasicHttpResponse>();
92 http_response->set_code(net::HTTP_OK);
93 http_response->set_content("hello");
94 http_response->set_content_type("text/plain");
95 return http_response;
96 }
97
OnTimeout()98 std::string OnTimeout() {
99 Quit();
100 return "Timeout in webview browsertest";
101 }
102
Quit()103 void Quit() { run_loop_->QuitWhenIdle(); }
104
105 std::unique_ptr<content::TestBrowserContext> context_;
106 std::unique_ptr<base::RunLoop> run_loop_;
107 MockClient client_;
108 };
109
IN_PROC_BROWSER_TEST_F(WebviewTest,Navigate)110 IN_PROC_BROWSER_TEST_F(WebviewTest, Navigate) {
111 auto check = [](const std::unique_ptr<webview::WebviewResponse>& response) {
112 return response->has_page_event() &&
113 response->page_event().current_page_state() ==
114 webview::AsyncPageEvent_State_LOADED;
115 };
116 EXPECT_CALL(client_, EnqueueSend(_)).Times(testing::AnyNumber());
117 EXPECT_CALL(client_, EnqueueSend(Truly(check)))
118 .Times(testing::AtLeast(1))
119 .WillOnce([this](std::unique_ptr<webview::WebviewResponse> response) {
120 Quit();
121 });
122 WebviewController webview(context_.get(), &client_, true);
123
124 GURL test_url = embedded_test_server()->GetURL("foo.com", "/test");
125
126 webview::WebviewRequest nav;
127 nav.mutable_navigate()->set_url(test_url.spec());
128 webview.ProcessRequest(nav);
129
130 RunMessageLoop();
131 }
132
133 } // namespace chromecast
134