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