Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / apps / guest_view / app_view_browsertest.cc
blob97f3c2bf8679618805a1bcf65d1f19b27f65016f
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/strings/stringprintf.h"
6 #include "chrome/browser/apps/app_browsertest_util.h"
7 #include "components/guest_view/browser/guest_view_manager.h"
8 #include "components/guest_view/browser/guest_view_manager_factory.h"
9 #include "components/guest_view/browser/test_guest_view_manager.h"
10 #include "content/public/browser/notification_service.h"
11 #include "content/public/browser/render_process_host.h"
12 #include "content/public/browser/render_process_host_observer.h"
13 #include "content/public/test/browser_test_utils.h"
14 #include "content/public/test/test_utils.h"
15 #include "extensions/browser/api/extensions_api_client.h"
16 #include "extensions/browser/app_window/app_window_registry.h"
17 #include "extensions/browser/guest_view/app_view/app_view_guest.h"
18 #include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h"
19 #include "extensions/browser/process_manager.h"
20 #include "extensions/common/switches.h"
21 #include "extensions/test/extension_test_message_listener.h"
22 #include "net/test/embedded_test_server/embedded_test_server.h"
23 #include "net/test/embedded_test_server/http_request.h"
24 #include "net/test/embedded_test_server/http_response.h"
26 using extensions::ExtensionsAPIClient;
27 using guest_view::GuestViewManager;
28 using guest_view::TestGuestViewManagerFactory;
30 namespace {
32 class RenderProcessHostObserverForExit
33 : public content::RenderProcessHostObserver {
34 public:
35 explicit RenderProcessHostObserverForExit(
36 content::RenderProcessHost* observed_host)
37 : render_process_host_exited_(false), observed_host_(observed_host) {
38 observed_host->AddObserver(this);
41 void WaitUntilRenderProcessHostKilled() {
42 if (render_process_host_exited_)
43 return;
44 message_loop_runner_ = new content::MessageLoopRunner;
45 message_loop_runner_->Run();
48 base::TerminationStatus termination_status() const { return status_; }
50 private:
51 void RenderProcessExited(content::RenderProcessHost* host,
52 base::TerminationStatus status,
53 int exit_code) override {
54 DCHECK(observed_host_ == host);
55 render_process_host_exited_ = true;
56 status_ = status;
57 observed_host_->RemoveObserver(this);
58 if (message_loop_runner_.get()) {
59 message_loop_runner_->Quit();
63 bool render_process_host_exited_;
64 content::RenderProcessHost* observed_host_;
65 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
66 base::TerminationStatus status_;
68 DISALLOW_COPY_AND_ASSIGN(RenderProcessHostObserverForExit);
71 } // namespace
73 class AppViewTest : public extensions::PlatformAppBrowserTest {
74 public:
75 AppViewTest() {
76 GuestViewManager::set_factory_for_testing(&factory_);
79 enum TestServer {
80 NEEDS_TEST_SERVER,
81 NO_TEST_SERVER
84 void TestHelper(const std::string& test_name,
85 const std::string& app_location,
86 const std::string& app_to_embed,
87 TestServer test_server) {
88 // For serving guest pages.
89 if (test_server == NEEDS_TEST_SERVER) {
90 if (!StartEmbeddedTestServer()) {
91 LOG(ERROR) << "FAILED TO START TEST SERVER.";
92 return;
96 LoadAndLaunchPlatformApp(app_location.c_str(), "Launched");
98 // Flush any pending events to make sure we start with a clean slate.
99 content::RunAllPendingInMessageLoop();
101 content::WebContents* embedder_web_contents =
102 GetFirstAppWindowWebContents();
103 if (!embedder_web_contents) {
104 LOG(ERROR) << "UNABLE TO FIND EMBEDDER WEB CONTENTS.";
105 return;
108 ExtensionTestMessageListener done_listener("TEST_PASSED", false);
109 done_listener.set_failure_message("TEST_FAILED");
110 if (!content::ExecuteScript(
111 embedder_web_contents,
112 base::StringPrintf("runTest('%s', '%s')", test_name.c_str(),
113 app_to_embed.c_str()))) {
114 LOG(ERROR) << "UNABLE TO START TEST.";
115 return;
117 ASSERT_TRUE(done_listener.WaitUntilSatisfied());
120 guest_view::TestGuestViewManager* test_guest_view_manager() const {
121 return test_guest_view_manager_;
124 private:
125 void SetUpCommandLine(base::CommandLine* command_line) override {
126 extensions::PlatformAppBrowserTest::SetUpCommandLine(command_line);
129 void SetUpOnMainThread() override {
130 extensions::PlatformAppBrowserTest::SetUpOnMainThread();
131 test_guest_view_manager_ = static_cast<guest_view::TestGuestViewManager*>(
132 guest_view::GuestViewManager::CreateWithDelegate(
133 browser()->profile(),
134 scoped_ptr<guest_view::GuestViewManagerDelegate>(
135 ExtensionsAPIClient::Get()->CreateGuestViewManagerDelegate(
136 browser()->profile()))));
139 TestGuestViewManagerFactory factory_;
140 guest_view::TestGuestViewManager* test_guest_view_manager_;
142 DISALLOW_COPY_AND_ASSIGN(AppViewTest);
145 // Tests that <appview> is able to navigate to another installed app.
146 IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewWithUndefinedDataShouldSucceed) {
147 const extensions::Extension* skeleton_app =
148 InstallPlatformApp("app_view/shim/skeleton");
149 TestHelper("testAppViewWithUndefinedDataShouldSucceed",
150 "app_view/shim",
151 skeleton_app->id(),
152 NO_TEST_SERVER);
155 // Tests that <appview> correctly processes parameters passed on connect.
156 IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewRefusedDataShouldFail) {
157 const extensions::Extension* skeleton_app =
158 InstallPlatformApp("app_view/shim/skeleton");
159 TestHelper("testAppViewRefusedDataShouldFail",
160 "app_view/shim",
161 skeleton_app->id(),
162 NO_TEST_SERVER);
165 // Tests that <appview> correctly processes parameters passed on connect.
166 IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewGoodDataShouldSucceed) {
167 const extensions::Extension* skeleton_app =
168 InstallPlatformApp("app_view/shim/skeleton");
169 TestHelper("testAppViewGoodDataShouldSucceed",
170 "app_view/shim",
171 skeleton_app->id(),
172 NO_TEST_SERVER);
175 // Tests that <appview> correctly handles multiple successive connects.
176 IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewMultipleConnects) {
177 const extensions::Extension* skeleton_app =
178 InstallPlatformApp("app_view/shim/skeleton");
179 TestHelper("testAppViewMultipleConnects",
180 "app_view/shim",
181 skeleton_app->id(),
182 NO_TEST_SERVER);
185 // Tests that <appview> does not embed self (the app which owns appview).
186 IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewEmbedSelfShouldFail) {
187 const extensions::Extension* skeleton_app =
188 InstallPlatformApp("app_view/shim/skeleton");
189 TestHelper("testAppViewEmbedSelfShouldFail",
190 "app_view/shim",
191 skeleton_app->id(),
192 NO_TEST_SERVER);
195 IN_PROC_BROWSER_TEST_F(AppViewTest, KillGuestWithInvalidInstanceID) {
196 const extensions::Extension* mock_bad_app =
197 LoadAndLaunchPlatformApp("app_view/bad_app", "AppViewTest.LAUNCHED");
199 content::RenderProcessHost* bad_app_render_process_host =
200 extensions::AppWindowRegistry::Get(browser()->profile())
201 ->GetCurrentAppWindowForApp(mock_bad_app->id())
202 ->web_contents()
203 ->GetRenderProcessHost();
205 // Monitor |mock_bad_app|'s RenderProcessHost for its exiting.
206 RenderProcessHostObserverForExit exit_observer(bad_app_render_process_host);
208 // Choosing a |guest_instance_id| which does not exist.
209 int invalid_guest_instance_id =
210 test_guest_view_manager()->GetNextInstanceID();
211 // Call the desired function to verify that the |mock_bad_app| gets killed if
212 // the provided |guest_instance_id| is not mapped to any "GuestView"'s.
213 extensions::AppViewGuest::CompletePendingRequest(
214 browser()->profile(), GURL("about:blank"), invalid_guest_instance_id,
215 mock_bad_app->id(), bad_app_render_process_host);
216 exit_observer.WaitUntilRenderProcessHostKilled();
219 // Failing on msan bot: crbug.com/507940 and Linux dbg http://crbug.com/533318
220 #if defined(MEMORY_SANITIZER) || (defined(OS_LINUX) && !defined(NDEBUG))
221 #define MAYBE_KillGuestCommunicatingWithWrongAppView \
222 DISABLED_KillGuestCommunicatingWithWrongAppView
223 #else
224 #define MAYBE_KillGuestCommunicatingWithWrongAppView \
225 KillGuestCommunicatingWithWrongAppView
226 #endif
228 IN_PROC_BROWSER_TEST_F(AppViewTest,
229 MAYBE_KillGuestCommunicatingWithWrongAppView) {
230 const extensions::Extension* host_app =
231 LoadAndLaunchPlatformApp("app_view/host_app", "AppViewTest.LAUNCHED");
232 const extensions::Extension* mock_guest_extension =
233 InstallPlatformApp("app_view/guest_app");
234 const extensions::Extension* mock_bad_app =
235 LoadAndLaunchPlatformApp("app_view/bad_app", "AppViewTest.LAUNCHED");
237 EXPECT_TRUE(content::ExecuteScript(
238 extensions::AppWindowRegistry::Get(browser()->profile())
239 ->GetCurrentAppWindowForApp(host_app->id())
240 ->web_contents(),
241 base::StringPrintf("onAppCommand('%s', '%s');", "EMBED",
242 mock_guest_extension->id().c_str())));
243 ExtensionTestMessageListener on_embed_requested_listener(
244 "AppViewTest.EmbedRequested", true);
245 EXPECT_TRUE(on_embed_requested_listener.WaitUntilSatisfied());
246 // Now assume the bad application is somehow sending a message to complete a
247 // pending request to attach to <appview>. It should be killed.
248 content::RenderProcessHost* bad_app_render_process_host =
249 extensions::ProcessManager::Get(browser()->profile())
250 ->GetBackgroundHostForExtension(mock_bad_app->id())
251 ->render_process_host();
252 RenderProcessHostObserverForExit bad_app_obs(bad_app_render_process_host);
253 // Make the false request.
254 int guest_instance_id =
255 extensions::AppViewGuest::GetAllRegisteredInstanceIdsForTesting()[0];
256 extensions::AppViewGuest::CompletePendingRequest(
257 browser()->profile(), GURL("about:blank"), guest_instance_id,
258 mock_bad_app->id(), bad_app_render_process_host);
260 on_embed_requested_listener.Reply("continue");
261 // Make sure the bad application has been terminated.
262 bad_app_obs.WaitUntilRenderProcessHostKilled();