Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / webui / web_ui_mojo_browsertest.cc
blob5ceb632a5d63f5e4c8722a1854d42aeeabd56b8e
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 <limits>
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_util.h"
12 #include "content/browser/webui/web_ui_controller_factory_registry.h"
13 #include "content/public/browser/browser_context.h"
14 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/render_process_host.h"
16 #include "content/public/browser/render_view_host.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/browser/web_ui_controller.h"
19 #include "content/public/browser/web_ui_data_source.h"
20 #include "content/public/common/content_paths.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/public/common/service_registry.h"
23 #include "content/public/common/url_utils.h"
24 #include "content/public/test/browser_test_utils.h"
25 #include "content/public/test/content_browser_test.h"
26 #include "content/public/test/content_browser_test_utils.h"
27 #include "content/shell/browser/shell.h"
28 #include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
29 #include "mojo/test/test_utils.h"
30 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
31 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
32 #include "third_party/mojo/src/mojo/public/js/constants.h"
34 namespace content {
35 namespace {
37 bool got_message = false;
39 // The bindings for the page are generated from a .mojom file. This code looks
40 // up the generated file from disk and returns it.
41 bool GetResource(const std::string& id,
42 const WebUIDataSource::GotDataCallback& callback) {
43 // These are handled by the WebUIDataSource that AddMojoDataSource() creates.
44 if (id == mojo::kBindingsModuleName ||
45 id == mojo::kBufferModuleName ||
46 id == mojo::kCodecModuleName ||
47 id == mojo::kConnectionModuleName ||
48 id == mojo::kConnectorModuleName ||
49 id == mojo::kUnicodeModuleName ||
50 id == mojo::kRouterModuleName ||
51 id == mojo::kValidatorModuleName)
52 return false;
54 std::string contents;
55 CHECK(base::ReadFileToString(mojo::test::GetFilePathForJSResource(id),
56 &contents,
57 std::string::npos)) << id;
58 base::RefCountedString* ref_contents = new base::RefCountedString;
59 ref_contents->data() = contents;
60 callback.Run(ref_contents);
61 return true;
64 class BrowserTargetImpl : public BrowserTarget {
65 public:
66 BrowserTargetImpl(base::RunLoop* run_loop,
67 mojo::InterfaceRequest<BrowserTarget> request)
68 : run_loop_(run_loop), binding_(this, request.Pass()) {}
70 ~BrowserTargetImpl() override {}
72 // BrowserTarget overrides:
73 void Start(const mojo::Closure& closure) override {
74 closure.Run();
76 void Stop() override {
77 got_message = true;
78 run_loop_->Quit();
81 protected:
82 base::RunLoop* run_loop_;
84 private:
85 mojo::Binding<BrowserTarget> binding_;
86 DISALLOW_COPY_AND_ASSIGN(BrowserTargetImpl);
89 // WebUIController that sets up mojo bindings.
90 class TestWebUIController : public WebUIController {
91 public:
92 TestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
93 : WebUIController(web_ui),
94 run_loop_(run_loop) {
95 content::WebUIDataSource* data_source =
96 WebUIDataSource::AddMojoDataSource(
97 web_ui->GetWebContents()->GetBrowserContext());
98 data_source->SetRequestFilter(base::Bind(&GetResource));
101 protected:
102 base::RunLoop* run_loop_;
103 scoped_ptr<BrowserTargetImpl> browser_target_;
105 private:
106 DISALLOW_COPY_AND_ASSIGN(TestWebUIController);
109 // TestWebUIController that additionally creates the ping test BrowserTarget
110 // implementation at the right time.
111 class PingTestWebUIController : public TestWebUIController {
112 public:
113 PingTestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
114 : TestWebUIController(web_ui, run_loop) {
116 ~PingTestWebUIController() override {}
118 // WebUIController overrides:
119 void RenderViewCreated(RenderViewHost* render_view_host) override {
120 render_view_host->GetMainFrame()->GetServiceRegistry()->
121 AddService<BrowserTarget>(base::Bind(
122 &PingTestWebUIController::CreateHandler, base::Unretained(this)));
125 void CreateHandler(mojo::InterfaceRequest<BrowserTarget> request) {
126 browser_target_.reset(new BrowserTargetImpl(run_loop_, request.Pass()));
129 private:
130 DISALLOW_COPY_AND_ASSIGN(PingTestWebUIController);
133 // WebUIControllerFactory that creates TestWebUIController.
134 class TestWebUIControllerFactory : public WebUIControllerFactory {
135 public:
136 TestWebUIControllerFactory() : run_loop_(NULL) {}
138 void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
140 WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
141 const GURL& url) const override {
142 if (url.query() == "ping")
143 return new PingTestWebUIController(web_ui, run_loop_);
144 return new TestWebUIController(web_ui, run_loop_);
146 WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
147 const GURL& url) const override {
148 return reinterpret_cast<WebUI::TypeID>(1);
150 bool UseWebUIForURL(BrowserContext* browser_context,
151 const GURL& url) const override {
152 return true;
154 bool UseWebUIBindingsForURL(BrowserContext* browser_context,
155 const GURL& url) const override {
156 return true;
159 private:
160 base::RunLoop* run_loop_;
162 DISALLOW_COPY_AND_ASSIGN(TestWebUIControllerFactory);
165 class WebUIMojoTest : public ContentBrowserTest {
166 public:
167 WebUIMojoTest() {
168 WebUIControllerFactory::RegisterFactory(&factory_);
171 ~WebUIMojoTest() override {
172 WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
175 TestWebUIControllerFactory* factory() { return &factory_; }
177 private:
178 TestWebUIControllerFactory factory_;
180 DISALLOW_COPY_AND_ASSIGN(WebUIMojoTest);
183 bool IsGeneratedResourceAvailable(const std::string& resource_path) {
184 // Currently there is no way to have a generated file included in the isolate
185 // files. If the bindings file doesn't exist assume we're on such a bot and
186 // pass.
187 // TODO(sky): remove this conditional when isolates support copying from gen.
188 const base::FilePath test_file_path(
189 mojo::test::GetFilePathForJSResource(resource_path));
190 if (base::PathExists(test_file_path))
191 return true;
192 LOG(WARNING) << " mojom binding file doesn't exist, assuming on isolate";
193 return false;
196 // Loads a webui page that contains mojo bindings and verifies a message makes
197 // it from the browser to the page and back.
198 IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndPing) {
199 if (!IsGeneratedResourceAvailable(
200 "content/test/data/web_ui_test_mojo_bindings.mojom"))
201 return;
203 got_message = false;
204 ASSERT_TRUE(test_server()->Start());
205 base::RunLoop run_loop;
206 factory()->set_run_loop(&run_loop);
207 GURL test_url(test_server()->GetURL("files/web_ui_mojo.html?ping"));
208 NavigateToURL(shell(), test_url);
209 // RunLoop is quit when message received from page.
210 run_loop.Run();
211 EXPECT_TRUE(got_message);
213 // Check that a second render frame in the same renderer process works
214 // correctly.
215 Shell* other_shell = CreateBrowser();
216 got_message = false;
217 base::RunLoop other_run_loop;
218 factory()->set_run_loop(&other_run_loop);
219 NavigateToURL(other_shell, test_url);
220 // RunLoop is quit when message received from page.
221 other_run_loop.Run();
222 EXPECT_TRUE(got_message);
223 EXPECT_EQ(shell()->web_contents()->GetRenderProcessHost(),
224 other_shell->web_contents()->GetRenderProcessHost());
227 // Loads a webui page that connects to a test Mojo application via the browser's
228 // Mojo shell interface.
229 IN_PROC_BROWSER_TEST_F(WebUIMojoTest, ConnectToApplication) {
230 if (!IsGeneratedResourceAvailable(
231 "content/public/test/test_mojo_service.mojom"))
232 return;
234 ASSERT_TRUE(test_server()->Start());
235 NavigateToURL(shell(),
236 test_server()->GetURL("files/web_ui_mojo_shell_test.html"));
238 DOMMessageQueue message_queue;
239 std::string message;
240 ASSERT_TRUE(message_queue.WaitForMessage(&message));
241 EXPECT_EQ("true", message);
244 } // namespace
245 } // namespace content