Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / webui / web_ui_mojo_browsertest.cc
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.
4
5 #include <limits>
6
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/content_browser_test.h"
25 #include "content/public/test/content_browser_test_utils.h"
26 #include "content/shell/browser/shell.h"
27 #include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
28 #include "mojo/edk/test/test_utils.h"
29 #include "mojo/public/cpp/bindings/interface_impl.h"
30 #include "mojo/public/cpp/bindings/interface_request.h"
31 #include "mojo/public/js/constants.h"
32
33 namespace content {
34 namespace {
35
36 bool got_message = false;
37
38 // The bindings for the page are generated from a .mojom file. This code looks
39 // up the generated file from disk and returns it.
40 bool GetResource(const std::string& id,
41                  const WebUIDataSource::GotDataCallback& callback) {
42   // These are handled by the WebUIDataSource that AddMojoDataSource() creates.
43   if (id == mojo::kBufferModuleName ||
44       id == mojo::kCodecModuleName ||
45       id == mojo::kConnectionModuleName ||
46       id == mojo::kConnectorModuleName ||
47       id == mojo::kUnicodeModuleName ||
48       id == mojo::kRouterModuleName ||
49       id == mojo::kValidatorModuleName)
50     return false;
51
52   std::string contents;
53   CHECK(base::ReadFileToString(mojo::test::GetFilePathForJSResource(id),
54                                &contents,
55                                std::string::npos)) << id;
56   base::RefCountedString* ref_contents = new base::RefCountedString;
57   ref_contents->data() = contents;
58   callback.Run(ref_contents);
59   return true;
60 }
61
62 class BrowserTargetImpl : public mojo::InterfaceImpl<BrowserTarget> {
63  public:
64   explicit BrowserTargetImpl(base::RunLoop* run_loop) : run_loop_(run_loop) {}
65
66   ~BrowserTargetImpl() override {}
67
68   // mojo::InterfaceImpl<BrowserTarget> overrides:
69   void PingResponse() override { NOTREACHED(); }
70
71  protected:
72   base::RunLoop* run_loop_;
73
74  private:
75   DISALLOW_COPY_AND_ASSIGN(BrowserTargetImpl);
76 };
77
78 class PingBrowserTargetImpl : public BrowserTargetImpl {
79  public:
80   explicit PingBrowserTargetImpl(base::RunLoop* run_loop)
81       : BrowserTargetImpl(run_loop) {}
82
83   ~PingBrowserTargetImpl() override {}
84
85   // mojo::InterfaceImpl<BrowserTarget> overrides:
86   void OnConnectionEstablished() override { client()->Ping(); }
87
88   // Quit the RunLoop when called.
89   void PingResponse() override {
90     got_message = true;
91     run_loop_->Quit();
92   }
93
94  private:
95   DISALLOW_COPY_AND_ASSIGN(PingBrowserTargetImpl);
96 };
97
98 // WebUIController that sets up mojo bindings.
99 class TestWebUIController : public WebUIController {
100  public:
101    TestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
102       : WebUIController(web_ui),
103         run_loop_(run_loop) {
104     content::WebUIDataSource* data_source =
105         WebUIDataSource::AddMojoDataSource(
106             web_ui->GetWebContents()->GetBrowserContext());
107     data_source->SetRequestFilter(base::Bind(&GetResource));
108   }
109
110  protected:
111   base::RunLoop* run_loop_;
112   scoped_ptr<BrowserTargetImpl> browser_target_;
113
114  private:
115   DISALLOW_COPY_AND_ASSIGN(TestWebUIController);
116 };
117
118 // TestWebUIController that additionally creates the ping test BrowserTarget
119 // implementation at the right time.
120 class PingTestWebUIController : public TestWebUIController {
121  public:
122    PingTestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
123        : TestWebUIController(web_ui, run_loop) {
124    }
125    ~PingTestWebUIController() override {}
126
127   // WebUIController overrides:
128    void RenderViewCreated(RenderViewHost* render_view_host) override {
129     render_view_host->GetMainFrame()->GetServiceRegistry()->
130         AddService<BrowserTarget>(base::Bind(
131             &PingTestWebUIController::CreateHandler, base::Unretained(this)));
132   }
133
134   void CreateHandler(mojo::InterfaceRequest<BrowserTarget> request) {
135     browser_target_.reset(mojo::WeakBindToRequest(
136         new PingBrowserTargetImpl(run_loop_), &request));
137   }
138
139  private:
140   DISALLOW_COPY_AND_ASSIGN(PingTestWebUIController);
141 };
142
143 // WebUIControllerFactory that creates TestWebUIController.
144 class TestWebUIControllerFactory : public WebUIControllerFactory {
145  public:
146   TestWebUIControllerFactory() : run_loop_(NULL) {}
147
148   void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
149
150   WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
151                                                const GURL& url) const override {
152     if (url.query() == "ping")
153       return new PingTestWebUIController(web_ui, run_loop_);
154     return NULL;
155   }
156   WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
157                              const GURL& url) const override {
158     return reinterpret_cast<WebUI::TypeID>(1);
159   }
160   bool UseWebUIForURL(BrowserContext* browser_context,
161                       const GURL& url) const override {
162     return true;
163   }
164   bool UseWebUIBindingsForURL(BrowserContext* browser_context,
165                               const GURL& url) const override {
166     return true;
167   }
168
169  private:
170   base::RunLoop* run_loop_;
171
172   DISALLOW_COPY_AND_ASSIGN(TestWebUIControllerFactory);
173 };
174
175 class WebUIMojoTest : public ContentBrowserTest {
176  public:
177   WebUIMojoTest() {
178     WebUIControllerFactory::RegisterFactory(&factory_);
179   }
180
181   ~WebUIMojoTest() override {
182     WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
183   }
184
185   TestWebUIControllerFactory* factory() { return &factory_; }
186
187  private:
188   TestWebUIControllerFactory factory_;
189
190   DISALLOW_COPY_AND_ASSIGN(WebUIMojoTest);
191 };
192
193 // Loads a webui page that contains mojo bindings and verifies a message makes
194 // it from the browser to the page and back.
195 IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndPing) {
196   // Currently there is no way to have a generated file included in the isolate
197   // files. If the bindings file doesn't exist assume we're on such a bot and
198   // pass.
199   // TODO(sky): remove this conditional when isolates support copying from gen.
200   const base::FilePath test_file_path(
201       mojo::test::GetFilePathForJSResource(
202           "content/test/data/web_ui_test_mojo_bindings.mojom"));
203   if (!base::PathExists(test_file_path)) {
204     LOG(WARNING) << " mojom binding file doesn't exist, assuming on isolate";
205     return;
206   }
207
208   got_message = false;
209   ASSERT_TRUE(test_server()->Start());
210   base::RunLoop run_loop;
211   factory()->set_run_loop(&run_loop);
212   GURL test_url(test_server()->GetURL("files/web_ui_mojo.html?ping"));
213   NavigateToURL(shell(), test_url);
214   // RunLoop is quit when message received from page.
215   run_loop.Run();
216   EXPECT_TRUE(got_message);
217
218   // Check that a second render frame in the same renderer process works
219   // correctly.
220   Shell* other_shell = CreateBrowser();
221   got_message = false;
222   base::RunLoop other_run_loop;
223   factory()->set_run_loop(&other_run_loop);
224   NavigateToURL(other_shell, test_url);
225   // RunLoop is quit when message received from page.
226   other_run_loop.Run();
227   EXPECT_TRUE(got_message);
228   EXPECT_EQ(shell()->web_contents()->GetRenderProcessHost(),
229             other_shell->web_contents()->GetRenderProcessHost());
230 }
231
232 }  // namespace
233 }  // namespace content