1 // Copyright 2014 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.
5 #include "base/command_line.h"
6 #include "base/file_util.h"
7 #include "base/files/file_path.h"
8 #include "base/path_service.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_util.h"
11 #include "content/browser/webui/web_ui_controller_factory_registry.h"
12 #include "content/common/mojo/mojo_channel_init.h"
13 #include "content/public/browser/browser_context.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/browser/web_ui_controller.h"
17 #include "content/public/browser/web_ui_data_source.h"
18 #include "content/public/common/content_paths.h"
19 #include "content/public/common/content_switches.h"
20 #include "content/public/common/url_utils.h"
21 #include "content/public/test/content_browser_test.h"
22 #include "content/public/test/content_browser_test_utils.h"
23 #include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
24 #include "grit/content_resources.h"
25 #include "mojo/public/bindings/js/constants.h"
26 #include "mojo/public/bindings/remote_ptr.h"
31 bool got_message
= false;
33 // Returns the path to the mojom js bindings file.
34 base::FilePath
GetFilePathForJSResource(const std::string
& path
) {
35 std::string binding_path
= "gen/" + path
+ ".js";
38 base::ReplaceChars(binding_path
, "//", "\\", &tmp
);
39 binding_path
.swap(tmp
);
41 base::FilePath file_path
;
42 PathService::Get(CHILD_PROCESS_EXE
, &file_path
);
43 return file_path
.DirName().AppendASCII(binding_path
);
46 // The bindings for the page are generated from a .mojom file. This code looks
47 // up the generated file from disk and returns it.
48 bool GetResource(const std::string
& id
,
49 const WebUIDataSource::GotDataCallback
& callback
) {
50 // These are handled by the WebUIDataSource that AddMojoDataSource() creates.
51 if (id
== mojo::kCodecModuleName
||
52 id
== mojo::kConnectionModuleName
||
53 id
== mojo::kConnectorModuleName
||
54 id
== mojo::kRouterModuleName
)
58 CHECK(base::ReadFileToString(GetFilePathForJSResource(id
), &contents
,
60 base::RefCountedString
* ref_contents
= new base::RefCountedString
;
61 ref_contents
->data() = contents
;
62 callback
.Run(ref_contents
);
66 // BrowserTarget implementation that quits a RunLoop when BrowserTarget::Test()
68 class BrowserTargetImpl
: public mojo::BrowserTarget
{
70 BrowserTargetImpl(mojo::ScopedRendererTargetHandle handle
,
71 base::RunLoop
* run_loop
)
72 : client_(handle
.Pass(), this),
76 virtual ~BrowserTargetImpl() {}
78 // mojo::BrowserTarget overrides:
79 virtual void Test() OVERRIDE
{
85 mojo::RemotePtr
<mojo::RendererTarget
> client_
;
87 base::RunLoop
* run_loop_
;
89 DISALLOW_COPY_AND_ASSIGN(BrowserTargetImpl
);
92 // WebUIController that sets up mojo bindings. Additionally it creates the
93 // BrowserTarget implementation at the right time.
94 class TestWebUIController
: public WebUIController
{
96 explicit TestWebUIController(WebUI
* web_ui
, base::RunLoop
* run_loop
)
97 : WebUIController(web_ui
),
99 content::WebUIDataSource
* data_source
=
100 WebUIDataSource::AddMojoDataSource(
101 web_ui
->GetWebContents()->GetBrowserContext());
102 data_source
->SetRequestFilter(base::Bind(&GetResource
));
105 // WebUIController overrides:
106 virtual void RenderViewCreated(RenderViewHost
* render_view_host
) OVERRIDE
{
107 mojo::InterfacePipe
<mojo::BrowserTarget
, mojo::RendererTarget
> pipe
;
108 browser_target_
.reset(
109 new BrowserTargetImpl(pipe
.handle_to_peer
.Pass(), run_loop_
));
110 render_view_host
->SetWebUIHandle(
111 mojo::ScopedMessagePipeHandle(pipe
.handle_to_self
.release()));
115 base::RunLoop
* run_loop_
;
117 scoped_ptr
<BrowserTargetImpl
> browser_target_
;
119 DISALLOW_COPY_AND_ASSIGN(TestWebUIController
);
122 // WebUIControllerFactory that creates TestWebUIController.
123 class TestWebUIControllerFactory
: public WebUIControllerFactory
{
125 TestWebUIControllerFactory() : run_loop_(NULL
) {}
127 void set_run_loop(base::RunLoop
* run_loop
) { run_loop_
= run_loop
; }
129 virtual WebUIController
* CreateWebUIControllerForURL(
130 WebUI
* web_ui
, const GURL
& url
) const OVERRIDE
{
131 return new TestWebUIController(web_ui
, run_loop_
);
133 virtual WebUI::TypeID
GetWebUIType(BrowserContext
* browser_context
,
134 const GURL
& url
) const OVERRIDE
{
135 return reinterpret_cast<WebUI::TypeID
>(1);
137 virtual bool UseWebUIForURL(BrowserContext
* browser_context
,
138 const GURL
& url
) const OVERRIDE
{
141 virtual bool UseWebUIBindingsForURL(BrowserContext
* browser_context
,
142 const GURL
& url
) const OVERRIDE
{
147 base::RunLoop
* run_loop_
;
149 DISALLOW_COPY_AND_ASSIGN(TestWebUIControllerFactory
);
152 class WebUIMojoTest
: public ContentBrowserTest
{
155 WebUIControllerFactory::RegisterFactory(&factory_
);
158 virtual ~WebUIMojoTest() {
159 WebUIControllerFactory::UnregisterFactoryForTesting(&factory_
);
162 TestWebUIControllerFactory
* factory() { return &factory_
; }
165 TestWebUIControllerFactory factory_
;
167 DISALLOW_COPY_AND_ASSIGN(WebUIMojoTest
);
170 // Loads a webui page that contains mojo bindings and verifies a message makes
171 // it from the browser to the page and back.
172 IN_PROC_BROWSER_TEST_F(WebUIMojoTest
, EndToEnd
) {
173 // Currently there is no way to have a generated file included in the isolate
174 // files. If the bindings file doesn't exist assume we're on such a bot and
176 // TODO(sky): remove this conditional when isolates support copying from gen.
177 const base::FilePath
test_file_path(
178 GetFilePathForJSResource(
179 "content/test/data/web_ui_test_mojo_bindings.mojom"));
180 if (!base::PathExists(test_file_path
)) {
181 LOG(WARNING
) << " mojom binding file doesn't exist, assuming on isolate";
186 ASSERT_TRUE(test_server()->Start());
187 base::RunLoop run_loop
;
188 factory()->set_run_loop(&run_loop
);
189 GURL
test_url(test_server()->GetURL("files/web_ui_mojo.html"));
190 NavigateToURL(shell(), test_url
);
191 // RunLoop is quit when message received from page.
193 EXPECT_TRUE(got_message
);
197 } // namespace content