1 // Copyright 2015 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.
6 #include "base/command_line.h"
7 #include "base/run_loop.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/test/test_timeouts.h"
10 #include "components/html_viewer/public/interfaces/test_html_viewer.mojom.h"
11 #include "components/view_manager/public/cpp/tests/view_manager_test_base.h"
12 #include "components/view_manager/public/cpp/view.h"
13 #include "components/view_manager/public/cpp/view_manager.h"
14 #include "mandoline/tab/frame.h"
15 #include "mandoline/tab/frame_connection.h"
16 #include "mandoline/tab/frame_tree.h"
17 #include "mandoline/tab/public/interfaces/frame_tree.mojom.h"
18 #include "mojo/application/public/cpp/application_impl.h"
19 #include "net/test/spawned_test_server/spawned_test_server.h"
20 #include "third_party/mojo_services/src/accessibility/public/interfaces/accessibility.mojom.h"
22 using mandoline::Frame
;
23 using mandoline::FrameConnection
;
24 using mandoline::FrameTree
;
25 using mandoline::FrameTreeClient
;
31 // Switch to enable out of process iframes.
32 const char kOOPIF
[] = "oopifs";
35 return base::CommandLine::ForCurrentProcess()->HasSwitch(kOOPIF
);
38 std::string
GetFrameText(ApplicationConnection
* connection
) {
39 html_viewer::TestHTMLViewerPtr test_html_viewer
;
40 connection
->ConnectToService(&test_html_viewer
);
42 test_html_viewer
->GetContentAsText(
43 [&result
](const String
& mojo_string
) { result
= mojo_string
; });
44 test_html_viewer
.WaitForIncomingResponse();
50 class HTMLFrameTest
: public ViewManagerTestBase
{
53 ~HTMLFrameTest() override
{}
56 mojo::URLRequestPtr
BuildRequestForURL(const std::string
& url_string
) {
57 const uint16_t assigned_port
= http_server_
->host_port_pair().port();
58 mojo::URLRequestPtr
request(mojo::URLRequest::New());
59 request
->url
= mojo::String::From(
60 base::StringPrintf(url_string
.c_str(), assigned_port
));
61 return request
.Pass();
64 FrameConnection
* InitFrameTree(View
* view
, const std::string
& url_string
) {
65 scoped_ptr
<FrameConnection
> frame_connection(new FrameConnection
);
66 FrameConnection
* result
= frame_connection
.get();
67 ViewManagerClientPtr view_manager_client
;
68 frame_connection
->Init(application_impl(), BuildRequestForURL(url_string
),
69 &view_manager_client
);
70 FrameTreeClient
* frame_tree_client
= frame_connection
->frame_tree_client();
71 frame_tree_
.reset(new FrameTree(view
, nullptr, frame_tree_client
,
72 frame_connection
.Pass()));
73 view
->Embed(view_manager_client
.Pass());
77 bool WaitForEmbedForDescendant() {
80 embed_run_loop_
.reset(new base::RunLoop
);
81 embed_run_loop_
->Run();
82 embed_run_loop_
.reset();
87 void SetUp() override
{
88 ViewManagerTestBase::SetUp();
90 // Make it so we get OnEmbedForDescendant().
91 window_manager()->SetEmbedRoot();
93 // Start a test server.
94 http_server_
.reset(new net::SpawnedTestServer(
95 net::SpawnedTestServer::TYPE_HTTP
, net::SpawnedTestServer::kLocalhost
,
96 base::FilePath(FILE_PATH_LITERAL("components/test/data/html_viewer"))));
97 ASSERT_TRUE(http_server_
->Start());
99 void TearDown() override
{
101 http_server_
.reset();
102 ViewManagerTestBase::TearDown();
104 void OnEmbedForDescendant(View
* view
,
105 URLRequestPtr request
,
106 ViewManagerClientPtr
* client
) override
{
107 Frame
* frame
= Frame::FindFirstFrameAncestor(view
);
108 scoped_ptr
<FrameConnection
> frame_connection(new FrameConnection
);
109 frame_connection
->Init(application_impl(), request
.Pass(), client
);
110 FrameTreeClient
* frame_tree_client
= frame_connection
->frame_tree_client();
111 frame_tree_
->CreateOrReplaceFrame(frame
, view
, frame_tree_client
,
112 frame_connection
.Pass());
114 embed_run_loop_
->Quit();
117 scoped_ptr
<net::SpawnedTestServer
> http_server_
;
118 scoped_ptr
<FrameTree
> frame_tree_
;
121 // A runloop specifically for OnEmbedForDescendant(). We use a separate
122 // runloop here as it's possible at the time OnEmbedForDescendant() is invoked
123 // a separate RunLoop is already running that we shouldn't quit.
124 scoped_ptr
<base::RunLoop
> embed_run_loop_
;
126 DISALLOW_COPY_AND_ASSIGN(HTMLFrameTest
);
129 TEST_F(HTMLFrameTest
, HelloWorld
) {
133 View
* embed_view
= window_manager()->CreateView();
135 FrameConnection
* root_connection
= InitFrameTree(
136 embed_view
, "http://127.0.0.1:%u/files/page_with_single_frame.html");
138 ASSERT_EQ("Page with single frame",
139 GetFrameText(root_connection
->application_connection()));
141 // page_with_single_frame contains a child frame. The child frame should
143 // a new View and Frame.
144 if (embed_view
->children().empty())
145 ASSERT_TRUE(WaitForEmbedForDescendant());
147 ASSERT_EQ(1u, embed_view
->children().size());
149 frame_tree_
->root()->FindFrame(embed_view
->children()[0]->id());
150 ASSERT_TRUE(child_frame
);
153 GetFrameText(static_cast<FrameConnection
*>(child_frame
->user_data())
154 ->application_connection()));