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
;
32 class RenderProcessHostObserverForExit
33 : public content::RenderProcessHostObserver
{
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_
)
44 message_loop_runner_
= new content::MessageLoopRunner
;
45 message_loop_runner_
->Run();
48 base::TerminationStatus
termination_status() const { return status_
; }
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;
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
);
73 class AppViewTest
: public extensions::PlatformAppBrowserTest
{
76 GuestViewManager::set_factory_for_testing(&factory_
);
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.";
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.";
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.";
117 ASSERT_TRUE(done_listener
.WaitUntilSatisfied());
120 guest_view::TestGuestViewManager
* test_guest_view_manager() const {
121 return test_guest_view_manager_
;
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",
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",
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",
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",
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",
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())
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
224 #define MAYBE_KillGuestCommunicatingWithWrongAppView \
225 KillGuestCommunicatingWithWrongAppView
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())
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();