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 "apps/shell_window_geometry_cache.h" 6 #include "chrome/browser/apps/app_browsertest_util.h" 7 #include "chrome/browser/extensions/extension_test_message_listener.h" 8 #include "chrome/browser/profiles/profile.h" 9 #include "chrome/browser/ui/browser.h" 10 #include "chrome/browser/ui/extensions/application_launch.h" 11 #include "content/public/browser/notification_service.h" 12 #include "content/public/test/test_utils.h" 13 #include "extensions/common/constants.h" 14 #include "extensions/common/extension.h" 15 16 using apps::ShellWindowGeometryCache; 17 18 // This helper class can be used to wait for changes in the shell window 19 // geometry cache registry for a specific window in a specific extension. 20 class GeometryCacheChangeHelper : ShellWindowGeometryCache::Observer { 21 public: 22 GeometryCacheChangeHelper(ShellWindowGeometryCache* cache, 23 const std::string& extension_id, 24 const std::string& window_id, 25 const gfx::Rect& bounds) 26 : cache_(cache), 27 extension_id_(extension_id), 28 window_id_(window_id), 29 bounds_(bounds), 30 satisfied_(false), 31 waiting_(false) { 32 cache_->AddObserver(this); 33 } 34 35 // This method will block until the shell window geometry cache registry will 36 // provide a bound for |window_id_| that is entirely different (as in x/y/w/h) 37 // from the initial |bounds_|. 38 void WaitForEntirelyChanged() { 39 if (satisfied_) 40 return; 41 42 waiting_ = true; 43 content::RunMessageLoop(); 44 } 45 46 // Implements the content::NotificationObserver interface. 47 virtual void OnGeometryCacheChanged(const std::string& extension_id, 48 const std::string& window_id, 49 const gfx::Rect& bounds) 50 OVERRIDE { 51 if (extension_id != extension_id_ || window_id != window_id_) 52 return; 53 54 if (bounds_.x() != bounds.x() && 55 bounds_.y() != bounds.y() && 56 bounds_.width() != bounds.width() && 57 bounds_.height() != bounds.height()) { 58 satisfied_ = true; 59 cache_->RemoveObserver(this); 60 61 if (waiting_) 62 base::MessageLoopForUI::current()->Quit(); 63 } 64 } 65 66 private: 67 ShellWindowGeometryCache* cache_; 68 std::string extension_id_; 69 std::string window_id_; 70 gfx::Rect bounds_; 71 bool satisfied_; 72 bool waiting_; 73 }; 74 75 // Helper class for tests related to the Apps Window API (chrome.app.window). 76 class AppWindowAPITest : public extensions::PlatformAppBrowserTest { 77 public: 78 bool RunAppWindowAPITest(const char* testName) { 79 ExtensionTestMessageListener launched_listener("Launched", true); 80 LoadAndLaunchPlatformApp("window_api"); 81 if (!launched_listener.WaitUntilSatisfied()) { 82 message_ = "Did not get the 'Launched' message."; 83 return false; 84 } 85 86 ResultCatcher catcher; 87 launched_listener.Reply(testName); 88 89 if (!catcher.GetNextResult()) { 90 message_ = catcher.message(); 91 return false; 92 } 93 94 return true; 95 } 96 }; 97 98 // These tests are flaky after https://codereview.chromium.org/57433010/. 99 // See http://crbug.com/319613. 100 101 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, DISABLED_TestCreate) { 102 ASSERT_TRUE(RunAppWindowAPITest("testCreate")) << message_; 103 } 104 105 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, TestSingleton) { 106 ASSERT_TRUE(RunAppWindowAPITest("testSingleton")) << message_; 107 } 108 109 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, DISABLED_TestBounds) { 110 ASSERT_TRUE(RunAppWindowAPITest("testBounds")) << message_; 111 } 112 113 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, TestCloseEvent) { 114 ASSERT_TRUE(RunAppWindowAPITest("testCloseEvent")) << message_; 115 } 116 117 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, DISABLED_TestMaximize) { 118 ASSERT_TRUE(RunAppWindowAPITest("testMaximize")) << message_; 119 } 120 121 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, DISABLED_TestRestore) { 122 ASSERT_TRUE(RunAppWindowAPITest("testRestore")) << message_; 123 } 124 125 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, DISABLED_TestRestoreAfterClose) { 126 ASSERT_TRUE(RunAppWindowAPITest("testRestoreAfterClose")) << message_; 127 } 128 129 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, DISABLED_TestSizeConstraints) { 130 ASSERT_TRUE(RunAppWindowAPITest("testSizeConstraints")) << message_; 131 } 132 133 // Flaky failures on mac_rel and WinXP, see http://crbug.com/324915. 134 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, 135 DISABLED_TestRestoreGeometryCacheChange) { 136 // This test is similar to the other AppWindowAPI tests except that at some 137 // point the app will send a 'ListenGeometryChange' message at which point the 138 // test will check if the geometry cache entry for the test window has 139 // changed. When the change happens, the test will let the app know so it can 140 // continue running. 141 ExtensionTestMessageListener launched_listener("Launched", true); 142 143 content::WindowedNotificationObserver app_loaded_observer( 144 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 145 content::NotificationService::AllSources()); 146 147 const extensions::Extension* extension = LoadExtension( 148 test_data_dir_.AppendASCII("platform_apps").AppendASCII("window_api")); 149 EXPECT_TRUE(extension); 150 151 OpenApplication(AppLaunchParams(browser()->profile(), 152 extension, 153 extensions::LAUNCH_CONTAINER_NONE, 154 NEW_WINDOW)); 155 156 ExtensionTestMessageListener geometry_listener("ListenGeometryChange", true); 157 158 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); 159 launched_listener.Reply("testRestoreAfterGeometryCacheChange"); 160 161 ASSERT_TRUE(geometry_listener.WaitUntilSatisfied()); 162 163 GeometryCacheChangeHelper geo_change_helper_1( 164 ShellWindowGeometryCache::Get(browser()->profile()), extension->id(), 165 // The next line has information that has to stay in sync with the app. 166 "test-ra", gfx::Rect(200, 200, 200, 200)); 167 168 GeometryCacheChangeHelper geo_change_helper_2( 169 ShellWindowGeometryCache::Get(browser()->profile()), extension->id(), 170 // The next line has information that has to stay in sync with the app. 171 "test-rb", gfx::Rect(200, 200, 200, 200)); 172 173 // These calls will block until the shell window geometry cache will change. 174 geo_change_helper_1.WaitForEntirelyChanged(); 175 geo_change_helper_2.WaitForEntirelyChanged(); 176 177 ResultCatcher catcher; 178 geometry_listener.Reply(""); 179 ASSERT_TRUE(catcher.GetNextResult()); 180 } 181 182