• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/app_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::AppWindowGeometryCache;
17 
18 // This helper class can be used to wait for changes in the app window
19 // geometry cache registry for a specific window in a specific extension.
20 class GeometryCacheChangeHelper : AppWindowGeometryCache::Observer {
21  public:
GeometryCacheChangeHelper(AppWindowGeometryCache * cache,const std::string & extension_id,const std::string & window_id,const gfx::Rect & bounds)22   GeometryCacheChangeHelper(AppWindowGeometryCache* 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 app 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_|.
WaitForEntirelyChanged()38   void WaitForEntirelyChanged() {
39     if (satisfied_)
40       return;
41 
42     waiting_ = true;
43     content::RunMessageLoop();
44   }
45 
46   // Implements the content::NotificationObserver interface.
OnGeometryCacheChanged(const std::string & extension_id,const std::string & window_id,const gfx::Rect & bounds)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   AppWindowGeometryCache* 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  protected:
RunAppWindowAPITest(const char * testName)78   bool RunAppWindowAPITest(const char* testName) {
79     if (!BeginAppWindowAPITest(testName))
80       return false;
81 
82     ResultCatcher catcher;
83     if (!catcher.GetNextResult()) {
84       message_ = catcher.message();
85       return false;
86     }
87 
88     return true;
89   }
90 
RunAppWindowAPITestAndWaitForRoundTrip(const char * testName)91   bool RunAppWindowAPITestAndWaitForRoundTrip(const char* testName) {
92     if (!BeginAppWindowAPITest(testName))
93       return false;
94 
95     ExtensionTestMessageListener round_trip_listener("WaitForRoundTrip", true);
96     if (!round_trip_listener.WaitUntilSatisfied()) {
97       message_ = "Did not get the 'WaitForRoundTrip' message.";
98       return false;
99     }
100 
101     round_trip_listener.Reply("");
102 
103     ResultCatcher catcher;
104     if (!catcher.GetNextResult()) {
105       message_ = catcher.message();
106       return false;
107     }
108 
109     return true;
110   }
111 
112  private:
BeginAppWindowAPITest(const char * testName)113   bool BeginAppWindowAPITest(const char* testName) {
114     ExtensionTestMessageListener launched_listener("Launched", true);
115     LoadAndLaunchPlatformApp("window_api", &launched_listener);
116     if (!launched_listener.WaitUntilSatisfied()) {
117       message_ = "Did not get the 'Launched' message.";
118       return false;
119     }
120 
121     launched_listener.Reply(testName);
122     return true;
123   }
124 };
125 
126 // These tests are flaky after https://codereview.chromium.org/57433010/.
127 // See http://crbug.com/319613.
128 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,TestCreate)129 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, TestCreate) {
130   ASSERT_TRUE(RunAppWindowAPITest("testCreate")) << message_;
131 }
132 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,TestSingleton)133 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, TestSingleton) {
134   ASSERT_TRUE(RunAppWindowAPITest("testSingleton")) << message_;
135 }
136 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,TestCloseEvent)137 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, TestCloseEvent) {
138   ASSERT_TRUE(RunAppWindowAPITest("testCloseEvent")) << message_;
139 }
140 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,DISABLED_TestMaximize)141 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, DISABLED_TestMaximize) {
142   ASSERT_TRUE(RunAppWindowAPITest("testMaximize")) << message_;
143 }
144 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,DISABLED_TestRestore)145 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, DISABLED_TestRestore) {
146   ASSERT_TRUE(RunAppWindowAPITest("testRestore")) << message_;
147 }
148 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,DISABLED_TestRestoreAfterClose)149 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, DISABLED_TestRestoreAfterClose) {
150   ASSERT_TRUE(RunAppWindowAPITest("testRestoreAfterClose")) << message_;
151 }
152 
153 // These tests will be flaky in Linux as window bounds change asynchronously.
154 #if defined(OS_LINUX)
155 #define MAYBE_TestDeprecatedBounds DISABLED_TestDeprecatedBounds
156 #define MAYBE_TestInitialBounds DISABLED_TestInitialBounds
157 #define MAYBE_TestInitialConstraints DISABLED_TestInitialConstraints
158 #define MAYBE_TestSetBounds DISABLED_TestSetBounds
159 #define MAYBE_TestSetSizeConstraints DISABLED_TestSetSizeConstraints
160 #else
161 #define MAYBE_TestDeprecatedBounds TestDeprecatedBounds
162 #define MAYBE_TestInitialBounds TestInitialBounds
163 #define MAYBE_TestInitialConstraints TestInitialConstraints
164 #define MAYBE_TestSetBounds TestSetBounds
165 #define MAYBE_TestSetSizeConstraints TestSetSizeConstraints
166 #endif
167 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,MAYBE_TestDeprecatedBounds)168 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, MAYBE_TestDeprecatedBounds) {
169   ASSERT_TRUE(RunAppWindowAPITest("testDeprecatedBounds")) << message_;
170 }
171 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,MAYBE_TestInitialBounds)172 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, MAYBE_TestInitialBounds) {
173   ASSERT_TRUE(RunAppWindowAPITest("testInitialBounds")) << message_;
174 }
175 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,MAYBE_TestInitialConstraints)176 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, MAYBE_TestInitialConstraints) {
177   ASSERT_TRUE(RunAppWindowAPITest("testInitialConstraints")) << message_;
178 }
179 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,MAYBE_TestSetBounds)180 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, MAYBE_TestSetBounds) {
181   ASSERT_TRUE(RunAppWindowAPITest("testSetBounds")) << message_;
182 }
183 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,MAYBE_TestSetSizeConstraints)184 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, MAYBE_TestSetSizeConstraints) {
185   ASSERT_TRUE(RunAppWindowAPITest("testSetSizeConstraints")) << message_;
186 }
187 
188 // Flaky failures on mac_rel and WinXP, see http://crbug.com/324915.
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,DISABLED_TestRestoreGeometryCacheChange)189 IN_PROC_BROWSER_TEST_F(AppWindowAPITest,
190                        DISABLED_TestRestoreGeometryCacheChange) {
191   // This test is similar to the other AppWindowAPI tests except that at some
192   // point the app will send a 'ListenGeometryChange' message at which point the
193   // test will check if the geometry cache entry for the test window has
194   // changed. When the change happens, the test will let the app know so it can
195   // continue running.
196   ExtensionTestMessageListener launched_listener("Launched", true);
197 
198   content::WindowedNotificationObserver app_loaded_observer(
199       content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
200       content::NotificationService::AllSources());
201 
202   const extensions::Extension* extension = LoadExtension(
203       test_data_dir_.AppendASCII("platform_apps").AppendASCII("window_api"));
204   EXPECT_TRUE(extension);
205 
206   OpenApplication(AppLaunchParams(browser()->profile(),
207                                   extension,
208                                   extensions::LAUNCH_CONTAINER_NONE,
209                                   NEW_WINDOW));
210 
211   ExtensionTestMessageListener geometry_listener("ListenGeometryChange", true);
212 
213   ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
214   launched_listener.Reply("testRestoreAfterGeometryCacheChange");
215 
216   ASSERT_TRUE(geometry_listener.WaitUntilSatisfied());
217 
218   GeometryCacheChangeHelper geo_change_helper_1(
219       AppWindowGeometryCache::Get(browser()->profile()),
220       extension->id(),
221       // The next line has information that has to stay in sync with the app.
222       "test-ra",
223       gfx::Rect(200, 200, 200, 200));
224 
225   GeometryCacheChangeHelper geo_change_helper_2(
226       AppWindowGeometryCache::Get(browser()->profile()),
227       extension->id(),
228       // The next line has information that has to stay in sync with the app.
229       "test-rb",
230       gfx::Rect(200, 200, 200, 200));
231 
232   // These calls will block until the app window geometry cache will change.
233   geo_change_helper_1.WaitForEntirelyChanged();
234   geo_change_helper_2.WaitForEntirelyChanged();
235 
236   ResultCatcher catcher;
237   geometry_listener.Reply("");
238   ASSERT_TRUE(catcher.GetNextResult());
239 }
240 
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,TestBadging)241 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, TestBadging) {
242   ASSERT_TRUE(
243       RunAppWindowAPITestAndWaitForRoundTrip("testBadging")) << message_;
244 }
245 
246 // TODO(benwells): Implement on Mac.
247 #if defined(USE_AURA)
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,TestFrameColors)248 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, TestFrameColors) {
249   ASSERT_TRUE(RunAppWindowAPITest("testFrameColors")) << message_;
250 }
251 
252 // TODO(benwells): Remove this test once all the things are merged together. It
253 // is currently present as this feature was previously disabled on stable
254 // channel, so the test is to ensure it has all been re-enabled properly.
IN_PROC_BROWSER_TEST_F(AppWindowAPITest,TestFrameColorsInStable)255 IN_PROC_BROWSER_TEST_F(AppWindowAPITest, TestFrameColorsInStable) {
256   extensions::ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_STABLE);
257   ASSERT_TRUE(RunAppWindowAPITest("testFrameColors")) << message_;
258 }
259 #endif
260