1 // Copyright 2013 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 <stddef.h>
6
7 #include <memory>
8
9 #include "apps/launcher.h"
10 #include "base/auto_reset.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/files/file_util.h"
14 #include "base/files/scoped_temp_dir.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/run_loop.h"
17 #include "base/stl_util.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/threading/thread_restrictions.h"
20 #include "build/build_config.h"
21 #include "chrome/app/chrome_command_ids.h"
22 #include "chrome/browser/apps/app_service/app_launch_params.h"
23 #include "chrome/browser/apps/app_service/app_service_proxy.h"
24 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
25 #include "chrome/browser/apps/app_service/browser_app_launcher.h"
26 #include "chrome/browser/apps/app_service/launch_utils.h"
27 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
28 #include "chrome/browser/chrome_notification_types.h"
29 #include "chrome/browser/devtools/devtools_window.h"
30 #include "chrome/browser/extensions/api/permissions/permissions_api.h"
31 #include "chrome/browser/extensions/component_loader.h"
32 #include "chrome/browser/extensions/extension_browsertest.h"
33 #include "chrome/browser/extensions/extension_service.h"
34 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
35 #include "chrome/browser/ui/browser.h"
36 #include "chrome/browser/ui/extensions/app_launch_params.h"
37 #include "chrome/browser/ui/tabs/tab_strip_model.h"
38 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
39 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
40 #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h"
41 #include "chrome/common/chrome_switches.h"
42 #include "chrome/common/url_constants.h"
43 #include "chrome/test/base/test_switches.h"
44 #include "chrome/test/base/ui_test_utils.h"
45 #include "components/pref_registry/pref_registry_syncable.h"
46 #include "components/prefs/pref_service.h"
47 #include "components/web_modal/web_contents_modal_dialog_manager.h"
48 #include "content/public/browser/devtools_agent_host.h"
49 #include "content/public/browser/host_zoom_map.h"
50 #include "content/public/browser/overlay_window.h"
51 #include "content/public/browser/picture_in_picture_window_controller.h"
52 #include "content/public/browser/render_process_host.h"
53 #include "content/public/browser/render_widget_host_view.h"
54 #include "content/public/test/browser_test.h"
55 #include "content/public/test/browser_test_utils.h"
56 #include "extensions/browser/app_window/app_window.h"
57 #include "extensions/browser/app_window/app_window_registry.h"
58 #include "extensions/browser/app_window/native_app_window.h"
59 #include "extensions/browser/event_router.h"
60 #include "extensions/browser/extension_prefs.h"
61 #include "extensions/browser/extension_registry.h"
62 #include "extensions/browser/extension_registry_observer.h"
63 #include "extensions/browser/pref_names.h"
64 #include "extensions/common/api/app_runtime.h"
65 #include "extensions/common/constants.h"
66 #include "extensions/test/extension_test_message_listener.h"
67 #include "extensions/test/result_catcher.h"
68 #include "net/test/embedded_test_server/embedded_test_server.h"
69 #include "printing/buildflags/buildflags.h"
70 #include "ui/base/window_open_disposition.h"
71 #include "ui/display/types/display_constants.h"
72 #include "url/gurl.h"
73
74 #if defined(OS_CHROMEOS)
75 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
76 #include "chromeos/dbus/dbus_thread_manager.h"
77 #include "chromeos/dbus/power/fake_power_manager_client.h"
78 #include "components/user_manager/scoped_user_manager.h"
79 #endif
80
81 using content::WebContents;
82 using web_modal::WebContentsModalDialogManager;
83
84 namespace app_runtime = extensions::api::app_runtime;
85
86 namespace extensions {
87
88 namespace {
89
90 // Non-abstract RenderViewContextMenu class.
91 class PlatformAppContextMenu : public RenderViewContextMenu {
92 public:
PlatformAppContextMenu(content::RenderFrameHost * render_frame_host,const content::ContextMenuParams & params)93 PlatformAppContextMenu(content::RenderFrameHost* render_frame_host,
94 const content::ContextMenuParams& params)
95 : RenderViewContextMenu(render_frame_host, params) {}
96
HasCommandWithId(int command_id)97 bool HasCommandWithId(int command_id) {
98 return menu_model_.GetIndexOfCommandId(command_id) != -1;
99 }
100
Show()101 void Show() override {}
102 };
103
104 // This class keeps track of tabs as they are added to the browser. It will be
105 // "done" (i.e. won't block on Wait()) once |observations| tabs have been added.
106 class TabsAddedNotificationObserver : public TabStripModelObserver {
107 public:
TabsAddedNotificationObserver(Browser * browser,size_t observations)108 TabsAddedNotificationObserver(Browser* browser, size_t observations)
109 : observations_(observations) {
110 browser->tab_strip_model()->AddObserver(this);
111 }
112 TabsAddedNotificationObserver(const TabsAddedNotificationObserver&) = delete;
113 TabsAddedNotificationObserver& operator=(
114 const TabsAddedNotificationObserver&) = delete;
115 ~TabsAddedNotificationObserver() override = default;
116
117 // TabStripModelObserver:
OnTabStripModelChanged(TabStripModel * tab_strip_model,const TabStripModelChange & change,const TabStripSelectionChange & selection)118 void OnTabStripModelChanged(
119 TabStripModel* tab_strip_model,
120 const TabStripModelChange& change,
121 const TabStripSelectionChange& selection) override {
122 if (change.type() != TabStripModelChange::kInserted)
123 return;
124
125 for (auto& tab : change.GetInsert()->contents)
126 observed_tabs_.push_back(tab.contents);
127
128 if (observed_tabs_.size() >= observations_)
129 run_loop_.Quit();
130 }
131
Wait()132 void Wait() { run_loop_.Run(); }
133
tabs()134 const std::vector<content::WebContents*>& tabs() { return observed_tabs_; }
135
136 private:
137 base::RunLoop run_loop_;
138 size_t observations_;
139 std::vector<content::WebContents*> observed_tabs_;
140 };
141
142 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
143 class ScopedPreviewTestDelegate : printing::PrintPreviewUI::TestDelegate {
144 public:
ScopedPreviewTestDelegate()145 ScopedPreviewTestDelegate() {
146 printing::PrintPreviewUI::SetDelegateForTesting(this);
147 }
148
~ScopedPreviewTestDelegate()149 ~ScopedPreviewTestDelegate() override {
150 printing::PrintPreviewUI::SetDelegateForTesting(nullptr);
151 }
152
153 // PrintPreviewUI::TestDelegate implementation.
DidGetPreviewPageCount(uint32_t page_count)154 void DidGetPreviewPageCount(uint32_t page_count) override {
155 total_page_count_ = page_count;
156 }
157
158 // PrintPreviewUI::TestDelegate implementation.
DidRenderPreviewPage(content::WebContents * preview_dialog)159 void DidRenderPreviewPage(content::WebContents* preview_dialog) override {
160 dialog_size_ = preview_dialog->GetContainerBounds().size();
161 ++rendered_page_count_;
162 CHECK(rendered_page_count_ <= total_page_count_);
163 if (rendered_page_count_ == total_page_count_ && run_loop_) {
164 run_loop_->Quit();
165 }
166 }
167
WaitUntilPreviewIsReady()168 void WaitUntilPreviewIsReady() {
169 if (rendered_page_count_ >= total_page_count_)
170 return;
171
172 base::RunLoop run_loop;
173 base::AutoReset<base::RunLoop*> auto_reset(&run_loop_, &run_loop);
174 run_loop.Run();
175 }
176
dialog_size()177 gfx::Size dialog_size() { return dialog_size_; }
178
179 private:
180 uint32_t total_page_count_ = 1;
181 uint32_t rendered_page_count_ = 0;
182 base::RunLoop* run_loop_ = nullptr;
183 gfx::Size dialog_size_;
184 };
185
186 #endif // ENABLE_PRINT_PREVIEW
187
188 #if !defined(OS_CHROMEOS) && !defined(OS_WIN)
CopyTestDataAndGetTestFilePath(const base::FilePath & test_data_file,const base::FilePath & temp_dir,const char * filename,base::FilePath * file_path)189 bool CopyTestDataAndGetTestFilePath(const base::FilePath& test_data_file,
190 const base::FilePath& temp_dir,
191 const char* filename,
192 base::FilePath* file_path) {
193 base::FilePath path =
194 temp_dir.AppendASCII(filename).NormalizePathSeparators();
195 if (!(base::CopyFile(test_data_file, path)))
196 return false;
197
198 *file_path = path;
199 return true;
200 }
201 #endif // !defined(OS_CHROMEOS) && !defined(OS_WIN)
202
203 class PlatformAppWithFileBrowserTest : public PlatformAppBrowserTest {
204 public:
PlatformAppWithFileBrowserTest()205 PlatformAppWithFileBrowserTest() {
206 set_open_about_blank_on_browser_launch(false);
207 }
208
209 protected:
RunPlatformAppTestWithFileInTestDataDir(const std::string & extension_name,const std::string & test_file)210 bool RunPlatformAppTestWithFileInTestDataDir(
211 const std::string& extension_name,
212 const std::string& test_file) {
213 base::FilePath test_doc(test_data_dir_.AppendASCII(test_file));
214 test_doc = test_doc.NormalizePathSeparators();
215 return RunPlatformAppTestWithCommandLine(
216 extension_name, MakeCommandLineWithTestFilePath(test_doc));
217 }
218
RunPlatformAppTestWithFile(const std::string & extension_name,const base::FilePath & test_file_path)219 bool RunPlatformAppTestWithFile(const std::string& extension_name,
220 const base::FilePath& test_file_path) {
221 return RunPlatformAppTestWithCommandLine(
222 extension_name, MakeCommandLineWithTestFilePath(test_file_path));
223 }
224
RunPlatformAppTestWithNothing(const std::string & extension_name)225 bool RunPlatformAppTestWithNothing(const std::string& extension_name) {
226 return RunPlatformAppTestWithCommandLine(
227 extension_name, *base::CommandLine::ForCurrentProcess());
228 }
229
RunPlatformAppTestWithFiles(const std::string & extension_name,const std::string & test_file)230 void RunPlatformAppTestWithFiles(const std::string& extension_name,
231 const std::string& test_file) {
232 extensions::ResultCatcher catcher;
233
234 base::FilePath test_doc(test_data_dir_.AppendASCII(test_file));
235 base::FilePath file_path = test_doc.NormalizePathSeparators();
236
237 base::FilePath extension_path = test_data_dir_.AppendASCII(extension_name);
238 const extensions::Extension* extension =
239 LoadExtensionWithFlags(extension_path, kFlagNone);
240 ASSERT_TRUE(extension);
241
242 apps::mojom::FilePathsPtr launch_files = apps::mojom::FilePaths::New();
243 launch_files->file_paths.push_back(file_path);
244 apps::AppServiceProxyFactory::GetForProfile(browser()->profile())
245 ->LaunchAppWithFiles(
246 extension->id(), apps::mojom::LaunchContainer::kLaunchContainerNone,
247 apps::GetEventFlags(
248 apps::mojom::LaunchContainer::kLaunchContainerNone,
249 WindowOpenDisposition::NEW_FOREGROUND_TAB,
250 true /* preferred_container */),
251 apps::mojom::LaunchSource::kFromTest, std::move(launch_files));
252 ASSERT_TRUE(catcher.GetNextResult());
253 }
254
255 private:
RunPlatformAppTestWithCommandLine(const std::string & extension_name,const base::CommandLine & command_line)256 bool RunPlatformAppTestWithCommandLine(
257 const std::string& extension_name,
258 const base::CommandLine& command_line) {
259 extensions::ResultCatcher catcher;
260
261 base::FilePath extension_path = test_data_dir_.AppendASCII(extension_name);
262 const extensions::Extension* extension =
263 LoadExtensionWithFlags(extension_path, kFlagNone);
264 if (!extension) {
265 message_ = "Failed to load extension.";
266 return false;
267 }
268
269 apps::AppLaunchParams params(
270 extension->id(), apps::mojom::LaunchContainer::kLaunchContainerNone,
271 WindowOpenDisposition::NEW_WINDOW,
272 apps::mojom::AppLaunchSource::kSourceTest);
273 params.command_line = command_line;
274 params.current_directory = test_data_dir_;
275 apps::AppServiceProxyFactory::GetForProfile(browser()->profile())
276 ->BrowserAppLauncher()
277 ->LaunchAppWithParams(std::move(params));
278
279 if (!catcher.GetNextResult()) {
280 message_ = catcher.message();
281 return false;
282 }
283
284 return true;
285 }
286
MakeCommandLineWithTestFilePath(const base::FilePath & test_file)287 base::CommandLine MakeCommandLineWithTestFilePath(
288 const base::FilePath& test_file) {
289 base::CommandLine command_line = *base::CommandLine::ForCurrentProcess();
290 command_line.AppendArgPath(test_file);
291 return command_line;
292 }
293 };
294
295 const char kChromiumURL[] = "http://chromium.org";
296 #if !defined(OS_CHROMEOS)
297 const char kTestFilePath[] = "platform_apps/launch_files/test.txt";
298 #endif
299
300 } // namespace
301
302 // Tests that CreateAppWindow doesn't crash if you close it straight away.
303 // LauncherPlatformAppBrowserTest relies on this behaviour, but is only run for
304 // ash, so we test that it works here.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,CreateAndCloseAppWindow)305 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, CreateAndCloseAppWindow) {
306 const Extension* extension = LoadAndLaunchPlatformApp("minimal", "Launched");
307 AppWindow* window = CreateAppWindow(browser()->profile(), extension);
308 CloseAppWindow(window);
309 }
310
311 // Tests that platform apps received the "launch" event when launched.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,OnLaunchedEvent)312 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OnLaunchedEvent) {
313 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch")) << message_;
314 }
315
316 // Tests that platform apps cannot use certain disabled window properties, but
317 // can override them and then use them.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,DisabledWindowProperties)318 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisabledWindowProperties) {
319 ASSERT_TRUE(RunPlatformAppTest("platform_apps/disabled_window_properties"))
320 << message_;
321 }
322
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,EmptyContextMenu)323 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, EmptyContextMenu) {
324 LoadAndLaunchPlatformApp("minimal", "Launched");
325
326 // The empty app doesn't add any context menu items, so its menu should
327 // only include the developer tools.
328 WebContents* web_contents = GetFirstAppWindowWebContents();
329 ASSERT_TRUE(web_contents);
330 content::ContextMenuParams params;
331 std::unique_ptr<PlatformAppContextMenu> menu;
332 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
333 menu->Init();
334 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
335 ASSERT_TRUE(
336 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
337 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
338 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
339 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
340 }
341
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWithContextMenu)342 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenu) {
343 LoadAndLaunchPlatformApp("context_menu", "Launched");
344
345 // The context_menu app has two context menu items. These, along with a
346 // separator and the developer tools, is all that should be in the menu.
347 WebContents* web_contents = GetFirstAppWindowWebContents();
348 ASSERT_TRUE(web_contents);
349 content::ContextMenuParams params;
350 std::unique_ptr<PlatformAppContextMenu> menu;
351 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
352 menu->Init();
353 int first_extensions_command_id =
354 ContextMenuMatcher::ConvertToExtensionsCustomCommandId(0);
355 ASSERT_TRUE(menu->HasCommandWithId(first_extensions_command_id));
356 ASSERT_TRUE(menu->HasCommandWithId(first_extensions_command_id + 1));
357 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
358 ASSERT_TRUE(
359 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
360 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
361 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
362 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
363 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
364 }
365
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,InstalledAppWithContextMenu)366 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, InstalledAppWithContextMenu) {
367 ExtensionTestMessageListener launched_listener("Launched", false);
368 InstallAndLaunchPlatformApp("context_menu");
369
370 // Wait for the extension to tell us it's initialized its context menus and
371 // launched a window.
372 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
373
374 // The context_menu app has two context menu items. For an installed app
375 // these are all that should be in the menu.
376 WebContents* web_contents = GetFirstAppWindowWebContents();
377 ASSERT_TRUE(web_contents);
378 content::ContextMenuParams params;
379 std::unique_ptr<PlatformAppContextMenu> menu;
380 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
381 menu->Init();
382 int extensions_custom_id =
383 ContextMenuMatcher::ConvertToExtensionsCustomCommandId(0);
384 ASSERT_TRUE(menu->HasCommandWithId(extensions_custom_id));
385 ASSERT_TRUE(menu->HasCommandWithId(extensions_custom_id + 1));
386 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
387 ASSERT_FALSE(
388 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
389 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
390 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
391 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
392 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
393 }
394
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWithContextMenuTextField)395 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuTextField) {
396 LoadAndLaunchPlatformApp("context_menu", "Launched");
397
398 // The context_menu app has one context menu item. This, along with a
399 // separator and the developer tools, is all that should be in the menu.
400 WebContents* web_contents = GetFirstAppWindowWebContents();
401 ASSERT_TRUE(web_contents);
402 content::ContextMenuParams params;
403 params.is_editable = true;
404 std::unique_ptr<PlatformAppContextMenu> menu;
405 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
406 menu->Init();
407 int extensions_custom_id =
408 ContextMenuMatcher::ConvertToExtensionsCustomCommandId(0);
409 ASSERT_TRUE(menu->HasCommandWithId(extensions_custom_id));
410 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
411 ASSERT_TRUE(
412 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
413 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
414 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
415 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY));
416 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
417 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
418 }
419
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWithContextMenuSelection)420 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuSelection) {
421 LoadAndLaunchPlatformApp("context_menu", "Launched");
422
423 // The context_menu app has one context menu item. This, along with a
424 // separator and the developer tools, is all that should be in the menu.
425 WebContents* web_contents = GetFirstAppWindowWebContents();
426 ASSERT_TRUE(web_contents);
427 content::ContextMenuParams params;
428 params.selection_text = base::ASCIIToUTF16("Hello World");
429 std::unique_ptr<PlatformAppContextMenu> menu;
430 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
431 menu->Init();
432 int extensions_custom_id =
433 ContextMenuMatcher::ConvertToExtensionsCustomCommandId(0);
434 ASSERT_TRUE(menu->HasCommandWithId(extensions_custom_id));
435 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
436 ASSERT_TRUE(
437 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
438 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
439 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
440 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY));
441 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
442 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
443 }
444
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWithContextMenuClicked)445 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuClicked) {
446 LoadAndLaunchPlatformApp("context_menu_click", "Launched");
447
448 // Test that the menu item shows up
449 WebContents* web_contents = GetFirstAppWindowWebContents();
450 ASSERT_TRUE(web_contents);
451 content::ContextMenuParams params;
452 params.page_url = GURL("http://foo.bar");
453 std::unique_ptr<PlatformAppContextMenu> menu;
454 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
455 menu->Init();
456 int extensions_custom_id =
457 ContextMenuMatcher::ConvertToExtensionsCustomCommandId(0);
458 ASSERT_TRUE(menu->HasCommandWithId(extensions_custom_id));
459
460 // Execute the menu item
461 ExtensionTestMessageListener onclicked_listener("onClicked fired for id1",
462 false);
463 menu->ExecuteCommand(extensions_custom_id, 0);
464
465 ASSERT_TRUE(onclicked_listener.WaitUntilSatisfied());
466 }
467
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,DisallowNavigation)468 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowNavigation) {
469 TabsAddedNotificationObserver observer(browser(), 1);
470
471 ASSERT_TRUE(StartEmbeddedTestServer());
472 ASSERT_TRUE(RunPlatformAppTest("platform_apps/navigation")) << message_;
473
474 observer.Wait();
475 ASSERT_EQ(1U, observer.tabs().size());
476 EXPECT_EQ(GURL(kChromiumURL), observer.tabs()[0]->GetURL());
477 }
478
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,DisallowBackgroundPageNavigation)479 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
480 DisallowBackgroundPageNavigation) {
481 // The test will try to open in app urls and external urls via clicking links
482 // and window.open(). Only the external urls should succeed in opening tabs.
483 const size_t kExpectedNumberOfTabs = 2u;
484 TabsAddedNotificationObserver observer(browser(), kExpectedNumberOfTabs);
485 ASSERT_TRUE(RunPlatformAppTest("platform_apps/background_page_navigation"))
486 << message_;
487 observer.Wait();
488 ASSERT_EQ(kExpectedNumberOfTabs, observer.tabs().size());
489 EXPECT_FALSE(
490 content::WaitForLoadStop(observer.tabs()[kExpectedNumberOfTabs - 1]));
491 EXPECT_EQ(GURL(kChromiumURL),
492 observer.tabs()[kExpectedNumberOfTabs - 1]->GetURL());
493 EXPECT_FALSE(
494 content::WaitForLoadStop(observer.tabs()[kExpectedNumberOfTabs - 2]));
495 EXPECT_EQ(GURL(kChromiumURL),
496 observer.tabs()[kExpectedNumberOfTabs - 2]->GetURL());
497 }
498
499 // Failing on some Win and Linux buildbots. See crbug.com/354425.
500 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS)
501 #define MAYBE_Iframes DISABLED_Iframes
502 #else
503 #define MAYBE_Iframes Iframes
504 #endif
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_Iframes)505 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_Iframes) {
506 ASSERT_TRUE(StartEmbeddedTestServer());
507 ASSERT_TRUE(RunPlatformAppTest("platform_apps/iframes")) << message_;
508 }
509
510 // Tests that localStorage and WebSQL are disabled for platform apps.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,DisallowStorage)511 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowStorage) {
512 ASSERT_TRUE(RunPlatformAppTest("platform_apps/storage")) << message_;
513 }
514
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,Restrictions)515 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Restrictions) {
516 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restrictions")) << message_;
517 }
518
519 // Tests that extensions can't use platform-app-only APIs.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,PlatformAppsOnly)520 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, PlatformAppsOnly) {
521 ASSERT_TRUE(RunExtensionTestIgnoreManifestWarnings("platform_apps/apps_only"))
522 << message_;
523 }
524
525 // Tests that platform apps have isolated storage by default.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,Isolation)526 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Isolation) {
527 ASSERT_TRUE(StartEmbeddedTestServer());
528
529 // Load a (non-app) page under the "localhost" origin that sets a cookie.
530 GURL set_cookie_url = embedded_test_server()->GetURL(
531 "/extensions/platform_apps/isolation/set_cookie.html");
532 GURL::Replacements replace_host;
533 replace_host.SetHostStr("localhost");
534 set_cookie_url = set_cookie_url.ReplaceComponents(replace_host);
535
536 ui_test_utils::NavigateToURL(browser(), set_cookie_url);
537
538 // Make sure the cookie is set.
539 int cookie_size;
540 std::string cookie_value;
541 ui_test_utils::GetCookies(set_cookie_url,
542 browser()->tab_strip_model()->GetWebContentsAt(0),
543 &cookie_size, &cookie_value);
544 ASSERT_EQ("testCookie=1", cookie_value);
545
546 // Let the platform app request the same URL, and make sure that it doesn't
547 // see the cookie.
548 ASSERT_TRUE(RunPlatformAppTest("platform_apps/isolation")) << message_;
549 }
550
551 // See crbug.com/248441
552 #if defined(OS_WIN)
553 #define MAYBE_ExtensionWindowingApis DISABLED_ExtensionWindowingApis
554 #else
555 #define MAYBE_ExtensionWindowingApis ExtensionWindowingApis
556 #endif
557
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_ExtensionWindowingApis)558 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_ExtensionWindowingApis) {
559 // Initially there should be just the one browser window visible to the
560 // extensions API.
561 const Extension* extension =
562 LoadExtension(test_data_dir_.AppendASCII("common/background_page"));
563 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension));
564
565 // And no app windows.
566 ASSERT_EQ(0U, GetAppWindowCount());
567
568 // Launch a platform app that shows a window.
569 LoadAndLaunchPlatformApp("minimal", "Launched");
570 ASSERT_EQ(1U, GetAppWindowCount());
571 int app_window_id = GetFirstAppWindow()->session_id().id();
572
573 // But it's not visible to the extensions API, it still thinks there's just
574 // one browser window.
575 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension));
576 // It can't look it up by ID either
577 ASSERT_FALSE(RunGetWindowFunctionForExtension(app_window_id, extension));
578
579 // The app can also only see one window (its own).
580 // TODO(jeremya): add an extension function to get an app window by ID, and
581 // to get a list of all the app windows, so we can test this.
582
583 // Launch another platform app that also shows a window.
584 LoadAndLaunchPlatformApp("context_menu", "Launched");
585
586 // There are two total app windows, but each app can only see its own.
587 ASSERT_EQ(2U, GetAppWindowCount());
588 // TODO(jeremya): as above, this requires more extension functions.
589 }
590
591 // ChromeOS does not support passing arguments on the command line, so the tests
592 // that rely on this functionality are disabled.
593 #if !defined(OS_CHROMEOS)
594 // Tests that launch data is sent through if the file extension matches.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchFilesWithFileExtension)595 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
596 LaunchFilesWithFileExtension) {
597 RunPlatformAppTestWithFiles("platform_apps/launch_file_by_extension",
598 kTestFilePath);
599 }
600
601 // Tests that command line parameters get passed through to platform apps
602 // via launchData correctly when launching with a file.
603 // TODO(benwells/jeremya): tests need a way to specify a handler ID.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithFile)604 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest, LaunchWithFile) {
605 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
606 "platform_apps/launch_file", kTestFilePath))
607 << message_;
608 }
609
610 // Tests that relative paths can be passed through to the platform app.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithRelativeFile)611 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest, LaunchWithRelativeFile) {
612 ASSERT_TRUE(
613 RunPlatformAppTestWithFile("platform_apps/launch_file",
614 base::FilePath::FromUTF8Unsafe(kTestFilePath)))
615 << message_;
616 }
617
618 // Tests that launch data is sent through if the file extension matches.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithFileExtension)619 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
620 LaunchWithFileExtension) {
621 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
622 "platform_apps/launch_file_by_extension", kTestFilePath))
623 << message_;
624 }
625
626 // Tests that launch data is sent through to an allowlisted extension if the
627 // file extension matches.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchAllowListedExtensionWithFile)628 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
629 LaunchAllowListedExtensionWithFile) {
630 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
631 "platform_apps/launch_allowlisted_ext_with_file", kTestFilePath))
632 << message_;
633 }
634
635 // Tests that launch data is sent through if the file extension and MIME type
636 // both match.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithFileExtensionAndMimeType)637 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
638 LaunchWithFileExtensionAndMimeType) {
639 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
640 "platform_apps/launch_file_by_extension_and_type", kTestFilePath))
641 << message_;
642 }
643
644 // Tests that launch data is sent through for a file with no extension if a
645 // handler accepts "".
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithFileWithoutExtension)646 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
647 LaunchWithFileWithoutExtension) {
648 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
649 "platform_apps/launch_file_with_no_extension",
650 "platform_apps/launch_files/test"))
651 << message_;
652 }
653
654 #if !defined(OS_WIN)
655 // Tests that launch data is sent through for a file with an empty extension if
656 // a handler accepts "".
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithFileEmptyExtension)657 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
658 LaunchWithFileEmptyExtension) {
659 base::ScopedAllowBlockingForTesting allow_blocking;
660 base::ScopedTempDir temp_dir;
661 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
662 base::FilePath test_file;
663 ASSERT_TRUE(
664 CopyTestDataAndGetTestFilePath(test_data_dir_.AppendASCII(kTestFilePath),
665 temp_dir.GetPath(), "test.", &test_file));
666 ASSERT_TRUE(RunPlatformAppTestWithFile(
667 "platform_apps/launch_file_with_no_extension", test_file))
668 << message_;
669 }
670
671 // Tests that launch data is sent through for a file with an empty extension if
672 // a handler accepts *.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithFileEmptyExtensionAcceptAny)673 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
674 LaunchWithFileEmptyExtensionAcceptAny) {
675 base::ScopedAllowBlockingForTesting allow_blocking;
676 base::ScopedTempDir temp_dir;
677 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
678 base::FilePath test_file;
679 ASSERT_TRUE(
680 CopyTestDataAndGetTestFilePath(test_data_dir_.AppendASCII(kTestFilePath),
681 temp_dir.GetPath(), "test.", &test_file));
682 ASSERT_TRUE(RunPlatformAppTestWithFile(
683 "platform_apps/launch_file_with_any_extension", test_file))
684 << message_;
685 }
686 #endif
687
688 // Tests that launch data is sent through for a file with no extension if a
689 // handler accepts *.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithFileWithoutExtensionAcceptAny)690 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
691 LaunchWithFileWithoutExtensionAcceptAny) {
692 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
693 "platform_apps/launch_file_with_any_extension",
694 "platform_apps/launch_files/test"))
695 << message_;
696 }
697
698 // Tests that launch data is sent through for a file with an extension if a
699 // handler accepts *.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithFileAcceptAnyExtension)700 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
701 LaunchWithFileAcceptAnyExtension) {
702 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
703 "platform_apps/launch_file_with_any_extension", kTestFilePath))
704 << message_;
705 }
706
707 // Tests that no launch data is sent through if the file has the wrong
708 // extension.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithWrongExtension)709 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
710 LaunchWithWrongExtension) {
711 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
712 "platform_apps/launch_wrong_extension", kTestFilePath))
713 << message_;
714 }
715
716 // Tests that no launch data is sent through if the file has no extension but
717 // the handler requires a specific extension.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithWrongEmptyExtension)718 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
719 LaunchWithWrongEmptyExtension) {
720 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
721 "platform_apps/launch_wrong_extension",
722 "platform_apps/launch_files/test"))
723 << message_;
724 }
725
726 // Tests that no launch data is sent through if the file is of the wrong MIME
727 // type.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithWrongType)728 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest, LaunchWithWrongType) {
729 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
730 "platform_apps/launch_wrong_type", kTestFilePath))
731 << message_;
732 }
733
734 // Tests that no launch data is sent through if the platform app does not
735 // provide an intent.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithNoIntent)736 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest, LaunchWithNoIntent) {
737 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
738 "platform_apps/launch_no_intent", kTestFilePath))
739 << message_;
740 }
741
742 // Tests that launch data is sent through when the file has unknown extension
743 // but the MIME type can be sniffed and the sniffed type matches.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithSniffableType)744 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
745 LaunchWithSniffableType) {
746 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
747 "platform_apps/launch_file_by_extension_and_type",
748 "platform_apps/launch_files/test.unknownextension"))
749 << message_;
750 }
751
752 // Tests that launch data is sent through with the MIME type set to
753 // application/octet-stream if the file MIME type cannot be read.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchNoType)754 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest, LaunchNoType) {
755 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
756 "platform_apps/launch_application_octet_stream",
757 "platform_apps/launch_files/test_binary.unknownextension"))
758 << message_;
759 }
760
761 // Tests that no launch data is sent through if the file does not exist.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchNoFile)762 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest, LaunchNoFile) {
763 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
764 "platform_apps/launch_invalid",
765 "platform_apps/launch_files/doesnotexist.txt"))
766 << message_;
767 }
768
769 // Tests that no launch data is sent through if the argument is a directory.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithDirectory)770 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest, LaunchWithDirectory) {
771 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
772 "platform_apps/launch_invalid", "platform_apps/launch_files"))
773 << message_;
774 }
775
776 // Tests that no launch data is sent through if there are no arguments passed
777 // on the command line
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchWithNothing)778 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest, LaunchWithNothing) {
779 ASSERT_TRUE(RunPlatformAppTestWithNothing("platform_apps/launch_nothing"))
780 << message_;
781 }
782
783 // Test that platform apps can use the chrome.fileSystem.getDisplayPath
784 // function to get the native file system path of a file they are launched with.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,GetDisplayPath)785 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest, GetDisplayPath) {
786 ASSERT_TRUE(RunPlatformAppTestWithFileInTestDataDir(
787 "platform_apps/get_display_path", kTestFilePath))
788 << message_;
789 }
790
791 // Tests that the file is created if the file does not exist and the app has the
792 // fileSystem.write permission.
IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,LaunchNewFile)793 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest, LaunchNewFile) {
794 base::ScopedAllowBlockingForTesting allow_blocking;
795 base::ScopedTempDir temp_dir;
796 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
797 ASSERT_TRUE(RunPlatformAppTestWithFile(
798 "platform_apps/launch_new_file",
799 temp_dir.GetPath().AppendASCII("new_file.txt")))
800 << message_;
801 }
802
803 #endif // !defined(OS_CHROMEOS)
804
805 #if defined(OS_CHROMEOS)
806 // TODO(https://crbug.com/1000234): Re-enable this test.
807 #define MAYBE_OpenLink DISABLED_OpenLink
808 #else
809 #define MAYBE_OpenLink OpenLink
810 #endif
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_OpenLink)811 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_OpenLink) {
812 ASSERT_TRUE(StartEmbeddedTestServer());
813 LoadAndLaunchPlatformApp("open_link", "Launched");
814 ui_test_utils::TabAddedWaiter(browser()).Wait();
815 ASSERT_EQ(2, browser()->tab_strip_model()->count());
816 }
817
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MutationEventsDisabled)818 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MutationEventsDisabled) {
819 ASSERT_TRUE(RunPlatformAppTest("platform_apps/mutation_events")) << message_;
820 }
821
822 // This appears to be unreliable.
823 // TODO(stevenjb): Investigate and enable
824 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) || defined(OS_WIN) || \
825 defined(OS_MAC)
826 #define MAYBE_AppWindowRestoreState DISABLED_AppWindowRestoreState
827 #else
828 #define MAYBE_AppWindowRestoreState AppWindowRestoreState
829 #endif
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_AppWindowRestoreState)830 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_AppWindowRestoreState) {
831 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restore_state"));
832 }
833
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWindowAdjustBoundsToBeVisibleOnScreen)834 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
835 AppWindowAdjustBoundsToBeVisibleOnScreen) {
836 const Extension* extension = LoadAndLaunchPlatformApp("minimal", "Launched");
837
838 AppWindow* window = CreateAppWindow(browser()->profile(), extension);
839
840 // The screen bounds didn't change, the cached bounds didn't need to adjust.
841 gfx::Rect cached_bounds(80, 100, 400, 400);
842 gfx::Rect cached_screen_bounds(0, 0, 1600, 900);
843 gfx::Rect current_screen_bounds(0, 0, 1600, 900);
844 gfx::Size minimum_size(200, 200);
845 gfx::Rect bounds;
846 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(
847 window, cached_bounds, cached_screen_bounds, current_screen_bounds,
848 minimum_size, &bounds);
849 EXPECT_EQ(bounds, cached_bounds);
850
851 // We have an empty screen bounds, the cached bounds didn't need to adjust.
852 gfx::Rect empty_screen_bounds;
853 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(
854 window, cached_bounds, empty_screen_bounds, current_screen_bounds,
855 minimum_size, &bounds);
856 EXPECT_EQ(bounds, cached_bounds);
857
858 // Cached bounds is completely off the new screen bounds in horizontal
859 // locations. Expect to reposition the bounds.
860 gfx::Rect horizontal_out_of_screen_bounds(-800, 100, 400, 400);
861 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(
862 window, horizontal_out_of_screen_bounds, gfx::Rect(-1366, 0, 1600, 900),
863 current_screen_bounds, minimum_size, &bounds);
864 EXPECT_EQ(bounds, gfx::Rect(0, 100, 400, 400));
865
866 // Cached bounds is completely off the new screen bounds in vertical
867 // locations. Expect to reposition the bounds.
868 gfx::Rect vertical_out_of_screen_bounds(10, 1000, 400, 400);
869 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(
870 window, vertical_out_of_screen_bounds, gfx::Rect(-1366, 0, 1600, 900),
871 current_screen_bounds, minimum_size, &bounds);
872 EXPECT_EQ(bounds, gfx::Rect(10, 500, 400, 400));
873
874 // From a large screen resulotion to a small one. Expect it fit on screen.
875 gfx::Rect big_cache_bounds(10, 10, 1000, 1000);
876 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(
877 window, big_cache_bounds, gfx::Rect(0, 0, 1600, 1000),
878 gfx::Rect(0, 0, 800, 600), minimum_size, &bounds);
879 EXPECT_EQ(bounds, gfx::Rect(0, 0, 800, 600));
880
881 // Don't resize the bounds smaller than minimum size, when the minimum size is
882 // larger than the screen.
883 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(
884 window, big_cache_bounds, gfx::Rect(0, 0, 1600, 1000),
885 gfx::Rect(0, 0, 800, 600), gfx::Size(900, 900), &bounds);
886 EXPECT_EQ(bounds, gfx::Rect(0, 0, 900, 900));
887 }
888
889 namespace {
890
891 class PlatformAppDevToolsBrowserTest : public PlatformAppBrowserTest {
892 protected:
893 enum TestFlags {
894 RELAUNCH = 0x1,
895 HAS_ID = 0x2,
896 };
897 // Runs a test inside a harness that opens DevTools on an app window.
898 void RunTestWithDevTools(const char* name, int test_flags);
899 };
900
RunTestWithDevTools(const char * name,int test_flags)901 void PlatformAppDevToolsBrowserTest::RunTestWithDevTools(const char* name,
902 int test_flags) {
903 using content::DevToolsAgentHost;
904 const Extension* extension = LoadAndLaunchPlatformApp(name, "Launched");
905 ASSERT_TRUE(extension);
906 AppWindow* window = GetFirstAppWindow();
907 ASSERT_TRUE(window);
908 ASSERT_EQ(window->window_key().empty(), (test_flags & HAS_ID) == 0);
909 content::WebContents* web_contents = window->web_contents();
910 ASSERT_TRUE(web_contents);
911
912 OpenDevToolsWindow(web_contents);
913
914 if (test_flags & RELAUNCH) {
915 // Close the AppWindow, and ensure it is gone.
916 CloseAppWindow(window);
917 ASSERT_FALSE(GetFirstAppWindow());
918
919 // Relaunch the app and get a new AppWindow.
920 content::WindowedNotificationObserver app_loaded_observer(
921 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
922 content::NotificationService::AllSources());
923 apps::AppServiceProxyFactory::GetForProfile(browser()->profile())
924 ->BrowserAppLauncher()
925 ->LaunchAppWithParams(apps::AppLaunchParams(
926 extension->id(), LaunchContainer::kLaunchContainerNone,
927 WindowOpenDisposition::NEW_WINDOW,
928 apps::mojom::AppLaunchSource::kSourceTest));
929 app_loaded_observer.Wait();
930 window = GetFirstAppWindow();
931 ASSERT_TRUE(window);
932
933 // DevTools should have reopened with the relaunch.
934 web_contents = window->web_contents();
935 ASSERT_TRUE(web_contents);
936 ASSERT_TRUE(DevToolsAgentHost::HasFor(web_contents));
937 }
938 }
939
940 } // namespace
941
IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest,ReOpenedWithID)942 IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, ReOpenedWithID) {
943 RunTestWithDevTools("minimal_id", RELAUNCH | HAS_ID);
944 }
945
IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest,ReOpenedWithURL)946 IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, ReOpenedWithURL) {
947 RunTestWithDevTools("minimal", RELAUNCH);
948 }
949
950 // Test that showing a permission request as a constrained window works and is
951 // correctly parented.
952 #if defined(OS_MAC)
953 #define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest
954 #else
955 // TODO(sail): Enable this on other platforms once http://crbug.com/95455 is
956 // fixed.
957 #define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest
958 #endif
959
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_ConstrainedWindowRequest)960 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_ConstrainedWindowRequest) {
961 PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
962 const Extension* extension =
963 LoadAndLaunchPlatformApp("optional_permission_request", "Launched");
964 ASSERT_TRUE(extension) << "Failed to load extension.";
965
966 WebContents* web_contents = GetFirstAppWindowWebContents();
967 ASSERT_TRUE(web_contents);
968
969 // Verify that the app window has a dialog attached.
970 WebContentsModalDialogManager* web_contents_modal_dialog_manager =
971 WebContentsModalDialogManager::FromWebContents(web_contents);
972 EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive());
973
974 // Close the constrained window and wait for the reply to the permission
975 // request.
976 ExtensionTestMessageListener listener("PermissionRequestDone", false);
977 WebContentsModalDialogManager::TestApi test_api(
978 web_contents_modal_dialog_manager);
979 test_api.CloseAllDialogs();
980 ASSERT_TRUE(listener.WaitUntilSatisfied());
981 }
982
983 // Tests that an app calling chrome.runtime.reload will reload the app and
984 // relaunch it if it was running.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,ReloadRelaunches)985 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ReloadRelaunches) {
986 ExtensionTestMessageListener launched_listener("Launched", true);
987 const Extension* extension =
988 LoadAndLaunchPlatformApp("reload", &launched_listener);
989 ASSERT_TRUE(extension);
990 ASSERT_TRUE(GetFirstAppWindow());
991
992 // Now tell the app to reload itself.
993 ExtensionTestMessageListener launched_listener2("Launched", false);
994 launched_listener.Reply("reload");
995 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
996 ASSERT_TRUE(GetFirstAppWindow());
997 }
998
999 // Tests that reloading a component app loads its (lazy) background page.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,ComponentReloadLoadsLazyBackgroundPage)1000 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
1001 ComponentReloadLoadsLazyBackgroundPage) {
1002 ExtensionTestMessageListener launched_listener("Launched", true);
1003 const Extension* component_app = LoadExtensionAsComponentWithManifest(
1004 test_data_dir_.AppendASCII("platform_apps")
1005 .AppendASCII("component_reload"),
1006 FILE_PATH_LITERAL("manifest.json"));
1007 ASSERT_TRUE(component_app);
1008 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
1009
1010 // Now tell the app to reload itself.
1011 ExtensionTestMessageListener launched_listener2("Launched", false);
1012 launched_listener.Reply("reload");
1013 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
1014 }
1015
1016 namespace {
1017
1018 // Utility class to ensure extension installation does or does not occur in
1019 // certain scenarios.
1020 class CheckExtensionInstalledObserver
1021 : public extensions::ExtensionRegistryObserver {
1022 public:
CheckExtensionInstalledObserver(Profile * profile)1023 explicit CheckExtensionInstalledObserver(Profile* profile)
1024 : seen_(false), registry_(extensions::ExtensionRegistry::Get(profile)) {
1025 registry_->AddObserver(this);
1026 }
~CheckExtensionInstalledObserver()1027 ~CheckExtensionInstalledObserver() override {
1028 registry_->RemoveObserver(this);
1029 }
1030
seen() const1031 bool seen() const { return seen_; }
1032
1033 // ExtensionRegistryObserver:
OnExtensionWillBeInstalled(content::BrowserContext * browser_context,const extensions::Extension * extension,bool is_update,const std::string & old_name)1034 void OnExtensionWillBeInstalled(content::BrowserContext* browser_context,
1035 const extensions::Extension* extension,
1036 bool is_update,
1037 const std::string& old_name) override {
1038 EXPECT_FALSE(seen_);
1039 seen_ = true;
1040 }
1041
1042 private:
1043 bool seen_;
1044 extensions::ExtensionRegistry* registry_;
1045 };
1046
1047 } // namespace
1048
1049 // Component App Test 1 of 3: ensure that the initial load of a component
1050 // extension utilizing a background page (e.g. a v2 platform app) has its
1051 // background page run and is launchable. Waits for the Launched response from
1052 // the script resource in the opened app window.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,PRE_PRE_ComponentAppBackgroundPage)1053 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
1054 PRE_PRE_ComponentAppBackgroundPage) {
1055 CheckExtensionInstalledObserver should_install(browser()->profile());
1056
1057 // Ensure that we wait until the background page is run (to register the
1058 // OnLaunched listener) before trying to open the application. This is similar
1059 // to LoadAndLaunchPlatformApp, but we want to load as a component extension.
1060 content::WindowedNotificationObserver app_loaded_observer(
1061 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
1062 content::NotificationService::AllSources());
1063
1064 const Extension* extension = LoadExtensionAsComponent(
1065 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
1066 ASSERT_TRUE(extension);
1067
1068 app_loaded_observer.Wait();
1069 ASSERT_TRUE(should_install.seen());
1070
1071 ExtensionTestMessageListener launched_listener("Launched", false);
1072 apps::AppServiceProxyFactory::GetForProfile(browser()->profile())
1073 ->BrowserAppLauncher()
1074 ->LaunchAppWithParams(apps::AppLaunchParams(
1075 extension->id(), LaunchContainer::kLaunchContainerNone,
1076 WindowOpenDisposition::NEW_WINDOW,
1077 apps::mojom::AppLaunchSource::kSourceTest));
1078
1079 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
1080 }
1081
1082 // Component App Test 2 of 3: ensure an installed component app can be launched
1083 // on a subsequent browser start, without requiring any install/upgrade logic
1084 // to be run, then perform setup for step 3.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,PRE_ComponentAppBackgroundPage)1085 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, PRE_ComponentAppBackgroundPage) {
1086 // Since the component app is now installed, re-adding it in the same profile
1087 // should not cause it to be re-installed. Instead, we wait for the OnLaunched
1088 // in a different observer (which would timeout if not the app was not
1089 // previously installed properly) and then check this observer to make sure it
1090 // never saw the NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED event.
1091 CheckExtensionInstalledObserver should_not_install(browser()->profile());
1092 const Extension* extension = LoadExtensionAsComponent(
1093 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
1094 ASSERT_TRUE(extension);
1095
1096 ExtensionTestMessageListener launched_listener("Launched", false);
1097 apps::AppServiceProxyFactory::GetForProfile(browser()->profile())
1098 ->BrowserAppLauncher()
1099 ->LaunchAppWithParams(apps::AppLaunchParams(
1100 extension->id(), LaunchContainer::kLaunchContainerNone,
1101 WindowOpenDisposition::NEW_WINDOW,
1102 apps::mojom::AppLaunchSource::kSourceTest));
1103
1104 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
1105 ASSERT_FALSE(should_not_install.seen());
1106
1107 // Simulate a "downgrade" from version 2 in the test manifest.json to 1.
1108 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser()->profile());
1109
1110 // Clear the registered events to ensure they are updated.
1111 extensions::EventRouter::Get(browser()->profile())
1112 ->ClearRegisteredEventsForTest(extension->id());
1113
1114 DictionaryPrefUpdate update(extension_prefs->pref_service(),
1115 extensions::pref_names::kExtensions);
1116 base::DictionaryValue* dict = update.Get();
1117 std::string key(extension->id());
1118 key += ".manifest.version";
1119 dict->SetString(key, "1");
1120 }
1121
1122 // Component App Test 3 of 3: simulate a component extension upgrade that
1123 // re-adds the OnLaunched event, and allows the app to be launched.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,ComponentAppBackgroundPage)1124 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ComponentAppBackgroundPage) {
1125 CheckExtensionInstalledObserver should_install(browser()->profile());
1126 // Since we are forcing an upgrade, we need to wait for the load again.
1127 content::WindowedNotificationObserver app_loaded_observer(
1128 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
1129 content::NotificationService::AllSources());
1130
1131 const Extension* extension = LoadExtensionAsComponent(
1132 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
1133 ASSERT_TRUE(extension);
1134 app_loaded_observer.Wait();
1135 ASSERT_TRUE(should_install.seen());
1136
1137 ExtensionTestMessageListener launched_listener("Launched", false);
1138 apps::AppServiceProxyFactory::GetForProfile(browser()->profile())
1139 ->BrowserAppLauncher()
1140 ->LaunchAppWithParams(apps::AppLaunchParams(
1141 extension->id(), LaunchContainer::kLaunchContainerNone,
1142 WindowOpenDisposition::NEW_WINDOW,
1143 apps::mojom::AppLaunchSource::kSourceTest));
1144
1145 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
1146 }
1147
1148 // Disabled due to flakiness. http://crbug.com/468609
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,DISABLED_ComponentExtensionRuntimeReload)1149 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
1150 DISABLED_ComponentExtensionRuntimeReload) {
1151 // Ensure that we wait until the background page is run (to register the
1152 // OnLaunched listener) before trying to open the application. This is similar
1153 // to LoadAndLaunchPlatformApp, but we want to load as a component extension.
1154 content::WindowedNotificationObserver app_loaded_observer(
1155 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
1156 content::NotificationService::AllSources());
1157
1158 const Extension* extension = LoadExtensionAsComponent(
1159 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
1160 ASSERT_TRUE(extension);
1161
1162 app_loaded_observer.Wait();
1163
1164 {
1165 ExtensionTestMessageListener launched_listener("Launched", false);
1166 apps::AppServiceProxyFactory::GetForProfile(browser()->profile())
1167 ->BrowserAppLauncher()
1168 ->LaunchAppWithParams(apps::AppLaunchParams(
1169 extension->id(), LaunchContainer::kLaunchContainerNone,
1170 WindowOpenDisposition::NEW_WINDOW,
1171 apps::mojom::AppLaunchSource::kSourceTest));
1172 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
1173 }
1174
1175 {
1176 ExtensionTestMessageListener launched_listener("Launched", false);
1177 ASSERT_TRUE(ExecuteScriptInBackgroundPageNoWait(
1178 extension->id(),
1179 // NoWait actually waits for a domAutomationController.send() which is
1180 // implicitly append to the script. Since reload() restarts the
1181 // extension, the send after reload may not get executed. To get around
1182 // this, send first, then execute the reload().
1183 "window.domAutomationController.send(0);"
1184 "chrome.runtime.reload();"));
1185 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
1186 }
1187 }
1188
1189 // Fails on Win7. http://crbug.com/171450
1190 #if defined(OS_WIN)
1191 #define MAYBE_Messaging DISABLED_Messaging
1192 #else
1193 #define MAYBE_Messaging Messaging
1194 #endif
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_Messaging)1195 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_Messaging) {
1196 ResultCatcher result_catcher;
1197 LoadAndLaunchPlatformApp("messaging/app2", "Ready");
1198 LoadAndLaunchPlatformApp("messaging/app1", "Launched");
1199 EXPECT_TRUE(result_catcher.GetNextResult());
1200 }
1201
1202 // This test depends on focus and so needs to be in interactive_ui_tests.
1203 // http://crbug.com/227041
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,DISABLED_WebContentsHasFocus)1204 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DISABLED_WebContentsHasFocus) {
1205 LoadAndLaunchPlatformApp("minimal", "Launched");
1206
1207 EXPECT_EQ(1LU, GetAppWindowCount());
1208 EXPECT_TRUE(GetFirstAppWindow()
1209 ->web_contents()
1210 ->GetRenderWidgetHostView()
1211 ->HasFocus());
1212 }
1213
1214 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
1215
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,WindowDotPrintShouldBringUpPrintPreview)1216 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
1217 WindowDotPrintShouldBringUpPrintPreview) {
1218 ScopedPreviewTestDelegate preview_delegate;
1219 ASSERT_TRUE(RunPlatformAppTest("platform_apps/print_api")) << message_;
1220 preview_delegate.WaitUntilPreviewIsReady();
1221 }
1222
1223 // This test verifies that http://crbug.com/297179 is fixed.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,DISABLED_ClosingWindowWhilePrintingShouldNotCrash)1224 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
1225 DISABLED_ClosingWindowWhilePrintingShouldNotCrash) {
1226 ScopedPreviewTestDelegate preview_delegate;
1227 ASSERT_TRUE(RunPlatformAppTest("platform_apps/print_api")) << message_;
1228 preview_delegate.WaitUntilPreviewIsReady();
1229 GetFirstAppWindow()->GetBaseWindow()->Close();
1230 }
1231
1232 #endif // ENABLE_PRINT_PREVIEW
1233
1234 #if defined(OS_CHROMEOS)
1235
1236 class PlatformAppIncognitoBrowserTest : public PlatformAppBrowserTest,
1237 public AppWindowRegistry::Observer {
1238 public:
SetUpCommandLine(base::CommandLine * command_line)1239 void SetUpCommandLine(base::CommandLine* command_line) override {
1240 // Tell chromeos to launch in Guest mode, aka incognito.
1241 command_line->AppendSwitch(switches::kIncognito);
1242 PlatformAppBrowserTest::SetUpCommandLine(command_line);
1243 }
SetUp()1244 void SetUp() override {
1245 // Make sure the file manager actually gets loaded.
1246 ComponentLoader::EnableBackgroundExtensionsForTesting();
1247 PlatformAppBrowserTest::SetUp();
1248 }
1249
1250 // AppWindowRegistry::Observer implementation.
OnAppWindowAdded(AppWindow * app_window)1251 void OnAppWindowAdded(AppWindow* app_window) override {
1252 opener_app_ids_.insert(app_window->extension_id());
1253 }
1254
1255 protected:
1256 // A set of ids of apps we've seen open a app window.
1257 std::set<std::string> opener_app_ids_;
1258 };
1259
1260 // Seen to fail repeatedly on CrOS; crbug.com/774011.
1261 #if !defined(OS_CHROMEOS)
1262 #define MAYBE_IncognitoComponentApp IncognitoComponentApp
1263 #else
1264 #define MAYBE_IncognitoComponentApp DISABLED_IncognitoComponentApp
1265 #endif
1266
IN_PROC_BROWSER_TEST_F(PlatformAppIncognitoBrowserTest,MAYBE_IncognitoComponentApp)1267 IN_PROC_BROWSER_TEST_F(PlatformAppIncognitoBrowserTest,
1268 MAYBE_IncognitoComponentApp) {
1269 // Get the file manager app.
1270 const Extension* file_manager = extension_registry()->GetExtensionById(
1271 "hhaomjibdihmijegdhdafkllkbggdgoj", ExtensionRegistry::ENABLED);
1272 ASSERT_TRUE(file_manager != NULL);
1273 Profile* incognito_profile = profile()->GetPrimaryOTRProfile();
1274 ASSERT_TRUE(incognito_profile != NULL);
1275
1276 // Wait until the file manager has had a chance to register its listener
1277 // for the launch event.
1278 EventRouter* router = EventRouter::Get(incognito_profile);
1279 ASSERT_TRUE(router != NULL);
1280 while (!router->ExtensionHasEventListener(
1281 file_manager->id(), app_runtime::OnLaunched::kEventName)) {
1282 content::RunAllPendingInMessageLoop();
1283 }
1284
1285 // Listen for new app windows so we see the file manager app launch itself.
1286 AppWindowRegistry* registry = AppWindowRegistry::Get(incognito_profile);
1287 ASSERT_TRUE(registry != NULL);
1288 registry->AddObserver(this);
1289 apps::AppServiceProxyFactory::GetForProfile(incognito_profile)
1290 ->Launch(file_manager->id(),
1291 apps::GetEventFlags(
1292 apps::mojom::LaunchContainer::kLaunchContainerWindow,
1293 WindowOpenDisposition::NEW_FOREGROUND_TAB,
1294 true /* prefer_container */),
1295 apps::mojom::LaunchSource::kFromTest,
1296 display::kInvalidDisplayId);
1297
1298 while (!base::Contains(opener_app_ids_, file_manager->id())) {
1299 content::RunAllPendingInMessageLoop();
1300 }
1301 }
1302
1303 class RestartDeviceTest : public PlatformAppBrowserTest {
1304 public:
1305 RestartDeviceTest() = default;
1306 RestartDeviceTest(const RestartDeviceTest&) = delete;
1307 RestartDeviceTest& operator=(const RestartDeviceTest&) = delete;
1308 ~RestartDeviceTest() override = default;
1309
1310 // PlatformAppBrowserTest overrides
SetUpInProcessBrowserTestFixture()1311 void SetUpInProcessBrowserTestFixture() override {
1312 PlatformAppBrowserTest::SetUpInProcessBrowserTestFixture();
1313 }
1314
SetUpOnMainThread()1315 void SetUpOnMainThread() override {
1316 PlatformAppBrowserTest::SetUpOnMainThread();
1317
1318 mock_user_manager_ = new chromeos::MockUserManager;
1319 user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
1320 base::WrapUnique(mock_user_manager_));
1321
1322 EXPECT_CALL(*mock_user_manager_, IsUserLoggedIn())
1323 .WillRepeatedly(testing::Return(true));
1324 EXPECT_CALL(*mock_user_manager_, IsLoggedInAsKioskApp())
1325 .WillRepeatedly(testing::Return(true));
1326 EXPECT_CALL(*mock_user_manager_, GetLoggedInUsers())
1327 .WillRepeatedly(testing::Invoke(mock_user_manager_,
1328 &chromeos::MockUserManager::GetUsers));
1329 }
1330
TearDownOnMainThread()1331 void TearDownOnMainThread() override {
1332 user_manager_enabler_.reset();
1333 PlatformAppBrowserTest::TearDownOnMainThread();
1334 }
1335
TearDownInProcessBrowserTestFixture()1336 void TearDownInProcessBrowserTestFixture() override {
1337 PlatformAppBrowserTest::TearDownInProcessBrowserTestFixture();
1338 }
1339
num_request_restart_calls() const1340 int num_request_restart_calls() const {
1341 return chromeos::FakePowerManagerClient::Get()->num_request_restart_calls();
1342 }
1343
1344 private:
1345 chromeos::MockUserManager* mock_user_manager_ = nullptr;
1346 std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
1347 };
1348
1349 // Tests that chrome.runtime.restart would request device restart in
1350 // ChromeOS kiosk mode.
IN_PROC_BROWSER_TEST_F(RestartDeviceTest,Restart)1351 IN_PROC_BROWSER_TEST_F(RestartDeviceTest, Restart) {
1352 ASSERT_EQ(0, num_request_restart_calls());
1353
1354 ExtensionTestMessageListener launched_listener("Launched", true);
1355 const Extension* extension =
1356 LoadAndLaunchPlatformApp("restart_device", &launched_listener);
1357 ASSERT_TRUE(extension);
1358
1359 launched_listener.Reply("restart");
1360 ExtensionTestMessageListener restart_requested_listener("restartRequested",
1361 false);
1362 ASSERT_TRUE(restart_requested_listener.WaitUntilSatisfied());
1363
1364 EXPECT_EQ(1, num_request_restart_calls());
1365 }
1366
1367 #endif // defined(OS_CHROMEOS)
1368
1369 // Test that when an application is uninstalled and re-install it does not have
1370 // access to the previously set data.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,ReinstallDataCleanup)1371 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ReinstallDataCleanup) {
1372 // The application is installed and launched. After the 'Launched' message is
1373 // acknowledged by the browser process, the application will test that some
1374 // data are not installed and then install them. The application will then be
1375 // uninstalled and the same process will be repeated.
1376 std::string extension_id;
1377
1378 {
1379 const Extension* extension =
1380 LoadAndLaunchPlatformApp("reinstall_data_cleanup", "Launched");
1381 ASSERT_TRUE(extension);
1382 extension_id = extension->id();
1383
1384 ResultCatcher result_catcher;
1385 EXPECT_TRUE(result_catcher.GetNextResult());
1386 }
1387
1388 UninstallExtension(extension_id);
1389 content::RunAllPendingInMessageLoop();
1390
1391 {
1392 const Extension* extension =
1393 LoadAndLaunchPlatformApp("reinstall_data_cleanup", "Launched");
1394 ASSERT_TRUE(extension);
1395 ASSERT_EQ(extension_id, extension->id());
1396
1397 ResultCatcher result_catcher;
1398 EXPECT_TRUE(result_catcher.GetNextResult());
1399 }
1400 }
1401
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppsIgnoreDefaultZoom)1402 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppsIgnoreDefaultZoom) {
1403 const Extension* extension = LoadAndLaunchPlatformApp("minimal", "Launched");
1404
1405 // Set the browser default zoom to something other than the default (which is
1406 // 0).
1407 browser()->profile()->GetZoomLevelPrefs()->SetDefaultZoomLevelPref(1);
1408
1409 // Launch another window. This is a simple way to guarantee that any messages
1410 // that would have been delivered to the app renderer and back for zoom have
1411 // made it through.
1412 ExtensionTestMessageListener launched_listener("Launched", false);
1413 LaunchPlatformApp(extension);
1414 EXPECT_TRUE(launched_listener.WaitUntilSatisfied());
1415
1416 // Now check that the app window's default zoom, and actual zoom level,
1417 // have not been changed from the default.
1418 WebContents* web_contents = GetFirstAppWindowWebContents();
1419 content::HostZoomMap* app_host_zoom_map =
1420 content::HostZoomMap::Get(web_contents->GetSiteInstance());
1421 EXPECT_EQ(0, app_host_zoom_map->GetDefaultZoomLevel());
1422 EXPECT_EQ(0, app_host_zoom_map->GetZoomLevel(web_contents));
1423 }
1424
1425 // Sends chrome.test.sendMessage from chrome.app.window.create's callback.
1426 // The app window also adds an <iframe> to the page during window.onload.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWindowIframe)1427 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWindowIframe) {
1428 LoadAndLaunchPlatformApp("app_window_send_message",
1429 "APP_WINDOW_CREATE_CALLBACK");
1430 }
1431
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,NewWindowWithNonExistingFile)1432 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, NewWindowWithNonExistingFile) {
1433 ASSERT_TRUE(
1434 RunPlatformAppTest("platform_apps/new_window_with_non_existing_file"));
1435 }
1436
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,SandboxedLocalFile)1437 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, SandboxedLocalFile) {
1438 ASSERT_TRUE(RunPlatformAppTest("platform_apps/sandboxed_local_file"));
1439 }
1440
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,NewWindowAboutBlank)1441 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, NewWindowAboutBlank) {
1442 ASSERT_TRUE(RunPlatformAppTest("platform_apps/new_window_about_blank"));
1443 }
1444
1445 // Test that an app window sees the synthetic wheel events of a touchpad pinch.
1446 // While the app window itself does not scale in response to a pinch, we
1447 // still offer the synthetic wheels for pages that want to implement custom
1448 // pinch zoom behaviour.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,TouchpadPinchSyntheticWheelEvents)1449 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
1450 TouchpadPinchSyntheticWheelEvents) {
1451 LoadAndLaunchPlatformApp("touchpad_pinch", "Launched");
1452
1453 WebContents* web_contents = GetFirstAppWindowWebContents();
1454 ASSERT_TRUE(web_contents);
1455
1456 // Ensure the compositor thread is aware of the wheel listener.
1457 content::MainThreadFrameObserver synchronize_threads(
1458 web_contents->GetRenderWidgetHostView()->GetRenderWidgetHost());
1459 synchronize_threads.Wait();
1460
1461 ExtensionTestMessageListener synthetic_wheel_listener("Seen wheel event",
1462 false);
1463
1464 const gfx::Rect contents_rect = web_contents->GetContainerBounds();
1465 const gfx::Point pinch_position(contents_rect.width() / 2,
1466 contents_rect.height() / 2);
1467 content::SimulateGesturePinchSequence(web_contents, pinch_position, 1.23,
1468 blink::WebGestureDevice::kTouchpad);
1469
1470 ASSERT_TRUE(synthetic_wheel_listener.WaitUntilSatisfied());
1471 }
1472
1473 // TODO(crbug.com/961017): Fix memory leaks in tests and re-enable on LSAN.
1474 #if defined(LEAK_SANITIZER)
1475 #define MAYBE_PictureInPicture DISABLED_PictureInPicture
1476 #else
1477 #define MAYBE_PictureInPicture PictureInPicture
1478 #endif
1479
1480 // Tests that platform apps can enter and exit Picture-in-Picture.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_PictureInPicture)1481 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_PictureInPicture) {
1482 LoadAndLaunchPlatformApp("picture_in_picture", "Launched");
1483
1484 WebContents* web_contents = GetFirstAppWindowWebContents();
1485 ASSERT_TRUE(web_contents);
1486 content::PictureInPictureWindowController* window_controller =
1487 content::PictureInPictureWindowController::GetOrCreateForWebContents(
1488 web_contents);
1489 ASSERT_TRUE(window_controller->GetWindowForTesting());
1490 EXPECT_FALSE(window_controller->GetWindowForTesting()->IsVisible());
1491
1492 bool result = false;
1493 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1494 web_contents, "enterPictureInPicture();", &result));
1495 EXPECT_TRUE(result);
1496 EXPECT_TRUE(window_controller->GetWindowForTesting()->IsVisible());
1497
1498 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1499 web_contents, "exitPictureInPicture();", &result));
1500 EXPECT_TRUE(result);
1501 EXPECT_FALSE(window_controller->GetWindowForTesting()->IsVisible());
1502 }
1503
1504 } // namespace extensions
1505