Home | History | Annotate | Download | only in apps
      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