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