Home | History | Annotate | Download | only in status_icons
      1 // Copyright 2014 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 "chrome/browser/ui/views/status_icons/status_tray_state_changer_win.h"
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/win/scoped_com_initializer.h"
      9 #include "base/win/windows_version.h"
     10 #include "chrome/browser/status_icons/status_icon.h"
     11 #include "chrome/browser/ui/views/status_icons/status_icon_win.h"
     12 #include "chrome/browser/ui/views/status_icons/status_tray_win.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 #include "third_party/skia/include/core/SkBitmap.h"
     15 #include "ui/gfx/image/image_skia.h"
     16 
     17 class StatusTrayStateChangerWinTest : public testing::Test {
     18  public:
     19   StatusTrayStateChangerWinTest() {}
     20 
     21   void SetUp() OVERRIDE {
     22     testing::Test::SetUp();
     23     com_.reset(new base::win::ScopedCOMInitializer());
     24     status_tray_.reset(new StatusTrayWin());
     25     SkBitmap bitmap;
     26 
     27     // Put a real bitmap into "bitmap".  2x2 bitmap of green 32 bit pixels.
     28     bitmap.allocN32Pixels(16, 16);
     29     bitmap.eraseColor(SK_ColorGREEN);
     30     status_icon_win_ = (StatusIconWin*)status_tray_->CreateStatusIcon(
     31         StatusTray::OTHER_ICON,
     32         gfx::ImageSkia::CreateFrom1xBitmap(bitmap),
     33         base::string16());
     34     tray_watcher_ = new StatusTrayStateChangerWin(status_icon_win_->icon_id(),
     35                                                   status_icon_win_->window());
     36   }
     37 
     38   void TearDown() OVERRIDE {
     39     tray_watcher_ = NULL;
     40     status_tray_.reset();
     41     com_.reset();
     42     testing::Test::TearDown();
     43   }
     44 
     45  protected:
     46   HWND icon_window() { return status_icon_win_->window(); }
     47   UINT icon_id() { return status_icon_win_->icon_id(); }
     48 
     49   scoped_ptr<NOTIFYITEM> SetupAndGetCurrentNotifyItem() {
     50     EXPECT_TRUE(CallCreateTrayNotify());
     51 
     52     EXPECT_TRUE(IsInterfaceKnown());
     53 
     54     scoped_ptr<NOTIFYITEM> notify_item = GetNotifyItem();
     55     EXPECT_TRUE(notify_item.get() != NULL);
     56     DCHECK_EQ(notify_item->hwnd, icon_window());
     57     DCHECK_EQ(notify_item->id, icon_id());
     58 
     59     return notify_item.Pass();
     60   }
     61 
     62   bool CallCreateTrayNotify() { return tray_watcher_->CreateTrayNotify(); }
     63 
     64   bool IsInterfaceKnown() {
     65     return StatusTrayStateChangerWin::INTERFACE_VERSION_UNKNOWN !=
     66            tray_watcher_->interface_version_;
     67   }
     68 
     69   void SendNotifyItemUpdate(scoped_ptr<NOTIFYITEM> notify_item) {
     70     tray_watcher_->SendNotifyItemUpdate(notify_item.Pass());
     71   }
     72 
     73   scoped_ptr<NOTIFYITEM> GetNotifyItem() {
     74     return tray_watcher_->RegisterCallback();
     75   }
     76 
     77   scoped_ptr<base::win::ScopedCOMInitializer> com_;
     78   scoped_ptr<StatusTrayWin> status_tray_;
     79   scoped_refptr<StatusTrayStateChangerWin> tray_watcher_;
     80 
     81   StatusIconWin* status_icon_win_;
     82 
     83   DISALLOW_COPY_AND_ASSIGN(StatusTrayStateChangerWinTest);
     84 };
     85 
     86 // Test is disabled due to multiple COM initialization errors.  See
     87 // http//crbug.com/367199 for details.
     88 TEST_F(StatusTrayStateChangerWinTest, DISABLED_Setup) {
     89   // This tests the code path that will read the NOTIFYITEM data structure for
     90   // use in future tests.
     91   scoped_ptr<NOTIFYITEM> notify_item = SetupAndGetCurrentNotifyItem();
     92   EXPECT_FALSE(notify_item.get() == NULL);
     93 }
     94 
     95 // Test is disabled due to multiple COM initialization errors.  See
     96 // http//crbug.com/367199 for details.
     97 TEST_F(StatusTrayStateChangerWinTest, DISABLED_ComApiTest) {
     98 
     99   // Setup code to read the current preference.
    100   scoped_ptr<NOTIFYITEM> notify_item = SetupAndGetCurrentNotifyItem();
    101   ASSERT_TRUE(notify_item.get() != NULL);
    102 
    103   // Store the current pref.
    104   DWORD current_preference = notify_item->preference;
    105 
    106   // Ensure that running our code will do something.
    107   if (notify_item->preference != PREFERENCE_SHOW_WHEN_ACTIVE) {
    108     scoped_ptr<NOTIFYITEM> notify_item_copy(new NOTIFYITEM(*notify_item));
    109     notify_item_copy->preference = PREFERENCE_SHOW_WHEN_ACTIVE;
    110     SendNotifyItemUpdate(notify_item_copy.Pass());
    111   }
    112 
    113   // Run the interesting code.
    114   tray_watcher_->EnsureTrayIconVisible();
    115 
    116   EXPECT_EQ(PREFERENCE_SHOW_ALWAYS, GetNotifyItem()->preference);
    117   SendNotifyItemUpdate(notify_item.Pass());
    118   notify_item = GetNotifyItem();
    119 
    120   EXPECT_EQ(notify_item->preference, current_preference);
    121 };
    122 
    123 // Test is disabled due to multiple COM initialization errors.  See
    124 // http//crbug.com/367199 for details.
    125 TEST_F(StatusTrayStateChangerWinTest, DISABLED_TraySizeApiTest) {
    126 
    127   // The tray does not auto-hide icons immediately on Vista so this test does
    128   // not detect a size change.
    129   if (base::win::GetVersion() <= base::win::VERSION_VISTA)
    130     return;
    131 
    132   // Used to reset operating system state afterwards.
    133   scoped_ptr<NOTIFYITEM> notify_item = SetupAndGetCurrentNotifyItem();
    134   // We can't actually run this test if we're already showing the icon.
    135   if (notify_item->preference == PREFERENCE_SHOW_ALWAYS)
    136     return;
    137 
    138   // This test can only run if the tray window structure conforms to what I've
    139   // seen in Win7 and Win8.
    140   HWND shell_tray_hwnd = ::FindWindow(L"Shell_TrayWnd", NULL);
    141   if (shell_tray_hwnd == NULL)
    142     return;
    143 
    144   HWND tray_notify_hwnd =
    145       ::FindWindowEx(shell_tray_hwnd, NULL, L"TrayNotifyWnd", NULL);
    146   ASSERT_TRUE(tray_notify_hwnd != NULL);
    147 
    148   RECT original_tray_notify_rect;
    149   ::GetWindowRect(tray_notify_hwnd, &original_tray_notify_rect);
    150 
    151   LONG width = original_tray_notify_rect.right - original_tray_notify_rect.left;
    152   ASSERT_GT(width, 0);
    153 
    154   tray_watcher_->EnsureTrayIconVisible();
    155 
    156   RECT new_tray_notify_rect;
    157   ::GetWindowRect(tray_notify_hwnd, &new_tray_notify_rect);
    158 
    159   LONG new_width = new_tray_notify_rect.right - new_tray_notify_rect.left;
    160 
    161   EXPECT_GT(new_width, width);
    162 
    163   SendNotifyItemUpdate(notify_item.Pass());
    164   ::GetWindowRect(tray_notify_hwnd, &new_tray_notify_rect);
    165   new_width = new_tray_notify_rect.right - new_tray_notify_rect.left;
    166   EXPECT_EQ(width, new_width);
    167 }
    168